aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2009-09-03 13:14:03 -0400
committerpaul <paul@twilight.(none)>2009-09-03 13:14:03 -0400
commit63c852384125ca0eff0e695f92cbbd439bed4aa3 (patch)
treead81b262c5b05aaa546ffdd4e43a3c31616f347f /arch
parentb3c6df3ab2b17cd7ddf927d39a64f235b25ac8d4 (diff)
OMAP2/3/4: create omap_hwmod layer
OMAP SoCs can be considered a collection of hardware IP blocks connected by various interconnects. The bus topology and device integration data is somewhat more complex than platform_device can encode. This patch creates code and structures to manage information about OMAP on-chip devices ("hardware modules") and their integration to the rest of the chip. Hardware module data is intended to be generated dynamically from the TI hardware database for the OMAP4 chips and beyond, easing Linux support for new chip variants. This code currently: - resets and configures all hardware modules upon startup, reducing bootloader dependencies; - provides hooks for Linux driver model code to enable, idle, and shutdown hardware modules (forthcoming patch); - waits for hardware modules to leave idle once their clocks are enabled and OCP_SYSCONFIG bits are set appropriately. - provides a means to pass arbitrary IP block configuration data (e.g., FIFO size) to the device driver (via the dev_attr void pointer) In the future this code is intended to: - estimate interconnect bandwidth and latency characteristics to ensure constraints are satisfied during DVFS - provide *GRPSEL bit data to the powerdomain code - handle pin/ball muxing for devices - generate IO mapping information dynamically - supply device firewall configuration data - provide hardware module data to other on-chip coprocessor software - allow the removal of the "disable unused clocks" code in the OMAP2/3 clock code This patch represents a collaborative effort involving many people from TI, Nokia, and the Linux-OMAP community. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Benoit Cousson <b-cousson@ti.com> Cc: Kevin Hilman <khilman@deeprootsystems.com> Cc: Tony Lindgren <tony@atomide.com> Cc: Rajendra Nayak <rnayak@ti.com> Cc: Vikram Pandita <vikram.pandita@ti.com> Cc: Sakari Poussa <sakari.poussa@nokia.com> Cc: Anand Sawant <sawant@ti.com> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com> Cc: Eric Thomas <ethomas@ti.com> Cc: Richard Woodruff <r-woodruff2@ti.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/Makefile2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c1555
-rw-r--r--arch/arm/plat-omap/include/mach/omap_hwmod.h447
3 files changed, 2003 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 59d730fa77e5..8cb16777661a 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -5,7 +5,7 @@
5# Common support 5# Common support
6obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o 6obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
7 7
8omap-2-3-common = irq.o sdrc.o 8omap-2-3-common = irq.o sdrc.o omap_hwmod.o
9prcm-common = prcm.o powerdomain.o 9prcm-common = prcm.o powerdomain.o
10clock-common = clock.o clockdomain.o 10clock-common = clock.o clockdomain.o
11 11
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
new file mode 100644
index 000000000000..3b10ad6c47d3
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -0,0 +1,1555 @@
1/*
2 * omap_hwmod implementation for OMAP2/3/4
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Paul Walmsley
6 * With fixes and testing from Kevin Hilman
7 *
8 * Created in collaboration with (alphabetical order): Benoit Cousson,
9 * Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari
10 * Poussa, Anand Sawant, Santosh Shilimkar, Richard Woodruff
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This code manages "OMAP modules" (on-chip devices) and their
17 * integration with Linux device driver and bus code.
18 *
19 * References:
20 * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
21 * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
22 * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
23 * - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
24 * - Open Core Protocol Specification 2.2
25 *
26 * To do:
27 * - pin mux handling
28 * - handle IO mapping
29 * - bus throughput & module latency measurement code
30 *
31 * XXX add tests at the beginning of each function to ensure the hwmod is
32 * in the appropriate state
33 * XXX error return values should be checked to ensure that they are
34 * appropriate
35 */
36#undef DEBUG
37
38#include <linux/kernel.h>
39#include <linux/errno.h>
40#include <linux/io.h>
41#include <linux/clk.h>
42#include <linux/delay.h>
43#include <linux/err.h>
44#include <linux/list.h>
45#include <linux/mutex.h>
46#include <linux/bootmem.h>
47
48#include <mach/cpu.h>
49#include <mach/clockdomain.h>
50#include <mach/powerdomain.h>
51#include <mach/clock.h>
52#include <mach/omap_hwmod.h>
53
54#include "cm.h"
55
56/* Maximum microseconds to wait for OMAP module to reset */
57#define MAX_MODULE_RESET_WAIT 10000
58
59/* Name of the OMAP hwmod for the MPU */
60#define MPU_INITIATOR_NAME "mpu_hwmod"
61
62/* omap_hwmod_list contains all registered struct omap_hwmods */
63static LIST_HEAD(omap_hwmod_list);
64
65static DEFINE_MUTEX(omap_hwmod_mutex);
66
67/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
68static struct omap_hwmod *mpu_oh;
69
70/* inited: 0 if omap_hwmod_init() has not yet been called; 1 otherwise */
71static u8 inited;
72
73
74/* Private functions */
75
76/**
77 * _update_sysc_cache - return the module OCP_SYSCONFIG register, keep copy
78 * @oh: struct omap_hwmod *
79 *
80 * Load the current value of the hwmod OCP_SYSCONFIG register into the
81 * struct omap_hwmod for later use. Returns -EINVAL if the hwmod has no
82 * OCP_SYSCONFIG register or 0 upon success.
83 */
84static int _update_sysc_cache(struct omap_hwmod *oh)
85{
86 if (!oh->sysconfig) {
87 WARN(!oh->sysconfig, "omap_hwmod: %s: cannot read "
88 "OCP_SYSCONFIG: not defined on hwmod\n", oh->name);
89 return -EINVAL;
90 }
91
92 /* XXX ensure module interface clock is up */
93
94 oh->_sysc_cache = omap_hwmod_readl(oh, oh->sysconfig->sysc_offs);
95
96 oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
97
98 return 0;
99}
100
101/**
102 * _write_sysconfig - write a value to the module's OCP_SYSCONFIG register
103 * @v: OCP_SYSCONFIG value to write
104 * @oh: struct omap_hwmod *
105 *
106 * Write @v into the module OCP_SYSCONFIG register, if it has one. No
107 * return value.
108 */
109static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
110{
111 if (!oh->sysconfig) {
112 WARN(!oh->sysconfig, "omap_hwmod: %s: cannot write "
113 "OCP_SYSCONFIG: not defined on hwmod\n", oh->name);
114 return;
115 }
116
117 /* XXX ensure module interface clock is up */
118
119 if (oh->_sysc_cache != v) {
120 oh->_sysc_cache = v;
121 omap_hwmod_writel(v, oh, oh->sysconfig->sysc_offs);
122 }
123}
124
125/**
126 * _set_master_standbymode: set the OCP_SYSCONFIG MIDLEMODE field in @v
127 * @oh: struct omap_hwmod *
128 * @standbymode: MIDLEMODE field bits
129 * @v: pointer to register contents to modify
130 *
131 * Update the master standby mode bits in @v to be @standbymode for
132 * the @oh hwmod. Does not write to the hardware. Returns -EINVAL
133 * upon error or 0 upon success.
134 */
135static int _set_master_standbymode(struct omap_hwmod *oh, u8 standbymode,
136 u32 *v)
137{
138 if (!oh->sysconfig ||
139 !(oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE))
140 return -EINVAL;
141
142 *v &= ~SYSC_MIDLEMODE_MASK;
143 *v |= __ffs(standbymode) << SYSC_MIDLEMODE_SHIFT;
144
145 return 0;
146}
147
148/**
149 * _set_slave_idlemode: set the OCP_SYSCONFIG SIDLEMODE field in @v
150 * @oh: struct omap_hwmod *
151 * @idlemode: SIDLEMODE field bits
152 * @v: pointer to register contents to modify
153 *
154 * Update the slave idle mode bits in @v to be @idlemode for the @oh
155 * hwmod. Does not write to the hardware. Returns -EINVAL upon error
156 * or 0 upon success.
157 */
158static int _set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode, u32 *v)
159{
160 if (!oh->sysconfig ||
161 !(oh->sysconfig->sysc_flags & SYSC_HAS_SIDLEMODE))
162 return -EINVAL;
163
164 *v &= ~SYSC_SIDLEMODE_MASK;
165 *v |= __ffs(idlemode) << SYSC_SIDLEMODE_SHIFT;
166
167 return 0;
168}
169
170/**
171 * _set_clockactivity: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
172 * @oh: struct omap_hwmod *
173 * @clockact: CLOCKACTIVITY field bits
174 * @v: pointer to register contents to modify
175 *
176 * Update the clockactivity mode bits in @v to be @clockact for the
177 * @oh hwmod. Used for additional powersaving on some modules. Does
178 * not write to the hardware. Returns -EINVAL upon error or 0 upon
179 * success.
180 */
181static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
182{
183 if (!oh->sysconfig ||
184 !(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY))
185 return -EINVAL;
186
187 *v &= ~SYSC_CLOCKACTIVITY_MASK;
188 *v |= clockact << SYSC_CLOCKACTIVITY_SHIFT;
189
190 return 0;
191}
192
193/**
194 * _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
195 * @oh: struct omap_hwmod *
196 * @v: pointer to register contents to modify
197 *
198 * Set the SOFTRESET bit in @v for hwmod @oh. Returns -EINVAL upon
199 * error or 0 upon success.
200 */
201static int _set_softreset(struct omap_hwmod *oh, u32 *v)
202{
203 if (!oh->sysconfig ||
204 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET))
205 return -EINVAL;
206
207 *v |= SYSC_SOFTRESET_MASK;
208
209 return 0;
210}
211
212/**
213 * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
214 * @oh: struct omap_hwmod *
215 *
216 * Allow the hardware module @oh to send wakeups. Returns -EINVAL
217 * upon error or 0 upon success.
218 */
219static int _enable_wakeup(struct omap_hwmod *oh)
220{
221 u32 v;
222
223 if (!oh->sysconfig ||
224 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
225 return -EINVAL;
226
227 v = oh->_sysc_cache;
228 v |= SYSC_ENAWAKEUP_MASK;
229 _write_sysconfig(v, oh);
230
231 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
232
233 oh->_int_flags |= _HWMOD_WAKEUP_ENABLED;
234
235 return 0;
236}
237
238/**
239 * _disable_wakeup: clear OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
240 * @oh: struct omap_hwmod *
241 *
242 * Prevent the hardware module @oh to send wakeups. Returns -EINVAL
243 * upon error or 0 upon success.
244 */
245static int _disable_wakeup(struct omap_hwmod *oh)
246{
247 u32 v;
248
249 if (!oh->sysconfig ||
250 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
251 return -EINVAL;
252
253 v = oh->_sysc_cache;
254 v &= ~SYSC_ENAWAKEUP_MASK;
255 _write_sysconfig(v, oh);
256
257 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
258
259 oh->_int_flags &= ~_HWMOD_WAKEUP_ENABLED;
260
261 return 0;
262}
263
264/**
265 * _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active
266 * @oh: struct omap_hwmod *
267 *
268 * Prevent the hardware module @oh from entering idle while the
269 * hardare module initiator @init_oh is active. Useful when a module
270 * will be accessed by a particular initiator (e.g., if a module will
271 * be accessed by the IVA, there should be a sleepdep between the IVA
272 * initiator and the module). Only applies to modules in smart-idle
273 * mode. Returns -EINVAL upon error or passes along
274 * pwrdm_add_sleepdep() value upon success.
275 */
276static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
277{
278 if (!oh->_clk)
279 return -EINVAL;
280
281 return pwrdm_add_sleepdep(oh->_clk->clkdm->pwrdm.ptr,
282 init_oh->_clk->clkdm->pwrdm.ptr);
283}
284
285/**
286 * _del_initiator_dep: allow @oh to smart-idle even if @init_oh is active
287 * @oh: struct omap_hwmod *
288 *
289 * Allow the hardware module @oh to enter idle while the hardare
290 * module initiator @init_oh is active. Useful when a module will not
291 * be accessed by a particular initiator (e.g., if a module will not
292 * be accessed by the IVA, there should be no sleepdep between the IVA
293 * initiator and the module). Only applies to modules in smart-idle
294 * mode. Returns -EINVAL upon error or passes along
295 * pwrdm_add_sleepdep() value upon success.
296 */
297static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
298{
299 if (!oh->_clk)
300 return -EINVAL;
301
302 return pwrdm_del_sleepdep(oh->_clk->clkdm->pwrdm.ptr,
303 init_oh->_clk->clkdm->pwrdm.ptr);
304}
305
306/**
307 * _init_main_clk - get a struct clk * for the the hwmod's main functional clk
308 * @oh: struct omap_hwmod *
309 *
310 * Called from _init_clocks(). Populates the @oh _clk (main
311 * functional clock pointer) if a main_clk is present. Returns 0 on
312 * success or -EINVAL on error.
313 */
314static int _init_main_clk(struct omap_hwmod *oh)
315{
316 struct clk *c;
317 int ret = 0;
318
319 if (!oh->clkdev_con_id)
320 return 0;
321
322 c = clk_get_sys(oh->clkdev_dev_id, oh->clkdev_con_id);
323 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get main_clk %s.%s\n",
324 oh->name, oh->clkdev_dev_id, oh->clkdev_con_id);
325 if (IS_ERR(c))
326 ret = -EINVAL;
327 oh->_clk = c;
328
329 return ret;
330}
331
332/**
333 * _init_interface_clk - get a struct clk * for the the hwmod's interface clks
334 * @oh: struct omap_hwmod *
335 *
336 * Called from _init_clocks(). Populates the @oh OCP slave interface
337 * clock pointers. Returns 0 on success or -EINVAL on error.
338 */
339static int _init_interface_clks(struct omap_hwmod *oh)
340{
341 struct omap_hwmod_ocp_if *os;
342 struct clk *c;
343 int i;
344 int ret = 0;
345
346 if (oh->slaves_cnt == 0)
347 return 0;
348
349 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
350 if (!os->clkdev_con_id)
351 continue;
352
353 c = clk_get_sys(os->clkdev_dev_id, os->clkdev_con_id);
354 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get "
355 "interface_clk %s.%s\n", oh->name,
356 os->clkdev_dev_id, os->clkdev_con_id);
357 if (IS_ERR(c))
358 ret = -EINVAL;
359 os->_clk = c;
360 }
361
362 return ret;
363}
364
365/**
366 * _init_opt_clk - get a struct clk * for the the hwmod's optional clocks
367 * @oh: struct omap_hwmod *
368 *
369 * Called from _init_clocks(). Populates the @oh omap_hwmod_opt_clk
370 * clock pointers. Returns 0 on success or -EINVAL on error.
371 */
372static int _init_opt_clks(struct omap_hwmod *oh)
373{
374 struct omap_hwmod_opt_clk *oc;
375 struct clk *c;
376 int i;
377 int ret = 0;
378
379 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
380 c = clk_get_sys(oc->clkdev_dev_id, oc->clkdev_con_id);
381 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get opt_clk "
382 "%s.%s\n", oh->name, oc->clkdev_dev_id,
383 oc->clkdev_con_id);
384 if (IS_ERR(c))
385 ret = -EINVAL;
386 oc->_clk = c;
387 }
388
389 return ret;
390}
391
392/**
393 * _enable_clocks - enable hwmod main clock and interface clocks
394 * @oh: struct omap_hwmod *
395 *
396 * Enables all clocks necessary for register reads and writes to succeed
397 * on the hwmod @oh. Returns 0.
398 */
399static int _enable_clocks(struct omap_hwmod *oh)
400{
401 struct omap_hwmod_ocp_if *os;
402 int i;
403
404 pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
405
406 if (oh->_clk && !IS_ERR(oh->_clk))
407 clk_enable(oh->_clk);
408
409 if (oh->slaves_cnt > 0) {
410 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
411 struct clk *c = os->_clk;
412
413 if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE))
414 clk_enable(c);
415 }
416 }
417
418 /* The opt clocks are controlled by the device driver. */
419
420 return 0;
421}
422
423/**
424 * _disable_clocks - disable hwmod main clock and interface clocks
425 * @oh: struct omap_hwmod *
426 *
427 * Disables the hwmod @oh main functional and interface clocks. Returns 0.
428 */
429static int _disable_clocks(struct omap_hwmod *oh)
430{
431 struct omap_hwmod_ocp_if *os;
432 int i;
433
434 pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
435
436 if (oh->_clk && !IS_ERR(oh->_clk))
437 clk_disable(oh->_clk);
438
439 if (oh->slaves_cnt > 0) {
440 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
441 struct clk *c = os->_clk;
442
443 if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE))
444 clk_disable(c);
445 }
446 }
447
448 /* The opt clocks are controlled by the device driver. */
449
450 return 0;
451}
452
453/**
454 * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
455 * @oh: struct omap_hwmod *
456 *
457 * Returns the array index of the OCP slave port that the MPU
458 * addresses the device on, or -EINVAL upon error or not found.
459 */
460static int _find_mpu_port_index(struct omap_hwmod *oh)
461{
462 struct omap_hwmod_ocp_if *os;
463 int i;
464 int found = 0;
465
466 if (!oh || oh->slaves_cnt == 0)
467 return -EINVAL;
468
469 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
470 if (os->user & OCP_USER_MPU) {
471 found = 1;
472 break;
473 }
474 }
475
476 if (found)
477 pr_debug("omap_hwmod: %s: MPU OCP slave port ID %d\n",
478 oh->name, i);
479 else
480 pr_debug("omap_hwmod: %s: no MPU OCP slave port found\n",
481 oh->name);
482
483 return (found) ? i : -EINVAL;
484}
485
486/**
487 * _find_mpu_rt_base - find hwmod register target base addr accessible by MPU
488 * @oh: struct omap_hwmod *
489 *
490 * Return the virtual address of the base of the register target of
491 * device @oh, or NULL on error.
492 */
493static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
494{
495 struct omap_hwmod_ocp_if *os;
496 struct omap_hwmod_addr_space *mem;
497 int i;
498 int found = 0;
499
500 if (!oh || oh->slaves_cnt == 0)
501 return NULL;
502
503 os = *oh->slaves + index;
504
505 for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) {
506 if (mem->flags & ADDR_TYPE_RT) {
507 found = 1;
508 break;
509 }
510 }
511
512 /* XXX use ioremap() instead? */
513
514 if (found)
515 pr_debug("omap_hwmod: %s: MPU register target at va %p\n",
516 oh->name, OMAP2_IO_ADDRESS(mem->pa_start));
517 else
518 pr_debug("omap_hwmod: %s: no MPU register target found\n",
519 oh->name);
520
521 return (found) ? OMAP2_IO_ADDRESS(mem->pa_start) : NULL;
522}
523
524/**
525 * _sysc_enable - try to bring a module out of idle via OCP_SYSCONFIG
526 * @oh: struct omap_hwmod *
527 *
528 * If module is marked as SWSUP_SIDLE, force the module out of slave
529 * idle; otherwise, configure it for smart-idle. If module is marked
530 * as SWSUP_MSUSPEND, force the module out of master standby;
531 * otherwise, configure it for smart-standby. No return value.
532 */
533static void _sysc_enable(struct omap_hwmod *oh)
534{
535 u8 idlemode;
536 u32 v;
537
538 if (!oh->sysconfig)
539 return;
540
541 v = oh->_sysc_cache;
542
543 if (oh->sysconfig->sysc_flags & SYSC_HAS_SIDLEMODE) {
544 idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
545 HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
546 _set_slave_idlemode(oh, idlemode, &v);
547 }
548
549 if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE) {
550 idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
551 HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
552 _set_master_standbymode(oh, idlemode, &v);
553 }
554
555 /* XXX OCP AUTOIDLE bit? */
556
557 if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT &&
558 oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY)
559 _set_clockactivity(oh, oh->sysconfig->clockact, &v);
560
561 _write_sysconfig(v, oh);
562}
563
564/**
565 * _sysc_idle - try to put a module into idle via OCP_SYSCONFIG
566 * @oh: struct omap_hwmod *
567 *
568 * If module is marked as SWSUP_SIDLE, force the module into slave
569 * idle; otherwise, configure it for smart-idle. If module is marked
570 * as SWSUP_MSUSPEND, force the module into master standby; otherwise,
571 * configure it for smart-standby. No return value.
572 */
573static void _sysc_idle(struct omap_hwmod *oh)
574{
575 u8 idlemode;
576 u32 v;
577
578 if (!oh->sysconfig)
579 return;
580
581 v = oh->_sysc_cache;
582
583 if (oh->sysconfig->sysc_flags & SYSC_HAS_SIDLEMODE) {
584 idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
585 HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART;
586 _set_slave_idlemode(oh, idlemode, &v);
587 }
588
589 if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE) {
590 idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
591 HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART;
592 _set_master_standbymode(oh, idlemode, &v);
593 }
594
595 _write_sysconfig(v, oh);
596}
597
598/**
599 * _sysc_shutdown - force a module into idle via OCP_SYSCONFIG
600 * @oh: struct omap_hwmod *
601 *
602 * Force the module into slave idle and master suspend. No return
603 * value.
604 */
605static void _sysc_shutdown(struct omap_hwmod *oh)
606{
607 u32 v;
608
609 if (!oh->sysconfig)
610 return;
611
612 v = oh->_sysc_cache;
613
614 if (oh->sysconfig->sysc_flags & SYSC_HAS_SIDLEMODE)
615 _set_slave_idlemode(oh, HWMOD_IDLEMODE_FORCE, &v);
616
617 if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE)
618 _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v);
619
620 /* XXX clear OCP AUTOIDLE bit? */
621
622 _write_sysconfig(v, oh);
623}
624
625/**
626 * _lookup - find an omap_hwmod by name
627 * @name: find an omap_hwmod by name
628 *
629 * Return a pointer to an omap_hwmod by name, or NULL if not found.
630 * Caller must hold omap_hwmod_mutex.
631 */
632static struct omap_hwmod *_lookup(const char *name)
633{
634 struct omap_hwmod *oh, *temp_oh;
635
636 oh = NULL;
637
638 list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
639 if (!strcmp(name, temp_oh->name)) {
640 oh = temp_oh;
641 break;
642 }
643 }
644
645 return oh;
646}
647
648/**
649 * _init_clocks - clk_get() all clocks associated with this hwmod
650 * @oh: struct omap_hwmod *
651 *
652 * Called by omap_hwmod_late_init() (after omap2_clk_init()).
653 * Resolves all clock names embedded in the hwmod. Must be called
654 * with omap_hwmod_mutex held. Returns -EINVAL if the omap_hwmod
655 * has not yet been registered or if the clocks have already been
656 * initialized, 0 on success, or a non-zero error on failure.
657 */
658static int _init_clocks(struct omap_hwmod *oh)
659{
660 int ret = 0;
661
662 if (!oh || (oh->_state != _HWMOD_STATE_REGISTERED))
663 return -EINVAL;
664
665 pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
666
667 ret |= _init_main_clk(oh);
668 ret |= _init_interface_clks(oh);
669 ret |= _init_opt_clks(oh);
670
671 oh->_state = _HWMOD_STATE_CLKS_INITED;
672
673 return ret;
674}
675
676/**
677 * _wait_target_ready - wait for a module to leave slave idle
678 * @oh: struct omap_hwmod *
679 *
680 * Wait for a module @oh to leave slave idle. Returns 0 if the module
681 * does not have an IDLEST bit or if the module successfully leaves
682 * slave idle; otherwise, pass along the return value of the
683 * appropriate *_cm_wait_module_ready() function.
684 */
685static int _wait_target_ready(struct omap_hwmod *oh)
686{
687 struct omap_hwmod_ocp_if *os;
688 int ret;
689
690 if (!oh)
691 return -EINVAL;
692
693 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
694 return 0;
695
696 os = *oh->slaves + oh->_mpu_port_index;
697
698 if (!(os->flags & OCPIF_HAS_IDLEST))
699 return 0;
700
701 /* XXX check module SIDLEMODE */
702
703 /* XXX check clock enable states */
704
705 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
706 ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
707 oh->prcm.omap2.idlest_reg_id,
708 oh->prcm.omap2.idlest_idle_bit);
709#if 0
710 } else if (cpu_is_omap44xx()) {
711 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.module_offs,
712 oh->prcm.omap4.device_offs);
713#endif
714 } else {
715 BUG();
716 };
717
718 return ret;
719}
720
721/**
722 * _reset - reset an omap_hwmod
723 * @oh: struct omap_hwmod *
724 *
725 * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
726 * enabled for this to work. Must be called with omap_hwmod_mutex
727 * held. Returns -EINVAL if the hwmod cannot be reset this way or if
728 * the hwmod is in the wrong state, -ETIMEDOUT if the module did not
729 * reset in time, or 0 upon success.
730 */
731static int _reset(struct omap_hwmod *oh)
732{
733 u32 r, v;
734 int c;
735
736 if (!oh->sysconfig ||
737 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET) ||
738 (oh->sysconfig->sysc_flags & SYSS_MISSING))
739 return -EINVAL;
740
741 /* clocks must be on for this operation */
742 if (oh->_state != _HWMOD_STATE_ENABLED) {
743 WARN(1, "omap_hwmod: %s: reset can only be entered from "
744 "enabled state\n", oh->name);
745 return -EINVAL;
746 }
747
748 pr_debug("omap_hwmod: %s: resetting\n", oh->name);
749
750 v = oh->_sysc_cache;
751 r = _set_softreset(oh, &v);
752 if (r)
753 return r;
754 _write_sysconfig(v, oh);
755
756 c = 0;
757 while (c < MAX_MODULE_RESET_WAIT &&
758 !(omap_hwmod_readl(oh, oh->sysconfig->syss_offs) &
759 SYSS_RESETDONE_MASK)) {
760 udelay(1);
761 c++;
762 }
763
764 if (c == MAX_MODULE_RESET_WAIT)
765 WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
766 oh->name, MAX_MODULE_RESET_WAIT);
767 else
768 pr_debug("omap_hwmod: %s: reset in %d usec\n", oh->name,
769 MAX_MODULE_RESET_WAIT);
770
771 /*
772 * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
773 * _wait_target_ready() or _reset()
774 */
775
776 return (c == MAX_MODULE_RESET_WAIT) ? -ETIMEDOUT : 0;
777}
778
779/**
780 * _enable - enable an omap_hwmod
781 * @oh: struct omap_hwmod *
782 *
783 * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
784 * register target. Must be called with omap_hwmod_mutex held.
785 * Returns -EINVAL if the hwmod is in the wrong state or passes along
786 * the return value of _wait_target_ready().
787 */
788static int _enable(struct omap_hwmod *oh)
789{
790 int r;
791
792 if (oh->_state != _HWMOD_STATE_INITIALIZED &&
793 oh->_state != _HWMOD_STATE_IDLE &&
794 oh->_state != _HWMOD_STATE_DISABLED) {
795 WARN(1, "omap_hwmod: %s: enabled state can only be entered "
796 "from initialized, idle, or disabled state\n", oh->name);
797 return -EINVAL;
798 }
799
800 pr_debug("omap_hwmod: %s: enabling\n", oh->name);
801
802 /* XXX mux balls */
803
804 _add_initiator_dep(oh, mpu_oh);
805 _enable_clocks(oh);
806
807 if (oh->sysconfig) {
808 if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
809 _update_sysc_cache(oh);
810 _sysc_enable(oh);
811 }
812
813 r = _wait_target_ready(oh);
814 if (!r)
815 oh->_state = _HWMOD_STATE_ENABLED;
816
817 return r;
818}
819
820/**
821 * _idle - idle an omap_hwmod
822 * @oh: struct omap_hwmod *
823 *
824 * Idles an omap_hwmod @oh. This should be called once the hwmod has
825 * no further work. Returns -EINVAL if the hwmod is in the wrong
826 * state or returns 0.
827 */
828static int _idle(struct omap_hwmod *oh)
829{
830 if (oh->_state != _HWMOD_STATE_ENABLED) {
831 WARN(1, "omap_hwmod: %s: idle state can only be entered from "
832 "enabled state\n", oh->name);
833 return -EINVAL;
834 }
835
836 pr_debug("omap_hwmod: %s: idling\n", oh->name);
837
838 if (oh->sysconfig)
839 _sysc_idle(oh);
840 _del_initiator_dep(oh, mpu_oh);
841 _disable_clocks(oh);
842
843 oh->_state = _HWMOD_STATE_IDLE;
844
845 return 0;
846}
847
848/**
849 * _shutdown - shutdown an omap_hwmod
850 * @oh: struct omap_hwmod *
851 *
852 * Shut down an omap_hwmod @oh. This should be called when the driver
853 * used for the hwmod is removed or unloaded or if the driver is not
854 * used by the system. Returns -EINVAL if the hwmod is in the wrong
855 * state or returns 0.
856 */
857static int _shutdown(struct omap_hwmod *oh)
858{
859 if (oh->_state != _HWMOD_STATE_IDLE &&
860 oh->_state != _HWMOD_STATE_ENABLED) {
861 WARN(1, "omap_hwmod: %s: disabled state can only be entered "
862 "from idle, or enabled state\n", oh->name);
863 return -EINVAL;
864 }
865
866 pr_debug("omap_hwmod: %s: disabling\n", oh->name);
867
868 if (oh->sysconfig)
869 _sysc_shutdown(oh);
870 _del_initiator_dep(oh, mpu_oh);
871 /* XXX what about the other system initiators here? DMA, tesla, d2d */
872 _disable_clocks(oh);
873 /* XXX Should this code also force-disable the optional clocks? */
874
875 /* XXX mux any associated balls to safe mode */
876
877 oh->_state = _HWMOD_STATE_DISABLED;
878
879 return 0;
880}
881
882/**
883 * _write_clockact_lock - set the module's clockactivity bits
884 * @oh: struct omap_hwmod *
885 * @clockact: CLOCKACTIVITY field bits
886 *
887 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
888 * OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the
889 * wrong state or returns 0.
890 */
891static int _write_clockact_lock(struct omap_hwmod *oh, u8 clockact)
892{
893 u32 v;
894
895 if (!oh->sysconfig ||
896 !(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY))
897 return -EINVAL;
898
899 mutex_lock(&omap_hwmod_mutex);
900 v = oh->_sysc_cache;
901 _set_clockactivity(oh, clockact, &v);
902 _write_sysconfig(v, oh);
903 mutex_unlock(&omap_hwmod_mutex);
904
905 return 0;
906}
907
908
909/**
910 * _setup - do initial configuration of omap_hwmod
911 * @oh: struct omap_hwmod *
912 *
913 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
914 * OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex
915 * held. Returns -EINVAL if the hwmod is in the wrong state or returns
916 * 0.
917 */
918static int _setup(struct omap_hwmod *oh)
919{
920 struct omap_hwmod_ocp_if *os;
921 int i;
922
923 if (!oh)
924 return -EINVAL;
925
926 /* Set iclk autoidle mode */
927 if (oh->slaves_cnt > 0) {
928 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
929 struct clk *c = os->_clk;
930
931 if (!c || IS_ERR(c))
932 continue;
933
934 if (os->flags & OCPIF_SWSUP_IDLE) {
935 /* XXX omap_iclk_deny_idle(c); */
936 } else {
937 /* XXX omap_iclk_allow_idle(c); */
938 clk_enable(c);
939 }
940 }
941 }
942
943 oh->_state = _HWMOD_STATE_INITIALIZED;
944
945 _enable(oh);
946
947 if (!(oh->flags & HWMOD_INIT_NO_RESET))
948 _reset(oh);
949
950 /* XXX OCP AUTOIDLE bit? */
951 /* XXX OCP ENAWAKEUP bit? */
952
953 if (!(oh->flags & HWMOD_INIT_NO_IDLE))
954 _idle(oh);
955
956 return 0;
957}
958
959
960
961/* Public functions */
962
963u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs)
964{
965 return __raw_readl(oh->_rt_va + reg_offs);
966}
967
968void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs)
969{
970 __raw_writel(v, oh->_rt_va + reg_offs);
971}
972
973/**
974 * omap_hwmod_register - register a struct omap_hwmod
975 * @oh: struct omap_hwmod *
976 *
977 * Registers the omap_hwmod @oh. Returns -EEXIST if an omap_hwmod already
978 * has been registered by the same name; -EINVAL if the omap_hwmod is in the
979 * wrong state, or 0 on success.
980 *
981 * XXX The data should be copied into bootmem, so the original data
982 * should be marked __initdata and freed after init. This would allow
983 * unneeded omap_hwmods to be freed on multi-OMAP configurations. Note
984 * that the copy process would be relatively complex due to the large number
985 * of substructures.
986 */
987int omap_hwmod_register(struct omap_hwmod *oh)
988{
989 int ret, ms_id;
990
991 if (!oh || (oh->_state != _HWMOD_STATE_UNKNOWN))
992 return -EINVAL;
993
994 mutex_lock(&omap_hwmod_mutex);
995
996 pr_debug("omap_hwmod: %s: registering\n", oh->name);
997
998 if (_lookup(oh->name)) {
999 ret = -EEXIST;
1000 goto ohr_unlock;
1001 }
1002
1003 ms_id = _find_mpu_port_index(oh);
1004 if (!IS_ERR_VALUE(ms_id)) {
1005 oh->_mpu_port_index = ms_id;
1006 oh->_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
1007 } else {
1008 oh->_int_flags |= _HWMOD_NO_MPU_PORT;
1009 }
1010
1011 list_add_tail(&oh->node, &omap_hwmod_list);
1012
1013 oh->_state = _HWMOD_STATE_REGISTERED;
1014
1015 ret = 0;
1016
1017ohr_unlock:
1018 mutex_unlock(&omap_hwmod_mutex);
1019 return ret;
1020}
1021
1022/**
1023 * omap_hwmod_lookup - look up a registered omap_hwmod by name
1024 * @name: name of the omap_hwmod to look up
1025 *
1026 * Given a @name of an omap_hwmod, return a pointer to the registered
1027 * struct omap_hwmod *, or NULL upon error.
1028 */
1029struct omap_hwmod *omap_hwmod_lookup(const char *name)
1030{
1031 struct omap_hwmod *oh;
1032
1033 if (!name)
1034 return NULL;
1035
1036 mutex_lock(&omap_hwmod_mutex);
1037 oh = _lookup(name);
1038 mutex_unlock(&omap_hwmod_mutex);
1039
1040 return oh;
1041}
1042
1043/**
1044 * omap_hwmod_for_each - call function for each registered omap_hwmod
1045 * @fn: pointer to a callback function
1046 *
1047 * Call @fn for each registered omap_hwmod, passing @data to each
1048 * function. @fn must return 0 for success or any other value for
1049 * failure. If @fn returns non-zero, the iteration across omap_hwmods
1050 * will stop and the non-zero return value will be passed to the
1051 * caller of omap_hwmod_for_each(). @fn is called with
1052 * omap_hwmod_for_each() held.
1053 */
1054int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh))
1055{
1056 struct omap_hwmod *temp_oh;
1057 int ret;
1058
1059 if (!fn)
1060 return -EINVAL;
1061
1062 mutex_lock(&omap_hwmod_mutex);
1063 list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
1064 ret = (*fn)(temp_oh);
1065 if (ret)
1066 break;
1067 }
1068 mutex_unlock(&omap_hwmod_mutex);
1069
1070 return ret;
1071}
1072
1073
1074/**
1075 * omap_hwmod_init - init omap_hwmod code and register hwmods
1076 * @ohs: pointer to an array of omap_hwmods to register
1077 *
1078 * Intended to be called early in boot before the clock framework is
1079 * initialized. If @ohs is not null, will register all omap_hwmods
1080 * listed in @ohs that are valid for this chip. Returns -EINVAL if
1081 * omap_hwmod_init() has already been called or 0 otherwise.
1082 */
1083int omap_hwmod_init(struct omap_hwmod **ohs)
1084{
1085 struct omap_hwmod *oh;
1086 int r;
1087
1088 if (inited)
1089 return -EINVAL;
1090
1091 inited = 1;
1092
1093 if (!ohs)
1094 return 0;
1095
1096 oh = *ohs;
1097 while (oh) {
1098 if (omap_chip_is(oh->omap_chip)) {
1099 r = omap_hwmod_register(oh);
1100 WARN(r, "omap_hwmod: %s: omap_hwmod_register returned "
1101 "%d\n", oh->name, r);
1102 }
1103 oh = *++ohs;
1104 }
1105
1106 return 0;
1107}
1108
1109/**
1110 * omap_hwmod_late_init - do some post-clock framework initialization
1111 *
1112 * Must be called after omap2_clk_init(). Resolves the struct clk names
1113 * to struct clk pointers for each registered omap_hwmod. Also calls
1114 * _setup() on each hwmod. Returns 0.
1115 */
1116int omap_hwmod_late_init(void)
1117{
1118 int r;
1119
1120 /* XXX check return value */
1121 r = omap_hwmod_for_each(_init_clocks);
1122 WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n");
1123
1124 mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME);
1125 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
1126 MPU_INITIATOR_NAME);
1127
1128 omap_hwmod_for_each(_setup);
1129
1130 return 0;
1131}
1132
1133/**
1134 * omap_hwmod_unregister - unregister an omap_hwmod
1135 * @oh: struct omap_hwmod *
1136 *
1137 * Unregisters a previously-registered omap_hwmod @oh. There's probably
1138 * no use case for this, so it is likely to be removed in a later version.
1139 *
1140 * XXX Free all of the bootmem-allocated structures here when that is
1141 * implemented. Make it clear that core code is the only code that is
1142 * expected to unregister modules.
1143 */
1144int omap_hwmod_unregister(struct omap_hwmod *oh)
1145{
1146 if (!oh)
1147 return -EINVAL;
1148
1149 pr_debug("omap_hwmod: %s: unregistering\n", oh->name);
1150
1151 mutex_lock(&omap_hwmod_mutex);
1152 list_del(&oh->node);
1153 mutex_unlock(&omap_hwmod_mutex);
1154
1155 return 0;
1156}
1157
1158/**
1159 * omap_hwmod_enable - enable an omap_hwmod
1160 * @oh: struct omap_hwmod *
1161 *
1162 * Enable an omap_hwomd @oh. Intended to be called by omap_device_enable().
1163 * Returns -EINVAL on error or passes along the return value from _enable().
1164 */
1165int omap_hwmod_enable(struct omap_hwmod *oh)
1166{
1167 int r;
1168
1169 if (!oh)
1170 return -EINVAL;
1171
1172 mutex_lock(&omap_hwmod_mutex);
1173 r = _enable(oh);
1174 mutex_unlock(&omap_hwmod_mutex);
1175
1176 return r;
1177}
1178
1179/**
1180 * omap_hwmod_idle - idle an omap_hwmod
1181 * @oh: struct omap_hwmod *
1182 *
1183 * Idle an omap_hwomd @oh. Intended to be called by omap_device_idle().
1184 * Returns -EINVAL on error or passes along the return value from _idle().
1185 */
1186int omap_hwmod_idle(struct omap_hwmod *oh)
1187{
1188 if (!oh)
1189 return -EINVAL;
1190
1191 mutex_lock(&omap_hwmod_mutex);
1192 _idle(oh);
1193 mutex_unlock(&omap_hwmod_mutex);
1194
1195 return 0;
1196}
1197
1198/**
1199 * omap_hwmod_shutdown - shutdown an omap_hwmod
1200 * @oh: struct omap_hwmod *
1201 *
1202 * Shutdown an omap_hwomd @oh. Intended to be called by
1203 * omap_device_shutdown(). Returns -EINVAL on error or passes along
1204 * the return value from _shutdown().
1205 */
1206int omap_hwmod_shutdown(struct omap_hwmod *oh)
1207{
1208 if (!oh)
1209 return -EINVAL;
1210
1211 mutex_lock(&omap_hwmod_mutex);
1212 _shutdown(oh);
1213 mutex_unlock(&omap_hwmod_mutex);
1214
1215 return 0;
1216}
1217
1218/**
1219 * omap_hwmod_enable_clocks - enable main_clk, all interface clocks
1220 * @oh: struct omap_hwmod *oh
1221 *
1222 * Intended to be called by the omap_device code.
1223 */
1224int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
1225{
1226 mutex_lock(&omap_hwmod_mutex);
1227 _enable_clocks(oh);
1228 mutex_unlock(&omap_hwmod_mutex);
1229
1230 return 0;
1231}
1232
1233/**
1234 * omap_hwmod_disable_clocks - disable main_clk, all interface clocks
1235 * @oh: struct omap_hwmod *oh
1236 *
1237 * Intended to be called by the omap_device code.
1238 */
1239int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
1240{
1241 mutex_lock(&omap_hwmod_mutex);
1242 _disable_clocks(oh);
1243 mutex_unlock(&omap_hwmod_mutex);
1244
1245 return 0;
1246}
1247
1248/**
1249 * omap_hwmod_ocp_barrier - wait for posted writes against the hwmod to complete
1250 * @oh: struct omap_hwmod *oh
1251 *
1252 * Intended to be called by drivers and core code when all posted
1253 * writes to a device must complete before continuing further
1254 * execution (for example, after clearing some device IRQSTATUS
1255 * register bits)
1256 *
1257 * XXX what about targets with multiple OCP threads?
1258 */
1259void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
1260{
1261 BUG_ON(!oh);
1262
1263 if (!oh->sysconfig || !oh->sysconfig->sysc_flags) {
1264 WARN(1, "omap_device: %s: OCP barrier impossible due to "
1265 "device configuration\n", oh->name);
1266 return;
1267 }
1268
1269 /*
1270 * Forces posted writes to complete on the OCP thread handling
1271 * register writes
1272 */
1273 omap_hwmod_readl(oh, oh->sysconfig->sysc_offs);
1274}
1275
1276/**
1277 * omap_hwmod_reset - reset the hwmod
1278 * @oh: struct omap_hwmod *
1279 *
1280 * Under some conditions, a driver may wish to reset the entire device.
1281 * Called from omap_device code. Returns -EINVAL on error or passes along
1282 * the return value from _reset()/_enable().
1283 */
1284int omap_hwmod_reset(struct omap_hwmod *oh)
1285{
1286 int r;
1287
1288 if (!oh || !(oh->_state & _HWMOD_STATE_ENABLED))
1289 return -EINVAL;
1290
1291 mutex_lock(&omap_hwmod_mutex);
1292 r = _reset(oh);
1293 if (!r)
1294 r = _enable(oh);
1295 mutex_unlock(&omap_hwmod_mutex);
1296
1297 return r;
1298}
1299
1300/**
1301 * omap_hwmod_count_resources - count number of struct resources needed by hwmod
1302 * @oh: struct omap_hwmod *
1303 * @res: pointer to the first element of an array of struct resource to fill
1304 *
1305 * Count the number of struct resource array elements necessary to
1306 * contain omap_hwmod @oh resources. Intended to be called by code
1307 * that registers omap_devices. Intended to be used to determine the
1308 * size of a dynamically-allocated struct resource array, before
1309 * calling omap_hwmod_fill_resources(). Returns the number of struct
1310 * resource array elements needed.
1311 *
1312 * XXX This code is not optimized. It could attempt to merge adjacent
1313 * resource IDs.
1314 *
1315 */
1316int omap_hwmod_count_resources(struct omap_hwmod *oh)
1317{
1318 int ret, i;
1319
1320 ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
1321
1322 for (i = 0; i < oh->slaves_cnt; i++)
1323 ret += (*oh->slaves + i)->addr_cnt;
1324
1325 return ret;
1326}
1327
1328/**
1329 * omap_hwmod_fill_resources - fill struct resource array with hwmod data
1330 * @oh: struct omap_hwmod *
1331 * @res: pointer to the first element of an array of struct resource to fill
1332 *
1333 * Fill the struct resource array @res with resource data from the
1334 * omap_hwmod @oh. Intended to be called by code that registers
1335 * omap_devices. See also omap_hwmod_count_resources(). Returns the
1336 * number of array elements filled.
1337 */
1338int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1339{
1340 int i, j;
1341 int r = 0;
1342
1343 /* For each IRQ, DMA, memory area, fill in array.*/
1344
1345 for (i = 0; i < oh->mpu_irqs_cnt; i++) {
1346 (res + r)->start = *(oh->mpu_irqs + i);
1347 (res + r)->end = *(oh->mpu_irqs + i);
1348 (res + r)->flags = IORESOURCE_IRQ;
1349 r++;
1350 }
1351
1352 for (i = 0; i < oh->sdma_chs_cnt; i++) {
1353 (res + r)->name = (oh->sdma_chs + i)->name;
1354 (res + r)->start = (oh->sdma_chs + i)->dma_ch;
1355 (res + r)->end = (oh->sdma_chs + i)->dma_ch;
1356 (res + r)->flags = IORESOURCE_DMA;
1357 r++;
1358 }
1359
1360 for (i = 0; i < oh->slaves_cnt; i++) {
1361 struct omap_hwmod_ocp_if *os;
1362
1363 os = *oh->slaves + i;
1364
1365 for (j = 0; j < os->addr_cnt; j++) {
1366 (res + r)->start = (os->addr + j)->pa_start;
1367 (res + r)->end = (os->addr + j)->pa_end;
1368 (res + r)->flags = IORESOURCE_MEM;
1369 r++;
1370 }
1371 }
1372
1373 return r;
1374}
1375
1376/**
1377 * omap_hwmod_get_pwrdm - return pointer to this module's main powerdomain
1378 * @oh: struct omap_hwmod *
1379 *
1380 * Return the powerdomain pointer associated with the OMAP module
1381 * @oh's main clock. If @oh does not have a main clk, return the
1382 * powerdomain associated with the interface clock associated with the
1383 * module's MPU port. (XXX Perhaps this should use the SDMA port
1384 * instead?) Returns NULL on error, or a struct powerdomain * on
1385 * success.
1386 */
1387struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
1388{
1389 struct clk *c;
1390
1391 if (!oh)
1392 return NULL;
1393
1394 if (oh->_clk) {
1395 c = oh->_clk;
1396 } else {
1397 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
1398 return NULL;
1399 c = oh->slaves[oh->_mpu_port_index]->_clk;
1400 }
1401
1402 return c->clkdm->pwrdm.ptr;
1403
1404}
1405
1406/**
1407 * omap_hwmod_add_initiator_dep - add sleepdep from @init_oh to @oh
1408 * @oh: struct omap_hwmod *
1409 * @init_oh: struct omap_hwmod * (initiator)
1410 *
1411 * Add a sleep dependency between the initiator @init_oh and @oh.
1412 * Intended to be called by DSP/Bridge code via platform_data for the
1413 * DSP case; and by the DMA code in the sDMA case. DMA code, *Bridge
1414 * code needs to add/del initiator dependencies dynamically
1415 * before/after accessing a device. Returns the return value from
1416 * _add_initiator_dep().
1417 *
1418 * XXX Keep a usecount in the clockdomain code
1419 */
1420int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh,
1421 struct omap_hwmod *init_oh)
1422{
1423 return _add_initiator_dep(oh, init_oh);
1424}
1425
1426/*
1427 * XXX what about functions for drivers to save/restore ocp_sysconfig
1428 * for context save/restore operations?
1429 */
1430
1431/**
1432 * omap_hwmod_del_initiator_dep - remove sleepdep from @init_oh to @oh
1433 * @oh: struct omap_hwmod *
1434 * @init_oh: struct omap_hwmod * (initiator)
1435 *
1436 * Remove a sleep dependency between the initiator @init_oh and @oh.
1437 * Intended to be called by DSP/Bridge code via platform_data for the
1438 * DSP case; and by the DMA code in the sDMA case. DMA code, *Bridge
1439 * code needs to add/del initiator dependencies dynamically
1440 * before/after accessing a device. Returns the return value from
1441 * _del_initiator_dep().
1442 *
1443 * XXX Keep a usecount in the clockdomain code
1444 */
1445int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
1446 struct omap_hwmod *init_oh)
1447{
1448 return _del_initiator_dep(oh, init_oh);
1449}
1450
1451/**
1452 * omap_hwmod_set_clockact_none - set clockactivity test to BOTH
1453 * @oh: struct omap_hwmod *
1454 *
1455 * On some modules, this function can affect the wakeup latency vs.
1456 * power consumption balance. Intended to be called by the
1457 * omap_device layer. Passes along the return value from
1458 * _write_clockact_lock().
1459 */
1460int omap_hwmod_set_clockact_both(struct omap_hwmod *oh)
1461{
1462 return _write_clockact_lock(oh, CLOCKACT_TEST_BOTH);
1463}
1464
1465/**
1466 * omap_hwmod_set_clockact_none - set clockactivity test to MAIN
1467 * @oh: struct omap_hwmod *
1468 *
1469 * On some modules, this function can affect the wakeup latency vs.
1470 * power consumption balance. Intended to be called by the
1471 * omap_device layer. Passes along the return value from
1472 * _write_clockact_lock().
1473 */
1474int omap_hwmod_set_clockact_main(struct omap_hwmod *oh)
1475{
1476 return _write_clockact_lock(oh, CLOCKACT_TEST_MAIN);
1477}
1478
1479/**
1480 * omap_hwmod_set_clockact_none - set clockactivity test to ICLK
1481 * @oh: struct omap_hwmod *
1482 *
1483 * On some modules, this function can affect the wakeup latency vs.
1484 * power consumption balance. Intended to be called by the
1485 * omap_device layer. Passes along the return value from
1486 * _write_clockact_lock().
1487 */
1488int omap_hwmod_set_clockact_iclk(struct omap_hwmod *oh)
1489{
1490 return _write_clockact_lock(oh, CLOCKACT_TEST_ICLK);
1491}
1492
1493/**
1494 * omap_hwmod_set_clockact_none - set clockactivity test to NONE
1495 * @oh: struct omap_hwmod *
1496 *
1497 * On some modules, this function can affect the wakeup latency vs.
1498 * power consumption balance. Intended to be called by the
1499 * omap_device layer. Passes along the return value from
1500 * _write_clockact_lock().
1501 */
1502int omap_hwmod_set_clockact_none(struct omap_hwmod *oh)
1503{
1504 return _write_clockact_lock(oh, CLOCKACT_TEST_NONE);
1505}
1506
1507/**
1508 * omap_hwmod_enable_wakeup - allow device to wake up the system
1509 * @oh: struct omap_hwmod *
1510 *
1511 * Sets the module OCP socket ENAWAKEUP bit to allow the module to
1512 * send wakeups to the PRCM. Eventually this should sets PRCM wakeup
1513 * registers to cause the PRCM to receive wakeup events from the
1514 * module. Does not set any wakeup routing registers beyond this
1515 * point - if the module is to wake up any other module or subsystem,
1516 * that must be set separately. Called by omap_device code. Returns
1517 * -EINVAL on error or 0 upon success.
1518 */
1519int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
1520{
1521 if (!oh->sysconfig ||
1522 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
1523 return -EINVAL;
1524
1525 mutex_lock(&omap_hwmod_mutex);
1526 _enable_wakeup(oh);
1527 mutex_unlock(&omap_hwmod_mutex);
1528
1529 return 0;
1530}
1531
1532/**
1533 * omap_hwmod_disable_wakeup - prevent device from waking the system
1534 * @oh: struct omap_hwmod *
1535 *
1536 * Clears the module OCP socket ENAWAKEUP bit to prevent the module
1537 * from sending wakeups to the PRCM. Eventually this should clear
1538 * PRCM wakeup registers to cause the PRCM to ignore wakeup events
1539 * from the module. Does not set any wakeup routing registers beyond
1540 * this point - if the module is to wake up any other module or
1541 * subsystem, that must be set separately. Called by omap_device
1542 * code. Returns -EINVAL on error or 0 upon success.
1543 */
1544int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
1545{
1546 if (!oh->sysconfig ||
1547 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
1548 return -EINVAL;
1549
1550 mutex_lock(&omap_hwmod_mutex);
1551 _disable_wakeup(oh);
1552 mutex_unlock(&omap_hwmod_mutex);
1553
1554 return 0;
1555}
diff --git a/arch/arm/plat-omap/include/mach/omap_hwmod.h b/arch/arm/plat-omap/include/mach/omap_hwmod.h
new file mode 100644
index 000000000000..1f79c20e2929
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/omap_hwmod.h
@@ -0,0 +1,447 @@
1/*
2 * omap_hwmod macros, structures
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Paul Walmsley
6 *
7 * Created in collaboration with (alphabetical order): Benoit Cousson,
8 * Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari
9 * Poussa, Anand Sawant, Santosh Shilimkar, Richard Woodruff
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * These headers and macros are used to define OMAP on-chip module
16 * data and their integration with other OMAP modules and Linux.
17 *
18 * References:
19 * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
20 * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
21 * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
22 * - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
23 * - Open Core Protocol Specification 2.2
24 *
25 * To do:
26 * - add interconnect error log structures
27 * - add pinmuxing
28 * - init_conn_id_bit (CONNID_BIT_VECTOR)
29 * - implement default hwmod SMS/SDRC flags?
30 *
31 */
32#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
33#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
34
35#include <linux/kernel.h>
36#include <linux/ioport.h>
37
38#include <mach/cpu.h>
39
40struct omap_device;
41
42/* OCP SYSCONFIG bit shifts/masks */
43#define SYSC_MIDLEMODE_SHIFT 12
44#define SYSC_MIDLEMODE_MASK (0x3 << SYSC_MIDLEMODE_SHIFT)
45#define SYSC_CLOCKACTIVITY_SHIFT 8
46#define SYSC_CLOCKACTIVITY_MASK (0x3 << SYSC_CLOCKACTIVITY_SHIFT)
47#define SYSC_SIDLEMODE_SHIFT 3
48#define SYSC_SIDLEMODE_MASK (0x3 << SYSC_SIDLEMODE_SHIFT)
49#define SYSC_ENAWAKEUP_SHIFT 2
50#define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT)
51#define SYSC_SOFTRESET_SHIFT 1
52#define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT)
53
54/* OCP SYSSTATUS bit shifts/masks */
55#define SYSS_RESETDONE_SHIFT 0
56#define SYSS_RESETDONE_MASK (1 << SYSS_RESETDONE_SHIFT)
57
58/* Master standby/slave idle mode flags */
59#define HWMOD_IDLEMODE_FORCE (1 << 0)
60#define HWMOD_IDLEMODE_NO (1 << 1)
61#define HWMOD_IDLEMODE_SMART (1 << 2)
62
63
64/**
65 * struct omap_hwmod_dma_info - MPU address space handled by the hwmod
66 * @name: name of the DMA channel (module local name)
67 * @dma_ch: DMA channel ID
68 *
69 * @name should be something short, e.g., "tx" or "rx". It is for use
70 * by platform_get_resource_byname(). It is defined locally to the
71 * hwmod.
72 */
73struct omap_hwmod_dma_info {
74 const char *name;
75 u16 dma_ch;
76};
77
78/**
79 * struct omap_hwmod_opt_clk - optional clocks used by this hwmod
80 * @role: "sys", "32k", "tv", etc -- for use in clk_get()
81 * @clkdev_dev_id: opt clock: clkdev dev_id string
82 * @clkdev_con_id: opt clock: clkdev con_id string
83 * @_clk: pointer to the struct clk (filled in at runtime)
84 *
85 * The module's interface clock and main functional clock should not
86 * be added as optional clocks.
87 */
88struct omap_hwmod_opt_clk {
89 const char *role;
90 const char *clkdev_dev_id;
91 const char *clkdev_con_id;
92 struct clk *_clk;
93};
94
95
96/* omap_hwmod_omap2_firewall.flags bits */
97#define OMAP_FIREWALL_L3 (1 << 0)
98#define OMAP_FIREWALL_L4 (1 << 1)
99
100/**
101 * struct omap_hwmod_omap2_firewall - OMAP2/3 device firewall data
102 * @l3_perm_bit: bit shift for L3_PM_*_PERMISSION_*
103 * @l4_fw_region: L4 firewall region ID
104 * @l4_prot_group: L4 protection group ID
105 * @flags: (see omap_hwmod_omap2_firewall.flags macros above)
106 */
107struct omap_hwmod_omap2_firewall {
108 u8 l3_perm_bit;
109 u8 l4_fw_region;
110 u8 l4_prot_group;
111 u8 flags;
112};
113
114
115/*
116 * omap_hwmod_addr_space.flags bits
117 *
118 * ADDR_MAP_ON_INIT: Map this address space during omap_hwmod init.
119 * ADDR_TYPE_RT: Address space contains module register target data.
120 */
121#define ADDR_MAP_ON_INIT (1 << 0)
122#define ADDR_TYPE_RT (1 << 1)
123
124/**
125 * struct omap_hwmod_addr_space - MPU address space handled by the hwmod
126 * @pa_start: starting physical address
127 * @pa_end: ending physical address
128 * @flags: (see omap_hwmod_addr_space.flags macros above)
129 *
130 * Address space doesn't necessarily follow physical interconnect
131 * structure. GPMC is one example.
132 */
133struct omap_hwmod_addr_space {
134 u32 pa_start;
135 u32 pa_end;
136 u8 flags;
137};
138
139
140/*
141 * omap_hwmod_ocp_if.user bits: these indicate the initiators that use this
142 * interface to interact with the hwmod. Used to add sleep dependencies
143 * when the module is enabled or disabled.
144 */
145#define OCP_USER_MPU (1 << 0)
146#define OCP_USER_SDMA (1 << 1)
147
148/* omap_hwmod_ocp_if.flags bits */
149#define OCPIF_HAS_IDLEST (1 << 0)
150#define OCPIF_SWSUP_IDLE (1 << 1)
151#define OCPIF_CAN_BURST (1 << 2)
152
153/**
154 * struct omap_hwmod_ocp_if - OCP interface data
155 * @master: struct omap_hwmod that initiates OCP transactions on this link
156 * @slave: struct omap_hwmod that responds to OCP transactions on this link
157 * @addr: address space associated with this link
158 * @clkdev_dev_id: interface clock: clkdev dev_id string
159 * @clkdev_con_id: interface clock: clkdev con_id string
160 * @_clk: pointer to the interface struct clk (filled in at runtime)
161 * @fw: interface firewall data
162 * @addr_cnt: ARRAY_SIZE(@addr)
163 * @width: OCP data width
164 * @thread_cnt: number of threads
165 * @max_burst_len: maximum burst length in @width sized words (0 if unlimited)
166 * @user: initiators using this interface (see OCP_USER_* macros above)
167 * @flags: OCP interface flags (see OCPIF_* macros above)
168 *
169 * It may also be useful to add a tag_cnt field for OCP2.x devices.
170 *
171 * Parameter names beginning with an underscore are managed internally by
172 * the omap_hwmod code and should not be set during initialization.
173 */
174struct omap_hwmod_ocp_if {
175 struct omap_hwmod *master;
176 struct omap_hwmod *slave;
177 struct omap_hwmod_addr_space *addr;
178 const char *clkdev_dev_id;
179 const char *clkdev_con_id;
180 struct clk *_clk;
181 union {
182 struct omap_hwmod_omap2_firewall omap2;
183 } fw;
184 u8 addr_cnt;
185 u8 width;
186 u8 thread_cnt;
187 u8 max_burst_len;
188 u8 user;
189 u8 flags;
190};
191
192
193/* Macros for use in struct omap_hwmod_sysconfig */
194
195/* Flags for use in omap_hwmod_sysconfig.idlemodes */
196#define MASTER_STANDBY_SHIFT 2
197#define SLAVE_IDLE_SHIFT 0
198#define SIDLE_FORCE (HWMOD_IDLEMODE_FORCE << SLAVE_IDLE_SHIFT)
199#define SIDLE_NO (HWMOD_IDLEMODE_NO << SLAVE_IDLE_SHIFT)
200#define SIDLE_SMART (HWMOD_IDLEMODE_SMART << SLAVE_IDLE_SHIFT)
201#define MSTANDBY_FORCE (HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT)
202#define MSTANDBY_NO (HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT)
203#define MSTANDBY_SMART (HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT)
204
205/* omap_hwmod_sysconfig.sysc_flags capability flags */
206#define SYSC_HAS_AUTOIDLE (1 << 0)
207#define SYSC_HAS_SOFTRESET (1 << 1)
208#define SYSC_HAS_ENAWAKEUP (1 << 2)
209#define SYSC_HAS_EMUFREE (1 << 3)
210#define SYSC_HAS_CLOCKACTIVITY (1 << 4)
211#define SYSC_HAS_SIDLEMODE (1 << 5)
212#define SYSC_HAS_MIDLEMODE (1 << 6)
213#define SYSS_MISSING (1 << 7)
214
215/* omap_hwmod_sysconfig.clockact flags */
216#define CLOCKACT_TEST_BOTH 0x0
217#define CLOCKACT_TEST_MAIN 0x1
218#define CLOCKACT_TEST_ICLK 0x2
219#define CLOCKACT_TEST_NONE 0x3
220
221/**
222 * struct omap_hwmod_sysconfig - hwmod OCP_SYSCONFIG/OCP_SYSSTATUS data
223 * @rev_offs: IP block revision register offset (from module base addr)
224 * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr)
225 * @syss_offs: OCP_SYSSTATUS register offset (from module base addr)
226 * @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART}
227 * @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported
228 * @clockact: the default value of the module CLOCKACTIVITY bits
229 *
230 * @clockact describes to the module which clocks are likely to be
231 * disabled when the PRCM issues its idle request to the module. Some
232 * modules have separate clockdomains for the interface clock and main
233 * functional clock, and can check whether they should acknowledge the
234 * idle request based on the internal module functionality that has
235 * been associated with the clocks marked in @clockact. This field is
236 * only used if HWMOD_SET_DEFAULT_CLOCKACT is set (see below)
237 *
238 */
239struct omap_hwmod_sysconfig {
240 u16 rev_offs;
241 u16 sysc_offs;
242 u16 syss_offs;
243 u8 idlemodes;
244 u8 sysc_flags;
245 u8 clockact;
246};
247
248/**
249 * struct omap_hwmod_omap2_prcm - OMAP2/3-specific PRCM data
250 * @module_offs: PRCM submodule offset from the start of the PRM/CM
251 * @prcm_reg_id: PRCM register ID (e.g., 3 for CM_AUTOIDLE3)
252 * @module_bit: register bit shift for AUTOIDLE, WKST, WKEN, GRPSEL regs
253 * @idlest_reg_id: IDLEST register ID (e.g., 3 for CM_IDLEST3)
254 * @idlest_idle_bit: register bit shift for CM_IDLEST slave idle bit
255 * @idlest_stdby_bit: register bit shift for CM_IDLEST master standby bit
256 *
257 * @prcm_reg_id and @module_bit are specific to the AUTOIDLE, WKST,
258 * WKEN, GRPSEL registers. In an ideal world, no extra information
259 * would be needed for IDLEST information, but alas, there are some
260 * exceptions, so @idlest_reg_id, @idlest_idle_bit, @idlest_stdby_bit
261 * are needed for the IDLEST registers (c.f. 2430 I2CHS, 3430 USBHOST)
262 */
263struct omap_hwmod_omap2_prcm {
264 s16 module_offs;
265 u8 prcm_reg_id;
266 u8 module_bit;
267 u8 idlest_reg_id;
268 u8 idlest_idle_bit;
269 u8 idlest_stdby_bit;
270};
271
272
273/**
274 * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
275 * @module_offs: PRCM submodule offset from the start of the PRM/CM1/CM2
276 * @device_offs: device register offset from @module_offs
277 * @submodule_wkdep_bit: bit shift of the WKDEP range
278 */
279struct omap_hwmod_omap4_prcm {
280 u32 module_offs;
281 u16 device_offs;
282 u8 submodule_wkdep_bit;
283};
284
285
286/*
287 * omap_hwmod.flags definitions
288 *
289 * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out
290 * of idle, rather than relying on module smart-idle
291 * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
292 * of standby, rather than relying on module smart-standby
293 * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
294 * SDRAM controller, etc.
295 * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
296 * controller, etc.
297 * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
298 */
299#define HWMOD_SWSUP_SIDLE (1 << 0)
300#define HWMOD_SWSUP_MSTANDBY (1 << 1)
301#define HWMOD_INIT_NO_RESET (1 << 2)
302#define HWMOD_INIT_NO_IDLE (1 << 3)
303#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 4)
304
305/*
306 * omap_hwmod._int_flags definitions
307 * These are for internal use only and are managed by the omap_hwmod code.
308 *
309 * _HWMOD_NO_MPU_PORT: no path exists for the MPU to write to this module
310 * _HWMOD_WAKEUP_ENABLED: set when the omap_hwmod code has enabled ENAWAKEUP
311 * _HWMOD_SYSCONFIG_LOADED: set when the OCP_SYSCONFIG value has been cached
312 */
313#define _HWMOD_NO_MPU_PORT (1 << 0)
314#define _HWMOD_WAKEUP_ENABLED (1 << 1)
315#define _HWMOD_SYSCONFIG_LOADED (1 << 2)
316
317/*
318 * omap_hwmod._state definitions
319 *
320 * INITIALIZED: reset (optionally), initialized, enabled, disabled
321 * (optionally)
322 *
323 *
324 */
325#define _HWMOD_STATE_UNKNOWN 0
326#define _HWMOD_STATE_REGISTERED 1
327#define _HWMOD_STATE_CLKS_INITED 2
328#define _HWMOD_STATE_INITIALIZED 3
329#define _HWMOD_STATE_ENABLED 4
330#define _HWMOD_STATE_IDLE 5
331#define _HWMOD_STATE_DISABLED 6
332
333/**
334 * struct omap_hwmod - integration data for OMAP hardware "modules" (IP blocks)
335 * @name: name of the hwmod
336 * @od: struct omap_device currently associated with this hwmod (internal use)
337 * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
338 * @sdma_chs: ptr to an array of SDMA channel IDs (see also sdma_chs_cnt)
339 * @prcm: PRCM data pertaining to this hwmod
340 * @clkdev_dev_id: main clock: clkdev dev_id string
341 * @clkdev_con_id: main clock: clkdev con_id string
342 * @_clk: pointer to the main struct clk (filled in at runtime)
343 * @opt_clks: other device clocks that drivers can request (0..*)
344 * @masters: ptr to array of OCP ifs that this hwmod can initiate on
345 * @slaves: ptr to array of OCP ifs that this hwmod can respond on
346 * @sysconfig: device SYSCONFIG/SYSSTATUS register data
347 * @dev_attr: arbitrary device attributes that can be passed to the driver
348 * @_sysc_cache: internal-use hwmod flags
349 * @_rt_va: cached register target start address (internal use)
350 * @_mpu_port_index: cached MPU register target slave ID (internal use)
351 * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
352 * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
353 * @mpu_irqs_cnt: number of @mpu_irqs
354 * @sdma_chs_cnt: number of @sdma_chs
355 * @opt_clks_cnt: number of @opt_clks
356 * @master_cnt: number of @master entries
357 * @slaves_cnt: number of @slave entries
358 * @response_lat: device OCP response latency (in interface clock cycles)
359 * @_int_flags: internal-use hwmod flags
360 * @_state: internal-use hwmod state
361 * @flags: hwmod flags (documented below)
362 * @omap_chip: OMAP chips this hwmod is present on
363 * @node: list node for hwmod list (internal use)
364 *
365 * @clkdev_dev_id, @clkdev_con_id, and @clk all refer to this module's "main
366 * clock," which for our purposes is defined as "the functional clock needed
367 * for register accesses to complete." Modules may not have a main clock if
368 * the interface clock also serves as a main clock.
369 *
370 * Parameter names beginning with an underscore are managed internally by
371 * the omap_hwmod code and should not be set during initialization.
372 */
373struct omap_hwmod {
374 const char *name;
375 struct omap_device *od;
376 u8 *mpu_irqs;
377 struct omap_hwmod_dma_info *sdma_chs;
378 union {
379 struct omap_hwmod_omap2_prcm omap2;
380 struct omap_hwmod_omap4_prcm omap4;
381 } prcm;
382 const char *clkdev_dev_id;
383 const char *clkdev_con_id;
384 struct clk *_clk;
385 struct omap_hwmod_opt_clk *opt_clks;
386 struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
387 struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */
388 struct omap_hwmod_sysconfig *sysconfig;
389 void *dev_attr;
390 u32 _sysc_cache;
391 void __iomem *_rt_va;
392 struct list_head node;
393 u16 flags;
394 u8 _mpu_port_index;
395 u8 msuspendmux_reg_id;
396 u8 msuspendmux_shift;
397 u8 response_lat;
398 u8 mpu_irqs_cnt;
399 u8 sdma_chs_cnt;
400 u8 opt_clks_cnt;
401 u8 masters_cnt;
402 u8 slaves_cnt;
403 u8 hwmods_cnt;
404 u8 _int_flags;
405 u8 _state;
406 const struct omap_chip_id omap_chip;
407};
408
409int omap_hwmod_init(struct omap_hwmod **ohs);
410int omap_hwmod_register(struct omap_hwmod *oh);
411int omap_hwmod_unregister(struct omap_hwmod *oh);
412struct omap_hwmod *omap_hwmod_lookup(const char *name);
413int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh));
414int omap_hwmod_late_init(void);
415
416int omap_hwmod_enable(struct omap_hwmod *oh);
417int omap_hwmod_idle(struct omap_hwmod *oh);
418int omap_hwmod_shutdown(struct omap_hwmod *oh);
419
420int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
421int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
422
423int omap_hwmod_reset(struct omap_hwmod *oh);
424void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
425
426void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs);
427u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs);
428
429int omap_hwmod_count_resources(struct omap_hwmod *oh);
430int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
431
432struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh);
433
434int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh,
435 struct omap_hwmod *init_oh);
436int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
437 struct omap_hwmod *init_oh);
438
439int omap_hwmod_set_clockact_both(struct omap_hwmod *oh);
440int omap_hwmod_set_clockact_main(struct omap_hwmod *oh);
441int omap_hwmod_set_clockact_iclk(struct omap_hwmod *oh);
442int omap_hwmod_set_clockact_none(struct omap_hwmod *oh);
443
444int omap_hwmod_enable_wakeup(struct omap_hwmod *oh);
445int omap_hwmod_disable_wakeup(struct omap_hwmod *oh);
446
447#endif