2006-04-02 16:46:20 +00:00
|
|
|
/*
|
|
|
|
* 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>
|
|
|
|
*
|
2008-09-26 12:18:31 +00:00
|
|
|
* Copyright (C) 2007 Texas Instruments, Inc.
|
|
|
|
* Rajendra Nayak <rnayak@ti.com>
|
|
|
|
*
|
2006-04-02 16:46:20 +00:00
|
|
|
* Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
|
2010-01-27 03:12:51 +00:00
|
|
|
* Upgraded with OMAP4 support by Abhijit Pagare <abhijitpagare@ti.com>
|
2006-04-02 16:46:20 +00:00
|
|
|
*
|
|
|
|
* 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>
|
2008-07-03 09:24:44 +00:00
|
|
|
#include <linux/io.h>
|
2009-07-25 01:44:03 +00:00
|
|
|
#include <linux/delay.h>
|
2006-04-02 16:46:20 +00:00
|
|
|
|
2009-10-20 16:40:47 +00:00
|
|
|
#include <plat/common.h>
|
|
|
|
#include <plat/prcm.h>
|
2008-09-26 12:18:31 +00:00
|
|
|
#include <plat/irqs.h>
|
2008-03-18 08:04:51 +00:00
|
|
|
|
2008-07-03 09:24:44 +00:00
|
|
|
#include "clock.h"
|
2010-01-27 03:13:11 +00:00
|
|
|
#include "clock2xxx.h"
|
2010-12-21 22:30:55 +00:00
|
|
|
#include "cm2xxx_3xxx.h"
|
|
|
|
#include "cm44xx.h"
|
|
|
|
#include "prm2xxx_3xxx.h"
|
2010-12-21 22:30:54 +00:00
|
|
|
#include "prm44xx.h"
|
OMAP4: PRCM: add OMAP4-specific accessor/mutator functions
In some ways, the OMAP4 PRCM register layout is quite different than
the OMAP2/3 PRCM register layout. For example, on OMAP2/3, from a
register layout point of view, all CM instances were located in the CM
subsystem, and all PRM instances were located in the PRM subsystem.
OMAP4 changes this. Now, for example, some CM instances, such as
WKUP_CM and EMU_CM, are located in the system PRM subsystem. And a
"local PRCM" exists for the MPU - this PRCM combines registers that
would normally appear in both CM and PRM instances, but uses its own
register layout which matches neither the OMAP2/3 PRCM layout nor the
OMAP4 PRCM layout.
To try to deal with this, introduce some new functions, omap4_cminst*
and omap4_prminst*. The former is to be used when writing to a CM
instance register (no matter what subsystem or hardware module it
exists in), and the latter, similarly, with PRM instance registers.
To determine which "PRCM partition" to write to, the functions take a
PRCM instance ID argument. Subsequent patches add these partition IDs
to the OMAP4 powerdomain and clockdomain definitions.
As far as I can see, there's really no good way to handle these types
of register access inconsistencies. This patch seemed like the least
bad approach.
Moving forward, the long-term goal is to remove all direct PRCM
register access from the PM code. PRCM register access should go
through layers such as the powerdomain and clockdomain code that can
hide the details of how to interact with the specific hardware
variant.
While here, rename cm4xxx.c to cm44xx.c to match the naming convention
of the other OMAP4 PRCM files.
Thanks to Santosh Shilimkar <santosh.shilimkar@ti.com>, Rajendra Nayak
<rnayak@ti.com>, and Benoît Cousson <b-cousson@ti.com> for some comments.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Benoît Cousson <b-cousson@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
2010-12-22 04:05:14 +00:00
|
|
|
#include "prcm44xx.h"
|
2008-03-18 08:04:51 +00:00
|
|
|
#include "prm-regbits-24xx.h"
|
2010-09-21 16:34:09 +00:00
|
|
|
#include "prm-regbits-44xx.h"
|
2010-10-08 17:40:20 +00:00
|
|
|
#include "control.h"
|
2006-04-02 16:46:20 +00:00
|
|
|
|
2010-12-21 22:30:55 +00:00
|
|
|
void __iomem *prm_base;
|
|
|
|
void __iomem *cm_base;
|
|
|
|
void __iomem *cm2_base;
|
2008-07-03 09:24:44 +00:00
|
|
|
|
2009-07-25 01:44:03 +00:00
|
|
|
#define MAX_MODULE_ENABLE_WAIT 100000
|
|
|
|
|
2006-04-02 16:46:20 +00:00
|
|
|
u32 omap_prcm_get_reset_sources(void)
|
|
|
|
{
|
2008-07-03 09:24:44 +00:00
|
|
|
/* XXX This presumably needs modification for 34XX */
|
2010-03-31 10:16:30 +00:00
|
|
|
if (cpu_is_omap24xx() || cpu_is_omap34xx())
|
2010-01-27 03:12:51 +00:00
|
|
|
return prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
|
|
|
|
if (cpu_is_omap44xx())
|
|
|
|
return prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
|
2010-02-24 19:05:56 +00:00
|
|
|
|
|
|
|
return 0;
|
2006-04-02 16:46:20 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(omap_prcm_get_reset_sources);
|
|
|
|
|
|
|
|
/* Resets clock rates and reboots the system. Only called from system.h */
|
2010-02-26 10:25:28 +00:00
|
|
|
void omap_prcm_arch_reset(char mode, const char *cmd)
|
2006-04-02 16:46:20 +00:00
|
|
|
{
|
2010-02-24 19:05:56 +00:00
|
|
|
s16 prcm_offs = 0;
|
2008-03-18 08:04:51 +00:00
|
|
|
|
2010-01-27 03:13:11 +00:00
|
|
|
if (cpu_is_omap24xx()) {
|
|
|
|
omap2xxx_clk_prepare_for_reboot();
|
|
|
|
|
2008-07-03 09:24:44 +00:00
|
|
|
prcm_offs = WKUP_MOD;
|
2010-01-27 03:13:11 +00:00
|
|
|
} else if (cpu_is_omap34xx()) {
|
2008-07-03 09:24:44 +00:00
|
|
|
prcm_offs = OMAP3430_GR_MOD;
|
2010-12-22 03:01:21 +00:00
|
|
|
omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
|
2010-01-27 03:12:51 +00:00
|
|
|
} else if (cpu_is_omap44xx())
|
OMAP4: PRCM: rename _MOD macros to _INST
Back in the OMAP2/3 PRCM interface days, the macros that referred to
the offsets of individual PRM/CM instances from the top of the PRM/CM
hardware modules were incorrectly suffixed with "_MOD". (They should
have been suffixed with something like "_INST" or "_INSTANCE".) These
days, now that we have better contact with the OMAP hardware people,
we know that this naming is wrong. And in fact in OMAP4, there are
actual hardware module offsets inside the instances, so the incorrect
naming gets confusing very quickly for anyone who knows the hardware.
Fix this naming for OMAP4, before things get too far along, by
changing "_MOD" to "_INST" on the end of these macros. So, for
example, OMAP4430_CM2_INSTR_MOD becomes OMAP4430_CM2_INSTR_INST.
This unfortunately creates quite a large diff, but it is a
straightforward rename. This patch should not result in any
functional changes.
The autogeneration scripts have been updated accordingly.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Benoît Cousson <b-cousson@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@deeprootsystems.com>
Tested-by: Kevin Hilman <khilman@deeprootsystems.com>
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: Rajendra Nayak <rnayak@ti.com>
2010-12-21 22:30:55 +00:00
|
|
|
prcm_offs = OMAP4430_PRM_DEVICE_INST;
|
2010-01-27 03:12:51 +00:00
|
|
|
else
|
2008-07-03 09:24:44 +00:00
|
|
|
WARN_ON(1);
|
|
|
|
|
2010-03-31 10:16:30 +00:00
|
|
|
if (cpu_is_omap24xx() || cpu_is_omap34xx())
|
2010-05-19 00:40:23 +00:00
|
|
|
prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
|
2010-01-27 03:12:51 +00:00
|
|
|
OMAP2_RM_RSTCTRL);
|
|
|
|
if (cpu_is_omap44xx())
|
2010-09-21 16:34:09 +00:00
|
|
|
prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK,
|
|
|
|
prcm_offs, OMAP4_RM_RSTCTRL);
|
2006-04-02 16:46:20 +00:00
|
|
|
}
|
2008-07-03 09:24:44 +00:00
|
|
|
|
2009-07-25 01:44:03 +00:00
|
|
|
/**
|
|
|
|
* 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
|
2010-02-24 19:05:54 +00:00
|
|
|
* @idlest: idle state indicator (0 or 1) for the clock
|
2009-07-25 01:44:03 +00:00
|
|
|
* @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.
|
2010-12-21 22:30:55 +00:00
|
|
|
*
|
|
|
|
* XXX This function is deprecated. It should be removed once the
|
|
|
|
* hwmod conversion is complete.
|
2009-07-25 01:44:03 +00:00
|
|
|
*/
|
2010-02-24 19:05:54 +00:00
|
|
|
int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
|
|
|
|
const char *name)
|
2009-07-25 01:44:03 +00:00
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
int ena = 0;
|
|
|
|
|
2010-02-24 19:05:54 +00:00
|
|
|
if (idlest)
|
2009-07-25 01:44:03 +00:00
|
|
|
ena = 0;
|
|
|
|
else
|
2010-02-24 19:05:54 +00:00
|
|
|
ena = mask;
|
2009-07-25 01:44:03 +00:00
|
|
|
|
|
|
|
/* Wait for lock */
|
2009-12-08 23:33:16 +00:00
|
|
|
omap_test_timeout(((__raw_readl(reg) & mask) == ena),
|
|
|
|
MAX_MODULE_ENABLE_WAIT, i);
|
2009-07-25 01:44:03 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2008-07-03 09:24:44 +00:00
|
|
|
void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
|
|
|
|
{
|
2010-02-15 12:33:37 +00:00
|
|
|
/* Static mapping, never released */
|
|
|
|
if (omap2_globals->prm) {
|
|
|
|
prm_base = ioremap(omap2_globals->prm, SZ_8K);
|
|
|
|
WARN_ON(!prm_base);
|
|
|
|
}
|
|
|
|
if (omap2_globals->cm) {
|
|
|
|
cm_base = ioremap(omap2_globals->cm, SZ_8K);
|
|
|
|
WARN_ON(!cm_base);
|
|
|
|
}
|
|
|
|
if (omap2_globals->cm2) {
|
|
|
|
cm2_base = ioremap(omap2_globals->cm2, SZ_8K);
|
|
|
|
WARN_ON(!cm2_base);
|
|
|
|
}
|
2008-07-03 09:24:44 +00:00
|
|
|
}
|