forked from Minki/linux
d8871cd245
Done in preparation to make PRM its own driver, as the cpu_is_XXX calls are not available outside mach-omap2 folder. The init functions are called only from cpu specific init chain, and thus don't need to double check against cpu type. The exit calls check against the data provided during init-time registration and thus don't need cpu check either. Signed-off-by: Tero Kristo <t-kristo@ti.com> [paul@pwsan.com: updated to apply] Signed-off-by: Paul Walmsley <paul@pwsan.com>
209 lines
5.4 KiB
C
209 lines
5.4 KiB
C
/*
|
|
* OMAP2xxx PRM module functions
|
|
*
|
|
* Copyright (C) 2010-2012 Texas Instruments, Inc.
|
|
* Copyright (C) 2010 Nokia Corporation
|
|
* Benoît Cousson
|
|
* Paul Walmsley
|
|
* Rajendra Nayak <rnayak@ti.com>
|
|
*
|
|
* 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/errno.h>
|
|
#include <linux/err.h>
|
|
#include <linux/io.h>
|
|
#include <linux/irq.h>
|
|
|
|
#include "powerdomain.h"
|
|
#include "clockdomain.h"
|
|
#include "prm2xxx.h"
|
|
#include "cm2xxx_3xxx.h"
|
|
#include "prm-regbits-24xx.h"
|
|
|
|
/*
|
|
* OMAP24xx PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED bits -
|
|
* these are reversed from the bits used on OMAP3+
|
|
*/
|
|
#define OMAP24XX_PWRDM_POWER_ON 0x0
|
|
#define OMAP24XX_PWRDM_POWER_RET 0x1
|
|
#define OMAP24XX_PWRDM_POWER_OFF 0x3
|
|
|
|
/*
|
|
* omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
|
|
* hardware register (which are specific to the OMAP2xxx SoCs) to
|
|
* reset source ID bit shifts (which is an OMAP SoC-independent
|
|
* enumeration)
|
|
*/
|
|
static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
|
|
{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
|
|
{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
|
|
{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
|
|
{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
|
|
{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
|
|
{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
|
|
{ -1, -1 },
|
|
};
|
|
|
|
/**
|
|
* omap2xxx_prm_read_reset_sources - return the last SoC reset source
|
|
*
|
|
* Return a u32 representing the last reset sources of the SoC. The
|
|
* returned reset source bits are standardized across OMAP SoCs.
|
|
*/
|
|
static u32 omap2xxx_prm_read_reset_sources(void)
|
|
{
|
|
struct prm_reset_src_map *p;
|
|
u32 r = 0;
|
|
u32 v;
|
|
|
|
v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
|
|
|
|
p = omap2xxx_prm_reset_src_map;
|
|
while (p->reg_shift >= 0 && p->std_shift >= 0) {
|
|
if (v & (1 << p->reg_shift))
|
|
r |= 1 << p->std_shift;
|
|
p++;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst
|
|
* @omap2xxx_pwrst: OMAP2xxx hardware power state to convert
|
|
*
|
|
* Return the common power state bits corresponding to the OMAP2xxx
|
|
* hardware power state bits @omap2xxx_pwrst, or -EINVAL upon error.
|
|
*/
|
|
static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)
|
|
{
|
|
u8 pwrst;
|
|
|
|
switch (omap2xxx_pwrst) {
|
|
case OMAP24XX_PWRDM_POWER_OFF:
|
|
pwrst = PWRDM_POWER_OFF;
|
|
break;
|
|
case OMAP24XX_PWRDM_POWER_RET:
|
|
pwrst = PWRDM_POWER_RET;
|
|
break;
|
|
case OMAP24XX_PWRDM_POWER_ON:
|
|
pwrst = PWRDM_POWER_ON;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
return pwrst;
|
|
}
|
|
|
|
/**
|
|
* omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
|
|
*
|
|
* Set the DPLL reset bit, which should reboot the SoC. This is the
|
|
* recommended way to restart the SoC. No return value.
|
|
*/
|
|
void omap2xxx_prm_dpll_reset(void)
|
|
{
|
|
omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
|
|
OMAP2_RM_RSTCTRL);
|
|
/* OCP barrier */
|
|
omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
|
|
}
|
|
|
|
int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
|
|
{
|
|
omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
|
|
clkdm->pwrdm.ptr->prcm_offs,
|
|
OMAP2_PM_PWSTCTRL);
|
|
return 0;
|
|
}
|
|
|
|
int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
|
|
{
|
|
omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
|
|
clkdm->pwrdm.ptr->prcm_offs,
|
|
OMAP2_PM_PWSTCTRL);
|
|
return 0;
|
|
}
|
|
|
|
static int omap2xxx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
|
{
|
|
u8 omap24xx_pwrst;
|
|
|
|
switch (pwrst) {
|
|
case PWRDM_POWER_OFF:
|
|
omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF;
|
|
break;
|
|
case PWRDM_POWER_RET:
|
|
omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET;
|
|
break;
|
|
case PWRDM_POWER_ON:
|
|
omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
|
|
(omap24xx_pwrst << OMAP_POWERSTATE_SHIFT),
|
|
pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
|
|
return 0;
|
|
}
|
|
|
|
static int omap2xxx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
|
{
|
|
u8 omap2xxx_pwrst;
|
|
|
|
omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
OMAP2_PM_PWSTCTRL,
|
|
OMAP_POWERSTATE_MASK);
|
|
|
|
return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
|
|
}
|
|
|
|
static int omap2xxx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
|
{
|
|
u8 omap2xxx_pwrst;
|
|
|
|
omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
OMAP2_PM_PWSTST,
|
|
OMAP_POWERSTATEST_MASK);
|
|
|
|
return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
|
|
}
|
|
|
|
struct pwrdm_ops omap2_pwrdm_operations = {
|
|
.pwrdm_set_next_pwrst = omap2xxx_pwrdm_set_next_pwrst,
|
|
.pwrdm_read_next_pwrst = omap2xxx_pwrdm_read_next_pwrst,
|
|
.pwrdm_read_pwrst = omap2xxx_pwrdm_read_pwrst,
|
|
.pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
|
|
.pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
|
|
.pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
|
|
.pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
|
|
.pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
|
|
.pwrdm_wait_transition = omap2_pwrdm_wait_transition,
|
|
};
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
static struct prm_ll_data omap2xxx_prm_ll_data = {
|
|
.read_reset_sources = &omap2xxx_prm_read_reset_sources,
|
|
};
|
|
|
|
int __init omap2xxx_prm_init(void)
|
|
{
|
|
return prm_register(&omap2xxx_prm_ll_data);
|
|
}
|
|
|
|
static void __exit omap2xxx_prm_exit(void)
|
|
{
|
|
prm_unregister(&omap2xxx_prm_ll_data);
|
|
}
|
|
__exitcall(omap2xxx_prm_exit);
|