| 
					
				 | 
			
			
				@@ -1654,3 +1654,169 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	int ret = -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	int hwsup = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!oh) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!soc_ops.deassert_hardreset) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -ENOSYS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ret = _lookup_hardreset(oh, name, &ohri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (IS_ERR_VALUE(ret)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (oh->clkdm) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * A clockdomain must be in SW_SUP otherwise reset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * might not be completed. The clockdomain can be set 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * in HW_AUTO only when the module become ready. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		hwsup = clkdm_in_hwsup(oh->clkdm); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ret = clkdm_hwmod_enable(oh->clkdm, oh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (ret) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			     oh->name, oh->clkdm->name, ret); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	_enable_clocks(oh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (soc_ops.enable_module) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		soc_ops.enable_module(oh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ret = soc_ops.deassert_hardreset(oh, &ohri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (soc_ops.disable_module) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		soc_ops.disable_module(oh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	_disable_clocks(oh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (ret == -EBUSY) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!ret) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * Set the clockdomain to HW_AUTO, assuming that the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * previous state was HW_AUTO. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (oh->clkdm && hwsup) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			clkdm_allow_idle(oh->clkdm); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (oh->clkdm) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			clkdm_hwmod_disable(oh->clkdm, oh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _read_hardreset - read the HW reset line state of submodules 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * contained in the hwmod module 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @oh: struct omap_hwmod * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @name: name of the reset line to look up and read 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Return the state of the reset line.  Returns -EINVAL if @oh is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * null, -ENOSYS if we have no way of reading the hardreset line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * status on the currently-booted SoC, or passes along the return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * value from _lookup_hardreset() or the SoC's is_hardreset_asserted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * code. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int _read_hardreset(struct omap_hwmod *oh, const char *name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct omap_hwmod_rst_info ohri; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int ret = -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!oh) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!soc_ops.is_hardreset_asserted) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -ENOSYS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ret = _lookup_hardreset(oh, name, &ohri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (ret < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return soc_ops.is_hardreset_asserted(oh, &ohri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _are_all_hardreset_lines_asserted - return true if the @oh is hard-reset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @oh: struct omap_hwmod * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If all hardreset lines associated with @oh are asserted, then return true. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Otherwise, if part of @oh is out hardreset or if no hardreset lines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * associated with @oh are asserted, then return false. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This function is used to avoid executing some parts of the IP block 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * enable/disable sequence if its hardreset line is set. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool _are_all_hardreset_lines_asserted(struct omap_hwmod *oh) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int i, rst_cnt = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (oh->rst_lines_cnt == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for (i = 0; i < oh->rst_lines_cnt; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (_read_hardreset(oh, oh->rst_lines[i].name) > 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			rst_cnt++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (oh->rst_lines_cnt == rst_cnt) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _are_any_hardreset_lines_asserted - return true if any part of @oh is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * hard-reset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @oh: struct omap_hwmod * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If any hardreset lines associated with @oh are asserted, then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * return true.  Otherwise, if no hardreset lines associated with @oh 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * are asserted, or if @oh has no hardreset lines, then return false. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This function is used to avoid executing some parts of the IP block 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * enable/disable sequence if any hardreset line is set. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int rst_cnt = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for (i = 0; i < oh->rst_lines_cnt && rst_cnt == 0; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (_read_hardreset(oh, oh->rst_lines[i].name) > 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			rst_cnt++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return (rst_cnt) ? true : false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @oh: struct omap_hwmod * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Disable the PRCM module mode related to the hwmod @oh. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Return EINVAL if the modulemode is not supported and 0 in case of success. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int _omap4_disable_module(struct omap_hwmod *oh) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int v; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!oh->clkdm || !oh->prcm.omap4.modulemode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Since integration code might still be doing something, only 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * disable if all lines are under hardreset. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (_are_any_hardreset_lines_asserted(oh)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap4_cminst_module_disable(oh->clkdm->prcm_partition, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				    oh->clkdm->cm_inst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				    oh->clkdm->clkdm_offs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				    oh->prcm.omap4.clkctrl_offs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	v = _omap4_wait_target_disable(oh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			oh->name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 |