42
42
*/
43
43
44
44
#include <linux/cpufreq.h>
45
+ #include <linux/delay.h>
45
46
#include <linux/interrupt.h>
46
47
#include <linux/io.h>
47
48
#include <linux/module.h>
@@ -178,6 +179,7 @@ struct private_data {
178
179
struct completion done ;
179
180
struct semaphore sem ;
180
181
struct pmap pmap ;
182
+ int host_irq ;
181
183
};
182
184
183
185
static void __iomem * __map_region (const char * name )
@@ -195,12 +197,36 @@ static void __iomem *__map_region(const char *name)
195
197
return ptr ;
196
198
}
197
199
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
+
198
224
static int __issue_avs_command (struct private_data * priv , unsigned int cmd ,
199
225
unsigned int num_in , unsigned int num_out ,
200
226
u32 args [])
201
227
{
202
- unsigned long time_left = msecs_to_jiffies (AVS_TIMEOUT );
203
228
void __iomem * base = priv -> base ;
229
+ unsigned long time_left ;
204
230
unsigned int i ;
205
231
int ret ;
206
232
u32 val ;
@@ -238,7 +264,7 @@ static int __issue_avs_command(struct private_data *priv, unsigned int cmd,
238
264
writel (AVS_CPU_L2_INT_MASK , priv -> avs_intr_base + AVS_CPU_L2_SET0 );
239
265
240
266
/* Wait for AVS co-processor to finish processing the command. */
241
- time_left = wait_for_completion_timeout ( & priv -> done , time_left );
267
+ time_left = wait_for_avs_command ( priv , AVS_TIMEOUT );
242
268
243
269
/*
244
270
* If the AVS status is not in the expected range, it means AVS didn't
@@ -509,7 +535,7 @@ static int brcm_avs_prepare_init(struct platform_device *pdev)
509
535
{
510
536
struct private_data * priv ;
511
537
struct device * dev ;
512
- int host_irq , ret ;
538
+ int ret ;
513
539
514
540
dev = & pdev -> dev ;
515
541
priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
@@ -536,19 +562,14 @@ static int brcm_avs_prepare_init(struct platform_device *pdev)
536
562
goto unmap_base ;
537
563
}
538
564
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
- }
565
+ priv -> host_irq = platform_get_irq_byname (pdev , BRCM_AVS_HOST_INTR );
546
566
547
- ret = devm_request_irq (dev , host_irq , irq_handler , IRQF_TRIGGER_RISING ,
567
+ ret = devm_request_irq (dev , priv -> host_irq , irq_handler ,
568
+ IRQF_TRIGGER_RISING ,
548
569
BRCM_AVS_HOST_INTR , priv );
549
- if (ret ) {
570
+ if (ret && priv -> host_irq >= 0 ) {
550
571
dev_err (dev , "IRQ request failed: %s (%d) -- %d\n" ,
551
- BRCM_AVS_HOST_INTR , host_irq , ret );
572
+ BRCM_AVS_HOST_INTR , priv -> host_irq , ret );
552
573
goto unmap_intr_base ;
553
574
}
554
575
0 commit comments