0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/kernel.h>
0019 #include <linux/acpi.h>
0020 #include <linux/completion.h>
0021 #include <linux/idr.h>
0022 #include <linux/io.h>
0023
0024 #include <acpi/pcc.h>
0025
0026 struct pcc_data {
0027 struct pcc_mbox_chan *pcc_chan;
0028 void __iomem *pcc_comm_addr;
0029 struct completion done;
0030 struct mbox_client cl;
0031 struct acpi_pcc_info ctx;
0032 };
0033
0034 static struct acpi_pcc_info pcc_ctx;
0035
0036 static void pcc_rx_callback(struct mbox_client *cl, void *m)
0037 {
0038 struct pcc_data *data = container_of(cl, struct pcc_data, cl);
0039
0040 complete(&data->done);
0041 }
0042
0043 static acpi_status
0044 acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
0045 void *handler_context, void **region_context)
0046 {
0047 struct pcc_data *data;
0048 struct acpi_pcc_info *ctx = handler_context;
0049 struct pcc_mbox_chan *pcc_chan;
0050
0051 data = kzalloc(sizeof(*data), GFP_KERNEL);
0052 if (!data)
0053 return AE_NO_MEMORY;
0054
0055 data->cl.rx_callback = pcc_rx_callback;
0056 data->cl.knows_txdone = true;
0057 data->ctx.length = ctx->length;
0058 data->ctx.subspace_id = ctx->subspace_id;
0059 data->ctx.internal_buffer = ctx->internal_buffer;
0060
0061 init_completion(&data->done);
0062 data->pcc_chan = pcc_mbox_request_channel(&data->cl, ctx->subspace_id);
0063 if (IS_ERR(data->pcc_chan)) {
0064 pr_err("Failed to find PCC channel for subspace %d\n",
0065 ctx->subspace_id);
0066 return AE_NOT_FOUND;
0067 }
0068
0069 pcc_chan = data->pcc_chan;
0070 data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr,
0071 pcc_chan->shmem_size);
0072 if (!data->pcc_comm_addr) {
0073 pr_err("Failed to ioremap PCC comm region mem for %d\n",
0074 ctx->subspace_id);
0075 return AE_NO_MEMORY;
0076 }
0077
0078 *region_context = data;
0079 return AE_OK;
0080 }
0081
0082 static acpi_status
0083 acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
0084 u32 bits, acpi_integer *value,
0085 void *handler_context, void *region_context)
0086 {
0087 int ret;
0088 struct pcc_data *data = region_context;
0089
0090 reinit_completion(&data->done);
0091
0092
0093 memcpy_toio(data->pcc_comm_addr, (void *)value, data->ctx.length);
0094
0095 ret = mbox_send_message(data->pcc_chan->mchan, NULL);
0096 if (ret < 0)
0097 return AE_ERROR;
0098
0099 if (data->pcc_chan->mchan->mbox->txdone_irq)
0100 wait_for_completion(&data->done);
0101
0102 mbox_client_txdone(data->pcc_chan->mchan, ret);
0103
0104 memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
0105
0106 return AE_OK;
0107 }
0108
0109 void __init acpi_init_pcc(void)
0110 {
0111 acpi_status status;
0112
0113 status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
0114 ACPI_ADR_SPACE_PLATFORM_COMM,
0115 &acpi_pcc_address_space_handler,
0116 &acpi_pcc_address_space_setup,
0117 &pcc_ctx);
0118 if (ACPI_FAILURE(status))
0119 pr_alert("OperationRegion handler could not be installed\n");
0120 }