xref: /openbmc/linux/arch/arm/mach-omap2/prm2xxx.c (revision 63a293e0)
149815399SPaul Walmsley /*
249815399SPaul Walmsley  * OMAP2xxx PRM module functions
349815399SPaul Walmsley  *
449815399SPaul Walmsley  * Copyright (C) 2010-2012 Texas Instruments, Inc.
549815399SPaul Walmsley  * Copyright (C) 2010 Nokia Corporation
649815399SPaul Walmsley  * Benoît Cousson
749815399SPaul Walmsley  * Paul Walmsley
849815399SPaul Walmsley  * Rajendra Nayak <rnayak@ti.com>
949815399SPaul Walmsley  *
1049815399SPaul Walmsley  * This program is free software; you can redistribute it and/or modify
1149815399SPaul Walmsley  * it under the terms of the GNU General Public License version 2 as
1249815399SPaul Walmsley  * published by the Free Software Foundation.
1349815399SPaul Walmsley  */
1449815399SPaul Walmsley 
1549815399SPaul Walmsley #include <linux/kernel.h>
1649815399SPaul Walmsley #include <linux/errno.h>
1749815399SPaul Walmsley #include <linux/err.h>
1849815399SPaul Walmsley #include <linux/io.h>
1949815399SPaul Walmsley #include <linux/irq.h>
2049815399SPaul Walmsley 
2149815399SPaul Walmsley #include "common.h"
2249815399SPaul Walmsley #include <plat/cpu.h>
2349815399SPaul Walmsley 
2449815399SPaul Walmsley #include "vp.h"
2549815399SPaul Walmsley #include "powerdomain.h"
264bd5259eSPaul Walmsley #include "clockdomain.h"
2749815399SPaul Walmsley #include "prm2xxx.h"
2849815399SPaul Walmsley #include "cm2xxx_3xxx.h"
2949815399SPaul Walmsley #include "prm-regbits-24xx.h"
3049815399SPaul Walmsley 
312bb2a5d3SPaul Walmsley /*
322bb2a5d3SPaul Walmsley  * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
332bb2a5d3SPaul Walmsley  *   hardware register (which are specific to the OMAP2xxx SoCs) to
342bb2a5d3SPaul Walmsley  *   reset source ID bit shifts (which is an OMAP SoC-independent
352bb2a5d3SPaul Walmsley  *   enumeration)
362bb2a5d3SPaul Walmsley  */
372bb2a5d3SPaul Walmsley static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
382bb2a5d3SPaul Walmsley 	{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
392bb2a5d3SPaul Walmsley 	{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
402bb2a5d3SPaul Walmsley 	{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
412bb2a5d3SPaul Walmsley 	{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
422bb2a5d3SPaul Walmsley 	{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
432bb2a5d3SPaul Walmsley 	{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
442bb2a5d3SPaul Walmsley 	{ -1, -1 },
452bb2a5d3SPaul Walmsley };
462bb2a5d3SPaul Walmsley 
472bb2a5d3SPaul Walmsley /**
482bb2a5d3SPaul Walmsley  * omap2xxx_prm_read_reset_sources - return the last SoC reset source
492bb2a5d3SPaul Walmsley  *
502bb2a5d3SPaul Walmsley  * Return a u32 representing the last reset sources of the SoC.  The
512bb2a5d3SPaul Walmsley  * returned reset source bits are standardized across OMAP SoCs.
522bb2a5d3SPaul Walmsley  */
532bb2a5d3SPaul Walmsley static u32 omap2xxx_prm_read_reset_sources(void)
542bb2a5d3SPaul Walmsley {
552bb2a5d3SPaul Walmsley 	struct prm_reset_src_map *p;
562bb2a5d3SPaul Walmsley 	u32 r = 0;
572bb2a5d3SPaul Walmsley 	u32 v;
582bb2a5d3SPaul Walmsley 
592bb2a5d3SPaul Walmsley 	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
602bb2a5d3SPaul Walmsley 
612bb2a5d3SPaul Walmsley 	p = omap2xxx_prm_reset_src_map;
622bb2a5d3SPaul Walmsley 	while (p->reg_shift >= 0 && p->std_shift >= 0) {
632bb2a5d3SPaul Walmsley 		if (v & (1 << p->reg_shift))
642bb2a5d3SPaul Walmsley 			r |= 1 << p->std_shift;
652bb2a5d3SPaul Walmsley 		p++;
662bb2a5d3SPaul Walmsley 	}
672bb2a5d3SPaul Walmsley 
682bb2a5d3SPaul Walmsley 	return r;
692bb2a5d3SPaul Walmsley }
702bb2a5d3SPaul Walmsley 
71d08cce6aSPaul Walmsley /**
72d08cce6aSPaul Walmsley  * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
73d08cce6aSPaul Walmsley  *
74d08cce6aSPaul Walmsley  * Set the DPLL reset bit, which should reboot the SoC.  This is the
75d08cce6aSPaul Walmsley  * recommended way to restart the SoC.  No return value.
76d08cce6aSPaul Walmsley  */
77d08cce6aSPaul Walmsley void omap2xxx_prm_dpll_reset(void)
78d08cce6aSPaul Walmsley {
79d08cce6aSPaul Walmsley 	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
80d08cce6aSPaul Walmsley 				   OMAP2_RM_RSTCTRL);
81d08cce6aSPaul Walmsley 	/* OCP barrier */
82d08cce6aSPaul Walmsley 	omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
83d08cce6aSPaul Walmsley }
84d08cce6aSPaul Walmsley 
854bd5259eSPaul Walmsley int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
864bd5259eSPaul Walmsley {
874bd5259eSPaul Walmsley 	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
884bd5259eSPaul Walmsley 				   clkdm->pwrdm.ptr->prcm_offs,
894bd5259eSPaul Walmsley 				   OMAP2_PM_PWSTCTRL);
904bd5259eSPaul Walmsley 	return 0;
914bd5259eSPaul Walmsley }
924bd5259eSPaul Walmsley 
934bd5259eSPaul Walmsley int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
944bd5259eSPaul Walmsley {
954bd5259eSPaul Walmsley 	omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
964bd5259eSPaul Walmsley 				     clkdm->pwrdm.ptr->prcm_offs,
974bd5259eSPaul Walmsley 				     OMAP2_PM_PWSTCTRL);
984bd5259eSPaul Walmsley 	return 0;
994bd5259eSPaul Walmsley }
1004bd5259eSPaul Walmsley 
10149815399SPaul Walmsley struct pwrdm_ops omap2_pwrdm_operations = {
10249815399SPaul Walmsley 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
10349815399SPaul Walmsley 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
10449815399SPaul Walmsley 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
10549815399SPaul Walmsley 	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
10649815399SPaul Walmsley 	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
10749815399SPaul Walmsley 	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
10849815399SPaul Walmsley 	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
10949815399SPaul Walmsley 	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
11049815399SPaul Walmsley 	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
11149815399SPaul Walmsley };
1122bb2a5d3SPaul Walmsley 
1132bb2a5d3SPaul Walmsley /*
1142bb2a5d3SPaul Walmsley  *
1152bb2a5d3SPaul Walmsley  */
1162bb2a5d3SPaul Walmsley 
1172bb2a5d3SPaul Walmsley static struct prm_ll_data omap2xxx_prm_ll_data = {
1182bb2a5d3SPaul Walmsley 	.read_reset_sources = &omap2xxx_prm_read_reset_sources,
1192bb2a5d3SPaul Walmsley };
1202bb2a5d3SPaul Walmsley 
12163a293e0SPaul Walmsley int __init omap2xxx_prm_init(void)
1222bb2a5d3SPaul Walmsley {
1232bb2a5d3SPaul Walmsley 	if (!cpu_is_omap24xx())
1242bb2a5d3SPaul Walmsley 		return 0;
1252bb2a5d3SPaul Walmsley 
1262bb2a5d3SPaul Walmsley 	return prm_register(&omap2xxx_prm_ll_data);
1272bb2a5d3SPaul Walmsley }
1282bb2a5d3SPaul Walmsley 
1292bb2a5d3SPaul Walmsley static void __exit omap2xxx_prm_exit(void)
1302bb2a5d3SPaul Walmsley {
1312bb2a5d3SPaul Walmsley 	if (!cpu_is_omap24xx())
1322bb2a5d3SPaul Walmsley 		return;
1332bb2a5d3SPaul Walmsley 
1342bb2a5d3SPaul Walmsley 	/* Should never happen */
1352bb2a5d3SPaul Walmsley 	WARN(prm_unregister(&omap2xxx_prm_ll_data),
1362bb2a5d3SPaul Walmsley 	     "%s: prm_ll_data function pointer mismatch\n", __func__);
1372bb2a5d3SPaul Walmsley }
1382bb2a5d3SPaul Walmsley __exitcall(omap2xxx_prm_exit);
139