2 * Copyright (C) 2014 Linaro Ltd.
3 * Author: Ashwin Chaugule <ashwin.chaugule@linaro.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * PCC (Platform Communication Channel) is defined in the ACPI 5.0+
16 * specification. It is a mailbox like mechanism to allow clients
17 * such as CPPC (Collaborative Processor Performance Control), RAS
18 * (Reliability, Availability and Serviceability) and MPST (Memory
19 * Node Power State Table) to talk to the platform (e.g. BMC) through
20 * shared memory regions as defined in the PCC table entries. The PCC
21 * specification supports a Doorbell mechanism for the PCC clients
22 * to notify the platform about new data. This Doorbell information
23 * is also specified in each PCC table entry. See pcc_send_data()
24 * and pcc_tx_done() for basic mode of operation.
26 * For more details about PCC, please see the ACPI specification from
27 * http://www.uefi.org/ACPIv5.1 Section 14.
29 * This file implements PCC as a Mailbox controller and allows for PCC
30 * clients to be implemented as its Mailbox Client Channels.
33 #include <linux/acpi.h>
34 #include <linux/delay.h>
36 #include <linux/init.h>
37 #include <linux/list.h>
38 #include <linux/platform_device.h>
39 #include <linux/mailbox_controller.h>
40 #include <linux/mailbox_client.h>
44 #define MAX_PCC_SUBSPACES 256
45 #define PCCS_SS_SIG_MAGIC 0x50434300
46 #define PCC_CMD_COMPLETE 0x1
48 static struct mbox_chan
*pcc_mbox_channels
;
50 static struct mbox_controller pcc_mbox_ctrl
= {};
52 * get_pcc_channel - Given a PCC subspace idx, get
53 * the respective mbox_channel.
54 * @id: PCC subspace index.
56 * Return: ERR_PTR(errno) if error, else pointer
59 static struct mbox_chan
*get_pcc_channel(int id
)
61 struct mbox_chan
*pcc_chan
;
63 if (id
< 0 || id
> pcc_mbox_ctrl
.num_chans
)
64 return ERR_PTR(-ENOENT
);
66 pcc_chan
= (struct mbox_chan
*)
67 (unsigned long) pcc_mbox_channels
+
68 (id
* sizeof(*pcc_chan
));
74 * get_subspace_id - Given a Mailbox channel, find out the
76 * @chan: Pointer to Mailbox Channel from which we want
78 * Return: Errno if not found, else positive index number.
80 static int get_subspace_id(struct mbox_chan
*chan
)
82 unsigned int id
= chan
- pcc_mbox_channels
;
84 if (id
< 0 || id
> pcc_mbox_ctrl
.num_chans
)
91 * pcc_mbox_request_channel - PCC clients call this function to
92 * request a pointer to their PCC subspace, from which they
93 * can get the details of communicating with the remote.
94 * @cl: Pointer to Mailbox client, so we know where to bind the
96 * @subspace_id: The PCC Subspace index as parsed in the PCC client
97 * ACPI package. This is used to lookup the array of PCC
98 * subspaces as parsed by the PCC Mailbox controller.
100 * Return: Pointer to the Mailbox Channel if successful or
103 struct mbox_chan
*pcc_mbox_request_channel(struct mbox_client
*cl
,
106 struct device
*dev
= pcc_mbox_ctrl
.dev
;
107 struct mbox_chan
*chan
;
111 * Each PCC Subspace is a Mailbox Channel.
112 * The PCC Clients get their PCC Subspace ID
113 * from their own tables and pass it here.
114 * This returns a pointer to the PCC subspace
115 * for the Client to operate on.
117 chan
= get_pcc_channel(subspace_id
);
119 if (!chan
|| chan
->cl
) {
120 dev_err(dev
, "%s: PCC mailbox not free\n", __func__
);
121 return ERR_PTR(-EBUSY
);
124 spin_lock_irqsave(&chan
->lock
, flags
);
127 chan
->active_req
= NULL
;
129 init_completion(&chan
->tx_complete
);
131 if (chan
->txdone_method
== TXDONE_BY_POLL
&& cl
->knows_txdone
)
132 chan
->txdone_method
|= TXDONE_BY_ACK
;
134 spin_unlock_irqrestore(&chan
->lock
, flags
);
138 EXPORT_SYMBOL_GPL(pcc_mbox_request_channel
);
141 * pcc_mbox_free_channel - Clients call this to free their Channel.
143 * @chan: Pointer to the mailbox channel as returned by
144 * pcc_mbox_request_channel()
146 void pcc_mbox_free_channel(struct mbox_chan
*chan
)
150 if (!chan
|| !chan
->cl
)
153 spin_lock_irqsave(&chan
->lock
, flags
);
155 chan
->active_req
= NULL
;
156 if (chan
->txdone_method
== (TXDONE_BY_POLL
| TXDONE_BY_ACK
))
157 chan
->txdone_method
= TXDONE_BY_POLL
;
159 spin_unlock_irqrestore(&chan
->lock
, flags
);
161 EXPORT_SYMBOL_GPL(pcc_mbox_free_channel
);
164 * pcc_tx_done - Callback from Mailbox controller code to
165 * check if PCC message transmission completed.
166 * @chan: Pointer to Mailbox channel on which previous
167 * transmission occurred.
169 * Return: TRUE if succeeded.
171 static bool pcc_tx_done(struct mbox_chan
*chan
)
173 struct acpi_pcct_hw_reduced
*pcct_ss
= chan
->con_priv
;
174 struct acpi_pcct_shared_memory
*generic_comm_base
=
175 (struct acpi_pcct_shared_memory
*) pcct_ss
->base_address
;
176 u16 cmd_delay
= pcct_ss
->latency
;
177 unsigned int retries
= 0;
179 /* Try a few times while waiting for platform to consume */
180 while (!(readw_relaxed(&generic_comm_base
->status
)
181 & PCC_CMD_COMPLETE
)) {
187 * If the remote is dead, this will cause the Mbox
188 * controller to timeout after mbox client.tx_tout
191 pr_err("PCC platform did not respond.\n");
199 * pcc_send_data - Called from Mailbox Controller code to finally
200 * transmit data over channel.
201 * @chan: Pointer to Mailbox channel over which to send data.
202 * @data: Actual data to be written over channel.
204 * Return: Err if something failed else 0 for success.
206 static int pcc_send_data(struct mbox_chan
*chan
, void *data
)
208 struct acpi_pcct_hw_reduced
*pcct_ss
= chan
->con_priv
;
209 struct acpi_pcct_shared_memory
*generic_comm_base
=
210 (struct acpi_pcct_shared_memory
*) pcct_ss
->base_address
;
211 struct acpi_generic_address doorbell
;
212 u64 doorbell_preserve
;
215 u16 cmd
= *(u16
*) data
;
218 ss_idx
= get_subspace_id(chan
);
221 pr_err("Invalid Subspace ID from PCC client\n");
225 doorbell
= pcct_ss
->doorbell_register
;
226 doorbell_preserve
= pcct_ss
->preserve_mask
;
227 doorbell_write
= pcct_ss
->write_mask
;
229 /* Write to the shared comm region. */
230 writew(cmd
, &generic_comm_base
->command
);
232 /* Write Subspace MAGIC value so platform can identify destination. */
233 writel((PCCS_SS_SIG_MAGIC
| ss_idx
), &generic_comm_base
->signature
);
235 /* Flip CMD COMPLETE bit */
236 writew(0, &generic_comm_base
->status
);
238 /* Sync notification from OSPM to Platform. */
239 acpi_read(&doorbell_val
, &doorbell
);
240 acpi_write((doorbell_val
& doorbell_preserve
) | doorbell_write
,
246 static struct mbox_chan_ops pcc_chan_ops
= {
247 .send_data
= pcc_send_data
,
248 .last_tx_done
= pcc_tx_done
,
252 * parse_pcc_subspace - Parse the PCC table and verify PCC subspace
253 * entries. There should be one entry per PCC client.
254 * @header: Pointer to the ACPI subtable header under the PCCT.
255 * @end: End of subtable entry.
257 * Return: 0 for Success, else errno.
259 * This gets called for each entry in the PCC table.
261 static int parse_pcc_subspace(struct acpi_subtable_header
*header
,
262 const unsigned long end
)
264 struct acpi_pcct_hw_reduced
*pcct_ss
;
266 if (pcc_mbox_ctrl
.num_chans
<= MAX_PCC_SUBSPACES
) {
267 pcct_ss
= (struct acpi_pcct_hw_reduced
*) header
;
269 if (pcct_ss
->header
.type
!=
270 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE
) {
271 pr_err("Incorrect PCC Subspace type detected\n");
280 * acpi_pcc_probe - Parse the ACPI tree for the PCCT.
282 * Return: 0 for Success, else errno.
284 static int __init
acpi_pcc_probe(void)
286 acpi_size pcct_tbl_header_size
;
287 struct acpi_table_header
*pcct_tbl
;
288 struct acpi_subtable_header
*pcct_entry
;
290 acpi_status status
= AE_OK
;
292 /* Search for PCCT */
293 status
= acpi_get_table_with_size(ACPI_SIG_PCCT
, 0,
295 &pcct_tbl_header_size
);
297 if (ACPI_FAILURE(status
) || !pcct_tbl
) {
298 pr_warn("PCCT header not found.\n");
302 count
= acpi_table_parse_entries(ACPI_SIG_PCCT
,
303 sizeof(struct acpi_table_pcct
),
304 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE
,
305 parse_pcc_subspace
, MAX_PCC_SUBSPACES
);
308 pr_err("Error parsing PCC subspaces from PCCT\n");
312 pcc_mbox_channels
= kzalloc(sizeof(struct mbox_chan
) *
315 if (!pcc_mbox_channels
) {
316 pr_err("Could not allocate space for PCC mbox channels\n");
320 /* Point to the first PCC subspace entry */
321 pcct_entry
= (struct acpi_subtable_header
*) (
322 (unsigned long) pcct_tbl
+ sizeof(struct acpi_table_pcct
));
324 for (i
= 0; i
< count
; i
++) {
325 pcc_mbox_channels
[i
].con_priv
= pcct_entry
;
326 pcct_entry
= (struct acpi_subtable_header
*)
327 ((unsigned long) pcct_entry
+ pcct_entry
->length
);
330 pcc_mbox_ctrl
.num_chans
= count
;
332 pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl
.num_chans
);
338 * pcc_mbox_probe - Called when we find a match for the
339 * PCCT platform device. This is purely used to represent
340 * the PCCT as a virtual device for registering with the
341 * generic Mailbox framework.
343 * @pdev: Pointer to platform device returned when a match
346 * Return: 0 for Success, else errno.
348 static int pcc_mbox_probe(struct platform_device
*pdev
)
352 pcc_mbox_ctrl
.chans
= pcc_mbox_channels
;
353 pcc_mbox_ctrl
.ops
= &pcc_chan_ops
;
354 pcc_mbox_ctrl
.txdone_poll
= true;
355 pcc_mbox_ctrl
.txpoll_period
= 10;
356 pcc_mbox_ctrl
.dev
= &pdev
->dev
;
358 pr_info("Registering PCC driver as Mailbox controller\n");
359 ret
= mbox_controller_register(&pcc_mbox_ctrl
);
362 pr_err("Err registering PCC as Mailbox controller: %d\n", ret
);
369 struct platform_driver pcc_mbox_driver
= {
370 .probe
= pcc_mbox_probe
,
373 .owner
= THIS_MODULE
,
377 static int __init
pcc_init(void)
380 struct platform_device
*pcc_pdev
;
385 /* Check if PCC support is available. */
386 ret
= acpi_pcc_probe();
389 pr_debug("ACPI PCC probe failed.\n");
393 pcc_pdev
= platform_create_bundle(&pcc_mbox_driver
,
394 pcc_mbox_probe
, NULL
, 0, NULL
, 0);
396 if (IS_ERR(pcc_pdev
)) {
397 pr_debug("Err creating PCC platform bundle\n");
398 return PTR_ERR(pcc_pdev
);
403 device_initcall(pcc_init
);