aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel Vadillo <vadillo@ti.com>2010-09-09 11:12:34 -0400
committerPaolo Pisati <paolo.pisati@canonical.com>2012-08-17 04:19:08 -0400
commit2b09254c67d989214783096b140ff10c6dea0825 (patch)
tree717f38f1241f4027765577a7f0a1786d3b21f2f3
parent4481003c2cf1d7d7ccf16b08900289f86007b804 (diff)
SYSLINK:IPU-PM-add ipu pm to syslink tree
Add ipu pm to syslink tree Signed-off-by: Miguel Vadillo <vadillo@ti.com> Signed-off-by: Juan Gutierrez <jgutierrez@ti.com> Signed-off-by: Paul Hunt <hunt@ti.com> Signed-off-by: Fernando Guzman Lugo <x0095840@ti.com> Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com> Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
-rw-r--r--drivers/dsp/syslink/ipu_pm/ipu_pm.c3490
-rw-r--r--drivers/dsp/syslink/ipu_pm/ipu_pm.h467
2 files changed, 3957 insertions, 0 deletions
diff --git a/drivers/dsp/syslink/ipu_pm/ipu_pm.c b/drivers/dsp/syslink/ipu_pm/ipu_pm.c
new file mode 100644
index 00000000000..30986f252c8
--- /dev/null
+++ b/drivers/dsp/syslink/ipu_pm/ipu_pm.c
@@ -0,0 +1,3490 @@
1/*
2 * ipu_pm.c
3 *
4 * IPU Power Management support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2009-2010 Texas Instruments, Inc.
7 *
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 */
16
17#include <generated/autoconf.h>
18#include <linux/kernel.h>
19#include <linux/delay.h>
20#include <linux/module.h>
21#include <linux/cdev.h>
22#include <linux/device.h>
23#include <linux/mod_devicetable.h>
24#include <linux/fs.h>
25#include <linux/mm.h>
26#include <linux/io.h>
27#include <linux/slab.h>
28#include <linux/vmalloc.h>
29#include <linux/uaccess.h>
30#include <linux/platform_device.h>
31#include <syslink/notify.h>
32#include <syslink/notify_driver.h>
33#include <syslink/notifydefs.h>
34#include <syslink/notify_driverdefs.h>
35#include <syslink/notify_ducatidriver.h>
36
37/* Power Management headers */
38#include <plat/omap_hwmod.h>
39#include <plat/omap_device.h>
40#include <plat/dma.h>
41#include <plat/dmtimer.h>
42#include <plat/clock.h>
43#include <plat/i2c.h>
44#include <plat/io.h>
45#include <plat/iommu.h>
46#include <plat/mailbox.h>
47#include <plat/remoteproc.h>
48#include <plat/omap-pm.h>
49#include <linux/i2c.h>
50#include <linux/gpio.h>
51#include <linux/semaphore.h>
52#include <linux/jiffies.h>
53#include <linux/clk.h>
54#include <linux/regulator/consumer.h>
55#include <linux/regulator/driver.h>
56#include <linux/regulator/machine.h>
57#include <linux/i2c/twl.h>
58
59/* Module headers */
60#include "ipu_pm.h"
61
62/** ============================================================================
63 * Macros and types
64 * ============================================================================
65 */
66#define A9 3
67#define SYS_M3 2
68#define APP_M3 1
69#define TESLA 0
70
71#define proc_supported(proc_id) (proc_id == SYS_M3 || proc_id == APP_M3)
72
73#define LINE_ID 0
74#define NUM_SELF_PROC 2
75#define IPU_KFIFO_SIZE 16
76#define PM_VERSION 0x00020000
77
78#define SYSM3_IDLE_FLAG_PHY_ADDR 0x9E0502D8
79#define APPM3_IDLE_FLAG_PHY_ADDR 0x9E0502DC
80
81#define NUM_IDLE_CORES ((__raw_readl(appm3Idle) << 1) + \
82 (__raw_readl(sysm3Idle)))
83
84/** ============================================================================
85 * Forward declarations of internal functions
86 * ============================================================================
87 */
88
89/* Request a resource on behalf of an IPU client */
90static inline int ipu_pm_req_res(u32 res_type, u32 proc_id, u32 rcb_num);
91
92/* Release a resource on behalf of an IPU client */
93static inline int ipu_pm_rel_res(u32 res_type, u32 proc_id, u32 rcb_num);
94
95/* Request a sdma channels on behalf of an IPU client */
96static inline int ipu_pm_get_sdma_chan(int proc_id, u32 rcb_num);
97
98/* Request a gptimer on behalf of an IPU client */
99static inline int ipu_pm_get_gptimer(int proc_id, u32 rcb_num);
100
101/* Request an i2c bus on behalf of an IPU client */
102static inline int ipu_pm_get_i2c_bus(int proc_id, u32 rcb_num);
103
104/* Request a gpio on behalf of an IPU client */
105static inline int ipu_pm_get_gpio(int proc_id, u32 rcb_num);
106
107/* Request a regulator on behalf of an IPU client */
108static inline int ipu_pm_get_regulator(int proc_id, u32 rcb_num);
109
110/* Request an Aux clk on behalf of an IPU client */
111static inline int ipu_pm_get_aux_clk(int proc_id, u32 rcb_num);
112
113/* Request sys m3 on behalf of an IPU client */
114static inline int ipu_pm_get_sys_m3(int proc_id, u32 rcb_num);
115
116/* Request app m3 on behalf of an IPU client */
117static inline int ipu_pm_get_app_m3(int proc_id, u32 rcb_num);
118
119/* Request L3 Bus on behalf of an IPU client */
120static inline int ipu_pm_get_l3_bus(int proc_id, u32 rcb_num);
121
122/* Request IVA HD on behalf of an IPU client */
123static inline int ipu_pm_get_iva_hd(int proc_id, u32 rcb_num);
124
125/* Request FDIF on behalf of an IPU client */
126static inline int ipu_pm_get_fdif(int proc_id, u32 rcb_num);
127
128/* Request MPU on behalf of an IPU client */
129static inline int ipu_pm_get_mpu(int proc_id, u32 rcb_num);
130
131/* Request IPU on behalf of an IPU client */
132static inline int ipu_pm_get_ipu(int proc_id, u32 rcb_num);
133
134/* Request IVA SEQ0 on behalf of an IPU client */
135static inline int ipu_pm_get_ivaseq0(int proc_id, u32 rcb_num);
136
137/* Request IVA SEQ1 on behalf of an IPU client */
138static inline int ipu_pm_get_ivaseq1(int proc_id, u32 rcb_num);
139
140/* Request ISS on behalf of an IPU client */
141static inline int ipu_pm_get_iss(int proc_id, u32 rcb_num);
142
143/* Release a sdma on behalf of an IPU client */
144static inline int ipu_pm_rel_sdma_chan(int proc_id, u32 rcb_num);
145
146/* Release a gptimer on behalf of an IPU client */
147static inline int ipu_pm_rel_gptimer(int proc_id, u32 rcb_num);
148
149/* Release an i2c buses on behalf of an IPU client */
150static inline int ipu_pm_rel_i2c_bus(int proc_id, u32 rcb_num);
151
152/* Release a gpio on behalf of an IPU client */
153static inline int ipu_pm_rel_gpio(int proc_id, u32 rcb_num);
154
155/* Release a regulator on behalf of an IPU client */
156static inline int ipu_pm_rel_regulator(int proc_id, u32 rcb_num);
157
158/* Release an Aux clk on behalf of an IPU client */
159static inline int ipu_pm_rel_aux_clk(int proc_id, u32 rcb_num);
160
161/* Release sys m3 on behalf of an IPU client */
162static inline int ipu_pm_rel_sys_m3(int proc_id, u32 rcb_num);
163
164/* Release app m3 on behalf of an IPU client */
165static inline int ipu_pm_rel_app_m3(int proc_id, u32 rcb_num);
166
167/* Release L3 Bus on behalf of an IPU client */
168static inline int ipu_pm_rel_l3_bus(int proc_id, u32 rcb_num);
169
170/* Release IVA HD on behalf of an IPU client */
171static inline int ipu_pm_rel_iva_hd(int proc_id, u32 rcb_num);
172
173/* Release FDIF on behalf of an IPU client */
174static inline int ipu_pm_rel_fdif(int proc_id, u32 rcb_num);
175
176/* Release MPU on behalf of an IPU client */
177static inline int ipu_pm_rel_mpu(int proc_id, u32 rcb_num);
178
179/* Release IPU on behalf of an IPU client */
180static inline int ipu_pm_rel_ipu(int proc_id, u32 rcb_num);
181
182/* Release IVA SEQ0 on behalf of an IPU client */
183static inline int ipu_pm_rel_ivaseq0(int proc_id, u32 rcb_num);
184
185/* Release IVA SEQ1 on behalf of an IPU client */
186static inline int ipu_pm_rel_ivaseq1(int proc_id, u32 rcb_num);
187
188/* Release ISS on behalf of an IPU client */
189static inline int ipu_pm_rel_iss(int proc_id, u32 rcb_num);
190
191/* Request a FDIF constraint on behalf of an IPU client */
192static inline int ipu_pm_req_cstr_fdif(int proc_id, u32 rcb_num);
193
194/* Request a IPU constraint on behalf of an IPU client */
195static inline int ipu_pm_req_cstr_ipu(int proc_id, u32 rcb_num);
196
197/* Request a L3 Bus constraint on behalf of an IPU client */
198static inline int ipu_pm_req_cstr_l3_bus(int proc_id, u32 rcb_num);
199
200/* Request an IVA HD constraint on behalf of an IPU client */
201static inline int ipu_pm_req_cstr_iva_hd(int proc_id, u32 rcb_num);
202
203/* Request an ISS constraint on behalf of an IPU client */
204static inline int ipu_pm_req_cstr_iss(int proc_id, u32 rcb_num);
205
206/* Request an MPU constraint on behalf of an IPU client */
207static inline int ipu_pm_req_cstr_mpu(int proc_id, u32 rcb_num);
208
209/* Release a FDFI constraint on behalf of an IPU client */
210static inline int ipu_pm_rel_cstr_fdif(int proc_id, u32 rcb_num);
211
212/* Release a IPU constraint on behalf of an IPU client */
213static inline int ipu_pm_rel_cstr_ipu(int proc_id, u32 rcb_num);
214
215/* Release a L3 Bus constraint on behalf of an IPU client */
216static inline int ipu_pm_rel_cstr_l3_bus(int proc_id, u32 rcb_num);
217
218/* Release an IVA HD constraint on behalf of an IPU client */
219static inline int ipu_pm_rel_cstr_iva_hd(int proc_id, u32 rcb_num);
220
221/* Release an ISS constraint on behalf of an IPU client */
222static inline int ipu_pm_rel_cstr_iss(int proc_id, u32 rcb_num);
223
224/* Release an MPU constraint on behalf of an IPU client */
225static inline int ipu_pm_rel_cstr_mpu(int proc_id, u32 rcb_num);
226
227/** ============================================================================
228 * Globals
229 * ============================================================================
230 */
231
232/* Usage Masks */
233static u32 GPTIMER_USE_MASK = 0xFFFF;
234static u32 I2C_USE_MASK = 0xFFFF;
235static u32 AUX_CLK_USE_MASK = 0xFFFF;
236
237/* Previous voltage value of secondary camera regulator */
238static u32 cam2_prev_volt;
239
240static struct ipu_pm_object *pm_handle_appm3;
241static struct ipu_pm_object *pm_handle_sysm3;
242static struct workqueue_struct *ipu_wq;
243static struct pm_qos_request_list *pm_qos_handle;
244static struct omap_rproc *sys_rproc;
245static struct omap_rproc *app_rproc;
246static struct omap_mbox *ducati_mbox;
247static struct iommu *ducati_iommu;
248static bool first_time = 1;
249static struct omap_dm_timer *pm_gpt;
250
251/* Ducati Interrupt Capable Gptimers */
252static int ipu_timer_list[NUM_IPU_TIMERS] = {
253 GP_TIMER_4,
254 GP_TIMER_9,
255 GP_TIMER_11};
256
257/* I2C spinlock assignment mapping table */
258static int i2c_spinlock_list[I2C_BUS_MAX + 1] = {
259 I2C_SL_INVAL,
260 I2C_1_SL,
261 I2C_2_SL,
262 I2C_3_SL,
263 I2C_4_SL};
264
265static char *ipu_regulator_name[REGULATOR_MAX] = {
266 "cam2pwr"};
267
268static struct ipu_pm_module_object ipu_pm_state = {
269 .def_cfg.reserved = 1,
270 .gate_handle = NULL
271} ;
272
273static struct ipu_pm_params pm_params = {
274 .pm_fdif_counter = 0,
275 .pm_ipu_counter = 0,
276 .pm_sys_m3_counter = 0,
277 .pm_app_m3_counter = 0,
278 .pm_iss_counter = 0,
279 .pm_iva_hd_counter = 0,
280 .pm_ivaseq0_counter = 0,
281 .pm_ivaseq1_counter = 0,
282 .pm_l3_bus_counter = 0,
283 .pm_mpu_counter = 0,
284 .pm_sdmachan_counter = 0,
285 .pm_gptimer_counter = 0,
286 .pm_gpio_counter = 0,
287 .pm_i2c_bus_counter = 0,
288 .pm_regulator_counter = 0,
289 .pm_aux_clk_counter = 0,
290 .timeout = 10000,
291 .shared_addr = NULL,
292 .pm_num_events = NUMBER_PM_EVENTS,
293 .pm_resource_event = PM_RESOURCE,
294 .pm_notification_event = PM_NOTIFICATION,
295 .proc_id = A9,
296 .remote_proc_id = -1,
297 .line_id = 0
298} ;
299
300static void __iomem *sysm3Idle;
301static void __iomem *appm3Idle;
302
303/*
304 Request a resource on behalf of an IPU client
305 *
306 */
307static inline int ipu_pm_req_res(u32 res_type, u32 proc_id, u32 rcb_num)
308{
309 int retval = PM_SUCCESS;
310
311 switch (res_type) {
312 case SDMA:
313 retval = ipu_pm_get_sdma_chan(proc_id, rcb_num);
314 break;
315 case GP_TIMER:
316 retval = ipu_pm_get_gptimer(proc_id, rcb_num);
317 break;
318 case GP_IO:
319 retval = ipu_pm_get_gpio(proc_id, rcb_num);
320 break;
321 case I2C:
322 retval = ipu_pm_get_i2c_bus(proc_id, rcb_num);
323 break;
324 case REGULATOR:
325 retval = ipu_pm_get_regulator(proc_id, rcb_num);
326 break;
327 case AUX_CLK:
328 retval = ipu_pm_get_aux_clk(proc_id, rcb_num);
329 break;
330 case SYSM3:
331 retval = ipu_pm_get_sys_m3(proc_id, rcb_num);
332 break;
333 case APPM3:
334 retval = ipu_pm_get_app_m3(proc_id, rcb_num);
335 break;
336 case L3_BUS:
337 retval = ipu_pm_get_l3_bus(proc_id, rcb_num);
338 break;
339 case IVA_HD:
340 retval = ipu_pm_get_iva_hd(proc_id, rcb_num);
341 break;
342 case IVASEQ0:
343 retval = ipu_pm_get_ivaseq0(proc_id, rcb_num);
344 break;
345 case IVASEQ1:
346 retval = ipu_pm_get_ivaseq1(proc_id, rcb_num);
347 break;
348 case ISS:
349 retval = ipu_pm_get_iss(proc_id, rcb_num);
350 break;
351 case FDIF:
352 retval = ipu_pm_get_fdif(proc_id, rcb_num);
353 break;
354 case MPU:
355 retval = ipu_pm_get_mpu(proc_id, rcb_num);
356 break;
357 case IPU:
358 retval = ipu_pm_get_ipu(proc_id, rcb_num);
359 break;
360 default:
361 pr_err("Unsupported resource\n");
362 retval = PM_UNSUPPORTED;
363 }
364
365 return retval;
366}
367
368/*
369 Release a resource on behalf of an IPU client
370 *
371 */
372static inline int ipu_pm_rel_res(u32 res_type, u32 proc_id, u32 rcb_num)
373{
374 int retval = PM_SUCCESS;
375
376 switch (res_type) {
377 case SDMA:
378 retval = ipu_pm_rel_sdma_chan(proc_id, rcb_num);
379 break;
380 case GP_TIMER:
381 retval = ipu_pm_rel_gptimer(proc_id, rcb_num);
382 break;
383 case GP_IO:
384 retval = ipu_pm_rel_gpio(proc_id, rcb_num);
385 break;
386 case I2C:
387 retval = ipu_pm_rel_i2c_bus(proc_id, rcb_num);
388 break;
389 case REGULATOR:
390 retval = ipu_pm_rel_regulator(proc_id, rcb_num);
391 break;
392 case AUX_CLK:
393 retval = ipu_pm_rel_aux_clk(proc_id, rcb_num);
394 break;
395 case SYSM3:
396 retval = ipu_pm_rel_sys_m3(proc_id, rcb_num);
397 break;
398 case APPM3:
399 retval = ipu_pm_rel_app_m3(proc_id, rcb_num);
400 break;
401 case L3_BUS:
402 retval = ipu_pm_rel_l3_bus(proc_id, rcb_num);
403 break;
404 case IVA_HD:
405 retval = ipu_pm_rel_iva_hd(proc_id, rcb_num);
406 break;
407 case IVASEQ0:
408 retval = ipu_pm_rel_ivaseq0(proc_id, rcb_num);
409 break;
410 case IVASEQ1:
411 retval = ipu_pm_rel_ivaseq1(proc_id, rcb_num);
412 break;
413 case ISS:
414 retval = ipu_pm_rel_iss(proc_id, rcb_num);
415 break;
416 case FDIF:
417 retval = ipu_pm_rel_fdif(proc_id, rcb_num);
418 break;
419 case MPU:
420 retval = ipu_pm_rel_mpu(proc_id, rcb_num);
421 break;
422 case IPU:
423 retval = ipu_pm_rel_ipu(proc_id, rcb_num);
424 break;
425 default:
426 pr_err("Unsupported resource\n");
427 retval = PM_UNSUPPORTED;
428 }
429
430 return retval;
431}
432
433/*
434 Request a resource constraint on behalf of an IPU client
435 *
436 */
437static inline int ipu_pm_req_cstr(u32 res_type, u32 proc_id, u32 rcb_num)
438{
439 int retval = PM_SUCCESS;
440
441 switch (res_type) {
442 case FDIF:
443 retval = ipu_pm_req_cstr_fdif(proc_id, rcb_num);
444 break;
445 case IPU:
446 retval = ipu_pm_req_cstr_ipu(proc_id, rcb_num);
447 break;
448 case L3_BUS:
449 retval = ipu_pm_req_cstr_l3_bus(proc_id, rcb_num);
450 break;
451 case IVA_HD:
452 retval = ipu_pm_req_cstr_iva_hd(proc_id, rcb_num);
453 break;
454 case ISS:
455 retval = ipu_pm_req_cstr_iss(proc_id, rcb_num);
456 break;
457 case MPU:
458 retval = ipu_pm_req_cstr_mpu(proc_id, rcb_num);
459 break;
460 default:
461 pr_err("Resource does not support constraints\n");
462 retval = PM_UNSUPPORTED;
463 }
464
465 return retval;
466}
467
468/*
469 Release a resource constraint on behalf of an IPU client
470 *
471 */
472static inline int ipu_pm_rel_cstr(u32 res_type, u32 proc_id, u32 rcb_num)
473{
474 int retval = PM_SUCCESS;
475
476 switch (res_type) {
477 case FDIF:
478 retval = ipu_pm_rel_cstr_fdif(proc_id, rcb_num);
479 break;
480 case IPU:
481 retval = ipu_pm_rel_cstr_ipu(proc_id, rcb_num);
482 break;
483 case L3_BUS:
484 retval = ipu_pm_rel_cstr_l3_bus(proc_id, rcb_num);
485 break;
486 case IVA_HD:
487 retval = ipu_pm_rel_cstr_iva_hd(proc_id, rcb_num);
488 break;
489 case ISS:
490 retval = ipu_pm_rel_cstr_iss(proc_id, rcb_num);
491 break;
492 case MPU:
493 retval = ipu_pm_rel_cstr_mpu(proc_id, rcb_num);
494 break;
495 default:
496 pr_err("Resource does not support constraints\n");
497 retval = PM_UNSUPPORTED;
498 }
499
500 return retval;
501}
502
503/*
504 Work Function to req/rel a resource
505 *
506 */
507static void ipu_pm_work(struct work_struct *work)
508{
509 struct ipu_pm_object *handle =
510 container_of(work, struct ipu_pm_object, work);
511 struct rcb_block *rcb_p;
512 struct ipu_pm_msg im;
513 struct ipu_pm_params *params = handle->params;
514 union message_slicer pm_msg;
515 int action_type;
516 int res_type;
517 int rcb_num;
518 int retval = PM_SUCCESS;
519
520 while (kfifo_len(&handle->fifo) >= sizeof(im)) {
521 spin_lock_irq(&handle->lock);
522 kfifo_out(&handle->fifo, &im, sizeof(im));
523 spin_unlock_irq(&handle->lock);
524
525 /* Get the payload */
526 pm_msg.whole = im.pm_msg;
527 /* Get the rcb_num */
528 rcb_num = pm_msg.fields.rcb_num;
529 /* Get pointer to the proper RCB */
530 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
531
532 /* Get the type of resource and the actions required */
533 action_type = rcb_p->msg_type;
534 res_type = rcb_p->sub_type;
535 switch (action_type) {
536 case PM_REQUEST_RESOURCE:
537 retval = ipu_pm_req_res(res_type, im.proc_id, rcb_num);
538 if (retval != PM_SUCCESS)
539 pm_msg.fields.msg_type = PM_FAIL;
540 break;
541 case PM_RELEASE_RESOURCE:
542 retval = ipu_pm_rel_res(res_type, im.proc_id, rcb_num);
543 if (retval != PM_SUCCESS)
544 pm_msg.fields.msg_type = PM_FAIL;
545 break;
546 case PM_REQUEST_CONSTRAINTS:
547 retval = ipu_pm_req_cstr(res_type, im.proc_id, rcb_num);
548 if (retval != PM_SUCCESS)
549 pm_msg.fields.msg_type = PM_FAIL;
550 break;
551 case PM_RELEASE_CONSTRAINTS:
552 retval = ipu_pm_rel_cstr(res_type, im.proc_id, rcb_num);
553 if (retval != PM_SUCCESS)
554 pm_msg.fields.msg_type = PM_FAIL;
555 break;
556 default:
557 pm_msg.fields.msg_type = PM_FAIL;
558 retval = PM_UNSUPPORTED;
559 break;
560 }
561
562 /* Update the payload with the reply msg */
563 pm_msg.fields.reply_flag = true;
564 pm_msg.fields.parm = retval;
565
566 /* Restore the payload and send to caller*/
567 im.pm_msg = pm_msg.whole;
568
569 /* Send the ACK to Remote Proc*/
570 retval = notify_send_event(
571 params->remote_proc_id,
572 params->line_id,
573 params->pm_resource_event | \
574 (NOTIFY_SYSTEMKEY << 16),
575 im.pm_msg,
576 true);
577 if (retval < 0)
578 pr_err("Error sending notify event\n");
579 }
580}
581
582void ipu_pm_callback(u16 proc_id, u16 line_id, u32 event_id,
583 uint *arg, u32 payload)
584{
585 struct ipu_pm_object *handle;
586 struct ipu_pm_msg im;
587
588 /*get the handle to proper ipu pm object */
589 handle = ipu_pm_get_handle(proc_id);
590
591 im.proc_id = proc_id;
592 im.pm_msg = payload;
593
594 spin_lock_irq(&handle->lock);
595 if (kfifo_avail(&handle->fifo) >= sizeof(im)) {
596 kfifo_in(&handle->fifo, (unsigned char *)&im, sizeof(im));
597 queue_work(ipu_wq, &handle->work);
598 }
599 spin_unlock_irq(&handle->lock);
600}
601EXPORT_SYMBOL(ipu_pm_callback);
602
603
604/*
605 Function for PM notifications Callback
606 *
607 */
608void ipu_pm_notify_callback(u16 proc_id, u16 line_id, u32 event_id,
609 uint *arg, u32 payload)
610{
611 /**
612 * Post semaphore based in eventType (payload);
613 * IPU has alreay finished the process for the
614 * notification
615 */
616 /* Get the payload */
617 struct ipu_pm_object *handle;
618 union message_slicer pm_msg;
619 struct ipu_pm_params *params;
620 int retval;
621
622 /* get the handle to proper ipu pm object */
623 handle = ipu_pm_get_handle(proc_id);
624 if (WARN_ON(unlikely(handle == NULL)))
625 return;
626 params = handle->params;
627 if (WARN_ON(unlikely(params == NULL)))
628 return;
629
630 pm_msg.whole = payload;
631 if (pm_msg.fields.msg_type == PM_NOTIFY_HIBERNATE) {
632 /* Remote proc requested hibernate */
633 /* Remote Proc is ready to hibernate */
634 retval = ipu_pm_save_ctx(proc_id);
635 if (retval)
636 pr_info("Unable to stop proc %d\n", proc_id);
637 } else {
638 switch (pm_msg.fields.msg_subtype) {
639 case PM_SUSPEND:
640 handle->pm_event[PM_SUSPEND].pm_msg = payload;
641 up(&handle->pm_event[PM_SUSPEND].sem_handle);
642 break;
643 case PM_RESUME:
644 handle->pm_event[PM_RESUME].pm_msg = payload;
645 up(&handle->pm_event[PM_RESUME].sem_handle);
646 break;
647 case PM_HIBERNATE:
648 handle->pm_event[PM_HIBERNATE].pm_msg = payload;
649 up(&handle->pm_event[PM_HIBERNATE].sem_handle);
650 break;
651 case PM_PID_DEATH:
652 handle->pm_event[PM_PID_DEATH].pm_msg = payload;
653 up(&handle->pm_event[PM_PID_DEATH].sem_handle);
654 break;
655 }
656 }
657}
658EXPORT_SYMBOL(ipu_pm_notify_callback);
659
660/*
661 Function for send PM Notifications
662 *
663 */
664int ipu_pm_notifications(enum pm_event_type event_type, void *data)
665{
666 /**
667 * Function called by linux driver
668 * Recieves evenType: Suspend, Resume, others...
669 * Send event to Ducati
670 * Pend semaphore based in event_type (payload)
671 * Return ACK to caller
672 */
673
674 struct ipu_pm_object *handle;
675 struct ipu_pm_params *params;
676 union message_slicer pm_msg;
677 int retval;
678 int pm_ack = 0;
679 int i;
680 int proc_id;
681
682 /*get the handle to proper ipu pm object */
683 for (i = 0; i < NUM_SELF_PROC; i++) {
684 proc_id = i + 1;
685 handle = ipu_pm_get_handle(proc_id);
686 if (handle == NULL)
687 continue;
688 params = handle->params;
689 if (params == NULL)
690 continue;
691 switch (event_type) {
692 case PM_SUSPEND:
693 pm_msg.fields.msg_type = PM_NOTIFICATIONS;
694 pm_msg.fields.msg_subtype = PM_SUSPEND;
695 pm_msg.fields.parm = PM_SUCCESS;
696 /* put general purpose message in share memory */
697 handle->rcb_table->gp_msg = (unsigned)data;
698 /* send the request to IPU*/
699 retval = notify_send_event(
700 params->remote_proc_id,
701 params->line_id,
702 params->pm_notification_event | \
703 (NOTIFY_SYSTEMKEY << 16),
704 (unsigned int)pm_msg.whole,
705 true);
706 if (retval < 0)
707 goto error_send;
708 /* wait until event from IPU (ipu_pm_notify_callback)*/
709 retval = down_timeout
710 (&handle->pm_event[PM_SUSPEND]
711 .sem_handle,
712 msecs_to_jiffies(params->timeout));
713 pm_msg.whole = handle->pm_event[PM_SUSPEND].pm_msg;
714 if (WARN_ON((retval < 0) ||
715 (pm_msg.fields.parm != PM_SUCCESS)))
716 goto error;
717 break;
718 case PM_RESUME:
719 pm_msg.fields.msg_type = PM_NOTIFICATIONS;
720 pm_msg.fields.msg_subtype = PM_RESUME;
721 pm_msg.fields.parm = PM_SUCCESS;
722 /* put general purpose message in share memory */
723 handle->rcb_table->gp_msg = (unsigned)data;
724 /* send the request to IPU*/
725 retval = notify_send_event(
726 params->remote_proc_id,
727 params->line_id,
728 params->pm_notification_event | \
729 (NOTIFY_SYSTEMKEY << 16),
730 (unsigned int)pm_msg.whole,
731 true);
732 if (retval < 0)
733 goto error_send;
734 /* wait until event from IPU (ipu_pm_notify_callback)*/
735 retval = down_timeout
736 (&handle->pm_event[PM_RESUME]
737 .sem_handle,
738 msecs_to_jiffies(params->timeout));
739 pm_msg.whole = handle->pm_event[PM_RESUME].pm_msg;
740 if (WARN_ON((retval < 0) ||
741 (pm_msg.fields.parm != PM_SUCCESS)))
742 goto error;
743 break;
744 case PM_HIBERNATE:
745 pm_msg.fields.msg_type = PM_NOTIFICATIONS;
746 pm_msg.fields.msg_subtype = PM_HIBERNATE;
747 pm_msg.fields.parm = PM_SUCCESS;
748 /* put general purpose message in share memory */
749 handle->rcb_table->gp_msg = (unsigned)data;
750 /* send the request to IPU*/
751 retval = notify_send_event(
752 params->remote_proc_id,
753 params->line_id,
754 params->pm_notification_event | \
755 (NOTIFY_SYSTEMKEY << 16),
756 (unsigned int)pm_msg.whole,
757 true);
758 if (retval < 0)
759 goto error_send;
760 /* wait until event from IPU (ipu_pm_notify_callback)*/
761 retval = down_timeout
762 (&handle->pm_event[PM_HIBERNATE]
763 .sem_handle,
764 msecs_to_jiffies(params->timeout));
765 pm_msg.whole = handle->pm_event[PM_HIBERNATE].pm_msg;
766 if (WARN_ON((retval < 0) ||
767 (pm_msg.fields.parm != PM_SUCCESS)))
768 goto error;
769 else {
770 /*Remote Proc is ready to hibernate*/
771 pm_ack = ipu_pm_save_ctx(proc_id);
772 }
773 break;
774 case PM_PID_DEATH:
775 pm_msg.fields.msg_type = PM_NOTIFICATIONS;
776 pm_msg.fields.msg_subtype = PM_PID_DEATH;
777 pm_msg.fields.parm = PM_SUCCESS;
778 /* put general purpose message in share memory */
779 handle->rcb_table->gp_msg = (unsigned)data;
780 /* send the request to IPU*/
781 retval = notify_send_event(
782 params->remote_proc_id,
783 params->line_id,
784 params->pm_notification_event | \
785 (NOTIFY_SYSTEMKEY << 16),
786 (unsigned int)pm_msg.whole,
787 true);
788 if (retval < 0)
789 goto error_send;
790 /* wait until event from IPU (ipu_pm_notify_callback)*/
791 retval = down_timeout
792 (&handle->pm_event[PM_PID_DEATH]
793 .sem_handle,
794 msecs_to_jiffies(params->timeout));
795 pm_msg.whole = handle->pm_event[PM_PID_DEATH].pm_msg;
796 if (WARN_ON((retval < 0) ||
797 (pm_msg.fields.parm != PM_SUCCESS)))
798 goto error;
799 break;
800 }
801 }
802 return pm_ack;
803
804error_send:
805 pr_err("Error notify_send event\n");
806error:
807 pr_err("Error sending Notification events\n");
808 return -EBUSY;
809}
810EXPORT_SYMBOL(ipu_pm_notifications);
811
812/*
813 Request a sdma channels on behalf of an IPU client
814 *
815 */
816static inline int ipu_pm_get_sdma_chan(int proc_id, u32 rcb_num)
817{
818 struct ipu_pm_object *handle;
819 struct ipu_pm_params *params;
820 struct rcb_block *rcb_p;
821 int pm_sdmachan_num;
822 int pm_sdmachan_dummy;
823 int ch;
824 int ch_aux;
825 int retval;
826
827 /* get the handle to proper ipu pm object */
828 handle = ipu_pm_get_handle(proc_id);
829 if (WARN_ON(unlikely(handle == NULL)))
830 return PM_NOT_INSTANTIATED;
831
832 params = handle->params;
833 if (WARN_ON(unlikely(params == NULL)))
834 return PM_NOT_INSTANTIATED;
835
836 /* Get pointer to the proper RCB */
837 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
838 return PM_INVAL_RCB_NUM;
839 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
840 /* Get number of channels from RCB */
841 pm_sdmachan_num = rcb_p->num_chan;
842 if (WARN_ON((pm_sdmachan_num <= 0) ||
843 (pm_sdmachan_num > SDMA_CHANNELS_MAX)))
844 return PM_INVAL_NUM_CHANNELS;
845
846 /* Request resource using PRCM API */
847 for (ch = 0; ch < pm_sdmachan_num; ch++) {
848 retval = omap_request_dma(proc_id,
849 "ducati-ss",
850 NULL,
851 NULL,
852 &pm_sdmachan_dummy);
853 if (retval == 0) {
854 params->pm_sdmachan_counter++;
855 rcb_p->channels[ch] = (unsigned char)pm_sdmachan_dummy;
856 } else
857 goto clean_sdma;
858 }
859 return PM_SUCCESS;
860clean_sdma:
861 /*failure, need to free the chanels*/
862 for (ch_aux = 0; ch_aux < ch; ch_aux++) {
863 pm_sdmachan_dummy = (int)rcb_p->channels[ch_aux];
864 omap_free_dma(pm_sdmachan_dummy);
865 params->pm_sdmachan_counter--;
866 }
867 return PM_INSUFFICIENT_CHANNELS;
868}
869
870/*
871 Request a gptimer on behalf of an IPU client
872 *
873 */
874static inline int ipu_pm_get_gptimer(int proc_id, u32 rcb_num)
875{
876 struct ipu_pm_object *handle;
877 struct ipu_pm_params *params;
878 struct rcb_block *rcb_p;
879 struct omap_dm_timer *p_gpt = NULL;
880 int pm_gp_num;
881
882 /* get the handle to proper ipu pm object */
883 handle = ipu_pm_get_handle(proc_id);
884 if (WARN_ON(unlikely(handle == NULL)))
885 return PM_NOT_INSTANTIATED;
886
887 params = handle->params;
888 if (WARN_ON(unlikely(params == NULL)))
889 return PM_NOT_INSTANTIATED;
890
891 /* Get pointer to the proper RCB */
892 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
893 return PM_INVAL_RCB_NUM;
894 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
895 /* Request resource using PRCM API */
896 for (pm_gp_num = 0; pm_gp_num < NUM_IPU_TIMERS; pm_gp_num++) {
897 if (GPTIMER_USE_MASK & (1 << ipu_timer_list[pm_gp_num])) {
898 p_gpt = omap_dm_timer_request_specific
899 (ipu_timer_list[pm_gp_num]);
900 } else
901 continue;
902 if (p_gpt != NULL) {
903 /* Clear the bit in the usage mask */
904 GPTIMER_USE_MASK &= ~(1 << ipu_timer_list[pm_gp_num]);
905 break;
906 }
907 }
908 if (p_gpt == NULL)
909 return PM_NO_GPTIMER;
910 else {
911 /* Store the gptimer number and base address */
912 rcb_p->fill9 = ipu_timer_list[pm_gp_num];
913 rcb_p->mod_base_addr = (unsigned)p_gpt;
914 params->pm_gptimer_counter++;
915 return PM_SUCCESS;
916 }
917}
918
919/*
920 Request an i2c bus on behalf of an IPU client
921 *
922 */
923static inline int ipu_pm_get_i2c_bus(int proc_id, u32 rcb_num)
924{
925 struct ipu_pm_object *handle;
926 struct ipu_pm_params *params;
927 struct rcb_block *rcb_p;
928 struct clk *p_i2c_clk;
929 int i2c_clk_status;
930 char i2c_name[I2C_NAME_SIZE];
931 int pm_i2c_bus_num;
932
933 /* get the handle to proper ipu pm object */
934 handle = ipu_pm_get_handle(proc_id);
935 if (WARN_ON(unlikely(handle == NULL)))
936 return PM_NOT_INSTANTIATED;
937
938 params = handle->params;
939 if (WARN_ON(unlikely(params == NULL)))
940 return PM_NOT_INSTANTIATED;
941
942 /* Get pointer to the proper RCB */
943 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
944 return PM_INVAL_RCB_NUM;
945 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
946
947 pm_i2c_bus_num = rcb_p->fill9;
948 if (WARN_ON((pm_i2c_bus_num < I2C_BUS_MIN) ||
949 (pm_i2c_bus_num > I2C_BUS_MAX)))
950 return PM_INVAL_NUM_I2C;
951
952 if (I2C_USE_MASK & (1 << pm_i2c_bus_num)) {
953 /* building the name for i2c_clk */
954 sprintf(i2c_name, "i2c%d_fck", pm_i2c_bus_num);
955
956 /* Request resource using PRCM API */
957 p_i2c_clk = omap_clk_get_by_name(i2c_name);
958 if (p_i2c_clk == NULL)
959 return PM_NO_I2C;
960 i2c_clk_status = clk_enable(p_i2c_clk);
961 if (i2c_clk_status != 0)
962 return PM_NO_I2C;
963 /* Clear the bit in the usage mask */
964 I2C_USE_MASK &= ~(1 << pm_i2c_bus_num);
965 rcb_p->mod_base_addr = (unsigned)p_i2c_clk;
966 /* Get the HW spinlock and store it in the RCB */
967 rcb_p->data[0] = i2c_spinlock_list[pm_i2c_bus_num];
968 params->pm_i2c_bus_counter++;
969
970 return PM_SUCCESS;
971 } else
972 return PM_NO_I2C;
973}
974
975/*
976 Request a gpio on behalf of an IPU client
977 *
978 */
979static inline int ipu_pm_get_gpio(int proc_id, u32 rcb_num)
980{
981 struct ipu_pm_object *handle;
982 struct ipu_pm_params *params;
983 struct rcb_block *rcb_p;
984 int pm_gpio_num;
985 int retval;
986
987 /* get the handle to proper ipu pm object */
988 handle = ipu_pm_get_handle(proc_id);
989 if (WARN_ON(unlikely(handle == NULL)))
990 return PM_NOT_INSTANTIATED;
991
992 params = handle->params;
993 if (WARN_ON(unlikely(params == NULL)))
994 return PM_NOT_INSTANTIATED;
995
996 /* Get pointer to the proper RCB */
997 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
998 return PM_INVAL_RCB_NUM;
999 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1000
1001 pm_gpio_num = rcb_p->fill9;
1002 retval = gpio_request(pm_gpio_num , "ducati-ss");
1003 if (retval != 0)
1004 return PM_NO_GPIO;
1005 params->pm_gpio_counter++;
1006
1007 return PM_SUCCESS;
1008}
1009
1010/*
1011 Request a regulator on behalf of an IPU client
1012 *
1013 */
1014static inline int ipu_pm_get_regulator(int proc_id, u32 rcb_num)
1015{
1016 struct ipu_pm_object *handle;
1017 struct ipu_pm_params *params;
1018 struct rcb_block *rcb_p;
1019 struct regulator *p_regulator = NULL;
1020 char *regulator_name;
1021 int pm_regulator_num;
1022 int retval = 0;
1023
1024 /* get the handle to proper ipu pm object */
1025 handle = ipu_pm_get_handle(proc_id);
1026 if (WARN_ON(unlikely(handle == NULL)))
1027 return PM_NOT_INSTANTIATED;
1028
1029 params = handle->params;
1030 if (WARN_ON(unlikely(params == NULL)))
1031 return PM_NOT_INSTANTIATED;
1032
1033 /* Get pointer to the proper RCB */
1034 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1035 return PM_INVAL_RCB_NUM;
1036 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1037
1038 pm_regulator_num = rcb_p->fill9;
1039 if (WARN_ON((pm_regulator_num < REGULATOR_MIN) ||
1040 (pm_regulator_num > REGULATOR_MAX)))
1041 return PM_INVAL_REGULATOR;
1042
1043 /*
1044 FIXME:Only providing 1 regulator, if more are provided
1045 * this check is not valid.
1046 */
1047 if (WARN_ON(params->pm_regulator_counter > 0))
1048 return PM_INVAL_REGULATOR;
1049
1050 /* Search the name of regulator based on the id and request it */
1051 regulator_name = ipu_regulator_name[pm_regulator_num - 1];
1052 p_regulator = regulator_get(NULL, regulator_name);
1053 if (p_regulator == NULL)
1054 return PM_NO_REGULATOR;
1055
1056 /* Get and store the regulator default voltage */
1057 cam2_prev_volt = regulator_get_voltage(p_regulator);
1058
1059 /* Set the regulator voltage min = data[0]; max = data[1]*/
1060 retval = regulator_set_voltage(p_regulator, rcb_p->data[0],
1061 rcb_p->data[1]);
1062 if (retval)
1063 return PM_INVAL_REGULATOR;
1064
1065 /* Store the regulator handle in the RCB */
1066 rcb_p->mod_base_addr = (unsigned)p_regulator;
1067 params->pm_regulator_counter++;
1068
1069 return PM_SUCCESS;
1070}
1071
1072/*
1073 Request an Aux clk on behalf of an IPU client
1074 *
1075 */
1076static inline int ipu_pm_get_aux_clk(int proc_id, u32 rcb_num)
1077{
1078 struct ipu_pm_object *handle;
1079 struct ipu_pm_params *params;
1080 struct rcb_block *rcb_p;
1081 u32 tmp = 0;
1082 int pm_aux_clk_num;
1083
1084 /* get the handle to proper ipu pm object */
1085 handle = ipu_pm_get_handle(proc_id);
1086 if (WARN_ON(unlikely(handle == NULL)))
1087 return PM_NOT_INSTANTIATED;
1088
1089 params = handle->params;
1090 if (WARN_ON(unlikely(params == NULL)))
1091 return PM_NOT_INSTANTIATED;
1092
1093 /* Get pointer to the proper RCB */
1094 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1095 return PM_INVAL_RCB_NUM;
1096 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1097
1098 pm_aux_clk_num = rcb_p->fill9;
1099
1100 if (WARN_ON((pm_aux_clk_num < AUX_CLK_MIN) ||
1101 (pm_aux_clk_num > AUX_CLK_MAX)))
1102 return PM_INVAL_AUX_CLK;
1103
1104 if (AUX_CLK_USE_MASK & (1 << pm_aux_clk_num)) {
1105 /* Build the value to write */
1106 MASK_SET_FIELD(tmp, AUX_CLK_ENABLE, 0x1);
1107 MASK_SET_FIELD(tmp, AUX_CLK_SRCSELECT, 0x2);
1108
1109 /* Clear the bit in the usage mask */
1110 AUX_CLK_USE_MASK &= ~(1 << pm_aux_clk_num);
1111
1112 /* Enabling aux clock */
1113 __raw_writel(tmp, AUX_CLK_REG(pm_aux_clk_num));
1114
1115 /* Store the aux clk addres in the RCB */
1116 rcb_p->mod_base_addr =
1117 (unsigned __force)AUX_CLK_REG(pm_aux_clk_num);
1118 params->pm_aux_clk_counter++;
1119 } else
1120 return PM_NO_AUX_CLK;
1121
1122 return PM_SUCCESS;
1123}
1124
1125/*
1126 Request sys m3 on behalf of an IPU client
1127 *
1128 */
1129static inline int ipu_pm_get_sys_m3(int proc_id, u32 rcb_num)
1130{
1131 struct ipu_pm_object *handle;
1132 struct ipu_pm_params *params;
1133 struct rcb_block *rcb_p;
1134
1135 /* get the handle to proper ipu pm object */
1136 handle = ipu_pm_get_handle(proc_id);
1137 if (WARN_ON(unlikely(handle == NULL)))
1138 return PM_NOT_INSTANTIATED;
1139
1140 params = handle->params;
1141 if (WARN_ON(unlikely(params == NULL)))
1142 return PM_NOT_INSTANTIATED;
1143
1144 /* Get pointer to the proper RCB */
1145 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1146 return PM_INVAL_RCB_NUM;
1147 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1148
1149 if (params->pm_sys_m3_counter)
1150 return PM_UNSUPPORTED;
1151
1152 pr_info("Request SYS M3\n");
1153
1154 params->pm_sys_m3_counter++;
1155
1156 return PM_SUCCESS;
1157}
1158
1159/*
1160 Request app m3 on behalf of an IPU client
1161 *
1162 */
1163static inline int ipu_pm_get_app_m3(int proc_id, u32 rcb_num)
1164{
1165 struct ipu_pm_object *handle;
1166 struct ipu_pm_params *params;
1167 struct rcb_block *rcb_p;
1168
1169 /* get the handle to proper ipu pm object */
1170 handle = ipu_pm_get_handle(proc_id);
1171 if (WARN_ON(unlikely(handle == NULL)))
1172 return PM_NOT_INSTANTIATED;
1173
1174 params = handle->params;
1175 if (WARN_ON(unlikely(params == NULL)))
1176 return PM_NOT_INSTANTIATED;
1177
1178 /* Get pointer to the proper RCB */
1179 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1180 return PM_INVAL_RCB_NUM;
1181 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1182
1183 if (params->pm_app_m3_counter)
1184 return PM_UNSUPPORTED;
1185
1186 pr_info("Request APP M3\n");
1187
1188 params->pm_app_m3_counter++;
1189
1190 return PM_SUCCESS;
1191}
1192
1193/*
1194 Request L3 Bus on behalf of an IPU client
1195 *
1196 */
1197static inline int ipu_pm_get_l3_bus(int proc_id, u32 rcb_num)
1198{
1199 struct ipu_pm_object *handle;
1200 struct ipu_pm_params *params;
1201 struct rcb_block *rcb_p;
1202
1203 /* get the handle to proper ipu pm object */
1204 handle = ipu_pm_get_handle(proc_id);
1205 if (WARN_ON(unlikely(handle == NULL)))
1206 return PM_NOT_INSTANTIATED;
1207
1208 params = handle->params;
1209 if (WARN_ON(unlikely(params == NULL)))
1210 return PM_NOT_INSTANTIATED;
1211
1212 /* Get pointer to the proper RCB */
1213 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1214 return PM_INVAL_RCB_NUM;
1215 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1216
1217 if (params->pm_l3_bus_counter)
1218 return PM_UNSUPPORTED;
1219
1220 pr_info("Request L3 BUS\n");
1221
1222 params->pm_l3_bus_counter++;
1223
1224 return PM_SUCCESS;
1225}
1226
1227/*
1228 Request IVA HD on behalf of an IPU client
1229 *
1230 */
1231static inline int ipu_pm_get_iva_hd(int proc_id, u32 rcb_num)
1232{
1233 struct ipu_pm_object *handle;
1234 struct ipu_pm_params *params;
1235 struct rcb_block *rcb_p;
1236 int retval;
1237
1238 /* get the handle to proper ipu pm object */
1239 handle = ipu_pm_get_handle(proc_id);
1240 if (WARN_ON(unlikely(handle == NULL)))
1241 return PM_NOT_INSTANTIATED;
1242
1243 params = handle->params;
1244 if (WARN_ON(unlikely(params == NULL)))
1245 return PM_NOT_INSTANTIATED;
1246
1247 /* Get pointer to the proper RCB */
1248 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1249 return PM_INVAL_RCB_NUM;
1250 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1251
1252 if (params->pm_iva_hd_counter)
1253 return PM_UNSUPPORTED;
1254
1255 pr_info("Request IVA_HD\n");
1256 retval = omap_pm_set_max_mpu_wakeup_lat(&pm_qos_handle,
1257 IPU_PM_MM_MPU_LAT_CONSTRAINT);
1258 if (retval)
1259 return PM_UNSUPPORTED;
1260
1261 params->pm_iva_hd_counter++;
1262
1263 return PM_SUCCESS;
1264}
1265
1266/*
1267 Request FDIF on behalf of an IPU client
1268 *
1269 */
1270static inline int ipu_pm_get_fdif(int proc_id, u32 rcb_num)
1271{
1272 struct ipu_pm_object *handle;
1273 struct ipu_pm_params *params;
1274 struct rcb_block *rcb_p;
1275 int retval;
1276
1277 /* get the handle to proper ipu pm object */
1278 handle = ipu_pm_get_handle(proc_id);
1279 if (WARN_ON(unlikely(handle == NULL)))
1280 return PM_NOT_INSTANTIATED;
1281
1282 params = handle->params;
1283 if (WARN_ON(unlikely(params == NULL)))
1284 return PM_NOT_INSTANTIATED;
1285
1286 /* Get pointer to the proper RCB */
1287 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1288 return PM_INVAL_RCB_NUM;
1289 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1290
1291 pr_info("Request FDIF\n");
1292 if (params->pm_fdif_counter)
1293 return PM_UNSUPPORTED;
1294
1295 retval = ipu_pm_module_start(rcb_p->sub_type);
1296 printk(KERN_ERR "@@@@ cop_module_start( ) %s @@@@\n",
1297 retval ? "Failed" : "Successful");
1298 params->pm_fdif_counter++;
1299
1300 return PM_SUCCESS;
1301}
1302
1303/*
1304 Request MPU on behalf of an IPU client
1305 *
1306 */
1307static inline int ipu_pm_get_mpu(int proc_id, u32 rcb_num)
1308{
1309 struct ipu_pm_object *handle;
1310 struct ipu_pm_params *params;
1311 struct rcb_block *rcb_p;
1312 int retval;
1313
1314 /* get the handle to proper ipu pm object */
1315 handle = ipu_pm_get_handle(proc_id);
1316 if (WARN_ON(unlikely(handle == NULL)))
1317 return PM_NOT_INSTANTIATED;
1318
1319 params = handle->params;
1320 if (WARN_ON(unlikely(params == NULL)))
1321 return PM_NOT_INSTANTIATED;
1322
1323 /* Get pointer to the proper RCB */
1324 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1325 return PM_INVAL_RCB_NUM;
1326 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1327
1328 pr_info("Request MPU\n");
1329 if (params->pm_mpu_counter)
1330 return PM_UNSUPPORTED;
1331
1332 retval = ipu_pm_module_start(rcb_p->sub_type);
1333 printk(KERN_ERR "@@@@ cop_module_start( ) %s @@@@\n",
1334 retval ? "Failed" : "Successful");
1335 params->pm_mpu_counter++;
1336
1337 return PM_SUCCESS;
1338}
1339
1340/*
1341 Request IPU on behalf of an IPU client
1342 *
1343 */
1344static inline int ipu_pm_get_ipu(int proc_id, u32 rcb_num)
1345{
1346 struct ipu_pm_object *handle;
1347 struct ipu_pm_params *params;
1348 struct rcb_block *rcb_p;
1349 int retval;
1350
1351 /* get the handle to proper ipu pm object */
1352 handle = ipu_pm_get_handle(proc_id);
1353 if (WARN_ON(unlikely(handle == NULL)))
1354 return PM_NOT_INSTANTIATED;
1355
1356 params = handle->params;
1357 if (WARN_ON(unlikely(params == NULL)))
1358 return PM_NOT_INSTANTIATED;
1359
1360 /* Get pointer to the proper RCB */
1361 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1362 return PM_INVAL_RCB_NUM;
1363 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1364
1365 pr_info("Request IPU\n");
1366 if (params->pm_ipu_counter)
1367 return PM_UNSUPPORTED;
1368
1369 retval = ipu_pm_module_start(rcb_p->sub_type);
1370 printk(KERN_ERR "@@@@ cop_module_start( ) %s @@@@\n",
1371 retval ? "Failed" : "Successful");
1372 params->pm_ipu_counter++;
1373
1374 return PM_SUCCESS;
1375}
1376
1377
1378
1379/*
1380 Request IVA SEQ0 on behalf of an IPU client
1381 *
1382 */
1383static inline int ipu_pm_get_ivaseq0(int proc_id, u32 rcb_num)
1384{
1385 struct ipu_pm_object *handle;
1386 struct ipu_pm_params *params;
1387 struct rcb_block *rcb_p;
1388 int retval;
1389
1390 /* get the handle to proper ipu pm object */
1391 handle = ipu_pm_get_handle(proc_id);
1392 if (WARN_ON(unlikely(handle == NULL)))
1393 return PM_NOT_INSTANTIATED;
1394
1395 params = handle->params;
1396 if (WARN_ON(unlikely(params == NULL)))
1397 return PM_NOT_INSTANTIATED;
1398
1399 /* Get pointer to the proper RCB */
1400 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1401 return PM_INVAL_RCB_NUM;
1402 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1403
1404 pr_info("Request IVASEQ0\n");
1405 if (params->pm_ivaseq0_counter)
1406 return PM_UNSUPPORTED;
1407
1408 retval = ipu_pm_module_start(rcb_p->sub_type);
1409 printk(KERN_ERR "@@@@ cop_module_start( ) %s @@@@\n",
1410 retval ? "Failed" : "Successful");
1411 params->pm_ivaseq0_counter++;
1412
1413 return PM_SUCCESS;
1414}
1415
1416/*
1417 Request IVA SEQ1 on behalf of an IPU client
1418 *
1419 */
1420static inline int ipu_pm_get_ivaseq1(int proc_id, u32 rcb_num)
1421{
1422 struct ipu_pm_object *handle;
1423 struct ipu_pm_params *params;
1424 struct rcb_block *rcb_p;
1425 int retval;
1426
1427 /* get the handle to proper ipu pm object */
1428 handle = ipu_pm_get_handle(proc_id);
1429 if (WARN_ON(unlikely(handle == NULL)))
1430 return PM_NOT_INSTANTIATED;
1431
1432 params = handle->params;
1433 if (WARN_ON(unlikely(params == NULL)))
1434 return PM_NOT_INSTANTIATED;
1435
1436 /* Get pointer to the proper RCB */
1437 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1438 return PM_INVAL_RCB_NUM;
1439 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1440
1441 pr_info("Request IVASEQ1\n");
1442 if (params->pm_ivaseq1_counter)
1443 return PM_UNSUPPORTED;
1444
1445 retval = ipu_pm_module_start(rcb_p->sub_type);
1446 printk(KERN_ERR "@@@@ cop_module_start( ) %s @@@@\n",
1447 retval ? "Failed" : "Successful");
1448 params->pm_ivaseq1_counter++;
1449
1450 return PM_SUCCESS;
1451}
1452
1453/*
1454 Request ISS on behalf of an IPU client
1455 *
1456 */
1457static inline int ipu_pm_get_iss(int proc_id, u32 rcb_num)
1458{
1459 struct ipu_pm_object *handle;
1460 struct ipu_pm_params *params;
1461 struct rcb_block *rcb_p;
1462 int retval;
1463
1464 /* get the handle to proper ipu pm object */
1465 handle = ipu_pm_get_handle(proc_id);
1466 if (WARN_ON(unlikely(handle == NULL)))
1467 return PM_NOT_INSTANTIATED;
1468
1469 params = handle->params;
1470 if (WARN_ON(unlikely(params == NULL)))
1471 return PM_NOT_INSTANTIATED;
1472
1473 /* Get pointer to the proper RCB */
1474 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1475 return PM_INVAL_RCB_NUM;
1476 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1477
1478 if (params->pm_iss_counter)
1479 return PM_UNSUPPORTED;
1480
1481 pr_info("Request ISS\n");
1482 retval = omap_pm_set_max_mpu_wakeup_lat(&pm_qos_handle,
1483 IPU_PM_MM_MPU_LAT_CONSTRAINT);
1484 if (retval)
1485 return PM_UNSUPPORTED;
1486
1487 params->pm_iss_counter++;
1488
1489 return PM_SUCCESS;
1490}
1491
1492/*
1493 Release a sdma on behalf of an IPU client
1494 *
1495 */
1496static inline int ipu_pm_rel_sdma_chan(int proc_id, u32 rcb_num)
1497{
1498 struct ipu_pm_object *handle;
1499 struct ipu_pm_params *params;
1500 struct rcb_block *rcb_p;
1501 int pm_sdmachan_num;
1502 int pm_sdmachan_dummy;
1503 int ch;
1504
1505 /* get the handle to proper ipu pm object */
1506 handle = ipu_pm_get_handle(proc_id);
1507 if (WARN_ON(unlikely(handle == NULL)))
1508 return PM_NOT_INSTANTIATED;
1509
1510 params = handle->params;
1511 if (WARN_ON(unlikely(params == NULL)))
1512 return PM_NOT_INSTANTIATED;
1513
1514 /* Get pointer to the proper RCB */
1515 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1516 return PM_INVAL_RCB_NUM;
1517
1518 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1519
1520 /* Release resource using PRCM API */
1521 pm_sdmachan_num = rcb_p->num_chan;
1522 for (ch = 0; ch < pm_sdmachan_num; ch++) {
1523 pm_sdmachan_dummy = (int)rcb_p->channels[ch];
1524 omap_free_dma(pm_sdmachan_dummy);
1525 params->pm_sdmachan_counter--;
1526 }
1527 return PM_SUCCESS;
1528}
1529
1530/*
1531 Release a gptimer on behalf of an IPU client
1532 *
1533 */
1534static inline int ipu_pm_rel_gptimer(int proc_id, u32 rcb_num)
1535{
1536 struct ipu_pm_object *handle;
1537 struct ipu_pm_params *params;
1538 struct rcb_block *rcb_p;
1539 struct omap_dm_timer *p_gpt;
1540 int pm_gptimer_num;
1541
1542 /* get the handle to proper ipu pm object */
1543 handle = ipu_pm_get_handle(proc_id);
1544 if (WARN_ON(unlikely(handle == NULL)))
1545 return PM_NOT_INSTANTIATED;
1546
1547 params = handle->params;
1548 if (WARN_ON(unlikely(params == NULL)))
1549 return PM_NOT_INSTANTIATED;
1550
1551 /* Get pointer to the proper RCB */
1552 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1553 return PM_INVAL_RCB_NUM;
1554
1555 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1556
1557 p_gpt = (struct omap_dm_timer *)rcb_p->mod_base_addr;
1558 pm_gptimer_num = rcb_p->fill9;
1559
1560 /* Check the usage mask */
1561 if (GPTIMER_USE_MASK & (1 << pm_gptimer_num))
1562 return PM_NO_GPTIMER;
1563
1564 /* Set the usage mask for reuse */
1565 GPTIMER_USE_MASK |= (1 << pm_gptimer_num);
1566
1567 /* Release resource using PRCM API */
1568 if (p_gpt != NULL)
1569 omap_dm_timer_free(p_gpt);
1570 rcb_p->mod_base_addr = 0;
1571 params->pm_gptimer_counter--;
1572 return PM_SUCCESS;
1573}
1574
1575/*
1576 Release an i2c buses on behalf of an IPU client
1577 *
1578 */
1579static inline int ipu_pm_rel_i2c_bus(int proc_id, u32 rcb_num)
1580{
1581 struct ipu_pm_object *handle;
1582 struct ipu_pm_params *params;
1583 struct rcb_block *rcb_p;
1584 struct clk *p_i2c_clk;
1585 int pm_i2c_bus_num;
1586
1587 /* get the handle to proper ipu pm object */
1588 handle = ipu_pm_get_handle(proc_id);
1589 if (WARN_ON(unlikely(handle == NULL)))
1590 return PM_NOT_INSTANTIATED;
1591
1592 params = handle->params;
1593 if (WARN_ON(unlikely(params == NULL)))
1594 return PM_NOT_INSTANTIATED;;
1595
1596 /* Get pointer to the proper RCB */
1597 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1598 return PM_INVAL_RCB_NUM;
1599
1600 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1601 pm_i2c_bus_num = rcb_p->fill9;
1602 p_i2c_clk = (struct clk *)rcb_p->mod_base_addr;
1603
1604 /* Check the usage mask */
1605 if (I2C_USE_MASK & (1 << pm_i2c_bus_num))
1606 return PM_NO_I2C;
1607
1608 /* Release resource using PRCM API */
1609 clk_disable(p_i2c_clk);
1610 rcb_p->mod_base_addr = 0;
1611
1612 /* Set the usage mask for reuse */
1613 I2C_USE_MASK |= (1 << pm_i2c_bus_num);
1614
1615 params->pm_i2c_bus_counter--;
1616
1617 return PM_SUCCESS;
1618}
1619
1620/*
1621 Release a gpio on behalf of an IPU client
1622 *
1623 */
1624static inline int ipu_pm_rel_gpio(int proc_id, u32 rcb_num)
1625{
1626 struct ipu_pm_object *handle;
1627 struct ipu_pm_params *params;
1628 struct rcb_block *rcb_p;
1629 int pm_gpio_num;
1630
1631 /* get the handle to proper ipu pm object */
1632 handle = ipu_pm_get_handle(proc_id);
1633 if (WARN_ON(unlikely(handle == NULL)))
1634 return PM_NOT_INSTANTIATED;
1635
1636 params = handle->params;
1637 if (WARN_ON(unlikely(params == NULL)))
1638 return PM_NOT_INSTANTIATED;
1639
1640 /* Get pointer to the proper RCB */
1641 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1642 return PM_INVAL_RCB_NUM;
1643 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1644
1645 pm_gpio_num = rcb_p->fill9;
1646 gpio_free(pm_gpio_num);
1647 params->pm_gpio_counter--;
1648
1649 return PM_SUCCESS;
1650}
1651
1652/*
1653 Release a regulator on behalf of an IPU client
1654 *
1655 */
1656static inline int ipu_pm_rel_regulator(int proc_id, u32 rcb_num)
1657{
1658 struct ipu_pm_object *handle;
1659 struct ipu_pm_params *params;
1660 struct rcb_block *rcb_p;
1661 struct regulator *p_regulator = NULL;
1662 int retval = 0;
1663
1664 /* get the handle to proper ipu pm object */
1665 handle = ipu_pm_get_handle(proc_id);
1666 if (WARN_ON(unlikely(handle == NULL)))
1667 return PM_NOT_INSTANTIATED;
1668
1669 params = handle->params;
1670 if (WARN_ON(unlikely(params == NULL)))
1671 return PM_NOT_INSTANTIATED;
1672
1673 /* Get pointer to the proper RCB */
1674 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1675 return PM_INVAL_RCB_NUM;
1676 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1677 /* Get the regulator */
1678 p_regulator = (struct regulator *)rcb_p->mod_base_addr;
1679
1680 /* Restart the voltage to the default value */
1681 retval = regulator_set_voltage(p_regulator, cam2_prev_volt,
1682 cam2_prev_volt);
1683 if (retval)
1684 return PM_INVAL_REGULATOR;
1685
1686 /* Release resource using PRCM API */
1687 regulator_put(p_regulator);
1688
1689 rcb_p->mod_base_addr = 0;
1690 params->pm_regulator_counter--;
1691
1692 return PM_SUCCESS;
1693}
1694
1695/*
1696 Release an Aux clk on behalf of an IPU client
1697 *
1698 */
1699static inline int ipu_pm_rel_aux_clk(int proc_id, u32 rcb_num)
1700{
1701 struct ipu_pm_object *handle;
1702 struct ipu_pm_params *params;
1703 struct rcb_block *rcb_p;
1704 u32 tmp = 0;
1705 int pm_aux_clk_num;
1706
1707 /* get the handle to proper ipu pm object */
1708 handle = ipu_pm_get_handle(proc_id);
1709 if (WARN_ON(unlikely(handle == NULL)))
1710 return PM_NOT_INSTANTIATED;
1711
1712 params = handle->params;
1713 if (WARN_ON(unlikely(params == NULL)))
1714 return PM_NOT_INSTANTIATED;
1715
1716 /* Get pointer to the proper RCB */
1717 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1718 return PM_INVAL_RCB_NUM;
1719 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1720
1721 pm_aux_clk_num = rcb_p->fill9;
1722
1723 /* Check the usage mask */
1724 if (AUX_CLK_USE_MASK & (1 << pm_aux_clk_num))
1725 return PM_NO_AUX_CLK;
1726
1727 /* Build the value to write */
1728 MASK_SET_FIELD(tmp, AUX_CLK_ENABLE, 0x0);
1729 MASK_SET_FIELD(tmp, AUX_CLK_SRCSELECT, 0x0);
1730
1731 /* Disabling aux clock */
1732 __raw_writel(tmp, AUX_CLK_REG(pm_aux_clk_num));
1733
1734 /* Set the usage mask for reuse */
1735 AUX_CLK_USE_MASK |= (1 << pm_aux_clk_num);
1736
1737 rcb_p->mod_base_addr = 0;
1738 params->pm_aux_clk_counter--;
1739
1740 return PM_SUCCESS;
1741}
1742
1743/*
1744 Release sys m3 on behalf of an IPU client
1745 *
1746 */
1747static inline int ipu_pm_rel_sys_m3(int proc_id, u32 rcb_num)
1748{
1749 struct ipu_pm_object *handle;
1750 struct ipu_pm_params *params;
1751 struct rcb_block *rcb_p;
1752
1753 /* get the handle to proper ipu pm object */
1754 handle = ipu_pm_get_handle(proc_id);
1755 if (WARN_ON(unlikely(handle == NULL)))
1756 return PM_NOT_INSTANTIATED;
1757
1758 params = handle->params;
1759 if (WARN_ON(unlikely(params == NULL)))
1760 return PM_NOT_INSTANTIATED;
1761
1762 /* Get pointer to the proper RCB */
1763 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1764 return PM_INVAL_RCB_NUM;
1765 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1766
1767 pr_info("Release SYS M3\n");
1768
1769 if (!params->pm_sys_m3_counter)
1770 goto error;
1771 params->pm_sys_m3_counter--;
1772
1773 return PM_SUCCESS;
1774error:
1775 return PM_UNSUPPORTED;
1776}
1777
1778/*
1779 Release app m3 on behalf of an IPU client
1780 *
1781 */
1782static inline int ipu_pm_rel_app_m3(int proc_id, u32 rcb_num)
1783{
1784 struct ipu_pm_object *handle;
1785 struct ipu_pm_params *params;
1786 struct rcb_block *rcb_p;
1787
1788 /* get the handle to proper ipu pm object */
1789 handle = ipu_pm_get_handle(proc_id);
1790 if (WARN_ON(unlikely(handle == NULL)))
1791 return PM_NOT_INSTANTIATED;
1792
1793 params = handle->params;
1794 if (WARN_ON(unlikely(params == NULL)))
1795 return PM_NOT_INSTANTIATED;
1796
1797 /* Get pointer to the proper RCB */
1798 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1799 return PM_INVAL_RCB_NUM;
1800 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1801
1802 pr_info("Release APP M3\n");
1803
1804 if (!params->pm_app_m3_counter)
1805 goto error;
1806 params->pm_app_m3_counter--;
1807
1808 return PM_SUCCESS;
1809error:
1810 return PM_UNSUPPORTED;
1811}
1812
1813/*
1814 Release L3 Bus on behalf of an IPU client
1815 *
1816 */
1817static inline int ipu_pm_rel_l3_bus(int proc_id, u32 rcb_num)
1818{
1819 struct ipu_pm_object *handle;
1820 struct ipu_pm_params *params;
1821 struct rcb_block *rcb_p;
1822
1823 /* get the handle to proper ipu pm object */
1824 handle = ipu_pm_get_handle(proc_id);
1825 if (WARN_ON(unlikely(handle == NULL)))
1826 return PM_NOT_INSTANTIATED;
1827
1828 params = handle->params;
1829 if (WARN_ON(unlikely(params == NULL)))
1830 return PM_NOT_INSTANTIATED;
1831
1832 /* Get pointer to the proper RCB */
1833 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1834 return PM_INVAL_RCB_NUM;
1835 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1836
1837 pr_info("Release L3 BUS\n");
1838
1839 if (!params->pm_l3_bus_counter)
1840 goto error;
1841 params->pm_l3_bus_counter--;
1842
1843 return PM_SUCCESS;
1844error:
1845 return PM_UNSUPPORTED;
1846}
1847
1848/*
1849 Release FDIF on behalf of an IPU client
1850 *
1851 */
1852static inline int ipu_pm_rel_fdif(int proc_id, u32 rcb_num)
1853{
1854 struct ipu_pm_object *handle;
1855 struct ipu_pm_params *params;
1856 struct rcb_block *rcb_p;
1857 int retval;
1858
1859 /* get the handle to proper ipu pm object */
1860 handle = ipu_pm_get_handle(proc_id);
1861 if (WARN_ON(unlikely(handle == NULL)))
1862 return PM_NOT_INSTANTIATED;
1863
1864 params = handle->params;
1865 if (WARN_ON(unlikely(params == NULL)))
1866 return PM_NOT_INSTANTIATED;
1867
1868 /* Get pointer to the proper RCB */
1869 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1870 return PM_INVAL_RCB_NUM;
1871 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1872
1873 pr_info("Release FDIF\n");
1874
1875 if (!params->pm_fdif_counter)
1876 goto error;
1877
1878 retval = ipu_pm_module_stop(rcb_p->sub_type);
1879 printk(KERN_ERR "@@@@ cop_module_stop( ) %s @@@@\n",
1880 retval ? "Failed" : "Successful");
1881 params->pm_fdif_counter--;
1882
1883 return PM_SUCCESS;
1884error:
1885 return PM_UNSUPPORTED;
1886}
1887
1888/*
1889 Release MPU on behalf of an IPU client
1890 *
1891 */
1892static inline int ipu_pm_rel_mpu(int proc_id, u32 rcb_num)
1893{
1894 struct ipu_pm_object *handle;
1895 struct ipu_pm_params *params;
1896 struct rcb_block *rcb_p;
1897 int retval;
1898
1899 /* get the handle to proper ipu pm object */
1900 handle = ipu_pm_get_handle(proc_id);
1901 if (WARN_ON(unlikely(handle == NULL)))
1902 return PM_NOT_INSTANTIATED;
1903
1904 params = handle->params;
1905 if (WARN_ON(unlikely(params == NULL)))
1906 return PM_NOT_INSTANTIATED;
1907
1908 /* Get pointer to the proper RCB */
1909 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1910 return PM_INVAL_RCB_NUM;
1911 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1912
1913 pr_info("Release MPU\n");
1914
1915 if (!params->pm_mpu_counter)
1916 goto error;
1917
1918 retval = ipu_pm_module_stop(rcb_p->sub_type);
1919 printk(KERN_ERR "@@@@ cop_module_stop( ) %s @@@@\n",
1920 retval ? "Failed" : "Successful");
1921 params->pm_mpu_counter--;
1922
1923 return PM_SUCCESS;
1924error:
1925 return PM_UNSUPPORTED;
1926}
1927
1928/*
1929 Release IPU on behalf of an IPU client
1930 *
1931 */
1932static inline int ipu_pm_rel_ipu(int proc_id, u32 rcb_num)
1933{
1934 struct ipu_pm_object *handle;
1935 struct ipu_pm_params *params;
1936 struct rcb_block *rcb_p;
1937 int retval;
1938
1939 /* get the handle to proper ipu pm object */
1940 handle = ipu_pm_get_handle(proc_id);
1941 if (WARN_ON(unlikely(handle == NULL)))
1942 return PM_NOT_INSTANTIATED;
1943
1944 params = handle->params;
1945 if (WARN_ON(unlikely(params == NULL)))
1946 return PM_NOT_INSTANTIATED;
1947
1948 /* Get pointer to the proper RCB */
1949 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1950 return PM_INVAL_RCB_NUM;
1951 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1952
1953 pr_info("Release IPU\n");
1954
1955 if (!params->pm_ipu_counter)
1956 goto error;
1957
1958 retval = ipu_pm_module_stop(rcb_p->sub_type);
1959 printk(KERN_ERR "@@@@ cop_module_stop( ) %s @@@@\n",
1960 retval ? "Failed" : "Successful");
1961 params->pm_ipu_counter--;
1962
1963 return PM_SUCCESS;
1964error:
1965 return PM_UNSUPPORTED;
1966}
1967
1968/*
1969 Release IVA HD on behalf of an IPU client
1970 *
1971 */
1972static inline int ipu_pm_rel_iva_hd(int proc_id, u32 rcb_num)
1973{
1974 struct ipu_pm_object *handle;
1975 struct ipu_pm_params *params;
1976 struct rcb_block *rcb_p;
1977 int retval;
1978
1979 /* get the handle to proper ipu pm object */
1980 handle = ipu_pm_get_handle(proc_id);
1981 if (WARN_ON(unlikely(handle == NULL)))
1982 return PM_NOT_INSTANTIATED;
1983
1984 params = handle->params;
1985 if (WARN_ON(unlikely(params == NULL)))
1986 return PM_NOT_INSTANTIATED;
1987
1988 /* Get pointer to the proper RCB */
1989 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
1990 return PM_INVAL_RCB_NUM;
1991 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
1992
1993 pr_info("Release IVA_HD\n");
1994
1995 if (!params->pm_iva_hd_counter)
1996 goto error;
1997
1998 params->pm_iva_hd_counter--;
1999
2000 if (params->pm_iva_hd_counter == 0 && params->pm_iss_counter == 0) {
2001 retval = omap_pm_set_max_mpu_wakeup_lat(&pm_qos_handle,
2002 IPU_PM_NO_MPU_LAT_CONSTRAINT);
2003 if (retval)
2004 goto error;
2005 }
2006
2007 return PM_SUCCESS;
2008error:
2009 return PM_UNSUPPORTED;
2010}
2011
2012/*
2013 Release IVA SEQ0 on behalf of an IPU client
2014 *
2015 */
2016static inline int ipu_pm_rel_ivaseq0(int proc_id, u32 rcb_num)
2017{
2018 struct ipu_pm_object *handle;
2019 struct ipu_pm_params *params;
2020 struct rcb_block *rcb_p;
2021 int retval;
2022
2023 /* get the handle to proper ipu pm object */
2024 handle = ipu_pm_get_handle(proc_id);
2025 if (WARN_ON(unlikely(handle == NULL)))
2026 return PM_NOT_INSTANTIATED;
2027
2028 params = handle->params;
2029 if (WARN_ON(unlikely(params == NULL)))
2030 return PM_NOT_INSTANTIATED;
2031
2032 /* Get pointer to the proper RCB */
2033 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2034 return PM_INVAL_RCB_NUM;
2035 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2036
2037 pr_info("Release IVASEQ0\n");
2038
2039 if (!params->pm_ivaseq0_counter)
2040 goto error;
2041
2042 retval = ipu_pm_module_stop(rcb_p->sub_type);
2043 printk(KERN_ERR "@@@@ cop_module_stop( ) %s @@@@\n",
2044 retval ? "Failed" : "Successful");
2045 params->pm_ivaseq0_counter--;
2046
2047 return PM_SUCCESS;
2048error:
2049 return PM_UNSUPPORTED;
2050}
2051
2052/*
2053 Release IVA SEQ1 on behalf of an IPU client
2054 *
2055 */
2056static inline int ipu_pm_rel_ivaseq1(int proc_id, u32 rcb_num)
2057{
2058 struct ipu_pm_object *handle;
2059 struct ipu_pm_params *params;
2060 struct rcb_block *rcb_p;
2061 int retval;
2062
2063 /* get the handle to proper ipu pm object */
2064 handle = ipu_pm_get_handle(proc_id);
2065 if (WARN_ON(unlikely(handle == NULL)))
2066 return PM_NOT_INSTANTIATED;
2067
2068 params = handle->params;
2069 if (WARN_ON(unlikely(params == NULL)))
2070 return PM_NOT_INSTANTIATED;
2071
2072 /* Get pointer to the proper RCB */
2073 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2074 return PM_INVAL_RCB_NUM;
2075 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2076
2077 pr_info("Release IVASEQ1\n");
2078
2079 if (!params->pm_ivaseq1_counter)
2080 goto error;
2081
2082 retval = ipu_pm_module_stop(rcb_p->sub_type);
2083 printk(KERN_ERR "@@@@ cop_module_stop( ) %s @@@@\n",
2084 retval ? "Failed" : "Successful");
2085 params->pm_ivaseq1_counter--;
2086
2087 return PM_SUCCESS;
2088error:
2089 return PM_UNSUPPORTED;
2090}
2091
2092/*
2093 Release ISS on behalf of an IPU client
2094 *
2095 */
2096static inline int ipu_pm_rel_iss(int proc_id, u32 rcb_num)
2097{
2098 struct ipu_pm_object *handle;
2099 struct ipu_pm_params *params;
2100 struct rcb_block *rcb_p;
2101 int retval;
2102
2103 /* get the handle to proper ipu pm object */
2104 handle = ipu_pm_get_handle(proc_id);
2105 if (WARN_ON(unlikely(handle == NULL)))
2106 return PM_NOT_INSTANTIATED;
2107
2108 params = handle->params;
2109 if (WARN_ON(unlikely(params == NULL)))
2110 return PM_NOT_INSTANTIATED;
2111
2112 /* Get pointer to the proper RCB */
2113 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2114 return PM_INVAL_RCB_NUM;
2115 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2116
2117 pr_info("Release ISS\n");
2118
2119 if (!params->pm_iss_counter)
2120 goto error;
2121
2122 params->pm_iss_counter--;
2123
2124 if (params->pm_iva_hd_counter == 0 && params->pm_iss_counter == 0) {
2125 retval = omap_pm_set_max_mpu_wakeup_lat(&pm_qos_handle,
2126 IPU_PM_NO_MPU_LAT_CONSTRAINT);
2127 if (retval)
2128 goto error;
2129 }
2130
2131 return PM_SUCCESS;
2132error:
2133 return PM_UNSUPPORTED;
2134}
2135
2136/*
2137 Request a FDIF constraint on behalf of an IPU client
2138 *
2139 */
2140static inline int ipu_pm_req_cstr_fdif(int proc_id, u32 rcb_num)
2141{
2142 struct ipu_pm_object *handle;
2143 struct ipu_pm_params *params;
2144 struct rcb_block *rcb_p;
2145 int perf;
2146 int lat;
2147 int bw;
2148 u32 cstr_flags;
2149
2150 /* get the handle to proper ipu pm object */
2151 handle = ipu_pm_get_handle(proc_id);
2152 if (WARN_ON(unlikely(handle == NULL)))
2153 return PM_NOT_INSTANTIATED;
2154
2155 params = handle->params;
2156 if (WARN_ON(unlikely(params == NULL)))
2157 return PM_NOT_INSTANTIATED;
2158
2159 /* Get pointer to the proper RCB */
2160 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2161 return PM_INVAL_RCB_NUM;
2162 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2163
2164 /* Get the configurable constraints */
2165 cstr_flags = rcb_p->data[0];
2166
2167 /* TODO: call the baseport APIs */
2168 if (cstr_flags & PM_CSTR_PERF_MASK) {
2169 perf = rcb_p->data[1];
2170 pr_info("Request perfomance Cstr FDIF:%d\n", perf);
2171 }
2172
2173 if (cstr_flags & PM_CSTR_LAT_MASK) {
2174 lat = rcb_p->data[2];
2175 pr_info("Request latency Cstr FDIF:%d\n", lat);
2176 }
2177
2178 if (cstr_flags & PM_CSTR_BW_MASK) {
2179 bw = rcb_p->data[3];
2180 pr_info("Request bandwidth Cstr FDIF:%d\n", bw);
2181 }
2182
2183 return PM_SUCCESS;
2184}
2185
2186/*
2187 Request a IPU constraint on behalf of an IPU client
2188 *
2189 */
2190static inline int ipu_pm_req_cstr_ipu(int proc_id, u32 rcb_num)
2191{
2192 struct ipu_pm_object *handle;
2193 struct ipu_pm_params *params;
2194 struct rcb_block *rcb_p;
2195 int perf;
2196 int lat;
2197 int bw;
2198 u32 cstr_flags;
2199
2200 /* get the handle to proper ipu pm object */
2201 handle = ipu_pm_get_handle(proc_id);
2202 if (WARN_ON(unlikely(handle == NULL)))
2203 return PM_NOT_INSTANTIATED;
2204
2205 params = handle->params;
2206 if (WARN_ON(unlikely(params == NULL)))
2207 return PM_NOT_INSTANTIATED;
2208
2209 /* Get pointer to the proper RCB */
2210 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2211 return PM_INVAL_RCB_NUM;
2212 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2213
2214 /* Get the configurable constraints */
2215 cstr_flags = rcb_p->data[0];
2216
2217 /* TODO: call the baseport APIs */
2218 if (cstr_flags & PM_CSTR_PERF_MASK) {
2219 perf = rcb_p->data[1];
2220 pr_info("Request perfomance Cstr IPU:%d\n", perf);
2221 }
2222
2223 if (cstr_flags & PM_CSTR_LAT_MASK) {
2224 lat = rcb_p->data[2];
2225 pr_info("Request latency Cstr IPU:%d\n", lat);
2226 }
2227
2228 if (cstr_flags & PM_CSTR_BW_MASK) {
2229 bw = rcb_p->data[3];
2230 pr_info("Request bandwidth Cstr IPU:%d\n", bw);
2231 }
2232
2233 return PM_SUCCESS;
2234}
2235
2236/*
2237 Request a L3 Bus constraint on behalf of an IPU client
2238 *
2239 */
2240static inline int ipu_pm_req_cstr_l3_bus(int proc_id, u32 rcb_num)
2241{
2242 struct ipu_pm_object *handle;
2243 struct ipu_pm_params *params;
2244 struct rcb_block *rcb_p;
2245 int perf;
2246 int lat;
2247 int bw;
2248 u32 cstr_flags;
2249
2250 /* get the handle to proper ipu pm object */
2251 handle = ipu_pm_get_handle(proc_id);
2252 if (WARN_ON(unlikely(handle == NULL)))
2253 return PM_NOT_INSTANTIATED;
2254
2255 params = handle->params;
2256 if (WARN_ON(unlikely(params == NULL)))
2257 return PM_NOT_INSTANTIATED;
2258
2259 /* Get pointer to the proper RCB */
2260 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2261 return PM_INVAL_RCB_NUM;
2262 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2263
2264 /* Get the configurable constraints */
2265 cstr_flags = rcb_p->data[0];
2266
2267 /* TODO: call the baseport APIs */
2268 if (cstr_flags & PM_CSTR_PERF_MASK) {
2269 perf = rcb_p->data[1];
2270 pr_info("Request perfomance Cstr L3 Bus:%d\n", perf);
2271 }
2272
2273 if (cstr_flags & PM_CSTR_LAT_MASK) {
2274 lat = rcb_p->data[2];
2275 pr_info("Request latency Cstr L3 Bus:%d\n", lat);
2276 }
2277
2278 if (cstr_flags & PM_CSTR_BW_MASK) {
2279 bw = rcb_p->data[3];
2280 pr_info("Request bandwidth Cstr L3 Bus:%d\n", bw);
2281 }
2282
2283 return PM_SUCCESS;
2284}
2285
2286/*
2287 Request an IVA HD constraint on behalf of an IPU client
2288 *
2289 */
2290static inline int ipu_pm_req_cstr_iva_hd(int proc_id, u32 rcb_num)
2291{
2292 struct ipu_pm_object *handle;
2293 struct ipu_pm_params *params;
2294 struct rcb_block *rcb_p;
2295 int perf;
2296 int lat;
2297 int bw;
2298 u32 cstr_flags;
2299
2300 /* get the handle to proper ipu pm object */
2301 handle = ipu_pm_get_handle(proc_id);
2302 if (WARN_ON(unlikely(handle == NULL)))
2303 return PM_NOT_INSTANTIATED;
2304
2305 params = handle->params;
2306 if (WARN_ON(unlikely(params == NULL)))
2307 return PM_NOT_INSTANTIATED;
2308
2309 /* Get pointer to the proper RCB */
2310 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2311 return PM_INVAL_RCB_NUM;
2312 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2313
2314 /* Get the configurable constraints */
2315 cstr_flags = rcb_p->data[0];
2316
2317 /* TODO: call the baseport APIs */
2318 if (cstr_flags & PM_CSTR_PERF_MASK) {
2319 perf = rcb_p->data[1];
2320 pr_info("Request perfomance Cstr IVA HD:%d\n", perf);
2321 }
2322
2323 if (cstr_flags & PM_CSTR_LAT_MASK) {
2324 lat = rcb_p->data[2];
2325 pr_info("Request latency Cstr IVA HD:%d\n", lat);
2326 }
2327
2328 if (cstr_flags & PM_CSTR_BW_MASK) {
2329 bw = rcb_p->data[3];
2330 pr_info("Request bandwidth Cstr IVA HD:%d\n", bw);
2331 }
2332
2333 return PM_SUCCESS;
2334}
2335
2336/*
2337 Request an ISS constraint on behalf of an IPU client
2338 *
2339 */
2340static inline int ipu_pm_req_cstr_iss(int proc_id, u32 rcb_num)
2341{
2342 struct ipu_pm_object *handle;
2343 struct ipu_pm_params *params;
2344 struct rcb_block *rcb_p;
2345 int perf;
2346 int lat;
2347 int bw;
2348 u32 cstr_flags;
2349
2350 /* get the handle to proper ipu pm object */
2351 handle = ipu_pm_get_handle(proc_id);
2352 if (WARN_ON(unlikely(handle == NULL)))
2353 return PM_NOT_INSTANTIATED;
2354
2355 params = handle->params;
2356 if (WARN_ON(unlikely(params == NULL)))
2357 return PM_NOT_INSTANTIATED;
2358
2359 /* Get pointer to the proper RCB */
2360 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2361 return PM_INVAL_RCB_NUM;
2362 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2363
2364 /* Get the configurable constraints */
2365 cstr_flags = rcb_p->data[0];
2366
2367 /* TODO: call the baseport APIs */
2368 if (cstr_flags & PM_CSTR_PERF_MASK) {
2369 perf = rcb_p->data[1];
2370 pr_info("Request perfomance Cstr ISS:%d\n", perf);
2371 }
2372
2373 if (cstr_flags & PM_CSTR_LAT_MASK) {
2374 lat = rcb_p->data[2];
2375 pr_info("Request latency Cstr ISS:%d\n", lat);
2376 }
2377
2378 if (cstr_flags & PM_CSTR_BW_MASK) {
2379 bw = rcb_p->data[3];
2380 pr_info("Request bandwidth Cstr ISS:%d\n", bw);
2381 }
2382
2383 return PM_SUCCESS;
2384}
2385
2386/*
2387 Request an MPU constraint on behalf of an IPU client
2388 *
2389 */
2390static inline int ipu_pm_req_cstr_mpu(int proc_id, u32 rcb_num)
2391{
2392 struct ipu_pm_object *handle;
2393 struct ipu_pm_params *params;
2394 struct rcb_block *rcb_p;
2395 int perf;
2396 int lat;
2397 int bw;
2398 u32 cstr_flags;
2399
2400 /* get the handle to proper ipu pm object */
2401 handle = ipu_pm_get_handle(proc_id);
2402 if (WARN_ON(unlikely(handle == NULL)))
2403 return PM_NOT_INSTANTIATED;
2404
2405 params = handle->params;
2406 if (WARN_ON(unlikely(params == NULL)))
2407 return PM_NOT_INSTANTIATED;
2408
2409 /* Get pointer to the proper RCB */
2410 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2411 return PM_INVAL_RCB_NUM;
2412 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2413
2414 /* Get the configurable constraints */
2415 cstr_flags = rcb_p->data[0];
2416
2417 /* TODO: call the baseport APIs */
2418 if (cstr_flags & PM_CSTR_PERF_MASK) {
2419 perf = rcb_p->data[1];
2420 pr_info("Request perfomance Cstr MPU:%d\n", perf);
2421 }
2422
2423 if (cstr_flags & PM_CSTR_LAT_MASK) {
2424 lat = rcb_p->data[2];
2425 pr_info("Request latency Cstr MPU:%d\n", lat);
2426 }
2427
2428 if (cstr_flags & PM_CSTR_BW_MASK) {
2429 bw = rcb_p->data[3];
2430 pr_info("Request bandwidth Cstr MPU:%d\n", bw);
2431 }
2432
2433 return PM_SUCCESS;
2434}
2435
2436
2437/*
2438 Release a FDIF constraint on behalf of an IPU client
2439 *
2440 */
2441static inline int ipu_pm_rel_cstr_fdif(int proc_id, u32 rcb_num)
2442{
2443 struct ipu_pm_object *handle;
2444 struct ipu_pm_params *params;
2445 struct rcb_block *rcb_p;
2446 int perf;
2447 int lat;
2448 int bw;
2449 u32 cstr_flags;
2450
2451 /* get the handle to proper ipu pm object */
2452 handle = ipu_pm_get_handle(proc_id);
2453 if (WARN_ON(unlikely(handle == NULL)))
2454 return PM_NOT_INSTANTIATED;
2455
2456 params = handle->params;
2457 if (WARN_ON(unlikely(params == NULL)))
2458 return PM_NOT_INSTANTIATED;
2459
2460 /* Get pointer to the proper RCB */
2461 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2462 return PM_INVAL_RCB_NUM;
2463 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2464
2465 /* Get the configurable constraints */
2466 cstr_flags = rcb_p->data[0];
2467
2468 /* TODO: call the baseport APIs */
2469 if (cstr_flags & PM_CSTR_PERF_MASK) {
2470 perf = rcb_p->data[1];
2471 pr_info("Release perfomance Cstr FDIF:%d\n", perf);
2472 }
2473
2474 if (cstr_flags & PM_CSTR_LAT_MASK) {
2475 lat = rcb_p->data[2];
2476 pr_info("Release latency Cstr FDIF:%d\n", lat);
2477 }
2478
2479 if (cstr_flags & PM_CSTR_BW_MASK) {
2480 bw = rcb_p->data[3];
2481 pr_info("Release bandwidth Cstr FDIF:%d\n", bw);
2482 }
2483
2484 return PM_SUCCESS;
2485}
2486
2487/*
2488 Release a IPU constraint on behalf of an IPU client
2489 *
2490 */
2491static inline int ipu_pm_rel_cstr_ipu(int proc_id, u32 rcb_num)
2492{
2493 struct ipu_pm_object *handle;
2494 struct ipu_pm_params *params;
2495 struct rcb_block *rcb_p;
2496 int perf;
2497 int lat;
2498 int bw;
2499 u32 cstr_flags;
2500
2501 /* get the handle to proper ipu pm object */
2502 handle = ipu_pm_get_handle(proc_id);
2503 if (WARN_ON(unlikely(handle == NULL)))
2504 return PM_NOT_INSTANTIATED;
2505
2506 params = handle->params;
2507 if (WARN_ON(unlikely(params == NULL)))
2508 return PM_NOT_INSTANTIATED;
2509
2510 /* Get pointer to the proper RCB */
2511 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2512 return PM_INVAL_RCB_NUM;
2513 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2514
2515 /* Get the configurable constraints */
2516 cstr_flags = rcb_p->data[0];
2517
2518 /* TODO: call the baseport APIs */
2519 if (cstr_flags & PM_CSTR_PERF_MASK) {
2520 perf = rcb_p->data[1];
2521 pr_info("Release perfomance Cstr IPU:%d\n", perf);
2522 }
2523
2524 if (cstr_flags & PM_CSTR_LAT_MASK) {
2525 lat = rcb_p->data[2];
2526 pr_info("Release latency Cstr IPU:%d\n", lat);
2527 }
2528
2529 if (cstr_flags & PM_CSTR_BW_MASK) {
2530 bw = rcb_p->data[3];
2531 pr_info("Release bandwidth Cstr IPU:%d\n", bw);
2532 }
2533
2534 return PM_SUCCESS;
2535}
2536
2537/*
2538 Release a L3 Bus constraint on behalf of an IPU client
2539 *
2540 */
2541static inline int ipu_pm_rel_cstr_l3_bus(int proc_id, u32 rcb_num)
2542{
2543 struct ipu_pm_object *handle;
2544 struct ipu_pm_params *params;
2545 struct rcb_block *rcb_p;
2546 int perf;
2547 int lat;
2548 int bw;
2549 u32 cstr_flags;
2550
2551 /* get the handle to proper ipu pm object */
2552 handle = ipu_pm_get_handle(proc_id);
2553 if (WARN_ON(unlikely(handle == NULL)))
2554 return PM_NOT_INSTANTIATED;
2555
2556 params = handle->params;
2557 if (WARN_ON(unlikely(params == NULL)))
2558 return PM_NOT_INSTANTIATED;
2559
2560 /* Get pointer to the proper RCB */
2561 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2562 return PM_INVAL_RCB_NUM;
2563 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2564
2565 /* Get the configurable constraints */
2566 cstr_flags = rcb_p->data[0];
2567
2568 /* TODO: call the baseport APIs */
2569 if (cstr_flags & PM_CSTR_PERF_MASK) {
2570 perf = rcb_p->data[1];
2571 pr_info("Release perfomance Cstr L3 Bus:%d\n", perf);
2572 }
2573
2574 if (cstr_flags & PM_CSTR_LAT_MASK) {
2575 lat = rcb_p->data[2];
2576 pr_info("Release latency Cstr L3 Bus:%d\n", lat);
2577 }
2578
2579 if (cstr_flags & PM_CSTR_BW_MASK) {
2580 bw = rcb_p->data[3];
2581 pr_info("Release bandwidth Cstr L3 Bus:%d\n", bw);
2582 }
2583
2584 return PM_SUCCESS;
2585}
2586
2587/*
2588 Release an IVA HD constraint on behalf of an IPU client
2589 *
2590 */
2591static inline int ipu_pm_rel_cstr_iva_hd(int proc_id, u32 rcb_num)
2592{
2593 struct ipu_pm_object *handle;
2594 struct ipu_pm_params *params;
2595 struct rcb_block *rcb_p;
2596 int perf;
2597 int lat;
2598 int bw;
2599 u32 cstr_flags;
2600
2601 /* get the handle to proper ipu pm object */
2602 handle = ipu_pm_get_handle(proc_id);
2603 if (WARN_ON(unlikely(handle == NULL)))
2604 return PM_NOT_INSTANTIATED;
2605
2606 params = handle->params;
2607 if (WARN_ON(unlikely(params == NULL)))
2608 return PM_NOT_INSTANTIATED;
2609
2610 /* Get pointer to the proper RCB */
2611 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2612 return PM_INVAL_RCB_NUM;
2613 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2614
2615 /* Get the configurable constraints */
2616 cstr_flags = rcb_p->data[0];
2617
2618 /* TODO: call the baseport APIs */
2619 if (cstr_flags & PM_CSTR_PERF_MASK) {
2620 perf = rcb_p->data[1];
2621 pr_info("Release perfomance Cstr IVA HD:%d\n", perf);
2622 }
2623
2624 if (cstr_flags & PM_CSTR_LAT_MASK) {
2625 lat = rcb_p->data[2];
2626 pr_info("Release latency Cstr IVA HD:%d\n", lat);
2627 }
2628
2629 if (cstr_flags & PM_CSTR_BW_MASK) {
2630 bw = rcb_p->data[3];
2631 pr_info("Release bandwidth Cstr IVA HD:%d\n", bw);
2632 }
2633
2634 return PM_SUCCESS;
2635}
2636
2637/*
2638 Release an ISS constraint on behalf of an IPU client
2639 *
2640 */
2641static inline int ipu_pm_rel_cstr_iss(int proc_id, u32 rcb_num)
2642{
2643 struct ipu_pm_object *handle;
2644 struct ipu_pm_params *params;
2645 struct rcb_block *rcb_p;
2646 int perf;
2647 int lat;
2648 int bw;
2649 u32 cstr_flags;
2650
2651 /* get the handle to proper ipu pm object */
2652 handle = ipu_pm_get_handle(proc_id);
2653 if (WARN_ON(unlikely(handle == NULL)))
2654 return PM_NOT_INSTANTIATED;
2655
2656 params = handle->params;
2657 if (WARN_ON(unlikely(params == NULL)))
2658 return PM_NOT_INSTANTIATED;
2659
2660 /* Get pointer to the proper RCB */
2661 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2662 return PM_INVAL_RCB_NUM;
2663 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2664
2665 /* Get the configurable constraints */
2666 cstr_flags = rcb_p->data[0];
2667
2668 /* TODO: call the baseport APIs */
2669 if (cstr_flags & PM_CSTR_PERF_MASK) {
2670 perf = rcb_p->data[1];
2671 pr_info("Release perfomance Cstr ISS:%d\n", perf);
2672 }
2673
2674 if (cstr_flags & PM_CSTR_LAT_MASK) {
2675 lat = rcb_p->data[2];
2676 pr_info("Release latency Cstr ISS:%d\n", lat);
2677 }
2678
2679 if (cstr_flags & PM_CSTR_BW_MASK) {
2680 bw = rcb_p->data[3];
2681 pr_info("Release bandwidth Cstr ISS:%d\n", bw);
2682 }
2683
2684 return PM_SUCCESS;
2685}
2686
2687/*
2688 Release an MPU constraint on behalf of an IPU client
2689 *
2690 */
2691static inline int ipu_pm_rel_cstr_mpu(int proc_id, u32 rcb_num)
2692{
2693 struct ipu_pm_object *handle;
2694 struct ipu_pm_params *params;
2695 struct rcb_block *rcb_p;
2696 int perf;
2697 int lat;
2698 int bw;
2699 u32 cstr_flags;
2700
2701 /* get the handle to proper ipu pm object */
2702 handle = ipu_pm_get_handle(proc_id);
2703 if (WARN_ON(unlikely(handle == NULL)))
2704 return PM_NOT_INSTANTIATED;
2705
2706 params = handle->params;
2707 if (WARN_ON(unlikely(params == NULL)))
2708 return PM_NOT_INSTANTIATED;
2709
2710 /* Get pointer to the proper RCB */
2711 if (WARN_ON((rcb_num < RCB_MIN) || (rcb_num > RCB_MAX)))
2712 return PM_INVAL_RCB_NUM;
2713 rcb_p = (struct rcb_block *)&handle->rcb_table->rcb[rcb_num];
2714
2715 /* Get the configurable constraints */
2716 cstr_flags = rcb_p->data[0];
2717
2718 /* TODO: call the baseport APIs */
2719 if (cstr_flags & PM_CSTR_PERF_MASK) {
2720 perf = rcb_p->data[1];
2721 pr_info("Release perfomance Cstr MPU:%d\n", perf);
2722 }
2723
2724 if (cstr_flags & PM_CSTR_LAT_MASK) {
2725 lat = rcb_p->data[2];
2726 pr_info("Release latency Cstr MPU:%d\n", lat);
2727 }
2728
2729 if (cstr_flags & PM_CSTR_BW_MASK) {
2730 bw = rcb_p->data[3];
2731 pr_info("Release bandwidth Cstr MPU:%d\n", bw);
2732 }
2733
2734 return PM_SUCCESS;
2735}
2736
2737/*
2738 Function to set init parameters
2739 *
2740 */
2741void ipu_pm_params_init(struct ipu_pm_params *params)
2742{
2743 int retval = 0;
2744
2745 if (WARN_ON(unlikely(params == NULL))) {
2746 retval = -EINVAL;
2747 goto exit;
2748 }
2749
2750 memcpy(params, &(pm_params), sizeof(struct ipu_pm_params));
2751 return;
2752exit:
2753 pr_err("ipu_pm_params_init failed status(0x%x)\n", retval);
2754}
2755EXPORT_SYMBOL(ipu_pm_params_init);
2756
2757/*
2758 Function to calculate ipu_pm mem required
2759 *
2760 */
2761int ipu_pm_mem_req(const struct ipu_pm_params *params)
2762{
2763 /* Memory required for ipu pm module */
2764 /* FIXME: Maybe more than this is needed */
2765 return sizeof(struct sms);
2766}
2767EXPORT_SYMBOL(ipu_pm_mem_req);
2768
2769/*
2770 Function to register events
2771 This function will register the events needed for ipu_pm
2772 the events reserved for power management are 2 and 3
2773 both sysm3 and appm3 will use the same events.
2774 */
2775int ipu_pm_init_transport(struct ipu_pm_object *handle)
2776{
2777 int retval = 0;
2778 struct ipu_pm_params *params;
2779
2780 if (WARN_ON(unlikely(handle == NULL))) {
2781 retval = -EINVAL;
2782 goto pm_register_fail;
2783 }
2784
2785 params = handle->params;
2786 if (WARN_ON(unlikely(params == NULL))) {
2787 retval = -EINVAL;
2788 goto pm_register_fail;
2789 }
2790
2791 retval = notify_register_event(
2792 params->remote_proc_id,
2793 params->line_id,
2794 params->pm_resource_event | \
2795 (NOTIFY_SYSTEMKEY << 16),
2796 (notify_fn_notify_cbck)ipu_pm_callback,
2797 (void *)NULL);
2798 if (retval < 0)
2799 goto pm_register_fail;
2800
2801 retval = notify_register_event(
2802 params->remote_proc_id,
2803 params->line_id,
2804 params->pm_notification_event | \
2805 (NOTIFY_SYSTEMKEY << 16),
2806 (notify_fn_notify_cbck)ipu_pm_notify_callback,
2807 (void *)NULL);
2808
2809 if (retval < 0) {
2810 retval = notify_unregister_event(
2811 params->remote_proc_id,
2812 params->line_id,
2813 params->pm_resource_event | \
2814 (NOTIFY_SYSTEMKEY << 16),
2815 (notify_fn_notify_cbck)ipu_pm_callback,
2816 (void *)NULL);
2817 if (retval < 0)
2818 pr_err("Error sending notify event\n");
2819 goto pm_register_fail;
2820 }
2821 return retval;
2822
2823pm_register_fail:
2824 pr_err("pm register events failed status(0x%x)", retval);
2825 return retval;
2826}
2827
2828/*
2829 Function to create ipu pm object
2830 *
2831 */
2832struct ipu_pm_object *ipu_pm_create(const struct ipu_pm_params *params)
2833{
2834 int i;
2835 int retval = 0;
2836
2837 if (WARN_ON(unlikely(params == NULL))) {
2838 retval = -EINVAL;
2839 goto exit;
2840 }
2841
2842 if (params->remote_proc_id == SYS_M3) {
2843 pm_handle_sysm3 = kmalloc(sizeof(struct ipu_pm_object),
2844 GFP_ATOMIC);
2845
2846 if (WARN_ON(unlikely(pm_handle_sysm3 == NULL))) {
2847 retval = -EINVAL;
2848 goto exit;
2849 }
2850
2851 pm_handle_sysm3->rcb_table = (struct sms *)params->shared_addr;
2852
2853 pm_handle_sysm3->pm_event = kzalloc(sizeof(struct pm_event)
2854 * params->pm_num_events, GFP_KERNEL);
2855
2856 if (WARN_ON(unlikely(pm_handle_sysm3->pm_event == NULL))) {
2857 retval = -EINVAL;
2858 kfree(pm_handle_sysm3);
2859 goto exit;
2860 }
2861
2862 /* Each event has it own sem */
2863 for (i = 0; i < params->pm_num_events; i++) {
2864 sema_init(&pm_handle_sysm3->pm_event[i].sem_handle, 0);
2865 pm_handle_sysm3->pm_event[i].event_type = i;
2866 }
2867
2868 pm_handle_sysm3->params = kzalloc(sizeof(struct ipu_pm_params)
2869 , GFP_KERNEL);
2870
2871 if (WARN_ON(unlikely(pm_handle_sysm3->params == NULL))) {
2872 retval = -EINVAL;
2873 kfree(pm_handle_sysm3->pm_event);
2874 kfree(pm_handle_sysm3);
2875 goto exit;
2876 }
2877
2878 memcpy(pm_handle_sysm3->params, params,
2879 sizeof(struct ipu_pm_params));
2880
2881 /* Check the SW version on both sides */
2882 if (WARN_ON(pm_handle_sysm3->rcb_table->pm_version !=
2883 PM_VERSION))
2884 pr_warning("Mismatch in PM version Host:0x%08x "
2885 "Remote:0x%08x", PM_VERSION,
2886 pm_handle_sysm3->rcb_table->pm_version);
2887
2888 spin_lock_init(&pm_handle_sysm3->lock);
2889 INIT_WORK(&pm_handle_sysm3->work, ipu_pm_work);
2890
2891 if (!kfifo_alloc(&pm_handle_sysm3->fifo,
2892 IPU_KFIFO_SIZE * sizeof(struct ipu_pm_msg),
2893 GFP_KERNEL))
2894 return pm_handle_sysm3;
2895
2896 retval = -ENOMEM;
2897 kfree(pm_handle_sysm3->params);
2898 kfree(pm_handle_sysm3->pm_event);
2899 kfree(pm_handle_sysm3);
2900 } else if (params->remote_proc_id == APP_M3) {
2901 pm_handle_appm3 = kmalloc(sizeof(struct ipu_pm_object),
2902 GFP_ATOMIC);
2903
2904 if (WARN_ON(unlikely(pm_handle_appm3 == NULL))) {
2905 retval = -EINVAL;
2906 goto exit;
2907 }
2908
2909 pm_handle_appm3->rcb_table = (struct sms *)params->shared_addr;
2910
2911 pm_handle_appm3->pm_event = kzalloc(sizeof(struct pm_event)
2912 * params->pm_num_events, GFP_KERNEL);
2913
2914 if (WARN_ON(unlikely(pm_handle_appm3->pm_event == NULL))) {
2915 retval = -EINVAL;
2916 kfree(pm_handle_appm3);
2917 goto exit;
2918 }
2919
2920 /* Each event has it own sem */
2921 for (i = 0; i < params->pm_num_events; i++) {
2922 sema_init(&pm_handle_appm3->pm_event[i].sem_handle, 0);
2923 pm_handle_appm3->pm_event[i].event_type = i;
2924 }
2925
2926 pm_handle_appm3->params = kzalloc(sizeof(struct ipu_pm_params)
2927 , GFP_KERNEL);
2928
2929 if (WARN_ON(unlikely(pm_handle_appm3->params == NULL))) {
2930 retval = -EINVAL;
2931 kfree(pm_handle_appm3->pm_event);
2932 kfree(pm_handle_appm3);
2933 goto exit;
2934 }
2935
2936 memcpy(pm_handle_appm3->params, params,
2937 sizeof(struct ipu_pm_params));
2938
2939 /* Check the SW version on both sides */
2940 if (WARN_ON(pm_handle_appm3->rcb_table->pm_version !=
2941 PM_VERSION))
2942 pr_warning("Mismatch in PM version Host:0x%08x "
2943 "Remote:0x%08x", PM_VERSION,
2944 pm_handle_appm3->rcb_table->pm_version);
2945
2946 spin_lock_init(&pm_handle_appm3->lock);
2947 INIT_WORK(&pm_handle_appm3->work, ipu_pm_work);
2948
2949 if (!kfifo_alloc(&pm_handle_appm3->fifo,
2950 IPU_KFIFO_SIZE * sizeof(struct ipu_pm_msg),
2951 GFP_KERNEL))
2952 return pm_handle_appm3;
2953
2954 retval = -ENOMEM;
2955 kfree(pm_handle_appm3->params);
2956 kfree(pm_handle_appm3->pm_event);
2957 kfree(pm_handle_appm3);
2958 } else
2959 retval = -EINVAL;
2960
2961exit:
2962 pr_err("ipu_pm_create failed! "
2963 "status = 0x%x\n", retval);
2964 return NULL;
2965}
2966
2967/*
2968 Function to delete ipu pm object
2969 *
2970 */
2971void ipu_pm_delete(struct ipu_pm_object *handle)
2972{
2973 int retval = 0;
2974 struct ipu_pm_params *params;
2975
2976 if (WARN_ON(unlikely(handle == NULL))) {
2977 retval = -EINVAL;
2978 goto exit;
2979 }
2980
2981 params = handle->params;
2982 if (WARN_ON(unlikely(params == NULL))) {
2983 retval = -EINVAL;
2984 goto exit;
2985 }
2986
2987 /* Release the shared RCB */
2988 handle->rcb_table = NULL;
2989
2990 kfree(handle->pm_event);
2991 if (params->remote_proc_id == SYS_M3)
2992 pm_handle_sysm3 = NULL;
2993 else
2994 pm_handle_appm3 = NULL;
2995 kfree(handle->params);
2996 kfree(handle);
2997 return;
2998exit:
2999 pr_err("ipu_pm_delete is already NULL "
3000 "status = 0x%x\n", retval);
3001}
3002
3003/*
3004 Function to get the ducati state flag from Share memory
3005 *
3006 */
3007u32 ipu_pm_get_state(int proc_id)
3008{
3009 struct ipu_pm_object *handle;
3010
3011 /* get the handle to proper ipu pm object */
3012 handle = ipu_pm_get_handle(proc_id);
3013 if (WARN_ON(unlikely(handle == NULL)))
3014 return -EINVAL;
3015
3016 return handle->rcb_table->state_flag;
3017}
3018
3019/*
3020 Function to get ipu pm object
3021 *
3022 */
3023struct ipu_pm_object *ipu_pm_get_handle(int proc_id)
3024{
3025 if (proc_id == SYS_M3)
3026 return pm_handle_sysm3;
3027 else if (proc_id == APP_M3)
3028 return pm_handle_appm3;
3029 else
3030 return NULL;
3031}
3032EXPORT_SYMBOL(ipu_pm_get_handle);
3033
3034/*
3035 Function to save a processor context and send it to hibernate
3036 *
3037 */
3038int ipu_pm_save_ctx(int proc_id)
3039{
3040 int retval = 0;
3041 int flag;
3042 int num_loaded_cores = 0;
3043 int sys_loaded;
3044 int app_loaded;
3045 unsigned long timeout;
3046 struct ipu_pm_object *handle;
3047
3048 /* get the handle to proper ipu pm object */
3049 handle = ipu_pm_get_handle(proc_id);
3050 if (WARN_ON(unlikely(handle == NULL)))
3051 return -EINVAL;
3052
3053 /* Check if the M3 was loaded */
3054 sys_loaded = (ipu_pm_get_state(proc_id) & SYS_PROC_LOADED) >>
3055 PROC_LD_SHIFT;
3056 app_loaded = (ipu_pm_get_state(proc_id) & APP_PROC_LOADED) >>
3057 PROC_LD_SHIFT;
3058
3059 /* Because of the current scheme, we need to check
3060 * if APPM3 is enable and we need to shut it down too
3061 * Sysm3 is the only want sending the hibernate message
3062 */
3063 mutex_lock(ipu_pm_state.gate_handle);
3064 if (proc_id == SYS_M3 || proc_id == APP_M3) {
3065 if (!sys_loaded)
3066 goto exit;
3067
3068 num_loaded_cores = app_loaded + sys_loaded;
3069
3070 flag = 1;
3071 timeout = jiffies + msecs_to_jiffies(WAIT_FOR_IDLE_TIMEOUT);
3072 /* Wait fot Ducati to hibernate */
3073 do {
3074 /* Checking if IPU is really in idle */
3075 if (NUM_IDLE_CORES == num_loaded_cores) {
3076 flag = 0;
3077 break;
3078 }
3079 } while (!time_after(jiffies, timeout));
3080 if (flag)
3081 goto error;
3082
3083 /* Check for APPM3, if loaded reset first */
3084 if (app_loaded) {
3085 retval = rproc_sleep(app_rproc);
3086 if (retval)
3087 goto error;
3088 handle->rcb_table->state_flag |= APP_PROC_DOWN;
3089 }
3090 retval = rproc_sleep(sys_rproc);
3091 if (retval)
3092 goto error;
3093 handle->rcb_table->state_flag |= SYS_PROC_DOWN;
3094 omap_mbox_save_ctx(ducati_mbox);
3095 iommu_save_ctx(ducati_iommu);
3096 } else
3097 goto error;
3098exit:
3099 mutex_unlock(ipu_pm_state.gate_handle);
3100 return 0;
3101error:
3102 mutex_unlock(ipu_pm_state.gate_handle);
3103 pr_info("Aborting hibernation process\n");
3104 return -EINVAL;
3105}
3106EXPORT_SYMBOL(ipu_pm_save_ctx);
3107
3108/*
3109 Function to check if a processor is shutdown
3110 if shutdown then restore context else return.
3111 *
3112 */
3113int ipu_pm_restore_ctx(int proc_id)
3114{
3115 int retval = 0;
3116 int sys_loaded;
3117 int app_loaded;
3118 struct ipu_pm_object *handle;
3119
3120 /*If feature not supported by proc, return*/
3121 if (!proc_supported(proc_id))
3122 return 0;
3123
3124 /* get the handle to proper ipu pm object */
3125 handle = ipu_pm_get_handle(proc_id);
3126
3127 if (WARN_ON(unlikely(handle == NULL)))
3128 return -EINVAL;
3129
3130 /* By default Ducati Hibernation is disable
3131 * enabling just the first time and if
3132 * CONFIG_SYSLINK_DUCATI_PM is defined
3133 */
3134 if (first_time) {
3135 handle->rcb_table->state_flag |= ENABLE_IPU_HIB;
3136 handle->rcb_table->pm_flags.hibernateAllowed = 1;
3137 first_time = 0;
3138 }
3139
3140 /* Check if the M3 was loaded */
3141 sys_loaded = (ipu_pm_get_state(proc_id) & SYS_PROC_LOADED) >>
3142 PROC_LD_SHIFT;
3143 app_loaded = (ipu_pm_get_state(proc_id) & APP_PROC_LOADED) >>
3144 PROC_LD_SHIFT;
3145
3146 /* Because of the current scheme, we need to check
3147 * if APPM3 is enable and we need to enable it too
3148 * In both cases we should check if for both cores
3149 * and enable them if they were loaded.
3150 */
3151 mutex_lock(ipu_pm_state.gate_handle);
3152 if (proc_id == SYS_M3 || proc_id == APP_M3) {
3153 if (!(ipu_pm_get_state(proc_id) & SYS_PROC_DOWN))
3154 goto exit;
3155
3156 omap_mbox_restore_ctx(ducati_mbox);
3157 iommu_restore_ctx(ducati_iommu);
3158 retval = rproc_wakeup(sys_rproc);
3159 if (retval)
3160 goto error;
3161 handle->rcb_table->state_flag &= ~SYS_PROC_DOWN;
3162 if (ipu_pm_get_state(proc_id) & APP_PROC_LOADED) {
3163 retval = rproc_wakeup(app_rproc);
3164 if (retval)
3165 goto error;
3166 handle->rcb_table->state_flag &= ~APP_PROC_DOWN;
3167 }
3168 } else
3169 goto error;
3170exit:
3171 mutex_unlock(ipu_pm_state.gate_handle);
3172 return 0;
3173error:
3174 mutex_unlock(ipu_pm_state.gate_handle);
3175 pr_info("Aborting restoring process\n");
3176 return -EINVAL;
3177}
3178EXPORT_SYMBOL(ipu_pm_restore_ctx);
3179
3180/*
3181 Function to start a module
3182 *
3183 */
3184int ipu_pm_module_start(unsigned res_type)
3185{
3186 return 0;
3187}
3188
3189/*
3190 Function to stop a module
3191 *
3192 */
3193int ipu_pm_module_stop(unsigned res_type)
3194{
3195 return 0;
3196}
3197
3198/*
3199 Get the default configuration for the ipu_pm module.
3200 needed in ipu_pm_setup.
3201 */
3202void ipu_pm_get_config(struct ipu_pm_config *cfg)
3203{
3204 int retval = 0;
3205
3206 if (WARN_ON(unlikely(cfg == NULL))) {
3207 retval = -EINVAL;
3208 goto exit;
3209 }
3210
3211 if (atomic_cmpmask_and_lt(&(ipu_pm_state.ref_count),
3212 IPU_PM_MAKE_MAGICSTAMP(0),
3213 IPU_PM_MAKE_MAGICSTAMP(1)) == true)
3214 memcpy(cfg, &ipu_pm_state.def_cfg,
3215 sizeof(struct ipu_pm_config));
3216 else
3217 memcpy(cfg, &ipu_pm_state.cfg, sizeof(struct ipu_pm_config));
3218 return;
3219
3220exit:
3221 if (retval < 0)
3222 pr_err("ipu_pm_get_config failed! status = 0x%x", retval);
3223 return;
3224}
3225EXPORT_SYMBOL(ipu_pm_get_config);
3226
3227/*
3228 Function to setup ipu pm object
3229 This function is called in platform_setup()
3230 This function will load the default configuration for ipu_pm
3231 in this function we can decide what is going to be controled
3232 by ipu_pm (DVFS, NOTIFICATIONS, ...) this configuration can
3233 can be changed on run-time.
3234 Also the workqueue is created and the local mutex
3235 */
3236int ipu_pm_setup(struct ipu_pm_config *cfg)
3237{
3238 struct ipu_pm_config tmp_cfg;
3239 int retval = 0;
3240 struct mutex *lock = NULL;
3241
3242 /* This sets the ref_count variable is not initialized, upper 16 bits is
3243 written with module Id to ensure correctness of refCount variable.
3244 */
3245 atomic_cmpmask_and_set(&ipu_pm_state.ref_count,
3246 IPU_PM_MAKE_MAGICSTAMP(0),
3247 IPU_PM_MAKE_MAGICSTAMP(0));
3248 if (atomic_inc_return(&ipu_pm_state.ref_count)
3249 != IPU_PM_MAKE_MAGICSTAMP(1)) {
3250 return 1;
3251 }
3252
3253 if (cfg == NULL) {
3254 ipu_pm_get_config(&tmp_cfg);
3255 cfg = &tmp_cfg;
3256 }
3257
3258 /* Create a default gate handle for local module protection */
3259 lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
3260 if (lock == NULL) {
3261 retval = -ENOMEM;
3262 goto exit;
3263 }
3264 mutex_init(lock);
3265 ipu_pm_state.gate_handle = lock;
3266
3267 /* Create the wq for req/rel resources */
3268 ipu_wq = create_singlethread_workqueue("ipu_wq");
3269
3270 /* No proc attached yet */
3271 pm_handle_appm3 = NULL;
3272 pm_handle_sysm3 = NULL;
3273 ducati_iommu = NULL;
3274 ducati_mbox = NULL;
3275 sys_rproc = NULL;
3276 app_rproc = NULL;
3277
3278 /* Get mailbox and iommu to save/restore */
3279 /* FIXME: This is not ready for Tesla */
3280 ducati_mbox = omap_mbox_get("mailbox-2", NULL);
3281 if (ducati_mbox == NULL) {
3282 retval = -ENOMEM;
3283 goto exit;
3284 }
3285 ducati_iommu = iommu_get("ducati");
3286 if (ducati_iommu == NULL) {
3287 retval = -ENOMEM;
3288 goto exit;
3289 }
3290
3291 memcpy(&ipu_pm_state.cfg, cfg, sizeof(struct ipu_pm_config));
3292 ipu_pm_state.is_setup = true;
3293
3294 sysm3Idle = ioremap(SYSM3_IDLE_FLAG_PHY_ADDR, sizeof(int));
3295 if (!sysm3Idle) {
3296 retval = -ENOMEM;
3297 goto exit;
3298 }
3299
3300 appm3Idle = ioremap(APPM3_IDLE_FLAG_PHY_ADDR, sizeof(int));
3301
3302 if (!appm3Idle) {
3303 retval = -ENOMEM;
3304 goto exit;
3305 }
3306
3307 pm_gpt = omap_dm_timer_request_specific(GP_TIMER_3);
3308 if (pm_gpt == NULL)
3309 retval = -EINVAL;
3310
3311 return retval;
3312exit:
3313 pr_err("ipu_pm_setup failed! retval = 0x%x", retval);
3314 return retval;
3315}
3316EXPORT_SYMBOL(ipu_pm_setup);
3317
3318/*
3319 Function to attach ipu pm object
3320 This function is called in ipc_attach()
3321 This function will create the object based on the remoteproc id
3322 It is also recieving the shared address pointer to use in rcb
3323 */
3324int ipu_pm_attach(u16 remote_proc_id, void *shared_addr)
3325{
3326 struct ipu_pm_params params;
3327 struct ipu_pm_object *handle;
3328 int retval = 0;
3329
3330 ipu_pm_params_init(&params);
3331 params.remote_proc_id = remote_proc_id;
3332 params.shared_addr = (void *)shared_addr;
3333 params.line_id = LINE_ID;
3334 params.shared_addr_size = ipu_pm_mem_req(NULL);
3335
3336 handle = ipu_pm_create(&params);
3337
3338 if (WARN_ON(unlikely(handle == NULL))) {
3339 retval = -EINVAL;
3340 goto exit;
3341 }
3342
3343 retval = ipu_pm_init_transport(handle);
3344
3345 /* Get remote processor handle to save/restore */
3346 if (remote_proc_id == SYS_M3) {
3347 sys_rproc = omap_rproc_get("ducati-proc0");
3348 if (sys_rproc == NULL) {
3349 retval = -ENOMEM;
3350 goto exit;
3351 }
3352 } else if (remote_proc_id == APP_M3) {
3353 app_rproc = omap_rproc_get("ducati-proc1");
3354 if (app_rproc == NULL) {
3355 retval = -ENOMEM;
3356 goto exit;
3357 }
3358 }
3359
3360 if (retval < 0)
3361 goto exit;
3362
3363 /* FIXME the physical address should be calculated */
3364 pr_info("ipu_pm_attach at va0x%x pa0x9cf00400\n",
3365 (unsigned int)shared_addr);
3366
3367 return retval;
3368exit:
3369 pr_err("ipu_pm_attach failed! retval = 0x%x", retval);
3370 return retval;
3371}
3372EXPORT_SYMBOL(ipu_pm_attach);
3373
3374/*
3375 Function to deattach ipu pm object
3376 This function is called in ipc_detach()
3377 This function will delete the object based
3378 on the remoteproc id and unregister the notify
3379 events used by ipu_pm module
3380 */
3381int ipu_pm_detach(u16 remote_proc_id)
3382{
3383 struct ipu_pm_object *handle;
3384 struct ipu_pm_params *params;
3385 int retval = 0;
3386
3387 /* get the handle to proper ipu pm object */
3388 handle = ipu_pm_get_handle(remote_proc_id);
3389 if (WARN_ON(unlikely(handle == NULL))) {
3390 retval = -EINVAL;
3391 goto exit;
3392 }
3393
3394 params = handle->params;
3395 if (WARN_ON(unlikely(params == NULL))) {
3396 retval = -EINVAL;
3397 goto exit;
3398 }
3399
3400 /* unregister the events used for ipu_pm */
3401 retval = notify_unregister_event(
3402 params->remote_proc_id,
3403 params->line_id,
3404 params->pm_resource_event | (NOTIFY_SYSTEMKEY << 16),
3405 (notify_fn_notify_cbck)ipu_pm_callback,
3406 (void *)NULL);
3407 if (retval < 0) {
3408 pr_err("Error registering notify event\n");
3409 goto exit;
3410 }
3411 retval = notify_unregister_event(
3412 params->remote_proc_id,
3413 params->line_id,
3414 params->pm_notification_event | (NOTIFY_SYSTEMKEY << 16),
3415 (notify_fn_notify_cbck)ipu_pm_notify_callback,
3416 (void *)NULL);
3417 if (retval < 0) {
3418 pr_err("Error registering notify event\n");
3419 goto exit;
3420 }
3421
3422 /* Deleting the handle based on remote_proc_id */
3423 ipu_pm_delete(handle);
3424 if (remote_proc_id == SYS_M3) {
3425 omap_rproc_put(sys_rproc);
3426 sys_rproc = NULL;
3427 } else if (remote_proc_id == APP_M3) {
3428 omap_rproc_put(app_rproc);
3429 app_rproc = NULL;
3430 }
3431 return retval;
3432exit:
3433 pr_err("ipu_pm_detach failed handle null retval 0x%x", retval);
3434 return retval;
3435}
3436EXPORT_SYMBOL(ipu_pm_detach);
3437
3438/*
3439 Function to destroy ipu_pm module
3440 this function will destroy the structs
3441 created to set the configuration
3442 */
3443int ipu_pm_destroy(void)
3444{
3445 int retval = 0;
3446 struct mutex *lock = NULL;
3447
3448 if (WARN_ON(unlikely(atomic_cmpmask_and_lt(
3449 &ipu_pm_state.ref_count,
3450 IPU_PM_MAKE_MAGICSTAMP(0),
3451 IPU_PM_MAKE_MAGICSTAMP(1)) == true))) {
3452 retval = -ENODEV;
3453 goto exit;
3454 }
3455
3456 if (!(atomic_dec_return(&ipu_pm_state.ref_count)
3457 == IPU_PM_MAKE_MAGICSTAMP(0))) {
3458 retval = 1;
3459 goto exit;
3460 }
3461
3462 if (WARN_ON(ipu_pm_state.gate_handle == NULL)) {
3463 retval = -ENODEV;
3464 goto exit;
3465 }
3466
3467 retval = mutex_lock_interruptible(ipu_pm_state.gate_handle);
3468 if (retval)
3469 goto exit;
3470
3471 lock = ipu_pm_state.gate_handle;
3472 ipu_pm_state.gate_handle = NULL;
3473 mutex_unlock(lock);
3474 kfree(lock);
3475 /* Delete the wq for req/rel resources */
3476 destroy_workqueue(ipu_wq);
3477
3478 omap_mbox_put(ducati_mbox, NULL);
3479 ducati_mbox = NULL;
3480 iommu_put(ducati_iommu);
3481 ducati_iommu = NULL;
3482 first_time = 1;
3483 omap_dm_timer_free(pm_gpt);
3484 return retval;
3485exit:
3486 if (retval < 0)
3487 pr_err("ipu_pm_destroy failed, retval: %x\n", retval);
3488 return retval;
3489}
3490EXPORT_SYMBOL(ipu_pm_destroy);
diff --git a/drivers/dsp/syslink/ipu_pm/ipu_pm.h b/drivers/dsp/syslink/ipu_pm/ipu_pm.h
new file mode 100644
index 00000000000..612cf2fbe56
--- /dev/null
+++ b/drivers/dsp/syslink/ipu_pm/ipu_pm.h
@@ -0,0 +1,467 @@
1/*
2* ipu_pm.h
3*
4* Syslink IPU Power Managament support functions for TI OMAP processors.
5*
6* Copyright (C) 2009-2010 Texas Instruments, Inc.
7*
8* This package is free software; you can redistribute it and/or modify
9* it under the terms of the GNU General Public License version 2 as
10* published by the Free Software Foundation.
11*
12* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15*
16* --------------------------------------------------------------------
17* | rcb_num | | | | |
18* | msg_type | | | | |
19* | sub_type | | | | |
20* | rqst_cpu | 1-|word | | |
21* | extd_mem_flag | | | | |
22* | num_chan | | | | |
23* | fill9 | | | | |
24* |-------------------------------------| ------ 4-words 4-words |
25* | process_id | 1-word | | |
26* |-------------------------------------| ------ | | |
27* | sem_hnd | 1-word | | |
28* |-------------------------------------| ------ | | |
29* | mod_base_addr | 1-word | | |
30* |-------------------------------------| ------ ----- ----- |
31* | channels[0] | data[0] | datax[0] | | | | |
32* | channels[1] | | | 1-word | | RCB_SIZE
33* | channels[2] | | | | | | =
34* | channels[3] | | | | | | 8WORDS
35* |--------------|---------|------------| ------ | | |
36* | channels[4] | data[0] | datax[1] | | | | |
37* | channels[5] | | | 1-word | RCB_SIZE-5 |
38* | channels[6] | | | | | | |
39* | channels[7] | | | | RCB_SIZE-4 | |
40* |--------------|---------|------------| ------ | | |
41* | channels[8] | data[0] | datax[2] | | | | |
42* | channels[9] | | | 1-word | | |
43* | channels[10] | | | | | | |
44* | channels[11] | | | | | | |
45* |--------------|---------|------------| ------ | ----- |
46* | channels[12] | data[0] |extd_mem_hnd| | | | |
47* | channels[13] | | | 1-word | 1-word |
48* | channels[14] | | | | | | |
49* | channels[15] | | | | | | |
50* --------------------------------------------------------------------
51*
52*The Ducati Power Management sub-system uses a structure called RCB_struct or
53*just RCB to share information with the MPU about a particular resource involved
54*in the communication. The information stored in this structure is needed to get
55*attributes and other useful data about the resource.
56*The fisrt fields of the RCB resemble the Rcb message sent across the NotifyDver
57*It retains the rcb_num, msg_type and msg_subtype from the rcb message as its
58*first 3 fields. The rqst_cpu fields indicates which remote processor originates
59*the request/release petition. When a particular resource is requested, some of
60*its parameters should be specify.
61*For devices like Gptimer and GPIO, the most significant attribute its itemID.
62*This value should be placed in the "fill9" field of the Rcb sruct. This field
63*should be fill by the requester if asking for a particular resource or by the
64*receiver if the resource granted is other than the one asked.
65*
66*Other variables related with the resource are:
67*"sem_hnd" which storage the semaphore handle associated in the ducati side.
68*We are pending on this semaphore when asked for the resource and
69*posted when granted.
70*"mod_base_addr". It is the virtual base addres for the resource.
71*"process_id". It is the Task Id where the petition for the resource was called.
72*
73*The last 16 bytes of the structure could be interpreted in 3 different ways
74*according to the context.
75*1) For the case of the Rcb is for SDMA. The last 16 bytes correspond to a array
76* of 16 channels[ ]. Each entry has the number of the SDMA channel granted.
77* As many number of channels indicated in num_chan as many are meaningful
78* in the channels[] array.
79*2) If the extd_mem_flag bit is NOT set the 16 last bytes are used as a data[]
80* array. Each entry is 4bytes long so the maximum number of entries is 4.
81*3) If the extd_mem_flag bit is NOT set the 16 last bytes are used as an array
82* datax[ ] 3 members Each entry 4bytes long and one additional field of
83* "extd_mem_hnd" which is a pointer to the continuation of this datax array
84*/
85
86#ifndef _IPU_PM_H_
87#define _IPU_PM_H_
88
89#include <linux/types.h>
90#include <linux/semaphore.h>
91#include <linux/workqueue.h>
92#include <linux/kfifo.h>
93
94/* Pm notify ducati driver */
95/* Suspend/resume/other... */
96#define NUMBER_PM_EVENTS 4
97
98#define PM_CSTR_PERF_MASK 0x00000001
99#define PM_CSTR_LAT_MASK 0x00000002
100#define PM_CSTR_BW_MASK 0x00000004
101
102#define IPU_PM_MM_MPU_LAT_CONSTRAINT 10
103#define IPU_PM_NO_MPU_LAT_CONSTRAINT -1
104
105#define RCB_SIZE 8
106
107#define DATA_MAX (RCB_SIZE - 4)
108#define DATAX_MAX (RCB_SIZE - 5)
109#define SDMA_CHANNELS_MAX 16
110#define I2C_BUS_MIN 1
111#define I2C_BUS_MAX 4
112#define REGULATOR_MIN 1
113#define REGULATOR_MAX 1
114#define AUX_CLK_MIN 1
115#define AUX_CLK_MAX 3
116
117#define GP_TIMER_3 3
118#define GP_TIMER_4 4
119#define GP_TIMER_9 9
120#define GP_TIMER_11 11
121#define NUM_IPU_TIMERS 4
122
123#define I2C_SL_INVAL -1
124#define I2C_1_SL 0
125#define I2C_2_SL 1
126#define I2C_3_SL 2
127#define I2C_4_SL 3
128
129#define RCB_MIN 1
130#define RCB_MAX 33
131
132#define PM_RESOURCE 2
133#define PM_NOTIFICATION 3
134#define PM_SUCCESS 0
135#define PM_FAILURE -1
136#define PM_SHM_BASE_ADDR 0x9cff0000
137
138/* Auxiliar Clocks Registers */
139#define SCRM_BASE OMAP2_L4_IO_ADDRESS(0x4a30A000)
140#define SCRM_BASE_AUX_CLK 0x00000314
141#define SCRM_BASE_AUX_CLK_REQ 0x00000214
142#define SCRM_AUX_CLK_OFFSET 0x4
143/* Auxiliar Clocks bit fields */
144#define SCRM_AUX_CLK_POLARITY 0x0
145#define SCRM_AUX_CLK_SRCSELECT 0x1
146#define SCRM_AUX_CLK_ENABLE 0x8
147#define SCRM_AUX_CLK_CLKDIV 0x10
148/* Auxiliar Clocks Masks */
149#define SCRM_AUX_CLK_POLARITY_MASK 0x00000001
150#define SCRM_AUX_CLK_SRCSELECT_MASK 0x00000006
151#define SCRM_AUX_CLK_ENABLE_MASK 0x00000100
152#define SCRM_AUX_CLK_CLKDIV_MASK 0x000F0000
153/* Auxiliar Clocks Request bit fields */
154#define SCRM_AUX_CLK_REQ_POLARITY 0x0
155#define SCRM_AUX_CLK_REQ_ACCURACY 0x1
156#define SCRM_AUX_CLK_REQ_MAPPING 0x2
157/* Auxiliar Clocks Request Masks */
158#define SCRM_AUX_CLK_REQ_POLARITY_MASK 0x00000001
159#define SCRM_AUX_CLK_REQ_ACCURACY_MASK 0x00000002
160#define SCRM_AUX_CLK_REQ_MAPPING_MASK 0x0000001C
161
162/* Macro to set a val in a bitfield*/
163#define MASK_SET_FIELD(tmp, bitfield, val) { \
164 tmp |= \
165 ((val << SCRM_##bitfield)\
166 & SCRM_##bitfield##_MASK);\
167 }
168
169/* Macro to return the address of the aux clk */
170#define AUX_CLK_REG(clk) (SCRM_BASE + (SCRM_BASE_AUX_CLK + \
171 (SCRM_AUX_CLK_OFFSET * clk)))
172
173/* Macro to return the address of the aux clk req */
174#define AUX_CLK_REG_REQ(clk) (SCRM_BASE + (SCRM_BASE_AUX_CLK_REQ + \
175 (SCRM_AUX_CLK_OFFSET * clk)))
176
177
178/*
179 * IPU_PM_MODULEID
180 * Unique module ID
181 */
182#define IPU_PM_MODULEID (0x6A6A)
183
184/* A9 state flag 0000 | 0000 Ducati internal use*/
185#define SYS_PROC_DOWN 0x00010000
186#define APP_PROC_DOWN 0x00020000
187#define ENABLE_IPU_HIB 0x00000040
188
189#define SYS_PROC_IDLING 0x00000001
190#define APP_PROC_IDLING 0x00000002
191
192#define SYS_PROC_LOADED 0x00000010
193#define APP_PROC_LOADED 0x00000020
194#define IPU_PROC_LOADED 0x00000030
195#define PROC_LD_SHIFT 4u
196
197#define IPU_PROC_IDLING 0x0000c000
198#define IPU_IDLING_SHIFT 14u
199
200#define SYS_IDLING_BIT 14
201#define APP_IDLING_BIT 15
202
203#define SYS_LOADED_BIT 4
204#define APP_LOADED_BIT 5
205
206#define ONLY_APPM3_IDLE 0x2
207#define ONLY_SYSM3_IDLE 0x1
208#define ALL_CORES_IDLE 0x3
209#define WAIT_FOR_IDLE_TIMEOUT 40u
210
211/* Macro to make a correct module magic number with refCount */
212#define IPU_PM_MAKE_MAGICSTAMP(x) ((IPU_PM_MODULEID << 12u) | (x))
213
214enum pm_failure_codes{
215 PM_INSUFFICIENT_CHANNELS = 1,
216 PM_NO_GPTIMER,
217 PM_NO_GPIO,
218 PM_NO_I2C,
219 PM_NO_REGULATOR,
220 PM_REGULATOR_IN_USE,
221 PM_INVAL_RCB_NUM,
222 PM_INVAL_NUM_CHANNELS,
223 PM_INVAL_NUM_I2C,
224 PM_INVAL_REGULATOR,
225 PM_NOT_INSTANTIATED,
226 PM_UNSUPPORTED,
227 PM_NO_AUX_CLK,
228 PM_INVAL_AUX_CLK
229};
230
231enum pm_msgtype_codes{PM_FAIL,
232 PM_NULLMSG,
233 PM_ACKNOWLEDGEMENT,
234 PM_REQUEST_RESOURCE,
235 PM_RELEASE_RESOURCE,
236 PM_NOTIFICATIONS,
237 PM_ENABLE_RESOURCE,
238 PM_WRITE_RESOURCE,
239 PM_READ_RESOURCE,
240 PM_DISABLE_RESOURCE,
241 PM_REQUEST_CONSTRAINTS,
242 PM_RELEASE_CONSTRAINTS,
243 PM_NOTIFY_HIBERNATE
244};
245
246enum pm_regulator_action{PM_SET_VOLTAGE,
247 PM_SET_CURRENT,
248 PM_SET_MODE,
249 PM_GET_MODE,
250 PM_GET_CURRENT,
251 PM_GET_VOLTAGE
252};
253
254enum res_type{
255 FDIF,
256 IPU,
257 SYSM3,
258 APPM3,
259 ISS,
260 IVA_HD,
261 IVASEQ0,
262 IVASEQ1,
263 L3_BUS,
264 MPU,
265 SDMA,
266 GP_TIMER,
267 GP_IO,
268 I2C,
269 REGULATOR,
270 AUX_CLK,
271};
272
273enum pm_event_type{PM_SUSPEND,
274 PM_RESUME,
275 PM_PID_DEATH,
276 PM_HIBERNATE
277};
278
279struct rcb_message {
280 unsigned rcb_flag:1;
281 unsigned rcb_num:6;
282 unsigned reply_flag:1;
283 unsigned msg_type:4;
284 unsigned msg_subtype:4;
285 unsigned parm:16;
286};
287
288union message_slicer {
289 struct rcb_message fields;
290 int whole;
291};
292
293struct ipu_pm_override {
294 unsigned hibernateAllowed:1;
295 unsigned retentionAllowed:1;
296 unsigned inactiveAllowed:1;
297 unsigned cmAutostateAllowed:1;
298 unsigned deepSleepAllowed:1;
299 unsigned wfiAllowed:1;
300 unsigned idleAllowed:1;
301 unsigned reserved:24;
302 unsigned highbit:1;
303};
304
305struct rcb_block {
306 unsigned rcb_num:6;
307 unsigned msg_type:4;
308 unsigned sub_type:4;
309 unsigned rqst_cpu:4;
310 unsigned extd_mem_flag:1;
311 unsigned num_chan:4;
312 unsigned fill9:9;
313
314 unsigned process_id;
315 unsigned *sem_hnd;
316 unsigned mod_base_addr;
317 union {
318 unsigned int data[DATA_MAX];
319 struct {
320 unsigned datax[DATAX_MAX];
321 unsigned extd_mem_hnd;
322 };
323 unsigned char channels[SDMA_CHANNELS_MAX];
324 };
325};
326
327struct sms {
328 unsigned rat;
329 unsigned pm_version;
330 unsigned gp_msg;
331 unsigned state_flag;
332 struct ipu_pm_override pm_flags;
333 unsigned hib_time;
334 struct rcb_block rcb[RCB_MAX];
335};
336
337struct pm_event {
338 enum pm_event_type event_type;
339 struct semaphore sem_handle;
340 int pm_msg;
341};
342
343struct ipu_pm_params {
344 int pm_fdif_counter;
345 int pm_ipu_counter;
346 int pm_sys_m3_counter;
347 int pm_app_m3_counter;
348 int pm_iss_counter;
349 int pm_iva_hd_counter;
350 int pm_ivaseq0_counter;
351 int pm_ivaseq1_counter;
352 int pm_l3_bus_counter;
353 int pm_mpu_counter;
354 int pm_sdmachan_counter;
355 int pm_gptimer_counter;
356 int pm_gpio_counter;
357 int pm_i2c_bus_counter;
358 int pm_regulator_counter;
359 int pm_aux_clk_counter;
360 int timeout;
361 void *shared_addr;
362 int shared_addr_size;
363 int pm_num_events;
364 int pm_resource_event;
365 int pm_notification_event;
366 int proc_id;
367 int remote_proc_id;
368 int line_id;
369 void *gate_mp;
370};
371
372/* This structure defines attributes for initialization of the ipu_pm module. */
373struct ipu_pm_config {
374 u32 reserved;
375};
376
377/* Defines the ipu_pm state object, which contains all the module
378 * specific information. */
379struct ipu_pm_module_object {
380 atomic_t ref_count;
381 /* Reference count */
382 struct ipu_pm_config cfg;
383 /* ipu_pm configuration structure */
384 struct ipu_pm_config def_cfg;
385 /* Default module configuration */
386 struct mutex *gate_handle;
387 /* Handle of gate to be used for local thread safety */
388 bool is_setup;
389 /* Indicates whether the ipu_pm module is setup. */
390};
391
392/* Store the payload and processor id for the wq */
393struct ipu_pm_msg {
394 u16 proc_id;
395 int pm_msg;
396};
397
398/* ipu_pm handle one for each proc SYSM3/APPM3 */
399struct ipu_pm_object {
400 struct sms *rcb_table;
401 struct pm_event *pm_event;
402 struct ipu_pm_params *params;
403 struct work_struct work;
404 struct kfifo fifo;
405 spinlock_t lock;
406};
407
408/* Function for PM resources Callback */
409void ipu_pm_callback(u16 proc_id, u16 line_id, u32 event_id,
410 uint *arg, u32 payload);
411
412/* Function for PM notifications Callback */
413void ipu_pm_notify_callback(u16 proc_id, u16 line_id, u32 event_id,
414 uint *arg, u32 payload);
415
416/* Function for send PM Notifications */
417int ipu_pm_notifications(enum pm_event_type event_type, void *data);
418
419/* Function to set init parameters */
420void ipu_pm_params_init(struct ipu_pm_params *params);
421
422/* Function to calculate ipu pm mem */
423int ipu_pm_mem_req(const struct ipu_pm_params *params);
424
425/* Function to config ipu_pm module */
426void ipu_pm_get_config(struct ipu_pm_config *cfg);
427
428/* Function to set up ipu_pm module */
429int ipu_pm_setup(struct ipu_pm_config *cfg);
430
431/* Function to create ipu pm object */
432struct ipu_pm_object *ipu_pm_create(const struct ipu_pm_params *params);
433
434/* Function to delete ipu pm object */
435void ipu_pm_delete(struct ipu_pm_object *handle);
436
437/* Function to destroy ipu_pm module */
438int ipu_pm_destroy(void);
439
440/* Function to attach ipu_pm module */
441int ipu_pm_attach(u16 remote_proc_id, void *shared_addr);
442
443/* Function to deattach ipu_pm module */
444int ipu_pm_detach(u16 remote_proc_id);
445
446/* Function to register the ipu_pm events */
447int ipu_pm_init_transport(struct ipu_pm_object *handle);
448
449/* Function to get ipu pm object */
450struct ipu_pm_object *ipu_pm_get_handle(int proc_id);
451
452/* Function to save a processor from hibernation */
453int ipu_pm_save_ctx(int proc_id);
454
455/* Function to restore a processor from hibernation */
456int ipu_pm_restore_ctx(int proc_id);
457
458/* Function to start a module */
459int ipu_pm_module_start(unsigned res_type);
460
461/* Function to stop a module */
462int ipu_pm_module_stop(unsigned res_type);
463
464/* Function to get ducati state flag from share memory */
465u32 ipu_pm_get_state(int proc_id);
466
467#endif