hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/cpufreq/brcmstb-avs-cpufreq.c
....@@ -42,6 +42,7 @@
4242 */
4343
4444 #include <linux/cpufreq.h>
45
+#include <linux/delay.h>
4546 #include <linux/interrupt.h>
4647 #include <linux/io.h>
4748 #include <linux/module.h>
....@@ -178,6 +179,7 @@
178179 struct completion done;
179180 struct semaphore sem;
180181 struct pmap pmap;
182
+ int host_irq;
181183 };
182184
183185 static void __iomem *__map_region(const char *name)
....@@ -195,11 +197,36 @@
195197 return ptr;
196198 }
197199
198
-static int __issue_avs_command(struct private_data *priv, int cmd, bool is_send,
200
+static unsigned long wait_for_avs_command(struct private_data *priv,
201
+ unsigned long timeout)
202
+{
203
+ unsigned long time_left = 0;
204
+ u32 val;
205
+
206
+ /* Event driven, wait for the command interrupt */
207
+ if (priv->host_irq >= 0)
208
+ return wait_for_completion_timeout(&priv->done,
209
+ msecs_to_jiffies(timeout));
210
+
211
+ /* Polling for command completion */
212
+ do {
213
+ time_left = timeout;
214
+ val = readl(priv->base + AVS_MBOX_STATUS);
215
+ if (val)
216
+ break;
217
+
218
+ usleep_range(1000, 2000);
219
+ } while (--timeout);
220
+
221
+ return time_left;
222
+}
223
+
224
+static int __issue_avs_command(struct private_data *priv, unsigned int cmd,
225
+ unsigned int num_in, unsigned int num_out,
199226 u32 args[])
200227 {
201
- unsigned long time_left = msecs_to_jiffies(AVS_TIMEOUT);
202228 void __iomem *base = priv->base;
229
+ unsigned long time_left;
203230 unsigned int i;
204231 int ret;
205232 u32 val;
....@@ -225,11 +252,9 @@
225252 /* Clear status before we begin. */
226253 writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
227254
228
- /* We need to send arguments for this command. */
229
- if (args && is_send) {
230
- for (i = 0; i < AVS_MAX_CMD_ARGS; i++)
231
- writel(args[i], base + AVS_MBOX_PARAM(i));
232
- }
255
+ /* Provide input parameters */
256
+ for (i = 0; i < num_in; i++)
257
+ writel(args[i], base + AVS_MBOX_PARAM(i));
233258
234259 /* Protect from spurious interrupts. */
235260 reinit_completion(&priv->done);
....@@ -239,7 +264,7 @@
239264 writel(AVS_CPU_L2_INT_MASK, priv->avs_intr_base + AVS_CPU_L2_SET0);
240265
241266 /* Wait for AVS co-processor to finish processing the command. */
242
- time_left = wait_for_completion_timeout(&priv->done, time_left);
267
+ time_left = wait_for_avs_command(priv, AVS_TIMEOUT);
243268
244269 /*
245270 * If the AVS status is not in the expected range, it means AVS didn't
....@@ -256,11 +281,9 @@
256281 goto out;
257282 }
258283
259
- /* This command returned arguments, so we read them back. */
260
- if (args && !is_send) {
261
- for (i = 0; i < AVS_MAX_CMD_ARGS; i++)
262
- args[i] = readl(base + AVS_MBOX_PARAM(i));
263
- }
284
+ /* Process returned values */
285
+ for (i = 0; i < num_out; i++)
286
+ args[i] = readl(base + AVS_MBOX_PARAM(i));
264287
265288 /* Clear status to tell AVS co-processor we are done. */
266289 writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
....@@ -338,7 +361,7 @@
338361 u32 args[AVS_MAX_CMD_ARGS];
339362 int ret;
340363
341
- ret = __issue_avs_command(priv, AVS_CMD_GET_PMAP, false, args);
364
+ ret = __issue_avs_command(priv, AVS_CMD_GET_PMAP, 0, 4, args);
342365 if (ret || !pmap)
343366 return ret;
344367
....@@ -359,7 +382,7 @@
359382 args[2] = pmap->p2;
360383 args[3] = pmap->state;
361384
362
- return __issue_avs_command(priv, AVS_CMD_SET_PMAP, true, args);
385
+ return __issue_avs_command(priv, AVS_CMD_SET_PMAP, 4, 0, args);
363386 }
364387
365388 static int brcm_avs_get_pstate(struct private_data *priv, unsigned int *pstate)
....@@ -367,7 +390,7 @@
367390 u32 args[AVS_MAX_CMD_ARGS];
368391 int ret;
369392
370
- ret = __issue_avs_command(priv, AVS_CMD_GET_PSTATE, false, args);
393
+ ret = __issue_avs_command(priv, AVS_CMD_GET_PSTATE, 0, 1, args);
371394 if (ret)
372395 return ret;
373396 *pstate = args[0];
....@@ -381,7 +404,8 @@
381404
382405 args[0] = pstate;
383406
384
- return __issue_avs_command(priv, AVS_CMD_SET_PSTATE, true, args);
407
+ return __issue_avs_command(priv, AVS_CMD_SET_PSTATE, 1, 0, args);
408
+
385409 }
386410
387411 static u32 brcm_avs_get_voltage(void __iomem *base)
....@@ -410,7 +434,11 @@
410434 if (ret)
411435 return ERR_PTR(ret);
412436
413
- table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1, sizeof(*table),
437
+ /*
438
+ * We allocate space for the 5 different P-STATES AVS,
439
+ * plus extra space for a terminating element.
440
+ */
441
+ table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1 + 1, sizeof(*table),
414442 GFP_KERNEL);
415443 if (!table)
416444 return ERR_PTR(-ENOMEM);
....@@ -455,6 +483,8 @@
455483 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
456484 struct private_data *priv = policy->driver_data;
457485
486
+ cpufreq_cpu_put(policy);
487
+
458488 return brcm_avs_get_frequency(priv->base);
459489 }
460490
....@@ -480,13 +510,23 @@
480510 * AVS co-processor, not necessarily the P-state we are running at now.
481511 * So, we get the current P-state explicitly.
482512 */
483
- return brcm_avs_get_pstate(priv, &priv->pmap.state);
513
+ ret = brcm_avs_get_pstate(priv, &priv->pmap.state);
514
+ if (ret)
515
+ return ret;
516
+
517
+ /* This is best effort. Nothing to do if it fails. */
518
+ (void)__issue_avs_command(priv, AVS_CMD_S2_ENTER, 0, 0, NULL);
519
+
520
+ return 0;
484521 }
485522
486523 static int brcm_avs_resume(struct cpufreq_policy *policy)
487524 {
488525 struct private_data *priv = policy->driver_data;
489526 int ret;
527
+
528
+ /* This is best effort. Nothing to do if it fails. */
529
+ (void)__issue_avs_command(priv, AVS_CMD_S2_EXIT, 0, 0, NULL);
490530
491531 ret = brcm_avs_set_pmap(priv, &priv->pmap);
492532 if (ret == -EEXIST) {
....@@ -509,7 +549,7 @@
509549 {
510550 struct private_data *priv;
511551 struct device *dev;
512
- int host_irq, ret;
552
+ int ret;
513553
514554 dev = &pdev->dev;
515555 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
....@@ -536,19 +576,14 @@
536576 goto unmap_base;
537577 }
538578
539
- host_irq = platform_get_irq_byname(pdev, BRCM_AVS_HOST_INTR);
540
- if (host_irq < 0) {
541
- dev_err(dev, "Couldn't find interrupt %s -- %d\n",
542
- BRCM_AVS_HOST_INTR, host_irq);
543
- ret = host_irq;
544
- goto unmap_intr_base;
545
- }
579
+ priv->host_irq = platform_get_irq_byname(pdev, BRCM_AVS_HOST_INTR);
546580
547
- ret = devm_request_irq(dev, host_irq, irq_handler, IRQF_TRIGGER_RISING,
581
+ ret = devm_request_irq(dev, priv->host_irq, irq_handler,
582
+ IRQF_TRIGGER_RISING,
548583 BRCM_AVS_HOST_INTR, priv);
549
- if (ret) {
584
+ if (ret && priv->host_irq >= 0) {
550585 dev_err(dev, "IRQ request failed: %s (%d) -- %d\n",
551
- BRCM_AVS_HOST_INTR, host_irq, ret);
586
+ BRCM_AVS_HOST_INTR, priv->host_irq, ret);
552587 goto unmap_intr_base;
553588 }
554589
....@@ -601,7 +636,7 @@
601636 /* All cores share the same clock and thus the same policy. */
602637 cpumask_setall(policy->cpus);
603638
604
- ret = __issue_avs_command(priv, AVS_CMD_ENABLE, false, NULL);
639
+ ret = __issue_avs_command(priv, AVS_CMD_ENABLE, 0, 0, NULL);
605640 if (!ret) {
606641 unsigned int pstate;
607642