diff options
author | Kevin Hilman <khilman@ti.com> | 2010-09-21 12:34:09 -0400 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-09-21 17:11:30 -0400 |
commit | 12b1fdb45c2594070bb36e39cd89a33547aad8fb (patch) | |
tree | 01af153ff32c155ca5a5392badf82ffcaca6bbaa /arch/arm | |
parent | ff4d3e186b7b92c74a4f64360f723c603193f344 (diff) |
OMAP: hwmod: separate list locking and hwmod hardware locking
Currently omap_hwmod_mutex is being used to protect both the list
access/modification and concurrent access to hwmod functions. This
patch separates these two types of locking.
First, omap_hwmod_mutex is used only to protect access and
modification of omap_hwmod_list. Also cleaned up some comments
referring to this mutex that are no longer needed.
Then, for protecting concurrent access to hwmod functions, use a
per-hwmod mutex. This protects concurrent access to a single hwmod,
but would allow concurrent access to different hwmods.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
[paul@pwsan.com: added structure documentation; changed mutex variable
name]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 62 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap_hwmod.h | 3 |
2 files changed, 33 insertions, 32 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 100115ff1d96..3084409ad1dc 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -767,10 +767,10 @@ static struct omap_hwmod *_lookup(const char *name) | |||
767 | * @data: not used; pass NULL | 767 | * @data: not used; pass NULL |
768 | * | 768 | * |
769 | * Called by omap_hwmod_late_init() (after omap2_clk_init()). | 769 | * Called by omap_hwmod_late_init() (after omap2_clk_init()). |
770 | * Resolves all clock names embedded in the hwmod. Must be called | 770 | * Resolves all clock names embedded in the hwmod. Returns -EINVAL if |
771 | * with omap_hwmod_mutex held. Returns -EINVAL if the omap_hwmod | 771 | * the omap_hwmod has not yet been registered or if the clocks have |
772 | * has not yet been registered or if the clocks have already been | 772 | * already been initialized, 0 on success, or a non-zero error on |
773 | * initialized, 0 on success, or a non-zero error on failure. | 773 | * failure. |
774 | */ | 774 | */ |
775 | static int _init_clocks(struct omap_hwmod *oh, void *data) | 775 | static int _init_clocks(struct omap_hwmod *oh, void *data) |
776 | { | 776 | { |
@@ -838,10 +838,9 @@ static int _wait_target_ready(struct omap_hwmod *oh) | |||
838 | * @oh: struct omap_hwmod * | 838 | * @oh: struct omap_hwmod * |
839 | * | 839 | * |
840 | * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be | 840 | * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be |
841 | * enabled for this to work. Must be called with omap_hwmod_mutex | 841 | * enabled for this to work. Returns -EINVAL if the hwmod cannot be |
842 | * held. Returns -EINVAL if the hwmod cannot be reset this way or if | 842 | * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if |
843 | * the hwmod is in the wrong state, -ETIMEDOUT if the module did not | 843 | * the module did not reset in time, or 0 upon success. |
844 | * reset in time, or 0 upon success. | ||
845 | */ | 844 | */ |
846 | static int _reset(struct omap_hwmod *oh) | 845 | static int _reset(struct omap_hwmod *oh) |
847 | { | 846 | { |
@@ -891,9 +890,8 @@ static int _reset(struct omap_hwmod *oh) | |||
891 | * @oh: struct omap_hwmod * | 890 | * @oh: struct omap_hwmod * |
892 | * | 891 | * |
893 | * Enables an omap_hwmod @oh such that the MPU can access the hwmod's | 892 | * Enables an omap_hwmod @oh such that the MPU can access the hwmod's |
894 | * register target. Must be called with omap_hwmod_mutex held. | 893 | * register target. Returns -EINVAL if the hwmod is in the wrong |
895 | * Returns -EINVAL if the hwmod is in the wrong state or passes along | 894 | * state or passes along the return value of _wait_target_ready(). |
896 | * the return value of _wait_target_ready(). | ||
897 | */ | 895 | */ |
898 | int _omap_hwmod_enable(struct omap_hwmod *oh) | 896 | int _omap_hwmod_enable(struct omap_hwmod *oh) |
899 | { | 897 | { |
@@ -1004,11 +1002,10 @@ static int _shutdown(struct omap_hwmod *oh) | |||
1004 | * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1 | 1002 | * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1 |
1005 | * | 1003 | * |
1006 | * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh | 1004 | * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh |
1007 | * OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex held. | 1005 | * OCP_SYSCONFIG register. @skip_setup_idle is intended to be used on |
1008 | * @skip_setup_idle is intended to be used on a system that will not | 1006 | * a system that will not call omap_hwmod_enable() to enable devices |
1009 | * call omap_hwmod_enable() to enable devices (e.g., a system without | 1007 | * (e.g., a system without PM runtime). Returns -EINVAL if the hwmod |
1010 | * PM runtime). Returns -EINVAL if the hwmod is in the wrong state or | 1008 | * is in the wrong state or returns 0. |
1011 | * returns 0. | ||
1012 | */ | 1009 | */ |
1013 | static int _setup(struct omap_hwmod *oh, void *data) | 1010 | static int _setup(struct omap_hwmod *oh, void *data) |
1014 | { | 1011 | { |
@@ -1038,6 +1035,7 @@ static int _setup(struct omap_hwmod *oh, void *data) | |||
1038 | } | 1035 | } |
1039 | } | 1036 | } |
1040 | 1037 | ||
1038 | mutex_init(&oh->_mutex); | ||
1041 | oh->_state = _HWMOD_STATE_INITIALIZED; | 1039 | oh->_state = _HWMOD_STATE_INITIALIZED; |
1042 | 1040 | ||
1043 | r = _omap_hwmod_enable(oh); | 1041 | r = _omap_hwmod_enable(oh); |
@@ -1323,9 +1321,9 @@ int omap_hwmod_enable(struct omap_hwmod *oh) | |||
1323 | if (!oh) | 1321 | if (!oh) |
1324 | return -EINVAL; | 1322 | return -EINVAL; |
1325 | 1323 | ||
1326 | mutex_lock(&omap_hwmod_mutex); | 1324 | mutex_lock(&oh->_mutex); |
1327 | r = _omap_hwmod_enable(oh); | 1325 | r = _omap_hwmod_enable(oh); |
1328 | mutex_unlock(&omap_hwmod_mutex); | 1326 | mutex_unlock(&oh->_mutex); |
1329 | 1327 | ||
1330 | return r; | 1328 | return r; |
1331 | } | 1329 | } |
@@ -1343,9 +1341,9 @@ int omap_hwmod_idle(struct omap_hwmod *oh) | |||
1343 | if (!oh) | 1341 | if (!oh) |
1344 | return -EINVAL; | 1342 | return -EINVAL; |
1345 | 1343 | ||
1346 | mutex_lock(&omap_hwmod_mutex); | 1344 | mutex_lock(&oh->_mutex); |
1347 | _omap_hwmod_idle(oh); | 1345 | _omap_hwmod_idle(oh); |
1348 | mutex_unlock(&omap_hwmod_mutex); | 1346 | mutex_unlock(&oh->_mutex); |
1349 | 1347 | ||
1350 | return 0; | 1348 | return 0; |
1351 | } | 1349 | } |
@@ -1363,9 +1361,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh) | |||
1363 | if (!oh) | 1361 | if (!oh) |
1364 | return -EINVAL; | 1362 | return -EINVAL; |
1365 | 1363 | ||
1366 | mutex_lock(&omap_hwmod_mutex); | 1364 | mutex_lock(&oh->_mutex); |
1367 | _shutdown(oh); | 1365 | _shutdown(oh); |
1368 | mutex_unlock(&omap_hwmod_mutex); | 1366 | mutex_unlock(&oh->_mutex); |
1369 | 1367 | ||
1370 | return 0; | 1368 | return 0; |
1371 | } | 1369 | } |
@@ -1378,9 +1376,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh) | |||
1378 | */ | 1376 | */ |
1379 | int omap_hwmod_enable_clocks(struct omap_hwmod *oh) | 1377 | int omap_hwmod_enable_clocks(struct omap_hwmod *oh) |
1380 | { | 1378 | { |
1381 | mutex_lock(&omap_hwmod_mutex); | 1379 | mutex_lock(&oh->_mutex); |
1382 | _enable_clocks(oh); | 1380 | _enable_clocks(oh); |
1383 | mutex_unlock(&omap_hwmod_mutex); | 1381 | mutex_unlock(&oh->_mutex); |
1384 | 1382 | ||
1385 | return 0; | 1383 | return 0; |
1386 | } | 1384 | } |
@@ -1393,9 +1391,9 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh) | |||
1393 | */ | 1391 | */ |
1394 | int omap_hwmod_disable_clocks(struct omap_hwmod *oh) | 1392 | int omap_hwmod_disable_clocks(struct omap_hwmod *oh) |
1395 | { | 1393 | { |
1396 | mutex_lock(&omap_hwmod_mutex); | 1394 | mutex_lock(&oh->_mutex); |
1397 | _disable_clocks(oh); | 1395 | _disable_clocks(oh); |
1398 | mutex_unlock(&omap_hwmod_mutex); | 1396 | mutex_unlock(&oh->_mutex); |
1399 | 1397 | ||
1400 | return 0; | 1398 | return 0; |
1401 | } | 1399 | } |
@@ -1443,9 +1441,9 @@ int omap_hwmod_reset(struct omap_hwmod *oh) | |||
1443 | if (!oh) | 1441 | if (!oh) |
1444 | return -EINVAL; | 1442 | return -EINVAL; |
1445 | 1443 | ||
1446 | mutex_lock(&omap_hwmod_mutex); | 1444 | mutex_lock(&oh->_mutex); |
1447 | r = _reset(oh); | 1445 | r = _reset(oh); |
1448 | mutex_unlock(&omap_hwmod_mutex); | 1446 | mutex_unlock(&oh->_mutex); |
1449 | 1447 | ||
1450 | return r; | 1448 | return r; |
1451 | } | 1449 | } |
@@ -1646,9 +1644,9 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) | |||
1646 | !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) | 1644 | !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) |
1647 | return -EINVAL; | 1645 | return -EINVAL; |
1648 | 1646 | ||
1649 | mutex_lock(&omap_hwmod_mutex); | 1647 | mutex_lock(&oh->_mutex); |
1650 | _enable_wakeup(oh); | 1648 | _enable_wakeup(oh); |
1651 | mutex_unlock(&omap_hwmod_mutex); | 1649 | mutex_unlock(&oh->_mutex); |
1652 | 1650 | ||
1653 | return 0; | 1651 | return 0; |
1654 | } | 1652 | } |
@@ -1671,9 +1669,9 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh) | |||
1671 | !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) | 1669 | !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) |
1672 | return -EINVAL; | 1670 | return -EINVAL; |
1673 | 1671 | ||
1674 | mutex_lock(&omap_hwmod_mutex); | 1672 | mutex_lock(&oh->_mutex); |
1675 | _disable_wakeup(oh); | 1673 | _disable_wakeup(oh); |
1676 | mutex_unlock(&omap_hwmod_mutex); | 1674 | mutex_unlock(&oh->_mutex); |
1677 | 1675 | ||
1678 | return 0; | 1676 | return 0; |
1679 | } | 1677 | } |
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 5506d80d94b9..03350bac01d8 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
36 | #include <linux/list.h> | 36 | #include <linux/list.h> |
37 | #include <linux/ioport.h> | 37 | #include <linux/ioport.h> |
38 | #include <linux/mutex.h> | ||
38 | #include <plat/cpu.h> | 39 | #include <plat/cpu.h> |
39 | 40 | ||
40 | struct omap_device; | 41 | struct omap_device; |
@@ -433,6 +434,7 @@ struct omap_hwmod_class { | |||
433 | * @_state: internal-use hwmod state | 434 | * @_state: internal-use hwmod state |
434 | * @flags: hwmod flags (documented below) | 435 | * @flags: hwmod flags (documented below) |
435 | * @omap_chip: OMAP chips this hwmod is present on | 436 | * @omap_chip: OMAP chips this hwmod is present on |
437 | * @_mutex: mutex serializing operations on this hwmod | ||
436 | * @node: list node for hwmod list (internal use) | 438 | * @node: list node for hwmod list (internal use) |
437 | * | 439 | * |
438 | * @main_clk refers to this module's "main clock," which for our | 440 | * @main_clk refers to this module's "main clock," which for our |
@@ -461,6 +463,7 @@ struct omap_hwmod { | |||
461 | void *dev_attr; | 463 | void *dev_attr; |
462 | u32 _sysc_cache; | 464 | u32 _sysc_cache; |
463 | void __iomem *_mpu_rt_va; | 465 | void __iomem *_mpu_rt_va; |
466 | struct mutex _mutex; | ||
464 | struct list_head node; | 467 | struct list_head node; |
465 | u16 flags; | 468 | u16 flags; |
466 | u8 _mpu_port_index; | 469 | u8 _mpu_port_index; |