aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c164
1 files changed, 64 insertions, 100 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 633b216a8b26..d8c8545875b1 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -45,6 +45,7 @@
45#include <linux/mutex.h> 45#include <linux/mutex.h>
46#include <linux/bootmem.h> 46#include <linux/bootmem.h>
47 47
48#include <plat/common.h>
48#include <plat/cpu.h> 49#include <plat/cpu.h>
49#include <plat/clockdomain.h> 50#include <plat/clockdomain.h>
50#include <plat/powerdomain.h> 51#include <plat/powerdomain.h>
@@ -210,6 +211,32 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
210} 211}
211 212
212/** 213/**
214 * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v
215 * @oh: struct omap_hwmod *
216 * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
217 * @v: pointer to register contents to modify
218 *
219 * Update the module autoidle bit in @v to be @autoidle for the @oh
220 * hwmod. The autoidle bit controls whether the module can gate
221 * internal clocks automatically when it isn't doing anything; the
222 * exact function of this bit varies on a per-module basis. This
223 * function does not write to the hardware. Returns -EINVAL upon
224 * error or 0 upon success.
225 */
226static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
227 u32 *v)
228{
229 if (!oh->sysconfig ||
230 !(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE))
231 return -EINVAL;
232
233 *v &= ~SYSC_AUTOIDLE_MASK;
234 *v |= autoidle << SYSC_AUTOIDLE_SHIFT;
235
236 return 0;
237}
238
239/**
213 * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware 240 * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
214 * @oh: struct omap_hwmod * 241 * @oh: struct omap_hwmod *
215 * 242 *
@@ -326,6 +353,9 @@ static int _init_main_clk(struct omap_hwmod *oh)
326 ret = -EINVAL; 353 ret = -EINVAL;
327 oh->_clk = c; 354 oh->_clk = c;
328 355
356 WARN(!c->clkdm, "omap_hwmod: %s: missing clockdomain for %s.\n",
357 oh->clkdev_con_id, c->name);
358
329 return ret; 359 return ret;
330} 360}
331 361
@@ -557,8 +587,19 @@ static void _sysc_enable(struct omap_hwmod *oh)
557 _set_master_standbymode(oh, idlemode, &v); 587 _set_master_standbymode(oh, idlemode, &v);
558 } 588 }
559 589
560 /* XXX OCP AUTOIDLE bit? */ 590 if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE) {
591 idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
592 0 : 1;
593 _set_module_autoidle(oh, idlemode, &v);
594 }
595
596 /* XXX OCP ENAWAKEUP bit? */
561 597
598 /*
599 * XXX The clock framework should handle this, by
600 * calling into this code. But this must wait until the
601 * clock structures are tagged with omap_hwmod entries
602 */
562 if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT && 603 if (oh->flags & HWMOD_SET_DEFAULT_CLOCKACT &&
563 oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY) 604 oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY)
564 _set_clockactivity(oh, oh->sysconfig->clockact, &v); 605 _set_clockactivity(oh, oh->sysconfig->clockact, &v);
@@ -622,7 +663,8 @@ static void _sysc_shutdown(struct omap_hwmod *oh)
622 if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE) 663 if (oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE)
623 _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v); 664 _set_master_standbymode(oh, HWMOD_IDLEMODE_FORCE, &v);
624 665
625 /* XXX clear OCP AUTOIDLE bit? */ 666 if (oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE)
667 _set_module_autoidle(oh, 1, &v);
626 668
627 _write_sysconfig(v, oh); 669 _write_sysconfig(v, oh);
628} 670}
@@ -736,7 +778,7 @@ static int _wait_target_ready(struct omap_hwmod *oh)
736static int _reset(struct omap_hwmod *oh) 778static int _reset(struct omap_hwmod *oh)
737{ 779{
738 u32 r, v; 780 u32 r, v;
739 int c; 781 int c = 0;
740 782
741 if (!oh->sysconfig || 783 if (!oh->sysconfig ||
742 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET) || 784 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET) ||
@@ -758,13 +800,9 @@ static int _reset(struct omap_hwmod *oh)
758 return r; 800 return r;
759 _write_sysconfig(v, oh); 801 _write_sysconfig(v, oh);
760 802
761 c = 0; 803 omap_test_timeout((omap_hwmod_readl(oh, oh->sysconfig->syss_offs) &
762 while (c < MAX_MODULE_RESET_WAIT && 804 SYSS_RESETDONE_MASK),
763 !(omap_hwmod_readl(oh, oh->sysconfig->syss_offs) & 805 MAX_MODULE_RESET_WAIT, c);
764 SYSS_RESETDONE_MASK)) {
765 udelay(1);
766 c++;
767 }
768 806
769 if (c == MAX_MODULE_RESET_WAIT) 807 if (c == MAX_MODULE_RESET_WAIT)
770 WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n", 808 WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
@@ -884,33 +922,6 @@ static int _shutdown(struct omap_hwmod *oh)
884} 922}
885 923
886/** 924/**
887 * _write_clockact_lock - set the module's clockactivity bits
888 * @oh: struct omap_hwmod *
889 * @clockact: CLOCKACTIVITY field bits
890 *
891 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
892 * OCP_SYSCONFIG register. Returns -EINVAL if the hwmod is in the
893 * wrong state or returns 0.
894 */
895static int _write_clockact_lock(struct omap_hwmod *oh, u8 clockact)
896{
897 u32 v;
898
899 if (!oh->sysconfig ||
900 !(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY))
901 return -EINVAL;
902
903 mutex_lock(&omap_hwmod_mutex);
904 v = oh->_sysc_cache;
905 _set_clockactivity(oh, clockact, &v);
906 _write_sysconfig(v, oh);
907 mutex_unlock(&omap_hwmod_mutex);
908
909 return 0;
910}
911
912
913/**
914 * _setup - do initial configuration of omap_hwmod 925 * _setup - do initial configuration of omap_hwmod
915 * @oh: struct omap_hwmod * 926 * @oh: struct omap_hwmod *
916 * 927 *
@@ -948,11 +959,19 @@ static int _setup(struct omap_hwmod *oh)
948 959
949 _enable(oh); 960 _enable(oh);
950 961
951 if (!(oh->flags & HWMOD_INIT_NO_RESET)) 962 if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
952 _reset(oh); 963 /*
953 964 * XXX Do the OCP_SYSCONFIG bits need to be
954 /* XXX OCP AUTOIDLE bit? */ 965 * reprogrammed after a reset? If not, then this can
955 /* XXX OCP ENAWAKEUP bit? */ 966 * be removed. If they do, then probably the
967 * _enable() function should be split to avoid the
968 * rewrite of the OCP_SYSCONFIG register.
969 */
970 if (oh->sysconfig) {
971 _update_sysc_cache(oh);
972 _sysc_enable(oh);
973 }
974 }
956 975
957 if (!(oh->flags & HWMOD_INIT_NO_IDLE)) 976 if (!(oh->flags & HWMOD_INIT_NO_IDLE))
958 _idle(oh); 977 _idle(oh);
@@ -1348,8 +1367,9 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1348 /* For each IRQ, DMA, memory area, fill in array.*/ 1367 /* For each IRQ, DMA, memory area, fill in array.*/
1349 1368
1350 for (i = 0; i < oh->mpu_irqs_cnt; i++) { 1369 for (i = 0; i < oh->mpu_irqs_cnt; i++) {
1351 (res + r)->start = *(oh->mpu_irqs + i); 1370 (res + r)->name = (oh->mpu_irqs + i)->name;
1352 (res + r)->end = *(oh->mpu_irqs + i); 1371 (res + r)->start = (oh->mpu_irqs + i)->irq;
1372 (res + r)->end = (oh->mpu_irqs + i)->irq;
1353 (res + r)->flags = IORESOURCE_IRQ; 1373 (res + r)->flags = IORESOURCE_IRQ;
1354 r++; 1374 r++;
1355 } 1375 }
@@ -1454,62 +1474,6 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
1454} 1474}
1455 1475
1456/** 1476/**
1457 * omap_hwmod_set_clockact_none - set clockactivity test to BOTH
1458 * @oh: struct omap_hwmod *
1459 *
1460 * On some modules, this function can affect the wakeup latency vs.
1461 * power consumption balance. Intended to be called by the
1462 * omap_device layer. Passes along the return value from
1463 * _write_clockact_lock().
1464 */
1465int omap_hwmod_set_clockact_both(struct omap_hwmod *oh)
1466{
1467 return _write_clockact_lock(oh, CLOCKACT_TEST_BOTH);
1468}
1469
1470/**
1471 * omap_hwmod_set_clockact_none - set clockactivity test to MAIN
1472 * @oh: struct omap_hwmod *
1473 *
1474 * On some modules, this function can affect the wakeup latency vs.
1475 * power consumption balance. Intended to be called by the
1476 * omap_device layer. Passes along the return value from
1477 * _write_clockact_lock().
1478 */
1479int omap_hwmod_set_clockact_main(struct omap_hwmod *oh)
1480{
1481 return _write_clockact_lock(oh, CLOCKACT_TEST_MAIN);
1482}
1483
1484/**
1485 * omap_hwmod_set_clockact_none - set clockactivity test to ICLK
1486 * @oh: struct omap_hwmod *
1487 *
1488 * On some modules, this function can affect the wakeup latency vs.
1489 * power consumption balance. Intended to be called by the
1490 * omap_device layer. Passes along the return value from
1491 * _write_clockact_lock().
1492 */
1493int omap_hwmod_set_clockact_iclk(struct omap_hwmod *oh)
1494{
1495 return _write_clockact_lock(oh, CLOCKACT_TEST_ICLK);
1496}
1497
1498/**
1499 * omap_hwmod_set_clockact_none - set clockactivity test to NONE
1500 * @oh: struct omap_hwmod *
1501 *
1502 * On some modules, this function can affect the wakeup latency vs.
1503 * power consumption balance. Intended to be called by the
1504 * omap_device layer. Passes along the return value from
1505 * _write_clockact_lock().
1506 */
1507int omap_hwmod_set_clockact_none(struct omap_hwmod *oh)
1508{
1509 return _write_clockact_lock(oh, CLOCKACT_TEST_NONE);
1510}
1511
1512/**
1513 * omap_hwmod_enable_wakeup - allow device to wake up the system 1477 * omap_hwmod_enable_wakeup - allow device to wake up the system
1514 * @oh: struct omap_hwmod * 1478 * @oh: struct omap_hwmod *
1515 * 1479 *