Merge tag 'riscv-for-linus-6.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / drivers / acpi / acpi_pcc.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Author: Sudeep Holla <sudeep.holla@arm.com>
4  * Copyright 2021 Arm Limited
5  *
6  * The PCC Address Space also referred as PCC Operation Region pertains to the
7  * region of PCC subspace that succeeds the PCC signature. The PCC Operation
8  * Region works in conjunction with the PCC Table(Platform Communications
9  * Channel Table). PCC subspaces that are marked for use as PCC Operation
10  * Regions must not be used as PCC subspaces for the standard ACPI features
11  * such as CPPC, RASF, PDTT and MPST. These standard features must always use
12  * the PCC Table instead.
13  *
14  * This driver sets up the PCC Address Space and installs an handler to enable
15  * handling of PCC OpRegion in the firmware.
16  *
17  */
18 #include <linux/kernel.h>
19 #include <linux/acpi.h>
20 #include <linux/completion.h>
21 #include <linux/idr.h>
22 #include <linux/io.h>
23
24 #include <acpi/pcc.h>
25
26 /*
27  * Arbitrary retries in case the remote processor is slow to respond
28  * to PCC commands
29  */
30 #define PCC_CMD_WAIT_RETRIES_NUM        500ULL
31
32 struct pcc_data {
33         struct pcc_mbox_chan *pcc_chan;
34         void __iomem *pcc_comm_addr;
35         struct completion done;
36         struct mbox_client cl;
37         struct acpi_pcc_info ctx;
38 };
39
40 static struct acpi_pcc_info pcc_ctx;
41
42 static void pcc_rx_callback(struct mbox_client *cl, void *m)
43 {
44         struct pcc_data *data = container_of(cl, struct pcc_data, cl);
45
46         complete(&data->done);
47 }
48
49 static acpi_status
50 acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
51                              void *handler_context,  void **region_context)
52 {
53         struct pcc_data *data;
54         struct acpi_pcc_info *ctx = handler_context;
55         struct pcc_mbox_chan *pcc_chan;
56         static acpi_status ret;
57
58         data = kzalloc(sizeof(*data), GFP_KERNEL);
59         if (!data)
60                 return AE_NO_MEMORY;
61
62         data->cl.rx_callback = pcc_rx_callback;
63         data->cl.knows_txdone = true;
64         data->ctx.length = ctx->length;
65         data->ctx.subspace_id = ctx->subspace_id;
66         data->ctx.internal_buffer = ctx->internal_buffer;
67
68         init_completion(&data->done);
69         data->pcc_chan = pcc_mbox_request_channel(&data->cl, ctx->subspace_id);
70         if (IS_ERR(data->pcc_chan)) {
71                 pr_err("Failed to find PCC channel for subspace %d\n",
72                        ctx->subspace_id);
73                 ret = AE_NOT_FOUND;
74                 goto err_free_data;
75         }
76
77         pcc_chan = data->pcc_chan;
78         if (!pcc_chan->mchan->mbox->txdone_irq) {
79                 pr_err("This channel-%d does not support interrupt.\n",
80                        ctx->subspace_id);
81                 ret = AE_SUPPORT;
82                 goto err_free_channel;
83         }
84         data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr,
85                                               pcc_chan->shmem_size);
86         if (!data->pcc_comm_addr) {
87                 pr_err("Failed to ioremap PCC comm region mem for %d\n",
88                        ctx->subspace_id);
89                 ret = AE_NO_MEMORY;
90                 goto err_free_channel;
91         }
92
93         *region_context = data;
94         return AE_OK;
95
96 err_free_channel:
97         pcc_mbox_free_channel(data->pcc_chan);
98 err_free_data:
99         kfree(data);
100
101         return ret;
102 }
103
104 static acpi_status
105 acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
106                                u32 bits, acpi_integer *value,
107                                void *handler_context, void *region_context)
108 {
109         int ret;
110         struct pcc_data *data = region_context;
111         u64 usecs_lat;
112
113         reinit_completion(&data->done);
114
115         /* Write to Shared Memory */
116         memcpy_toio(data->pcc_comm_addr, (void *)value, data->ctx.length);
117
118         ret = mbox_send_message(data->pcc_chan->mchan, NULL);
119         if (ret < 0)
120                 return AE_ERROR;
121
122         /*
123          * pcc_chan->latency is just a Nominal value. In reality the remote
124          * processor could be much slower to reply. So add an arbitrary
125          * amount of wait on top of Nominal.
126          */
127         usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency;
128         ret = wait_for_completion_timeout(&data->done,
129                                                 usecs_to_jiffies(usecs_lat));
130         if (ret == 0) {
131                 pr_err("PCC command executed timeout!\n");
132                 return AE_TIME;
133         }
134
135         mbox_chan_txdone(data->pcc_chan->mchan, ret);
136
137         memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
138
139         return AE_OK;
140 }
141
142 void __init acpi_init_pcc(void)
143 {
144         acpi_status status;
145
146         status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
147                                                     ACPI_ADR_SPACE_PLATFORM_COMM,
148                                                     &acpi_pcc_address_space_handler,
149                                                     &acpi_pcc_address_space_setup,
150                                                     &pcc_ctx);
151         if (ACPI_FAILURE(status))
152                 pr_alert("OperationRegion handler could not be installed\n");
153 }