 72350b29a4
			
		
	
	
	72350b29a4
	
	
	
		
			
			Some OMAP2/3 hardware modules have CM_IDLEST attributes that are not handled by the current omap2_wait_clock_ready() code. In preparation for patches that fix the unusual devices, rename the function omap2_wait_clock_ready() to omap2_wait_module_ready() and split it into three parts: 1. A clkops-specific companion clock return function (by default, omap2_clk_dflt_find_companion()) 2. A clkops-specific CM_IDLEST register address and bit shift return function (by default, omap2_clk_dflt_find_idlest()) 3. Code to wait for the CM to indicate that the module is ready (omap2_cm_wait_idlest()) Clocks can now specify their own custom find_companion() and find_idlest() functions; used in subsequent patches. Signed-off-by: Paul Walmsley <paul@pwsan.com>
		
			
				
	
	
		
			170 lines
		
	
	
	
		
			4.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
	
		
			4.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * linux/arch/arm/mach-omap2/prcm.c
 | |
|  *
 | |
|  * OMAP 24xx Power Reset and Clock Management (PRCM) functions
 | |
|  *
 | |
|  * Copyright (C) 2005 Nokia Corporation
 | |
|  *
 | |
|  * Written by Tony Lindgren <tony.lindgren@nokia.com>
 | |
|  *
 | |
|  * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License version 2 as
 | |
|  * published by the Free Software Foundation.
 | |
|  */
 | |
| #include <linux/module.h>
 | |
| #include <linux/init.h>
 | |
| #include <linux/clk.h>
 | |
| #include <linux/io.h>
 | |
| #include <linux/delay.h>
 | |
| 
 | |
| #include <mach/common.h>
 | |
| #include <mach/prcm.h>
 | |
| 
 | |
| #include "clock.h"
 | |
| #include "prm.h"
 | |
| #include "prm-regbits-24xx.h"
 | |
| 
 | |
| static void __iomem *prm_base;
 | |
| static void __iomem *cm_base;
 | |
| 
 | |
| #define MAX_MODULE_ENABLE_WAIT		100000
 | |
| 
 | |
| u32 omap_prcm_get_reset_sources(void)
 | |
| {
 | |
| 	/* XXX This presumably needs modification for 34XX */
 | |
| 	return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f;
 | |
| }
 | |
| EXPORT_SYMBOL(omap_prcm_get_reset_sources);
 | |
| 
 | |
| /* Resets clock rates and reboots the system. Only called from system.h */
 | |
| void omap_prcm_arch_reset(char mode)
 | |
| {
 | |
| 	s16 prcm_offs;
 | |
| 	omap2_clk_prepare_for_reboot();
 | |
| 
 | |
| 	if (cpu_is_omap24xx())
 | |
| 		prcm_offs = WKUP_MOD;
 | |
| 	else if (cpu_is_omap34xx())
 | |
| 		prcm_offs = OMAP3430_GR_MOD;
 | |
| 	else
 | |
| 		WARN_ON(1);
 | |
| 
 | |
| 	prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs, RM_RSTCTRL);
 | |
| }
 | |
| 
 | |
| static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
 | |
| {
 | |
| 	BUG_ON(!base);
 | |
| 	return __raw_readl(base + module + reg);
 | |
| }
 | |
| 
 | |
| static inline void __omap_prcm_write(u32 value, void __iomem *base,
 | |
| 						s16 module, u16 reg)
 | |
| {
 | |
| 	BUG_ON(!base);
 | |
| 	__raw_writel(value, base + module + reg);
 | |
| }
 | |
| 
 | |
| /* Read a register in a PRM module */
 | |
| u32 prm_read_mod_reg(s16 module, u16 idx)
 | |
| {
 | |
| 	return __omap_prcm_read(prm_base, module, idx);
 | |
| }
 | |
| EXPORT_SYMBOL(prm_read_mod_reg);
 | |
| 
 | |
| /* Write into a register in a PRM module */
 | |
| void prm_write_mod_reg(u32 val, s16 module, u16 idx)
 | |
| {
 | |
| 	__omap_prcm_write(val, prm_base, module, idx);
 | |
| }
 | |
| EXPORT_SYMBOL(prm_write_mod_reg);
 | |
| 
 | |
| /* Read-modify-write a register in a PRM module. Caller must lock */
 | |
| u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
 | |
| {
 | |
| 	u32 v;
 | |
| 
 | |
| 	v = prm_read_mod_reg(module, idx);
 | |
| 	v &= ~mask;
 | |
| 	v |= bits;
 | |
| 	prm_write_mod_reg(v, module, idx);
 | |
| 
 | |
| 	return v;
 | |
| }
 | |
| EXPORT_SYMBOL(prm_rmw_mod_reg_bits);
 | |
| 
 | |
| /* Read a register in a CM module */
 | |
| u32 cm_read_mod_reg(s16 module, u16 idx)
 | |
| {
 | |
| 	return __omap_prcm_read(cm_base, module, idx);
 | |
| }
 | |
| EXPORT_SYMBOL(cm_read_mod_reg);
 | |
| 
 | |
| /* Write into a register in a CM module */
 | |
| void cm_write_mod_reg(u32 val, s16 module, u16 idx)
 | |
| {
 | |
| 	__omap_prcm_write(val, cm_base, module, idx);
 | |
| }
 | |
| EXPORT_SYMBOL(cm_write_mod_reg);
 | |
| 
 | |
| /* Read-modify-write a register in a CM module. Caller must lock */
 | |
| u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
 | |
| {
 | |
| 	u32 v;
 | |
| 
 | |
| 	v = cm_read_mod_reg(module, idx);
 | |
| 	v &= ~mask;
 | |
| 	v |= bits;
 | |
| 	cm_write_mod_reg(v, module, idx);
 | |
| 
 | |
| 	return v;
 | |
| }
 | |
| EXPORT_SYMBOL(cm_rmw_mod_reg_bits);
 | |
| 
 | |
| /**
 | |
|  * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness
 | |
|  * @reg: physical address of module IDLEST register
 | |
|  * @mask: value to mask against to determine if the module is active
 | |
|  * @name: name of the clock (for printk)
 | |
|  *
 | |
|  * Returns 1 if the module indicated readiness in time, or 0 if it
 | |
|  * failed to enable in roughly MAX_MODULE_ENABLE_WAIT microseconds.
 | |
|  */
 | |
| int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name)
 | |
| {
 | |
| 	int i = 0;
 | |
| 	int ena = 0;
 | |
| 
 | |
| 	/*
 | |
| 	 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
 | |
| 	 * 34xx reverses this, just to keep us on our toes
 | |
| 	 */
 | |
| 	if (cpu_is_omap24xx())
 | |
| 		ena = mask;
 | |
| 	else if (cpu_is_omap34xx())
 | |
| 		ena = 0;
 | |
| 	else
 | |
| 		BUG();
 | |
| 
 | |
| 	/* Wait for lock */
 | |
| 	while (((__raw_readl(reg) & mask) != ena) &&
 | |
| 	       (i++ < MAX_MODULE_ENABLE_WAIT))
 | |
| 		udelay(1);
 | |
| 
 | |
| 	if (i < MAX_MODULE_ENABLE_WAIT)
 | |
| 		pr_debug("cm: Module associated with clock %s ready after %d "
 | |
| 			 "loops\n", name, i);
 | |
| 	else
 | |
| 		pr_err("cm: Module associated with clock %s didn't enable in "
 | |
| 		       "%d tries\n", name, MAX_MODULE_ENABLE_WAIT);
 | |
| 
 | |
| 	return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
 | |
| };
 | |
| 
 | |
| void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
 | |
| {
 | |
| 	prm_base = omap2_globals->prm;
 | |
| 	cm_base = omap2_globals->cm;
 | |
| }
 |