diff options
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
-rw-r--r-- | drivers/acpi/cppc_acpi.c | 48 |
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 4446fa6c820e..d9ce4b162e2c 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c | |||
@@ -39,6 +39,7 @@ | |||
39 | 39 | ||
40 | #include <linux/cpufreq.h> | 40 | #include <linux/cpufreq.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/iopoll.h> | ||
42 | #include <linux/ktime.h> | 43 | #include <linux/ktime.h> |
43 | #include <linux/rwsem.h> | 44 | #include <linux/rwsem.h> |
44 | #include <linux/wait.h> | 45 | #include <linux/wait.h> |
@@ -49,7 +50,7 @@ struct cppc_pcc_data { | |||
49 | struct mbox_chan *pcc_channel; | 50 | struct mbox_chan *pcc_channel; |
50 | void __iomem *pcc_comm_addr; | 51 | void __iomem *pcc_comm_addr; |
51 | bool pcc_channel_acquired; | 52 | bool pcc_channel_acquired; |
52 | ktime_t deadline; | 53 | unsigned int deadline_us; |
53 | unsigned int pcc_mpar, pcc_mrtt, pcc_nominal; | 54 | unsigned int pcc_mpar, pcc_mrtt, pcc_nominal; |
54 | 55 | ||
55 | bool pending_pcc_write_cmd; /* Any pending/batched PCC write cmds? */ | 56 | bool pending_pcc_write_cmd; /* Any pending/batched PCC write cmds? */ |
@@ -198,42 +199,31 @@ static struct kobj_type cppc_ktype = { | |||
198 | 199 | ||
199 | static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit) | 200 | static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit) |
200 | { | 201 | { |
201 | int ret = -EIO, status = 0; | 202 | int ret, status; |
202 | struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id]; | 203 | struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id]; |
203 | struct acpi_pcct_shared_memory __iomem *generic_comm_base = | 204 | struct acpi_pcct_shared_memory __iomem *generic_comm_base = |
204 | pcc_ss_data->pcc_comm_addr; | 205 | pcc_ss_data->pcc_comm_addr; |
205 | ktime_t next_deadline = ktime_add(ktime_get(), | ||
206 | pcc_ss_data->deadline); | ||
207 | 206 | ||
208 | if (!pcc_ss_data->platform_owns_pcc) | 207 | if (!pcc_ss_data->platform_owns_pcc) |
209 | return 0; | 208 | return 0; |
210 | 209 | ||
211 | /* Retry in case the remote processor was too slow to catch up. */ | 210 | /* |
212 | while (!ktime_after(ktime_get(), next_deadline)) { | 211 | * Poll PCC status register every 3us(delay_us) for maximum of |
213 | /* | 212 | * deadline_us(timeout_us) until PCC command complete bit is set(cond) |
214 | * Per spec, prior to boot the PCC space wil be initialized by | 213 | */ |
215 | * platform and should have set the command completion bit when | 214 | ret = readw_relaxed_poll_timeout(&generic_comm_base->status, status, |
216 | * PCC can be used by OSPM | 215 | status & PCC_CMD_COMPLETE_MASK, 3, |
217 | */ | 216 | pcc_ss_data->deadline_us); |
218 | status = readw_relaxed(&generic_comm_base->status); | ||
219 | if (status & PCC_CMD_COMPLETE_MASK) { | ||
220 | ret = 0; | ||
221 | if (chk_err_bit && (status & PCC_ERROR_MASK)) | ||
222 | ret = -EIO; | ||
223 | break; | ||
224 | } | ||
225 | /* | ||
226 | * Reducing the bus traffic in case this loop takes longer than | ||
227 | * a few retries. | ||
228 | */ | ||
229 | udelay(3); | ||
230 | } | ||
231 | 217 | ||
232 | if (likely(!ret)) | 218 | if (likely(!ret)) { |
233 | pcc_ss_data->platform_owns_pcc = false; | 219 | pcc_ss_data->platform_owns_pcc = false; |
234 | else | 220 | if (chk_err_bit && (status & PCC_ERROR_MASK)) |
235 | pr_err("PCC check channel failed for ss: %d. Status=%x\n", | 221 | ret = -EIO; |
236 | pcc_ss_id, status); | 222 | } |
223 | |||
224 | if (unlikely(ret)) | ||
225 | pr_err("PCC check channel failed for ss: %d. ret=%d\n", | ||
226 | pcc_ss_id, ret); | ||
237 | 227 | ||
238 | return ret; | 228 | return ret; |
239 | } | 229 | } |
@@ -585,7 +575,7 @@ static int register_pcc_channel(int pcc_ss_idx) | |||
585 | * So add an arbitrary amount of wait on top of Nominal. | 575 | * So add an arbitrary amount of wait on top of Nominal. |
586 | */ | 576 | */ |
587 | usecs_lat = NUM_RETRIES * cppc_ss->latency; | 577 | usecs_lat = NUM_RETRIES * cppc_ss->latency; |
588 | pcc_data[pcc_ss_idx]->deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC); | 578 | pcc_data[pcc_ss_idx]->deadline_us = usecs_lat; |
589 | pcc_data[pcc_ss_idx]->pcc_mrtt = cppc_ss->min_turnaround_time; | 579 | pcc_data[pcc_ss_idx]->pcc_mrtt = cppc_ss->min_turnaround_time; |
590 | pcc_data[pcc_ss_idx]->pcc_mpar = cppc_ss->max_access_rate; | 580 | pcc_data[pcc_ss_idx]->pcc_mpar = cppc_ss->max_access_rate; |
591 | pcc_data[pcc_ss_idx]->pcc_nominal = cppc_ss->latency; | 581 | pcc_data[pcc_ss_idx]->pcc_nominal = cppc_ss->latency; |