2006-04-03 00:46:20 +08: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 20:18:31 +08:00
|
|
|
* Copyright (C) 2007 Texas Instruments, Inc.
|
|
|
|
* Rajendra Nayak <rnayak@ti.com>
|
|
|
|
*
|
2006-04-03 00:46:20 +08:00
|
|
|
* Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
|
2010-01-27 11:12:51 +08:00
|
|
|
* Upgraded with OMAP4 support by Abhijit Pagare <abhijitpagare@ti.com>
|
2006-04-03 00:46:20 +08: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 17:24:44 +08:00
|
|
|
#include <linux/io.h>
|
2009-07-25 09:44:03 +08:00
|
|
|
#include <linux/delay.h>
|
2006-04-03 00:46:20 +08:00
|
|
|
|
2009-10-21 00:40:47 +08:00
|
|
|
#include <plat/common.h>
|
|
|
|
#include <plat/prcm.h>
|
2008-09-26 20:18:31 +08:00
|
|
|
#include <plat/irqs.h>
|
2008-03-18 16:04:51 +08:00
|
|
|
|
2008-07-03 17:24:44 +08:00
|
|
|
#include "clock.h"
|
2010-01-27 11:13:11 +08:00
|
|
|
#include "clock2xxx.h"
|
2010-12-22 06:30:55 +08:00
|
|
|
#include "cm2xxx_3xxx.h"
|
|
|
|
#include "cm44xx.h"
|
|
|
|
#include "prm2xxx_3xxx.h"
|
2010-12-22 06:30:54 +08:00
|
|
|
#include "prm44xx.h"
|
2008-03-18 16:04:51 +08:00
|
|
|
#include "prm-regbits-24xx.h"
|
2010-09-22 00:34:09 +08:00
|
|
|
#include "prm-regbits-44xx.h"
|
2010-10-09 01:40:20 +08:00
|
|
|
#include "control.h"
|
2006-04-03 00:46:20 +08:00
|
|
|
|
2010-12-22 06:30:55 +08:00
|
|
|
void __iomem *prm_base;
|
|
|
|
void __iomem *cm_base;
|
|
|
|
void __iomem *cm2_base;
|
2008-07-03 17:24:44 +08:00
|
|
|
|
2009-07-25 09:44:03 +08:00
|
|
|
#define MAX_MODULE_ENABLE_WAIT 100000
|
|
|
|
|
2006-04-03 00:46:20 +08:00
|
|
|
u32 omap_prcm_get_reset_sources(void)
|
|
|
|
{
|
2008-07-03 17:24:44 +08:00
|
|
|
/* XXX This presumably needs modification for 34XX */
|
2010-03-31 18:16:30 +08:00
|
|
|
if (cpu_is_omap24xx() || cpu_is_omap34xx())
|
2010-01-27 11:12:51 +08: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-25 03:05:56 +08:00
|
|
|
|
|
|
|
return 0;
|
2006-04-03 00:46:20 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(omap_prcm_get_reset_sources);
|
|
|
|
|
|
|
|
/* Resets clock rates and reboots the system. Only called from system.h */
|
2010-02-26 18:25:28 +08:00
|
|
|
void omap_prcm_arch_reset(char mode, const char *cmd)
|
2006-04-03 00:46:20 +08:00
|
|
|
{
|
2010-02-25 03:05:56 +08:00
|
|
|
s16 prcm_offs = 0;
|
2008-03-18 16:04:51 +08:00
|
|
|
|
2010-01-27 11:13:11 +08:00
|
|
|
if (cpu_is_omap24xx()) {
|
|
|
|
omap2xxx_clk_prepare_for_reboot();
|
|
|
|
|
2008-07-03 17:24:44 +08:00
|
|
|
prcm_offs = WKUP_MOD;
|
2010-01-27 11:13:11 +08:00
|
|
|
} else if (cpu_is_omap34xx()) {
|
2008-07-03 17:24:44 +08:00
|
|
|
prcm_offs = OMAP3430_GR_MOD;
|
2010-12-22 11:01:21 +08:00
|
|
|
omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
|
2010-01-27 11:12:51 +08: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-22 06:30:55 +08:00
|
|
|
prcm_offs = OMAP4430_PRM_DEVICE_INST;
|
2010-01-27 11:12:51 +08:00
|
|
|
else
|
2008-07-03 17:24:44 +08:00
|
|
|
WARN_ON(1);
|
|
|
|
|
2010-03-31 18:16:30 +08:00
|
|
|
if (cpu_is_omap24xx() || cpu_is_omap34xx())
|
2010-05-19 08:40:23 +08:00
|
|
|
prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
|
2010-01-27 11:12:51 +08:00
|
|
|
OMAP2_RM_RSTCTRL);
|
|
|
|
if (cpu_is_omap44xx())
|
2010-09-22 00:34:09 +08:00
|
|
|
prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK,
|
|
|
|
prcm_offs, OMAP4_RM_RSTCTRL);
|
2006-04-03 00:46:20 +08:00
|
|
|
}
|
2008-07-03 17:24:44 +08:00
|
|
|
|
2010-09-22 00:34:10 +08:00
|
|
|
/* Read a PRM register, AND it, and shift the result down to bit 0 */
|
|
|
|
u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
|
|
|
|
{
|
|
|
|
u32 v;
|
|
|
|
|
|
|
|
v = __raw_readl(reg);
|
|
|
|
v &= mask;
|
|
|
|
v >>= __ffs(mask);
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read-modify-write a register in a PRM module. Caller must lock */
|
|
|
|
u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
|
|
|
|
{
|
|
|
|
u32 v;
|
|
|
|
|
|
|
|
v = __raw_readl(reg);
|
|
|
|
v &= ~mask;
|
|
|
|
v |= bits;
|
|
|
|
__raw_writel(v, reg);
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
2008-07-03 17:24:44 +08:00
|
|
|
|
2009-07-25 09:44:03 +08: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-25 03:05:54 +08:00
|
|
|
* @idlest: idle state indicator (0 or 1) for the clock
|
2009-07-25 09:44:03 +08: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-22 06:30:55 +08:00
|
|
|
*
|
|
|
|
* XXX This function is deprecated. It should be removed once the
|
|
|
|
* hwmod conversion is complete.
|
2009-07-25 09:44:03 +08:00
|
|
|
*/
|
2010-02-25 03:05:54 +08:00
|
|
|
int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
|
|
|
|
const char *name)
|
2009-07-25 09:44:03 +08:00
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
int ena = 0;
|
|
|
|
|
2010-02-25 03:05:54 +08:00
|
|
|
if (idlest)
|
2009-07-25 09:44:03 +08:00
|
|
|
ena = 0;
|
|
|
|
else
|
2010-02-25 03:05:54 +08:00
|
|
|
ena = mask;
|
2009-07-25 09:44:03 +08:00
|
|
|
|
|
|
|
/* Wait for lock */
|
2009-12-09 07:33:16 +08:00
|
|
|
omap_test_timeout(((__raw_readl(reg) & mask) == ena),
|
|
|
|
MAX_MODULE_ENABLE_WAIT, i);
|
2009-07-25 09:44:03 +08: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 17:24:44 +08:00
|
|
|
void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
|
|
|
|
{
|
2010-02-15 20:33:37 +08: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 17:24:44 +08:00
|
|
|
}
|