aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c168
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h17
2 files changed, 177 insertions, 8 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 3084409ad1dc..f4a569c74700 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -50,11 +50,13 @@
50#include <plat/powerdomain.h> 50#include <plat/powerdomain.h>
51#include <plat/clock.h> 51#include <plat/clock.h>
52#include <plat/omap_hwmod.h> 52#include <plat/omap_hwmod.h>
53#include <plat/prcm.h>
53 54
54#include "cm.h" 55#include "cm.h"
56#include "prm.h"
55 57
56/* Maximum microseconds to wait for OMAP module to reset */ 58/* Maximum microseconds to wait for OMAP module to softreset */
57#define MAX_MODULE_RESET_WAIT 10000 59#define MAX_MODULE_SOFTRESET_WAIT 10000
58 60
59/* Name of the OMAP hwmod for the MPU */ 61/* Name of the OMAP hwmod for the MPU */
60#define MPU_INITIATOR_NAME "mpu" 62#define MPU_INITIATOR_NAME "mpu"
@@ -834,6 +836,130 @@ static int _wait_target_ready(struct omap_hwmod *oh)
834} 836}
835 837
836/** 838/**
839 * _lookup_hardreset - return the register bit shift for this hwmod/reset line
840 * @oh: struct omap_hwmod *
841 * @name: name of the reset line in the context of this hwmod
842 *
843 * Return the bit position of the reset line that match the
844 * input name. Return -ENOENT if not found.
845 */
846static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
847{
848 int i;
849
850 for (i = 0; i < oh->rst_lines_cnt; i++) {
851 const char *rst_line = oh->rst_lines[i].name;
852 if (!strcmp(rst_line, name)) {
853 u8 shift = oh->rst_lines[i].rst_shift;
854 pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
855 oh->name, rst_line, shift);
856
857 return shift;
858 }
859 }
860
861 return -ENOENT;
862}
863
864/**
865 * _assert_hardreset - assert the HW reset line of submodules
866 * contained in the hwmod module.
867 * @oh: struct omap_hwmod *
868 * @name: name of the reset line to lookup and assert
869 *
870 * Some IP like dsp, ipu or iva contain processor that require
871 * an HW reset line to be assert / deassert in order to enable fully
872 * the IP.
873 */
874static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
875{
876 u8 shift;
877
878 if (!oh)
879 return -EINVAL;
880
881 shift = _lookup_hardreset(oh, name);
882 if (IS_ERR_VALUE(shift))
883 return shift;
884
885 if (cpu_is_omap24xx() || cpu_is_omap34xx())
886 return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
887 shift);
888 else if (cpu_is_omap44xx())
889 return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
890 shift);
891 else
892 return -EINVAL;
893}
894
895/**
896 * _deassert_hardreset - deassert the HW reset line of submodules contained
897 * in the hwmod module.
898 * @oh: struct omap_hwmod *
899 * @name: name of the reset line to look up and deassert
900 *
901 * Some IP like dsp, ipu or iva contain processor that require
902 * an HW reset line to be assert / deassert in order to enable fully
903 * the IP.
904 */
905static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
906{
907 u8 shift;
908 int r;
909
910 if (!oh)
911 return -EINVAL;
912
913 shift = _lookup_hardreset(oh, name);
914 if (IS_ERR_VALUE(shift))
915 return shift;
916
917 if (cpu_is_omap24xx() || cpu_is_omap34xx())
918 r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
919 shift);
920 else if (cpu_is_omap44xx())
921 r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
922 shift);
923 else
924 return -EINVAL;
925
926 if (r == -EBUSY)
927 pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
928
929 return r;
930}
931
932/**
933 * _read_hardreset - read the HW reset line state of submodules
934 * contained in the hwmod module
935 * @oh: struct omap_hwmod *
936 * @name: name of the reset line to look up and read
937 *
938 * Return the state of the reset line.
939 */
940static int _read_hardreset(struct omap_hwmod *oh, const char *name)
941{
942 u8 shift;
943
944 if (!oh)
945 return -EINVAL;
946
947 shift = _lookup_hardreset(oh, name);
948 if (IS_ERR_VALUE(shift))
949 return shift;
950
951 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
952 return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
953 shift);
954 } else if (cpu_is_omap44xx()) {
955 return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
956 shift);
957 } else {
958 return -EINVAL;
959 }
960}
961
962/**
837 * _reset - reset an omap_hwmod 963 * _reset - reset an omap_hwmod
838 * @oh: struct omap_hwmod * 964 * @oh: struct omap_hwmod *
839 * 965 *
@@ -869,20 +995,20 @@ static int _reset(struct omap_hwmod *oh)
869 995
870 omap_test_timeout((omap_hwmod_readl(oh, oh->class->sysc->syss_offs) & 996 omap_test_timeout((omap_hwmod_readl(oh, oh->class->sysc->syss_offs) &
871 SYSS_RESETDONE_MASK), 997 SYSS_RESETDONE_MASK),
872 MAX_MODULE_RESET_WAIT, c); 998 MAX_MODULE_SOFTRESET_WAIT, c);
873 999
874 if (c == MAX_MODULE_RESET_WAIT) 1000 if (c == MAX_MODULE_SOFTRESET_WAIT)
875 WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n", 1001 WARN(1, "omap_hwmod: %s: softreset failed (waited %d usec)\n",
876 oh->name, MAX_MODULE_RESET_WAIT); 1002 oh->name, MAX_MODULE_SOFTRESET_WAIT);
877 else 1003 else
878 pr_debug("omap_hwmod: %s: reset in %d usec\n", oh->name, c); 1004 pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
879 1005
880 /* 1006 /*
881 * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from 1007 * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
882 * _wait_target_ready() or _reset() 1008 * _wait_target_ready() or _reset()
883 */ 1009 */
884 1010
885 return (c == MAX_MODULE_RESET_WAIT) ? -ETIMEDOUT : 0; 1011 return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
886} 1012}
887 1013
888/** 1014/**
@@ -907,6 +1033,15 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
907 1033
908 pr_debug("omap_hwmod: %s: enabling\n", oh->name); 1034 pr_debug("omap_hwmod: %s: enabling\n", oh->name);
909 1035
1036 /*
1037 * If an IP contains only one HW reset line, then de-assert it in order
1038 * to allow to enable the clocks. Otherwise the PRCM will return
1039 * Intransition status, and the init will failed.
1040 */
1041 if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
1042 oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
1043 _deassert_hardreset(oh, oh->rst_lines[0].name);
1044
910 /* XXX mux balls */ 1045 /* XXX mux balls */
911 1046
912 _add_initiator_dep(oh, mpu_oh); 1047 _add_initiator_dep(oh, mpu_oh);
@@ -981,6 +1116,13 @@ static int _shutdown(struct omap_hwmod *oh)
981 if (oh->class->sysc) 1116 if (oh->class->sysc)
982 _sysc_shutdown(oh); 1117 _sysc_shutdown(oh);
983 1118
1119 /*
1120 * If an IP contains only one HW reset line, then assert it
1121 * before disabling the clocks and shutting down the IP.
1122 */
1123 if (oh->rst_lines_cnt == 1)
1124 _assert_hardreset(oh, oh->rst_lines[0].name);
1125
984 /* clocks and deps are already disabled in idle */ 1126 /* clocks and deps are already disabled in idle */
985 if (oh->_state == _HWMOD_STATE_ENABLED) { 1127 if (oh->_state == _HWMOD_STATE_ENABLED) {
986 _del_initiator_dep(oh, mpu_oh); 1128 _del_initiator_dep(oh, mpu_oh);
@@ -1038,6 +1180,16 @@ static int _setup(struct omap_hwmod *oh, void *data)
1038 mutex_init(&oh->_mutex); 1180 mutex_init(&oh->_mutex);
1039 oh->_state = _HWMOD_STATE_INITIALIZED; 1181 oh->_state = _HWMOD_STATE_INITIALIZED;
1040 1182
1183 /*
1184 * In the case of hwmod with hardreset that should not be
1185 * de-assert at boot time, we have to keep the module
1186 * initialized, because we cannot enable it properly with the
1187 * reset asserted. Exit without warning because that behavior is
1188 * expected.
1189 */
1190 if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
1191 return 0;
1192
1041 r = _omap_hwmod_enable(oh); 1193 r = _omap_hwmod_enable(oh);
1042 if (r) { 1194 if (r) {
1043 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n", 1195 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 03350bac01d8..590bfae250e8 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -109,6 +109,19 @@ struct omap_hwmod_dma_info {
109}; 109};
110 110
111/** 111/**
112 * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
113 * @name: name of the reset line (module local name)
114 * @rst_shift: Offset of the reset bit
115 *
116 * @name should be something short, e.g., "cpu0" or "rst". It is defined
117 * locally to the hwmod.
118 */
119struct omap_hwmod_rst_info {
120 const char *name;
121 u8 rst_shift;
122};
123
124/**
112 * struct omap_hwmod_opt_clk - optional clocks used by this hwmod 125 * struct omap_hwmod_opt_clk - optional clocks used by this hwmod
113 * @role: "sys", "32k", "tv", etc -- for use in clk_get() 126 * @role: "sys", "32k", "tv", etc -- for use in clk_get()
114 * @clk: opt clock: OMAP clock name 127 * @clk: opt clock: OMAP clock name
@@ -328,10 +341,12 @@ struct omap_hwmod_omap2_prcm {
328/** 341/**
329 * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data 342 * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
330 * @clkctrl_reg: PRCM address of the clock control register 343 * @clkctrl_reg: PRCM address of the clock control register
344 * @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
331 * @submodule_wkdep_bit: bit shift of the WKDEP range 345 * @submodule_wkdep_bit: bit shift of the WKDEP range
332 */ 346 */
333struct omap_hwmod_omap4_prcm { 347struct omap_hwmod_omap4_prcm {
334 void __iomem *clkctrl_reg; 348 void __iomem *clkctrl_reg;
349 void __iomem *rstctrl_reg;
335 u8 submodule_wkdep_bit; 350 u8 submodule_wkdep_bit;
336}; 351};
337 352
@@ -451,6 +466,7 @@ struct omap_hwmod {
451 struct omap_device *od; 466 struct omap_device *od;
452 struct omap_hwmod_irq_info *mpu_irqs; 467 struct omap_hwmod_irq_info *mpu_irqs;
453 struct omap_hwmod_dma_info *sdma_reqs; 468 struct omap_hwmod_dma_info *sdma_reqs;
469 struct omap_hwmod_rst_info *rst_lines;
454 union { 470 union {
455 struct omap_hwmod_omap2_prcm omap2; 471 struct omap_hwmod_omap2_prcm omap2;
456 struct omap_hwmod_omap4_prcm omap4; 472 struct omap_hwmod_omap4_prcm omap4;
@@ -472,6 +488,7 @@ struct omap_hwmod {
472 u8 response_lat; 488 u8 response_lat;
473 u8 mpu_irqs_cnt; 489 u8 mpu_irqs_cnt;
474 u8 sdma_reqs_cnt; 490 u8 sdma_reqs_cnt;
491 u8 rst_lines_cnt;
475 u8 opt_clks_cnt; 492 u8 opt_clks_cnt;
476 u8 masters_cnt; 493 u8 masters_cnt;
477 u8 slaves_cnt; 494 u8 slaves_cnt;