-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OMAP2/3/4 PRCM: add module IDLEST wait code
After a hardware module's clocks are enabled, Linux must wait for it to indicate readiness via its IDLEST bit before attempting to access the device, otherwise register accesses to the device may trigger an abort. This has traditionally been implemented in the clock framework, but this is the wrong place for it: the clock framework doesn't know which module clocks must be enabled for a module to leave idle; and if a module is not in smart-idle mode, it may never leave idle at all. This type of information is best stored in a per-hardware module data structure (coming in a following patch), rather than a per-clock data structure. The new code will use these new functions to handle waiting for modules to enable. Once hardware module data is filled in for all of the on-chip devices, the clock framework code to handle IDLEST waiting can be removed. Signed-off-by: Paul Walmsley <paul@pwsan.com>
- Loading branch information
Paul Walmsley
authored and
paul
committed
Sep 3, 2009
1 parent
c0407a9
commit 71348bc
Showing
4 changed files
with
147 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* OMAP2/3 CM module functions | ||
* | ||
* Copyright (C) 2009 Nokia Corporation | ||
* Paul Walmsley | ||
* | ||
* 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/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/types.h> | ||
#include <linux/delay.h> | ||
#include <linux/spinlock.h> | ||
#include <linux/list.h> | ||
#include <linux/errno.h> | ||
#include <linux/err.h> | ||
#include <linux/io.h> | ||
|
||
#include <asm/atomic.h> | ||
|
||
#include "cm.h" | ||
#include "cm-regbits-24xx.h" | ||
#include "cm-regbits-34xx.h" | ||
|
||
/* MAX_MODULE_READY_TIME: max milliseconds for module to leave idle */ | ||
#define MAX_MODULE_READY_TIME 20000 | ||
|
||
static const u8 cm_idlest_offs[] = { | ||
CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3 | ||
}; | ||
|
||
/** | ||
* omap2_cm_wait_idlest_ready - wait for a module to leave idle or standby | ||
* @prcm_mod: PRCM module offset | ||
* @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3) | ||
* @idlest_shift: shift of the bit in the CM_IDLEST* register to check | ||
* | ||
* XXX document | ||
*/ | ||
int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift) | ||
{ | ||
int ena = 0, i = 0; | ||
u8 cm_idlest_reg; | ||
u32 mask; | ||
|
||
if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs))) | ||
return -EINVAL; | ||
|
||
cm_idlest_reg = cm_idlest_offs[idlest_id - 1]; | ||
|
||
if (cpu_is_omap24xx()) | ||
ena = idlest_shift; | ||
else if (cpu_is_omap34xx()) | ||
ena = 0; | ||
else | ||
BUG(); | ||
|
||
mask = 1 << idlest_shift; | ||
|
||
/* XXX should be OMAP2 CM */ | ||
while (((cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) != ena) && | ||
(i++ < MAX_MODULE_READY_TIME)) | ||
udelay(1); | ||
|
||
return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* OMAP4 CM module functions | ||
* | ||
* Copyright (C) 2009 Nokia Corporation | ||
* Paul Walmsley | ||
* | ||
* 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/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/types.h> | ||
#include <linux/delay.h> | ||
#include <linux/spinlock.h> | ||
#include <linux/list.h> | ||
#include <linux/errno.h> | ||
#include <linux/err.h> | ||
#include <linux/io.h> | ||
|
||
#include <asm/atomic.h> | ||
|
||
#include "cm.h" | ||
#include "cm-regbits-4xxx.h" | ||
|
||
/* XXX move this to cm.h */ | ||
/* MAX_MODULE_READY_TIME: max milliseconds for module to leave idle */ | ||
#define MAX_MODULE_READY_TIME 20000 | ||
|
||
/* | ||
* OMAP4_PRCM_CM_CLKCTRL_IDLEST_MASK: isolates the IDLEST field in the | ||
* CM_CLKCTRL register. | ||
*/ | ||
#define OMAP4_PRCM_CM_CLKCTRL_IDLEST_MASK (0x2 << 16) | ||
|
||
/* | ||
* OMAP4 prcm_mod u32 fields contain packed data: the CM ID in bit 16 and | ||
* the PRCM module offset address (from the CM module base) in bits 15-0. | ||
*/ | ||
#define OMAP4_PRCM_MOD_CM_ID_SHIFT 16 | ||
#define OMAP4_PRCM_MOD_OFFS_MASK 0xffff | ||
|
||
/** | ||
* omap4_cm_wait_idlest_ready - wait for a module to leave idle or standby | ||
* @prcm_mod: PRCM module offset (XXX example) | ||
* @prcm_dev_offs: PRCM device offset (e.g. MCASP XXX example) | ||
* | ||
* XXX document | ||
*/ | ||
int omap4_cm_wait_idlest_ready(u32 prcm_mod, u8 prcm_dev_offs) | ||
{ | ||
int i = 0; | ||
u8 cm_id; | ||
u16 prcm_mod_offs; | ||
u32 mask = OMAP4_PRCM_CM_CLKCTRL_IDLEST_MASK; | ||
|
||
cm_id = prcm_mod >> OMAP4_PRCM_MOD_CM_ID_SHIFT; | ||
prcm_mod_offs = prcm_mod & OMAP4_PRCM_MOD_OFFS_MASK; | ||
|
||
while (((omap4_cm_read_mod_reg(cm_id, prcm_mod_offs, prcm_dev_offs, | ||
OMAP4_CM_CLKCTRL_DREG) & mask) != 0) && | ||
(i++ < MAX_MODULE_READY_TIME)) | ||
udelay(1); | ||
|
||
return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; | ||
} | ||
|