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.c106
1 files changed, 79 insertions, 27 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index b7a4133267d8..cb911d7d1a3c 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * omap_hwmod implementation for OMAP2/3/4 2 * omap_hwmod implementation for OMAP2/3/4
3 * 3 *
4 * Copyright (C) 2009 Nokia Corporation 4 * Copyright (C) 2009-2010 Nokia Corporation
5 * 5 *
6 * Paul Walmsley, Benoît Cousson, Kevin Hilman 6 * Paul Walmsley, Benoît Cousson, Kevin Hilman
7 * 7 *
@@ -423,7 +423,7 @@ static int _init_main_clk(struct omap_hwmod *oh)
423} 423}
424 424
425/** 425/**
426 * _init_interface_clk - get a struct clk * for the the hwmod's interface clks 426 * _init_interface_clks - get a struct clk * for the the hwmod's interface clks
427 * @oh: struct omap_hwmod * 427 * @oh: struct omap_hwmod *
428 * 428 *
429 * Called from _init_clocks(). Populates the @oh OCP slave interface 429 * Called from _init_clocks(). Populates the @oh OCP slave interface
@@ -764,6 +764,7 @@ static struct omap_hwmod *_lookup(const char *name)
764/** 764/**
765 * _init_clocks - clk_get() all clocks associated with this hwmod 765 * _init_clocks - clk_get() all clocks associated with this hwmod
766 * @oh: struct omap_hwmod * 766 * @oh: struct omap_hwmod *
767 * @data: not used; pass NULL
767 * 768 *
768 * Called by omap_hwmod_late_init() (after omap2_clk_init()). 769 * Called by omap_hwmod_late_init() (after omap2_clk_init()).
769 * Resolves all clock names embedded in the hwmod. Must be called 770 * Resolves all clock names embedded in the hwmod. Must be called
@@ -771,7 +772,7 @@ static struct omap_hwmod *_lookup(const char *name)
771 * has not yet been registered or if the clocks have already been 772 * has not yet been registered or if the clocks have already been
772 * initialized, 0 on success, or a non-zero error on failure. 773 * initialized, 0 on success, or a non-zero error on failure.
773 */ 774 */
774static int _init_clocks(struct omap_hwmod *oh) 775static int _init_clocks(struct omap_hwmod *oh, void *data)
775{ 776{
776 int ret = 0; 777 int ret = 0;
777 778
@@ -886,7 +887,7 @@ static int _reset(struct omap_hwmod *oh)
886} 887}
887 888
888/** 889/**
889 * _enable - enable an omap_hwmod 890 * _omap_hwmod_enable - enable an omap_hwmod
890 * @oh: struct omap_hwmod * 891 * @oh: struct omap_hwmod *
891 * 892 *
892 * Enables an omap_hwmod @oh such that the MPU can access the hwmod's 893 * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
@@ -894,7 +895,7 @@ static int _reset(struct omap_hwmod *oh)
894 * Returns -EINVAL if the hwmod is in the wrong state or passes along 895 * Returns -EINVAL if the hwmod is in the wrong state or passes along
895 * the return value of _wait_target_ready(). 896 * the return value of _wait_target_ready().
896 */ 897 */
897static int _enable(struct omap_hwmod *oh) 898int _omap_hwmod_enable(struct omap_hwmod *oh)
898{ 899{
899 int r; 900 int r;
900 901
@@ -939,7 +940,7 @@ static int _enable(struct omap_hwmod *oh)
939 * no further work. Returns -EINVAL if the hwmod is in the wrong 940 * no further work. Returns -EINVAL if the hwmod is in the wrong
940 * state or returns 0. 941 * state or returns 0.
941 */ 942 */
942static int _idle(struct omap_hwmod *oh) 943int _omap_hwmod_idle(struct omap_hwmod *oh)
943{ 944{
944 if (oh->_state != _HWMOD_STATE_ENABLED) { 945 if (oh->_state != _HWMOD_STATE_ENABLED) {
945 WARN(1, "omap_hwmod: %s: idle state can only be entered from " 946 WARN(1, "omap_hwmod: %s: idle state can only be entered from "
@@ -996,19 +997,25 @@ static int _shutdown(struct omap_hwmod *oh)
996/** 997/**
997 * _setup - do initial configuration of omap_hwmod 998 * _setup - do initial configuration of omap_hwmod
998 * @oh: struct omap_hwmod * 999 * @oh: struct omap_hwmod *
1000 * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
999 * 1001 *
1000 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh 1002 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
1001 * OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex 1003 * OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex held.
1002 * held. Returns -EINVAL if the hwmod is in the wrong state or returns 1004 * @skip_setup_idle is intended to be used on a system that will not
1003 * 0. 1005 * call omap_hwmod_enable() to enable devices (e.g., a system without
1006 * PM runtime). Returns -EINVAL if the hwmod is in the wrong state or
1007 * returns 0.
1004 */ 1008 */
1005static int _setup(struct omap_hwmod *oh) 1009static int _setup(struct omap_hwmod *oh, void *data)
1006{ 1010{
1007 int i, r; 1011 int i, r;
1012 u8 skip_setup_idle;
1008 1013
1009 if (!oh) 1014 if (!oh || !data)
1010 return -EINVAL; 1015 return -EINVAL;
1011 1016
1017 skip_setup_idle = *(u8 *)data;
1018
1012 /* Set iclk autoidle mode */ 1019 /* Set iclk autoidle mode */
1013 if (oh->slaves_cnt > 0) { 1020 if (oh->slaves_cnt > 0) {
1014 for (i = 0; i < oh->slaves_cnt; i++) { 1021 for (i = 0; i < oh->slaves_cnt; i++) {
@@ -1029,7 +1036,7 @@ static int _setup(struct omap_hwmod *oh)
1029 1036
1030 oh->_state = _HWMOD_STATE_INITIALIZED; 1037 oh->_state = _HWMOD_STATE_INITIALIZED;
1031 1038
1032 r = _enable(oh); 1039 r = _omap_hwmod_enable(oh);
1033 if (r) { 1040 if (r) {
1034 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n", 1041 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
1035 oh->name, oh->_state); 1042 oh->name, oh->_state);
@@ -1041,7 +1048,7 @@ static int _setup(struct omap_hwmod *oh)
1041 * XXX Do the OCP_SYSCONFIG bits need to be 1048 * XXX Do the OCP_SYSCONFIG bits need to be
1042 * reprogrammed after a reset? If not, then this can 1049 * reprogrammed after a reset? If not, then this can
1043 * be removed. If they do, then probably the 1050 * be removed. If they do, then probably the
1044 * _enable() function should be split to avoid the 1051 * _omap_hwmod_enable() function should be split to avoid the
1045 * rewrite of the OCP_SYSCONFIG register. 1052 * rewrite of the OCP_SYSCONFIG register.
1046 */ 1053 */
1047 if (oh->class->sysc) { 1054 if (oh->class->sysc) {
@@ -1050,8 +1057,8 @@ static int _setup(struct omap_hwmod *oh)
1050 } 1057 }
1051 } 1058 }
1052 1059
1053 if (!(oh->flags & HWMOD_INIT_NO_IDLE)) 1060 if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle)
1054 _idle(oh); 1061 _omap_hwmod_idle(oh);
1055 1062
1056 return 0; 1063 return 0;
1057} 1064}
@@ -1062,14 +1069,29 @@ static int _setup(struct omap_hwmod *oh)
1062 1069
1063u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs) 1070u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs)
1064{ 1071{
1065 return __raw_readl(oh->_rt_va + reg_offs); 1072 return __raw_readl(oh->_mpu_rt_va + reg_offs);
1066} 1073}
1067 1074
1068void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs) 1075void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs)
1069{ 1076{
1070 __raw_writel(v, oh->_rt_va + reg_offs); 1077 __raw_writel(v, oh->_mpu_rt_va + reg_offs);
1071} 1078}
1072 1079
1080/**
1081 * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
1082 * @oh: struct omap_hwmod *
1083 * @idlemode: SIDLEMODE field bits (shifted to bit 0)
1084 *
1085 * Sets the IP block's OCP slave idlemode in hardware, and updates our
1086 * local copy. Intended to be used by drivers that have some erratum
1087 * that requires direct manipulation of the SIDLEMODE bits. Returns
1088 * -EINVAL if @oh is null, or passes along the return value from
1089 * _set_slave_idlemode().
1090 *
1091 * XXX Does this function have any current users? If not, we should
1092 * remove it; it is better to let the rest of the hwmod code handle this.
1093 * Any users of this function should be scrutinized carefully.
1094 */
1073int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode) 1095int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode)
1074{ 1096{
1075 u32 v; 1097 u32 v;
@@ -1124,7 +1146,7 @@ int omap_hwmod_register(struct omap_hwmod *oh)
1124 ms_id = _find_mpu_port_index(oh); 1146 ms_id = _find_mpu_port_index(oh);
1125 if (!IS_ERR_VALUE(ms_id)) { 1147 if (!IS_ERR_VALUE(ms_id)) {
1126 oh->_mpu_port_index = ms_id; 1148 oh->_mpu_port_index = ms_id;
1127 oh->_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index); 1149 oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
1128 } else { 1150 } else {
1129 oh->_int_flags |= _HWMOD_NO_MPU_PORT; 1151 oh->_int_flags |= _HWMOD_NO_MPU_PORT;
1130 } 1152 }
@@ -1164,6 +1186,7 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name)
1164/** 1186/**
1165 * omap_hwmod_for_each - call function for each registered omap_hwmod 1187 * omap_hwmod_for_each - call function for each registered omap_hwmod
1166 * @fn: pointer to a callback function 1188 * @fn: pointer to a callback function
1189 * @data: void * data to pass to callback function
1167 * 1190 *
1168 * Call @fn for each registered omap_hwmod, passing @data to each 1191 * Call @fn for each registered omap_hwmod, passing @data to each
1169 * function. @fn must return 0 for success or any other value for 1192 * function. @fn must return 0 for success or any other value for
@@ -1172,7 +1195,8 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name)
1172 * caller of omap_hwmod_for_each(). @fn is called with 1195 * caller of omap_hwmod_for_each(). @fn is called with
1173 * omap_hwmod_for_each() held. 1196 * omap_hwmod_for_each() held.
1174 */ 1197 */
1175int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh)) 1198int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
1199 void *data)
1176{ 1200{
1177 struct omap_hwmod *temp_oh; 1201 struct omap_hwmod *temp_oh;
1178 int ret; 1202 int ret;
@@ -1182,7 +1206,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh))
1182 1206
1183 mutex_lock(&omap_hwmod_mutex); 1207 mutex_lock(&omap_hwmod_mutex);
1184 list_for_each_entry(temp_oh, &omap_hwmod_list, node) { 1208 list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
1185 ret = (*fn)(temp_oh); 1209 ret = (*fn)(temp_oh, data);
1186 if (ret) 1210 if (ret)
1187 break; 1211 break;
1188 } 1212 }
@@ -1229,24 +1253,28 @@ int omap_hwmod_init(struct omap_hwmod **ohs)
1229 1253
1230/** 1254/**
1231 * omap_hwmod_late_init - do some post-clock framework initialization 1255 * omap_hwmod_late_init - do some post-clock framework initialization
1256 * @skip_setup_idle: if 1, do not idle hwmods in _setup()
1232 * 1257 *
1233 * Must be called after omap2_clk_init(). Resolves the struct clk names 1258 * Must be called after omap2_clk_init(). Resolves the struct clk names
1234 * to struct clk pointers for each registered omap_hwmod. Also calls 1259 * to struct clk pointers for each registered omap_hwmod. Also calls
1235 * _setup() on each hwmod. Returns 0. 1260 * _setup() on each hwmod. Returns 0.
1236 */ 1261 */
1237int omap_hwmod_late_init(void) 1262int omap_hwmod_late_init(u8 skip_setup_idle)
1238{ 1263{
1239 int r; 1264 int r;
1240 1265
1241 /* XXX check return value */ 1266 /* XXX check return value */
1242 r = omap_hwmod_for_each(_init_clocks); 1267 r = omap_hwmod_for_each(_init_clocks, NULL);
1243 WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n"); 1268 WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n");
1244 1269
1245 mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME); 1270 mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME);
1246 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n", 1271 WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
1247 MPU_INITIATOR_NAME); 1272 MPU_INITIATOR_NAME);
1248 1273
1249 omap_hwmod_for_each(_setup); 1274 if (skip_setup_idle)
1275 pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");
1276
1277 omap_hwmod_for_each(_setup, &skip_setup_idle);
1250 1278
1251 return 0; 1279 return 0;
1252} 1280}
@@ -1270,7 +1298,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh)
1270 pr_debug("omap_hwmod: %s: unregistering\n", oh->name); 1298 pr_debug("omap_hwmod: %s: unregistering\n", oh->name);
1271 1299
1272 mutex_lock(&omap_hwmod_mutex); 1300 mutex_lock(&omap_hwmod_mutex);
1273 iounmap(oh->_rt_va); 1301 iounmap(oh->_mpu_rt_va);
1274 list_del(&oh->node); 1302 list_del(&oh->node);
1275 mutex_unlock(&omap_hwmod_mutex); 1303 mutex_unlock(&omap_hwmod_mutex);
1276 1304
@@ -1292,12 +1320,13 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
1292 return -EINVAL; 1320 return -EINVAL;
1293 1321
1294 mutex_lock(&omap_hwmod_mutex); 1322 mutex_lock(&omap_hwmod_mutex);
1295 r = _enable(oh); 1323 r = _omap_hwmod_enable(oh);
1296 mutex_unlock(&omap_hwmod_mutex); 1324 mutex_unlock(&omap_hwmod_mutex);
1297 1325
1298 return r; 1326 return r;
1299} 1327}
1300 1328
1329
1301/** 1330/**
1302 * omap_hwmod_idle - idle an omap_hwmod 1331 * omap_hwmod_idle - idle an omap_hwmod
1303 * @oh: struct omap_hwmod * 1332 * @oh: struct omap_hwmod *
@@ -1311,7 +1340,7 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
1311 return -EINVAL; 1340 return -EINVAL;
1312 1341
1313 mutex_lock(&omap_hwmod_mutex); 1342 mutex_lock(&omap_hwmod_mutex);
1314 _idle(oh); 1343 _omap_hwmod_idle(oh);
1315 mutex_unlock(&omap_hwmod_mutex); 1344 mutex_unlock(&omap_hwmod_mutex);
1316 1345
1317 return 0; 1346 return 0;
@@ -1413,7 +1442,7 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
1413 mutex_lock(&omap_hwmod_mutex); 1442 mutex_lock(&omap_hwmod_mutex);
1414 r = _reset(oh); 1443 r = _reset(oh);
1415 if (!r) 1444 if (!r)
1416 r = _enable(oh); 1445 r = _omap_hwmod_enable(oh);
1417 mutex_unlock(&omap_hwmod_mutex); 1446 mutex_unlock(&omap_hwmod_mutex);
1418 1447
1419 return r; 1448 return r;
@@ -1530,6 +1559,29 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
1530} 1559}
1531 1560
1532/** 1561/**
1562 * omap_hwmod_get_mpu_rt_va - return the module's base address (for the MPU)
1563 * @oh: struct omap_hwmod *
1564 *
1565 * Returns the virtual address corresponding to the beginning of the
1566 * module's register target, in the address range that is intended to
1567 * be used by the MPU. Returns the virtual address upon success or NULL
1568 * upon error.
1569 */
1570void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh)
1571{
1572 if (!oh)
1573 return NULL;
1574
1575 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
1576 return NULL;
1577
1578 if (oh->_state == _HWMOD_STATE_UNKNOWN)
1579 return NULL;
1580
1581 return oh->_mpu_rt_va;
1582}
1583
1584/**
1533 * omap_hwmod_add_initiator_dep - add sleepdep from @init_oh to @oh 1585 * omap_hwmod_add_initiator_dep - add sleepdep from @init_oh to @oh
1534 * @oh: struct omap_hwmod * 1586 * @oh: struct omap_hwmod *
1535 * @init_oh: struct omap_hwmod * (initiator) 1587 * @init_oh: struct omap_hwmod * (initiator)