diff options
author | Paul Hunt <hunt@ti.com> | 2010-09-08 15:04:12 -0400 |
---|---|---|
committer | Paolo Pisati <paolo.pisati@canonical.com> | 2012-08-17 04:19:08 -0400 |
commit | aaca0103c44efa5cbca6720309856ddfacd6ffa6 (patch) | |
tree | 09c34b1698d739d60a7eaf0e54fab58cd9a7b2bf /arch/arm | |
parent | 77508e0bdabffccd9106c79b74170a8a4a87f321 (diff) |
omap:ipu_pm: Patchset to introduce ipu_pm functionality. omap:ipu_pm: add ipu_dev header to mach-omap2 tree
Header file needed fot mach-omap2/ipu_dev.c file
Signed-off-by: Paul Hunt <hunt@ti.com>
omap:ipu_pm: add ipu_utility to mach-omap2 tree
IVAHD Sequencer WFI Boot Code for IPU PM Driver
Signed-off-by: Paul Hunt <hunt@ti.com>
omap:ipu_pm: add ipu_drv to mach-omap2 tree
Add needed api for ipu_pm module
Signed-off-by: Paul Hunt <hunt@ti.com>
omap:ipu_pm: add ipu_dev to mach-omap2 tree.
Platform Device handling for IPU PM Driver
Includes:
- ipu_pm_module_start
- ipu_pm_module_stop
- platform data definition for the following devices:
+ fdif
+ ipu
+ ipu_c0
+ ipu_c1
+ iss
+ iva
+ iva_seq0
+ iva_seq1
+ L3
+ mpu
-ipussdev_init to init all devices.
Signed-off-by: Paul Hunt <hunt@ti.com>
syslink:ipu_pm: add/remove ipu_pm_start/stop
Add the calls to api that will enable:
- iva_hd
- iva_seq0
- iva_seq1
- fdif
- iss
modules using the hwmod implementation.
Hibernation disabled.
Gptimer3 used for hibernation was disabled.
Setting CM_MPU_M3_CLKSTCTRL.CLKTRCTRL[1:0] = HW_AUTO
Retention is disable by default.
Signed-off-by: Paul Hunt <hunt@ti.com>
syslink:ipu_pm: fix req/rel aux_clk/iss/iva/idle
The current implementation was not meeting all
the requiriments needed to properly enable and
use aux_clk.
Anyway this is a hack way to do it, the proper
implementation is still pending.
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Temporary path using cmm_write_reg to enable CAM_PHY
Signed-off-by: Paul Hunt <hunt@ti.com>
Ivahd requesting was not fully working since
sl2 was not being requested and that is needed
for ivahd to be fully functional.
In ipu_dev sl2 is initialized
In ipu_pm the flow to request iva should be:
- Requesting (ivaseq1 call is requesting sl2)
ivahd>ivaseq0>(ivaseq1>sl2)
- Releasing (iva call is first releasing sl2)
ivaseq0>ivaseq1>(sl2>ivahd)
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Setting IdleAllowed flag that enables the idle mode
in Ducati. WFI can be called in Ducati flag
whenever this flag is set
Signed-off-by: Juan Gutierrez <jgutierrez@ti.com>
Fix a compile error related to iva/iss when trying
to build with ES1.0 configuration. In ES1.0, the
PM is not supported.
Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com>
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
syslink:ipu_pm: DFVS support for freq
Fix bug in error message string referencing
Signed-off-by: Paul Hunt <hunt@ti.com>
Add platform data for DSP resource and fix
attributes for MPU and L3 interconnect.
Signed-off-by: Paul Hunt <hunt@ti.com>
Provide internal APIs for performance and
latency constraint frameworks to use to assert
these constraints into the system power management.
Signed-off-by: Paul Hunt <hunt@ti.com>
MPU and CORE freq/lat cstrs
Add special handling for MPU and CORE frequency and
latency constraints.
To specify a constraint to MPU or CORE the api needs
to be called passing the following to the api:
- IPUPM_SELF
- IPUPM_MPU
- IPUPM_CORE
Signed-off-by: Paul Hunt <hunt@ti.com>
DVFS support in ipu_pm
Calling the dvfs apis per resource.
Included:
- ipu[perf|lat]
- iss[perf|lat]
- ivahd[perf|lat]
- L3 bus[lat]
- mpu[perf|lat]
Pending:
- fdif
- dsp
Note: Latency calls are working but hasnt been tested.
Perf/rate calls are working.
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Signed-off-by: Paul Hunt <hunt@ti.com>
(cherry picked from commit 3c1cdb45bb67d11eda14420a7b8eaacff0c24173)
SYSLINK:IPU-PM-move iommu handles to attach and detach
Move getting iommu handle to attach and detach from setup/destroy.
Having the iommu get in setup is causing the mmu fault recovery fail
since the iommu object gets incremented before the fault application
closes the iommu handle which leads to failure in shutting down the
iommu device completely.
Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com>
syslink:ipu_pm: add L3 bw and fdif cstr
ipu_pm api to set the bandwidth constraint for L3 bus
New api is:
ipu_pm_module_set_bandwidth(rsrc,
target_rsrc,
bw);
bw is received in KiB/s and converted into Hz
Add support to set performance and latency cstrs to
fdif.
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Signed-off-by: Paul Hunt <hunt@ti.com>
Signed-off-by: Juan Gutierrez <jgutierrez@ti.com>
syslink:ipu_pm: send pid_death just to appm3
ipu_pm_notification is broadcasting all events to both
sys/app processors whenever an event is sent using that
api.
For PID_DEATH event the requirement is only to send the
message to APPM3 since is the one that will be executing
the resource manager; also because of that sending the
message to SYSM3 is unnecessary.
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
syslink:ipu_pm: allow IPU hibernation
-IPU self hibernation-
After 5 seconds of inactivity ipu will send a notification to
MPU indicating it can be turned off, mpu can proceed to turn off
IPU just if there is no message (notify_send_event) going to IPU,
in that case hibernation will be aborted. IPU is prepared to abort
hibernation when a message arrives to its mbox. When mpu is
hibernating IPU the iommu and mbox context will be saved and then
rproc_sleep will be called to disable each core and also the
associated gptimer, that is needed to allow retention. Whenever a
message is sent to IPU the ipu_pm_restore will check and wake up IPU,
if needed, restoring the iommu and mbox context and calling rproc_wake
that will enable IPU and the associated gptimer again.
-MPU hibernating IPU-
Whenever the system suspend is sent to ipu_drv the suspend_drv will
send a SUSPEND notification to IPU, it will send back an ack to MPU
and then start the hibernation proccess by it self following the same
scheme mentioned above but without waiting the 5 seconds, once
ipu_drv receives the suspend ack it will call ipu_pm_save_ctx() in
order to wait for IPU to be hibernated and in really idle then turn IPU
off. This will work even if self hibernation in IPU is disable.
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Signed-off-by: Juan Gutierrez <jgutierrez@ti.com>
Signed-off-by: Paul Hunt <hunt@ti.com>
IPU PM: adapt aux clk funcs to new framework entities
Signed-off-by: Paul Hunt <hunt@ti.com>
IPU PM: temporary workaround for missing MM AUX_CLK requests
Signed-off-by: Paul Hunt <hunt@ti.com>
syslink: ipu_pm: add support for all the auxclk
Previously ipu_pm was only supporting the request of
AUX_CLK_1/3 now all the available aux_clk 0-5 are
supported and can be requested/released via ipu_pm.
Also the base address of the AUX_CLK was fixed since
it was assuming AUX_CLK_0 as AUX_CLK_1 leading to a
misalignment when requesting.
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
syslink: ipu_pm: add a core latency constraint when the ipu is running.
Due to the enabling of C4 and C5 states IPU was being
put in reset without allowing it to properly save the
context leading to an invalid resume operation and an
MMU fault by IPU side.
Putting a latency constraint on IPU_CORE whenever IPU
is up and running is avoiding this scenario.
The constraint is released once the IPU has properly
saved the context and requested again when resuming
to avoid letting the ipu_core going to retention.
Change-Id: Iced64ff0744b2d6b0a0ecfc1952ed26e9e560278
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Signed-off-by: Paul Hunt <hunt@ti.com>
omap:syslink: removing gpt4 as available
Gptimers 3 & 4 are reserving for ipu_pm internal use
gpt3 was removed in previous patch from the list of
available gptimers that IPU can request but gpt4 was
still in the list.
This patch removes gpt4 from the list.
Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/ipu_dev.c | 384 | ||||
-rw-r--r-- | arch/arm/mach-omap2/ipu_drv.c | 343 | ||||
-rw-r--r-- | arch/arm/mach-omap2/ipu_utility.c | 69 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/ipu_dev.h | 107 |
4 files changed, 903 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/ipu_dev.c b/arch/arm/mach-omap2/ipu_dev.c new file mode 100644 index 00000000000..8d3386f1f86 --- /dev/null +++ b/arch/arm/mach-omap2/ipu_dev.c | |||
@@ -0,0 +1,384 @@ | |||
1 | /** | ||
2 | * linux/arch/arm/mach-omap2/ipu_dev.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments, Inc. | ||
5 | * Paul Hunt <hunt@ti.com> | ||
6 | * | ||
7 | * OMAP4 Image Processing Unit | ||
8 | * This program 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 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/err.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <plat/omap_hwmod.h> | ||
20 | #include <plat/omap_device.h> | ||
21 | #include <plat/omap-pm.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <plat/remoteproc.h> | ||
24 | |||
25 | #include <plat/ipu_dev.h> | ||
26 | |||
27 | #include "../../../drivers/dsp/syslink/ipu_pm/ipu_pm.h" | ||
28 | |||
29 | #define IPU_DRIVER_NAME "omap-ipu-pm" | ||
30 | #define ISS_IPU_BUS_ID 0 | ||
31 | #define IVA_IPU_BUS_ID 1 | ||
32 | |||
33 | struct omap_ipupm_mod_platform_data *ipupm_get_plat_data(void); | ||
34 | |||
35 | static char *hwmod_state_strings[] = { | ||
36 | "_HWMOD_STATE_UNKNOWN", | ||
37 | "_HWMOD_STATE_REGISTERED", | ||
38 | "_HWMOD_STATE_CLKS_INITED", | ||
39 | "_HWMOD_STATE_INITIALIZED", | ||
40 | "_HWMOD_STATE_ENABLED", | ||
41 | "_HWMOD_STATE_IDLE", | ||
42 | "_HWMOD_STATE_DISABLED", | ||
43 | }; | ||
44 | static void print_hwmod_state(struct omap_hwmod *oh) | ||
45 | { | ||
46 | u32 _state = (u32) oh->_state; | ||
47 | pr_info("HWMOD name = %s\n", oh->name); | ||
48 | if (_state > _HWMOD_STATE_LAST) | ||
49 | WARN(1, "Illegal hwmod _state = %d\n", _state); | ||
50 | else | ||
51 | pr_info("state = %s\n", hwmod_state_strings[_state]); | ||
52 | } | ||
53 | |||
54 | inline int ipu_pm_module_start(unsigned rsrc) | ||
55 | { | ||
56 | int ret; | ||
57 | struct omap_ipupm_mod_platform_data *pd; | ||
58 | |||
59 | pd = ipupm_get_plat_data(); | ||
60 | |||
61 | print_hwmod_state(pd[rsrc].oh); | ||
62 | ret = omap_device_enable(pd[rsrc].pdev); | ||
63 | if (ret) | ||
64 | pr_err("device enable failed %s", pd[rsrc].oh_name); | ||
65 | |||
66 | return ret; | ||
67 | } | ||
68 | EXPORT_SYMBOL(ipu_pm_module_start); | ||
69 | |||
70 | inline int ipu_pm_module_stop(unsigned rsrc) | ||
71 | { | ||
72 | int ret; | ||
73 | struct omap_ipupm_mod_platform_data *pd; | ||
74 | |||
75 | pd = ipupm_get_plat_data(); | ||
76 | |||
77 | print_hwmod_state(pd[rsrc].oh); | ||
78 | ret = omap_device_shutdown(pd[rsrc].pdev); | ||
79 | if (ret) | ||
80 | pr_err("device disable failed %s", pd[rsrc].oh_name); | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | EXPORT_SYMBOL(ipu_pm_module_stop); | ||
85 | |||
86 | inline int ipu_pm_module_set_rate(unsigned rsrc, | ||
87 | unsigned target_rsrc, | ||
88 | unsigned rate) | ||
89 | { | ||
90 | int ret; | ||
91 | unsigned target; | ||
92 | struct device *dp; | ||
93 | struct omap_ipupm_mod_platform_data *pd; | ||
94 | |||
95 | pd = ipupm_get_plat_data(); | ||
96 | |||
97 | if (target_rsrc == IPU_PM_MPU) | ||
98 | dp = omap2_get_mpuss_device(); | ||
99 | else if (target_rsrc == IPU_PM_CORE) | ||
100 | dp = omap2_get_l3_device(); | ||
101 | else { | ||
102 | if (target_rsrc == IPU_PM_SELF) | ||
103 | target = rsrc; | ||
104 | else | ||
105 | target = target_rsrc; | ||
106 | |||
107 | if ((pd[target].caps & IPUPM_CAPS_PERF) == 0) { | ||
108 | pr_err("device set rate not supported for %s", | ||
109 | pd[target].oh_name); | ||
110 | ret = -EINVAL; | ||
111 | goto err_ret; | ||
112 | } else | ||
113 | dp = pd[target].dev; | ||
114 | } | ||
115 | |||
116 | ret = omap_device_set_rate(pd[rsrc].dev, dp, rate); | ||
117 | if (ret) | ||
118 | pr_err("device set rate failed %s", pd[target_rsrc].oh_name); | ||
119 | err_ret: | ||
120 | return ret; | ||
121 | } | ||
122 | EXPORT_SYMBOL(ipu_pm_module_set_rate); | ||
123 | |||
124 | inline int ipu_pm_module_set_latency(unsigned rsrc, | ||
125 | unsigned target_rsrc, | ||
126 | int latency) | ||
127 | { | ||
128 | int ret = 0; | ||
129 | unsigned target; | ||
130 | struct omap_ipupm_mod_platform_data *pd; | ||
131 | |||
132 | pd = ipupm_get_plat_data(); | ||
133 | |||
134 | if (target_rsrc == IPU_PM_MPU) { | ||
135 | #ifdef CONFIG_OMAP_PM | ||
136 | ret = omap_pm_set_max_mpu_wakeup_lat(&pd[rsrc].qos_request, | ||
137 | latency); | ||
138 | #endif | ||
139 | if (ret) | ||
140 | goto err_ret; | ||
141 | } else if (target_rsrc == IPU_PM_CORE) { | ||
142 | #ifdef CONFIG_OMAP_PM | ||
143 | ret = omap_pm_set_max_sdma_lat(&pd[rsrc].qos_request, | ||
144 | latency); | ||
145 | #endif | ||
146 | if (ret) | ||
147 | goto err_ret; | ||
148 | } else { | ||
149 | if (target_rsrc == IPU_PM_SELF) | ||
150 | target = rsrc; | ||
151 | else | ||
152 | target = target_rsrc; | ||
153 | |||
154 | if ((pd[target].caps & IPUPM_CAPS_LAT) == 0) { | ||
155 | pr_err("device set latency not supported for %s", | ||
156 | pd[target].oh_name); | ||
157 | ret = -EINVAL; | ||
158 | } else { | ||
159 | #ifdef CONFIG_OMAP_PM | ||
160 | ret = omap_pm_set_max_dev_wakeup_lat(pd[rsrc].dev, | ||
161 | pd[target].dev, | ||
162 | latency); | ||
163 | #endif | ||
164 | } | ||
165 | } | ||
166 | |||
167 | if (ret) | ||
168 | pr_err("module set latency failed %s", pd[target].oh_name); | ||
169 | err_ret: | ||
170 | return ret; | ||
171 | } | ||
172 | EXPORT_SYMBOL(ipu_pm_module_set_latency); | ||
173 | |||
174 | inline int ipu_pm_module_set_bandwidth(unsigned rsrc, | ||
175 | unsigned target_rsrc, | ||
176 | int bandwidth) | ||
177 | { | ||
178 | int ret = 0; | ||
179 | struct omap_ipupm_mod_platform_data *pd; | ||
180 | |||
181 | pd = ipupm_get_plat_data(); | ||
182 | |||
183 | if ((pd[target_rsrc].caps & IPUPM_CAPS_BDW) == 0) { | ||
184 | pr_err("device set bandwidth not supported for %s", | ||
185 | pd[target_rsrc].oh_name); | ||
186 | ret = -EINVAL; | ||
187 | } else { | ||
188 | #ifdef CONFIG_OMAP_PM | ||
189 | struct device *dp; | ||
190 | dp = omap2_get_l3_device(); | ||
191 | ret = omap_pm_set_min_bus_tput(dp, | ||
192 | OCP_INITIATOR_AGENT, | ||
193 | bandwidth); | ||
194 | #endif | ||
195 | } | ||
196 | |||
197 | if (ret) | ||
198 | pr_err("module set bandwidth failed %s", | ||
199 | pd[target_rsrc].oh_name); | ||
200 | return ret; | ||
201 | } | ||
202 | EXPORT_SYMBOL(ipu_pm_module_set_bandwidth); | ||
203 | |||
204 | /* FIXME: not in use now | ||
205 | * static struct omap_ipupm_mod_ops omap_ipu_ops = { | ||
206 | * .start = NULL, | ||
207 | * .stop = NULL, | ||
208 | * }; | ||
209 | * | ||
210 | * static struct omap_ipupm_mod_ops omap_ipu0_ops = { | ||
211 | * .start = NULL, | ||
212 | * .stop = NULL, | ||
213 | * }; | ||
214 | * | ||
215 | * static struct omap_ipupm_mod_ops omap_ipu1_ops = { | ||
216 | * .start = NULL, | ||
217 | * .stop = NULL, | ||
218 | * }; | ||
219 | */ | ||
220 | |||
221 | /* ipupm generic operations */ | ||
222 | static struct omap_ipupm_mod_ops omap_ipupm_ops = { | ||
223 | .start = NULL, | ||
224 | .stop = NULL, | ||
225 | }; | ||
226 | |||
227 | static struct omap_ipupm_mod_platform_data omap_ipupm_data[] = { | ||
228 | { | ||
229 | .name = "omap-ipu-pm", | ||
230 | .oh_name = "fdif", | ||
231 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP | ||
232 | | IPUPM_CAPS_PERF | IPUPM_CAPS_LAT, | ||
233 | .ops = &omap_ipupm_ops, | ||
234 | }, | ||
235 | { | ||
236 | .name = "omap-ipu-pm", | ||
237 | .oh_name = "ipu", | ||
238 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP | ||
239 | | IPUPM_CAPS_PERF | IPUPM_CAPS_LAT | ||
240 | | IPUPM_CAPS_EXTINIT, | ||
241 | .ops = &omap_ipupm_ops, | ||
242 | }, | ||
243 | { | ||
244 | .name = "omap-ipu-pm", | ||
245 | .oh_name = "ipu_c0", | ||
246 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP | ||
247 | | IPUPM_CAPS_EXTINIT, | ||
248 | .ops = &omap_ipupm_ops, | ||
249 | }, | ||
250 | { | ||
251 | .name = "omap-ipu-pm", | ||
252 | .oh_name = "ipu_c1", | ||
253 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP | ||
254 | | IPUPM_CAPS_EXTINIT, | ||
255 | .ops = &omap_ipupm_ops, | ||
256 | }, | ||
257 | { | ||
258 | .name = "omap-ipu-pm", | ||
259 | .oh_name = "iss", | ||
260 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP | ||
261 | | IPUPM_CAPS_PERF | IPUPM_CAPS_LAT, | ||
262 | .ops = &omap_ipupm_ops, | ||
263 | }, | ||
264 | { | ||
265 | .name = "omap-ipu-pm", | ||
266 | .oh_name = "iva", | ||
267 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP | ||
268 | | IPUPM_CAPS_PERF | IPUPM_CAPS_LAT, | ||
269 | .ops = &omap_ipupm_ops, | ||
270 | }, | ||
271 | { | ||
272 | .name = "omap-ipu-pm", | ||
273 | .oh_name = "iva_seq0", | ||
274 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP, | ||
275 | .ops = &omap_ipupm_ops, | ||
276 | }, | ||
277 | { | ||
278 | .name = "omap-ipu-pm", | ||
279 | .oh_name = "iva_seq1", | ||
280 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP, | ||
281 | .ops = &omap_ipupm_ops, | ||
282 | }, | ||
283 | { | ||
284 | .name = "omap-ipu-pm", | ||
285 | .oh_name = "l3_main_1", | ||
286 | .caps = IPUPM_CAPS_LAT | IPUPM_CAPS_BDW | ||
287 | | IPUPM_CAPS_EXTINIT, | ||
288 | .ops = &omap_ipupm_ops, | ||
289 | }, | ||
290 | { | ||
291 | .name = "omap-ipu-pm", | ||
292 | .oh_name = "mpu", | ||
293 | .caps = IPUPM_CAPS_PERF | IPUPM_CAPS_LAT | ||
294 | | IPUPM_CAPS_EXTINIT, | ||
295 | .ops = &omap_ipupm_ops, | ||
296 | }, | ||
297 | { | ||
298 | .name = "omap-ipu-pm", | ||
299 | .oh_name = "sl2if", | ||
300 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP, | ||
301 | .ops = &omap_ipupm_ops, | ||
302 | }, | ||
303 | { | ||
304 | .name = "omap-ipu-pm", | ||
305 | .oh_name = "dsp", | ||
306 | .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP | ||
307 | | IPUPM_CAPS_PERF | IPUPM_CAPS_LAT | ||
308 | | IPUPM_CAPS_EXTINIT, | ||
309 | .ops = &omap_ipupm_ops, | ||
310 | }, | ||
311 | }; | ||
312 | |||
313 | struct omap_ipupm_mod_platform_data *ipupm_get_plat_data(void) | ||
314 | { | ||
315 | return omap_ipupm_data; | ||
316 | } | ||
317 | EXPORT_SYMBOL(ipupm_get_plat_data); | ||
318 | |||
319 | static struct omap_device_pm_latency omap_ipupm_latency[] = { | ||
320 | { | ||
321 | .deactivate_func = omap_device_idle_hwmods, | ||
322 | .activate_func = omap_device_enable_hwmods, | ||
323 | .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, | ||
324 | }, | ||
325 | }; | ||
326 | |||
327 | static int __init omap_ipussdev_init(void) | ||
328 | { | ||
329 | int status = -ENODEV; | ||
330 | int i; | ||
331 | int first = 1; | ||
332 | struct omap_hwmod *oh; | ||
333 | struct omap_device *od; | ||
334 | char *oh_name; | ||
335 | char *pdev_name = IPU_DRIVER_NAME; | ||
336 | struct omap_device_pm_latency *ohl = omap_ipupm_latency; | ||
337 | int ohl_cnt = ARRAY_SIZE(omap_ipupm_latency); | ||
338 | |||
339 | for (i = 0; i < ARRAY_SIZE(omap_ipupm_data); i++) { | ||
340 | oh_name = omap_ipupm_data[i].oh_name; | ||
341 | |||
342 | if (omap_ipupm_data[i].caps & IPUPM_CAPS_EXTINIT) | ||
343 | continue; | ||
344 | |||
345 | oh = omap_hwmod_lookup(oh_name); | ||
346 | if (!oh) { | ||
347 | pr_err("%s: could not look up %s\n", __func__, oh_name); | ||
348 | |||
349 | continue; /* to allow init to continue with other IPs | ||
350 | * we probably do not want to completely stop progress | ||
351 | * due to one module anyway, but need to be able to | ||
352 | * not try to use it if init fails | ||
353 | * this was put in to handle disabled hwmods | ||
354 | */ | ||
355 | |||
356 | status = -ENODEV; | ||
357 | goto err_init; | ||
358 | } | ||
359 | omap_ipupm_data[i].oh = oh; | ||
360 | |||
361 | od = omap_device_build(pdev_name, IVA_IPU_BUS_ID+i, oh, | ||
362 | &omap_ipupm_data[i], | ||
363 | sizeof(struct omap_ipupm_mod_platform_data), | ||
364 | ohl, ohl_cnt, false); | ||
365 | |||
366 | status = IS_ERR(od); | ||
367 | WARN(status, "Could not build omap_device for %s %s\n", | ||
368 | pdev_name, oh_name); | ||
369 | if (!status) { | ||
370 | /* Save the id of the first registered dev */ | ||
371 | if (first) { | ||
372 | ipu_pm_first_dev = od->pdev.id; | ||
373 | first = 0; | ||
374 | } | ||
375 | omap_ipupm_data[i].pdev = &od->pdev; | ||
376 | omap_ipupm_data[i].dev = &od->pdev.dev; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | err_init: | ||
381 | return status; | ||
382 | } | ||
383 | |||
384 | arch_initcall(omap_ipussdev_init); | ||
diff --git a/arch/arm/mach-omap2/ipu_drv.c b/arch/arm/mach-omap2/ipu_drv.c new file mode 100644 index 00000000000..88a78ba7be2 --- /dev/null +++ b/arch/arm/mach-omap2/ipu_drv.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/ipu_drv.c | ||
3 | * | ||
4 | * OMAP Image Processing Unit Power Management Driver | ||
5 | * | ||
6 | * Copyright (C) 2010 Texas Instruments | ||
7 | * Paul Hunt <hunt@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
17 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
19 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
21 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License along | ||
24 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #include <linux/init.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/device.h> | ||
35 | #include <linux/file.h> | ||
36 | #include <linux/fs.h> | ||
37 | #include <linux/sysfs.h> | ||
38 | #include <linux/proc_fs.h> | ||
39 | #include <linux/seq_file.h> | ||
40 | #include <linux/platform_device.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | #include <plat/ipu_dev.h> | ||
43 | |||
44 | #define IPU_CLASS_NAME "ipu-power" | ||
45 | #define IPU_DRIVER_NAME "omap-ipu-pm" | ||
46 | |||
47 | static struct class *omap_ipu_pm_class; | ||
48 | static dev_t omap_ipu_pm_dev; | ||
49 | |||
50 | int ipu_pm_first_dev; | ||
51 | |||
52 | static struct proc_dir_entry *ipu_pm_proc_entry; | ||
53 | /* we could iterate over something much more | ||
54 | * complicated than a set of lines of text | ||
55 | * Just debugging. | ||
56 | */ | ||
57 | static char *lines[] = { | ||
58 | "This is the first line from ipu_pm_seq", | ||
59 | "This is the second line from ipu_pm_seq", | ||
60 | }; | ||
61 | |||
62 | static int ipu_pm_num_procs = ARRAY_SIZE(lines); | ||
63 | |||
64 | static void *ipu_pm_seq_start(struct seq_file *s, loff_t *pos) | ||
65 | { | ||
66 | if (*pos >= ipu_pm_num_procs) | ||
67 | return NULL;/* no more to read */ | ||
68 | return lines[*pos]; | ||
69 | } | ||
70 | static void *ipu_pm_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
71 | { | ||
72 | (*pos)++; | ||
73 | if (*pos >= ipu_pm_num_procs) | ||
74 | return NULL;/* no more to read */ | ||
75 | return lines[*pos]; | ||
76 | } | ||
77 | static void ipu_pm_seq_stop(struct seq_file *s, void *v) | ||
78 | { | ||
79 | /* nothing to do */ | ||
80 | } | ||
81 | static int ipu_pm_seq_show(struct seq_file *s, void *v) | ||
82 | { | ||
83 | seq_printf(s, "IPU_PM: %s\n", (char *) v); | ||
84 | return 0; | ||
85 | } | ||
86 | static const struct seq_operations ipu_pm_seq_ops = { | ||
87 | .start = ipu_pm_seq_start, | ||
88 | .next = ipu_pm_seq_next, | ||
89 | .stop = ipu_pm_seq_stop, | ||
90 | .show = ipu_pm_seq_show, | ||
91 | }; | ||
92 | static int ipu_pm_proc_open(struct inode *inode, struct file *file) | ||
93 | { | ||
94 | return seq_open(file, &ipu_pm_seq_ops); | ||
95 | } | ||
96 | |||
97 | static const struct file_operations ipu_pm_proc_ops = { | ||
98 | .owner = THIS_MODULE, | ||
99 | .open = ipu_pm_proc_open, | ||
100 | .read = seq_read, | ||
101 | .llseek = seq_lseek, | ||
102 | .release = seq_release, | ||
103 | }; | ||
104 | |||
105 | static void _suspend_stub(void) | ||
106 | { | ||
107 | pr_info("Suspend IOCTL received\n"); | ||
108 | } | ||
109 | |||
110 | static void _resume_stub(void) | ||
111 | { | ||
112 | pr_info("Resume IOCTL received!\n"); | ||
113 | } | ||
114 | |||
115 | /* arg should encode the IPU-managed HWMOD | ||
116 | * to be suspended, 0 for system wide | ||
117 | */ | ||
118 | static int ipu_pm_ioctl(struct inode *inode, struct file *filp, | ||
119 | unsigned int cmd, unsigned long arg) | ||
120 | { | ||
121 | int ret = 0; | ||
122 | /* struct omap_ipu_pm *ipu_pm = filp->private_data; */ | ||
123 | |||
124 | /* FIXME: check for ipu_pm when requested */ | ||
125 | |||
126 | if (_IOC_TYPE(cmd) != IPU_PM_IOC_MAGIC) | ||
127 | return -ENOTTY; | ||
128 | if (_IOC_NR(cmd) > IPU_PM_IOC_MAXNR) | ||
129 | return -ENOTTY; | ||
130 | |||
131 | /* FIXME:not using the next two yet, since no args */ | ||
132 | if (_IOC_DIR(cmd) & _IOC_READ) { | ||
133 | if (!access_ok(VERIFY_WRITE, | ||
134 | (void __user *)arg, | ||
135 | _IOC_SIZE(cmd))) | ||
136 | return -EFAULT; | ||
137 | } else if (_IOC_DIR(cmd) & _IOC_WRITE) { | ||
138 | if (!access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd))) | ||
139 | return -EFAULT; | ||
140 | } | ||
141 | |||
142 | switch (cmd) { | ||
143 | case IPU_PM_IOC_SUSPEND: | ||
144 | _suspend_stub(); | ||
145 | break; | ||
146 | case IPU_PM_IOC_RESUME: | ||
147 | _resume_stub(); | ||
148 | break; | ||
149 | |||
150 | default: | ||
151 | return -ENOTTY; | ||
152 | } | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | |||
158 | #ifdef ZERO | ||
159 | static const struct sysfs_ops { | ||
160 | ssize_t (*show)(struct kobject *, struct attribute *, char *); | ||
161 | ssize_t (*store)(struct kobject *, struct attribute *, const char *, | ||
162 | size_t); | ||
163 | }; | ||
164 | #endif | ||
165 | |||
166 | static int is_driver_init; | ||
167 | |||
168 | static const struct file_operations ipm_pm_fops = { | ||
169 | .owner = THIS_MODULE, | ||
170 | .ioctl = ipu_pm_ioctl, | ||
171 | .open = NULL, | ||
172 | }; | ||
173 | |||
174 | static struct ipu_pm_dev ipu_pm_dev; | ||
175 | |||
176 | static int __devinit ipu_pm_probe(struct platform_device *pdev) | ||
177 | { | ||
178 | /* FIXME: get pdata */ | ||
179 | /* struct ipu_pm_platform_data *pdata = pdev->dev.platform_data; */ | ||
180 | /* int id = pdev->id; */ | ||
181 | /* ivahd.pdev = pdev; */ | ||
182 | |||
183 | if (!is_driver_init) { | ||
184 | is_driver_init = 1; | ||
185 | /* FIXME: maybe needed for multiple dev */ | ||
186 | /* spin_lock_init(&ipu_pm_lock); */ | ||
187 | } | ||
188 | /* FIXME: add kobjects to kset */ | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int ipu_pm_drv_suspend(struct device *dev) | ||
194 | { | ||
195 | struct platform_device *pdev = to_platform_device(dev); | ||
196 | int retval = 0; | ||
197 | |||
198 | if (pdev->id == ipu_pm_first_dev) { | ||
199 | pr_debug("%s.%d ASKED TO SUSPEND", pdev->name, pdev->id); | ||
200 | /* save any local context, | ||
201 | * BIOS timers could be saved locally or on Ducati | ||
202 | */ | ||
203 | |||
204 | /* call our notification function */ | ||
205 | retval = ipu_pm_notifications(PM_SUSPEND, NULL); | ||
206 | |||
207 | /* FIXME: Currently sending SUSPEND is enough to send | ||
208 | * Ducati to hibernate, save ctx can be called at this | ||
209 | * point to save ctx and reset remote procs | ||
210 | * Currently the save ctx process can be called using | ||
211 | * which ever proc_id, maybe this will change when | ||
212 | * Tesla support is added. | ||
213 | */ | ||
214 | /* sysm3 is handling hibernation of ducati currently */ | ||
215 | ipu_pm_save_ctx(SYS_M3); | ||
216 | |||
217 | /* return result, should be zero if all Ducati clients | ||
218 | * returned zero else fail code | ||
219 | */ | ||
220 | } | ||
221 | |||
222 | return retval; | ||
223 | } | ||
224 | |||
225 | static int ipu_pm_drv_resume(struct device *dev) | ||
226 | { | ||
227 | struct platform_device *pdev = to_platform_device(dev); | ||
228 | int retval = 0; | ||
229 | |||
230 | if (pdev->id == ipu_pm_first_dev) { | ||
231 | pr_debug("%s.%d ASKED TO RESUME", pdev->name, pdev->id); | ||
232 | /* restore any local context, | ||
233 | * BIOS timers could be restored locally or on Ducati | ||
234 | */ | ||
235 | |||
236 | /* call our notification function */ | ||
237 | retval = ipu_pm_notifications(PM_RESUME, NULL); | ||
238 | |||
239 | /* return result, should be zero if all Ducati clients | ||
240 | * returned zero else fail code | ||
241 | */ | ||
242 | } | ||
243 | |||
244 | return retval; | ||
245 | } | ||
246 | |||
247 | static const struct dev_pm_ops ipu_pm_ops = { | ||
248 | .suspend = ipu_pm_drv_suspend, | ||
249 | .resume = ipu_pm_drv_resume, | ||
250 | }; | ||
251 | |||
252 | static struct platform_driver ipu_pm_driver = { | ||
253 | .probe = ipu_pm_probe, | ||
254 | /*.remove = ipu_pm_remove, */ | ||
255 | .driver = { | ||
256 | .name = IPU_DRIVER_NAME, | ||
257 | .owner = THIS_MODULE, | ||
258 | .pm = &ipu_pm_ops, | ||
259 | }, | ||
260 | }; | ||
261 | |||
262 | static int __init ipu_pm_init(void) | ||
263 | { | ||
264 | int ret; | ||
265 | struct device *tmpdev; | ||
266 | |||
267 | if (!is_driver_init) { | ||
268 | is_driver_init = 1; | ||
269 | /* FIXME: maybe needed for multiple dev */ | ||
270 | /* spin_lock_init(&ipu_pm_lock); */ | ||
271 | } | ||
272 | |||
273 | ret = alloc_chrdev_region(&omap_ipu_pm_dev, 0, 2, IPU_CLASS_NAME); | ||
274 | if (ret) { | ||
275 | pr_err("%s: alloc_chrdev_region failed: %d\n", __func__, ret); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | /* create device class */ | ||
280 | omap_ipu_pm_class = class_create(THIS_MODULE, IPU_CLASS_NAME); | ||
281 | if (IS_ERR(omap_ipu_pm_class)) { | ||
282 | ret = PTR_ERR(omap_ipu_pm_class); | ||
283 | pr_err("%s: class_create failed: %d\n", __func__, ret); | ||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | /* create an instance of this device class */ | ||
288 | cdev_init(&ipu_pm_dev.cdev, &ipm_pm_fops); | ||
289 | ipu_pm_dev.cdev.owner = THIS_MODULE; | ||
290 | ipu_pm_dev.cdev.ops = &ipm_pm_fops; | ||
291 | ret = cdev_add(&ipu_pm_dev.cdev, omap_ipu_pm_dev, 1); | ||
292 | if (ret) | ||
293 | pr_err("%s: cdev_add failed: %d\n", __func__, omap_ipu_pm_dev); | ||
294 | |||
295 | tmpdev = device_create(omap_ipu_pm_class, NULL, | ||
296 | omap_ipu_pm_dev, | ||
297 | NULL, | ||
298 | "ipu%d", | ||
299 | MINOR(omap_ipu_pm_dev)); | ||
300 | |||
301 | if (IS_ERR(tmpdev)) { | ||
302 | ret = PTR_ERR(tmpdev); | ||
303 | pr_err("%s: device_create failed: %d\n", __func__, ret); | ||
304 | /* FIXME: add clean_cdev when error */ | ||
305 | /*goto clean_cdev;*/ | ||
306 | } | ||
307 | dev_info(tmpdev, "Test of writing to the device message log," | ||
308 | "done from %s\n", __func__); | ||
309 | |||
310 | pr_info("%s initialized %s, major: %d, minor: %d\n", | ||
311 | IPU_CLASS_NAME, | ||
312 | /*pdata->name,*/ | ||
313 | "ipu", | ||
314 | MAJOR(omap_ipu_pm_dev), | ||
315 | MINOR(omap_ipu_pm_dev)); | ||
316 | |||
317 | /* FIXME:add a kset pointing to this new class */ | ||
318 | /* omap_ipu_pm_class->dev_kobj */ | ||
319 | |||
320 | /* add proc interface */ | ||
321 | ipu_pm_proc_entry = create_proc_entry("ipu_proc_loads", 0, NULL); | ||
322 | if (ipu_pm_proc_entry) | ||
323 | ipu_pm_proc_entry->proc_fops = &ipu_pm_proc_ops; | ||
324 | else | ||
325 | pr_err("%s: proc entry create failed for: %s\n", | ||
326 | __func__, IPU_CLASS_NAME); | ||
327 | |||
328 | return platform_driver_register(&ipu_pm_driver); | ||
329 | } | ||
330 | |||
331 | static void __exit ipu_pm_exit(void) | ||
332 | { | ||
333 | platform_driver_unregister(&ipu_pm_driver); | ||
334 | } | ||
335 | |||
336 | /* early_platform_init("earlytimer", &ipu_pm_driver); */ | ||
337 | module_init(ipu_pm_init); | ||
338 | module_exit(ipu_pm_exit); | ||
339 | |||
340 | MODULE_DESCRIPTION("OMAP IMAGE PROCESSING UNIT POWER MGMT DRIVER"); | ||
341 | MODULE_LICENSE("GPL"); | ||
342 | MODULE_ALIAS("platform:" IPU_CLASS_NAME); | ||
343 | MODULE_AUTHOR("Texas Instruments Inc"); | ||
diff --git a/arch/arm/mach-omap2/ipu_utility.c b/arch/arm/mach-omap2/ipu_utility.c new file mode 100644 index 00000000000..b16b5ad891d --- /dev/null +++ b/arch/arm/mach-omap2/ipu_utility.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * OMAP IPU_PM utility | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments Inc. | ||
5 | * | ||
6 | * Written by Paul Hunt <hunt@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <plat/io.h> | ||
29 | |||
30 | #define ICONT1_ITCM_BASE 0x5A008000 | ||
31 | #define ICONT2_ITCM_BASE 0x5A018000 | ||
32 | |||
33 | static void __iomem *icont_itcm_ptr; | ||
34 | |||
35 | /* Op-codes for simple boot sequence ending in WFI */ | ||
36 | static const u32 ICONT_Boot_WFI[] = { | ||
37 | 0xEA000006, | ||
38 | 0xEAFFFFFE, | ||
39 | 0xEAFFFFFE, | ||
40 | 0xEAFFFFFE, | ||
41 | 0xEAFFFFFE, | ||
42 | 0xEAFFFFFE, | ||
43 | 0xEAFFFFFE, | ||
44 | 0xEAFFFFFE, | ||
45 | 0xE3A00000, | ||
46 | 0xEE070F9A, | ||
47 | 0xEE070F90, | ||
48 | 0xE3A00000, | ||
49 | 0xEAFFFFFE, | ||
50 | 0xEAFFFFF1, | ||
51 | }; | ||
52 | |||
53 | static const u32 ICONT_Boot_WFI_length = ARRAY_SIZE(ICONT_Boot_WFI); | ||
54 | |||
55 | static void load_ivahd_idle_boot_code(void) | ||
56 | { | ||
57 | int i; | ||
58 | |||
59 | icont_itcm_ptr = ioremap((u32) ICONT1_ITCM_BASE, 0x1000); | ||
60 | for (i = 0; i < ICONT_Boot_WFI_length; i++) | ||
61 | __raw_writel(ICONT_Boot_WFI[i], (icont_itcm_ptr + i)); | ||
62 | iounmap(icont_itcm_ptr); | ||
63 | |||
64 | icont_itcm_ptr = ioremap((u32) ICONT2_ITCM_BASE, 0x1000); | ||
65 | for (i = 0; i < ICONT_Boot_WFI_length; i++) | ||
66 | __raw_writel(ICONT_Boot_WFI[i], (icont_itcm_ptr + i)); | ||
67 | iounmap(icont_itcm_ptr); | ||
68 | } | ||
69 | EXPORT_SYMBOL(load_ivahd_idle_boot_code); | ||
diff --git a/arch/arm/plat-omap/include/plat/ipu_dev.h b/arch/arm/plat-omap/include/plat/ipu_dev.h new file mode 100644 index 00000000000..c7b7959c38b --- /dev/null +++ b/arch/arm/plat-omap/include/plat/ipu_dev.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * OMAP IPU_PM driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments Inc. | ||
5 | * | ||
6 | * Written by Paul Hunt <hunt@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef IPU_PM_H | ||
25 | #define IPU_PM_H | ||
26 | |||
27 | #include <linux/ioctl.h> | ||
28 | #include <linux/cdev.h> | ||
29 | |||
30 | #include "../../../drivers/dsp/syslink/ipu_pm/ipu_pm.h" | ||
31 | |||
32 | #define IPU_PM_IOC_MAGIC (0xDB) | ||
33 | |||
34 | /* magic char is irrelevant until trying to upstream | ||
35 | * except for reducing exposure to misdirected ioctls | ||
36 | * see Documentation/ioctl/ioctl-number.txt | ||
37 | */ | ||
38 | #define IPU_PM_IOC_SUSPEND _IOW(IPU_PM_IOC_MAGIC, 0, int) | ||
39 | #define IPU_PM_IOC_RESUME _IOW(IPU_PM_IOC_MAGIC, 1, int) | ||
40 | |||
41 | #define IPU_PM_IOC_MAXNR 3 | ||
42 | |||
43 | #define IPUPM_CAPS_START_BIT 0 | ||
44 | #define IPUPM_CAPS_STOP_BIT 1 | ||
45 | #define IPUPM_CAPS_PERF_BIT 2 | ||
46 | #define IPUPM_CAPS_LAT_BIT 3 | ||
47 | #define IPUPM_CAPS_BDW_BIT 4 | ||
48 | /* omap_device built elsewhere */ | ||
49 | #define IPUPM_CAPS_EXTINIT_BIT 5 | ||
50 | #define IPUPM_CAPS_START (1 << IPUPM_CAPS_START_BIT) | ||
51 | #define IPUPM_CAPS_STOP (1 << IPUPM_CAPS_STOP_BIT) | ||
52 | #define IPUPM_CAPS_PERF (1 << IPUPM_CAPS_PERF_BIT) | ||
53 | #define IPUPM_CAPS_LAT (1 << IPUPM_CAPS_LAT_BIT) | ||
54 | #define IPUPM_CAPS_BDW (1 << IPUPM_CAPS_BDW_BIT) | ||
55 | #define IPUPM_CAPS_EXTINIT (1 << IPUPM_CAPS_EXTINIT_BIT) | ||
56 | |||
57 | #define IPU_PM_SELF 100 | ||
58 | #define IPU_PM_MPU 101 | ||
59 | #define IPU_PM_CORE 102 | ||
60 | |||
61 | struct omap_ipupm_mod; | ||
62 | |||
63 | struct omap_ipupm_mod_ops { | ||
64 | int (*start)(enum res_type ipupm_modnum); | ||
65 | int (*stop)(enum res_type ipupm_modnum); | ||
66 | }; | ||
67 | |||
68 | struct omap_ipupm_mod_platform_data { | ||
69 | struct platform_device *pdev; | ||
70 | struct device *dev; | ||
71 | char *name; | ||
72 | char *oh_name; | ||
73 | struct omap_hwmod *oh; | ||
74 | struct kobject kobj; | ||
75 | u32 caps; | ||
76 | struct pm_qos_request_list *qos_request; | ||
77 | struct omap_ipupm_mod_ops *ops; | ||
78 | }; | ||
79 | |||
80 | struct omap_ipupm_mod { | ||
81 | struct device *dev; | ||
82 | struct cdev cdev; | ||
83 | atomic_t count; | ||
84 | int state; | ||
85 | int minor; | ||
86 | }; | ||
87 | |||
88 | struct ipu_pm_dev { | ||
89 | /* FIXME: maybe more is needed */ | ||
90 | struct cdev cdev; | ||
91 | }; | ||
92 | |||
93 | extern int ipu_pm_first_dev; | ||
94 | |||
95 | extern int ipu_pm_module_start(unsigned rsrc); | ||
96 | extern int ipu_pm_module_stop(unsigned rsrc); | ||
97 | extern int ipu_pm_module_set_rate(unsigned rsrc, | ||
98 | unsigned target_rsrc, | ||
99 | unsigned rate); | ||
100 | extern int ipu_pm_module_set_latency(unsigned rsrc, | ||
101 | unsigned target_rsrc, | ||
102 | int latency); | ||
103 | extern int ipu_pm_module_set_bandwidth(unsigned rsrc, | ||
104 | unsigned target_rsrc, | ||
105 | int bandwidth); | ||
106 | |||
107 | #endif /* IPU_PM_H */ | ||