xref: /openbmc/linux/arch/arm/mach-omap2/prm2xxx.c (revision d2912cb1)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
249815399SPaul Walmsley /*
349815399SPaul Walmsley  * OMAP2xxx PRM module functions
449815399SPaul Walmsley  *
549815399SPaul Walmsley  * Copyright (C) 2010-2012 Texas Instruments, Inc.
649815399SPaul Walmsley  * Copyright (C) 2010 Nokia Corporation
749815399SPaul Walmsley  * Benoît Cousson
849815399SPaul Walmsley  * Paul Walmsley
949815399SPaul Walmsley  * Rajendra Nayak <rnayak@ti.com>
1049815399SPaul Walmsley  */
1149815399SPaul Walmsley 
1249815399SPaul Walmsley #include <linux/kernel.h>
1349815399SPaul Walmsley #include <linux/errno.h>
1449815399SPaul Walmsley #include <linux/err.h>
1549815399SPaul Walmsley #include <linux/io.h>
1649815399SPaul Walmsley #include <linux/irq.h>
1749815399SPaul Walmsley 
1849815399SPaul Walmsley #include "powerdomain.h"
194bd5259eSPaul Walmsley #include "clockdomain.h"
2049815399SPaul Walmsley #include "prm2xxx.h"
2149815399SPaul Walmsley #include "cm2xxx_3xxx.h"
2249815399SPaul Walmsley #include "prm-regbits-24xx.h"
2349815399SPaul Walmsley 
242bb2a5d3SPaul Walmsley /*
257e7fff82SPaul Walmsley  * OMAP24xx PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED bits -
267e7fff82SPaul Walmsley  * these are reversed from the bits used on OMAP3+
277e7fff82SPaul Walmsley  */
287e7fff82SPaul Walmsley #define OMAP24XX_PWRDM_POWER_ON			0x0
297e7fff82SPaul Walmsley #define OMAP24XX_PWRDM_POWER_RET		0x1
307e7fff82SPaul Walmsley #define OMAP24XX_PWRDM_POWER_OFF		0x3
317e7fff82SPaul Walmsley 
327e7fff82SPaul Walmsley /*
332bb2a5d3SPaul Walmsley  * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
342bb2a5d3SPaul Walmsley  *   hardware register (which are specific to the OMAP2xxx SoCs) to
352bb2a5d3SPaul Walmsley  *   reset source ID bit shifts (which is an OMAP SoC-independent
362bb2a5d3SPaul Walmsley  *   enumeration)
372bb2a5d3SPaul Walmsley  */
382bb2a5d3SPaul Walmsley static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
392bb2a5d3SPaul Walmsley 	{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
402bb2a5d3SPaul Walmsley 	{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
412bb2a5d3SPaul Walmsley 	{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
422bb2a5d3SPaul Walmsley 	{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
432bb2a5d3SPaul Walmsley 	{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
442bb2a5d3SPaul Walmsley 	{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
452bb2a5d3SPaul Walmsley 	{ -1, -1 },
462bb2a5d3SPaul Walmsley };
472bb2a5d3SPaul Walmsley 
482bb2a5d3SPaul Walmsley /**
492bb2a5d3SPaul Walmsley  * omap2xxx_prm_read_reset_sources - return the last SoC reset source
502bb2a5d3SPaul Walmsley  *
512bb2a5d3SPaul Walmsley  * Return a u32 representing the last reset sources of the SoC.  The
522bb2a5d3SPaul Walmsley  * returned reset source bits are standardized across OMAP SoCs.
532bb2a5d3SPaul Walmsley  */
omap2xxx_prm_read_reset_sources(void)542bb2a5d3SPaul Walmsley static u32 omap2xxx_prm_read_reset_sources(void)
552bb2a5d3SPaul Walmsley {
562bb2a5d3SPaul Walmsley 	struct prm_reset_src_map *p;
572bb2a5d3SPaul Walmsley 	u32 r = 0;
582bb2a5d3SPaul Walmsley 	u32 v;
592bb2a5d3SPaul Walmsley 
602bb2a5d3SPaul Walmsley 	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
612bb2a5d3SPaul Walmsley 
622bb2a5d3SPaul Walmsley 	p = omap2xxx_prm_reset_src_map;
632bb2a5d3SPaul Walmsley 	while (p->reg_shift >= 0 && p->std_shift >= 0) {
642bb2a5d3SPaul Walmsley 		if (v & (1 << p->reg_shift))
652bb2a5d3SPaul Walmsley 			r |= 1 << p->std_shift;
662bb2a5d3SPaul Walmsley 		p++;
672bb2a5d3SPaul Walmsley 	}
682bb2a5d3SPaul Walmsley 
692bb2a5d3SPaul Walmsley 	return r;
702bb2a5d3SPaul Walmsley }
712bb2a5d3SPaul Walmsley 
72d08cce6aSPaul Walmsley /**
737e7fff82SPaul Walmsley  * omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst
747e7fff82SPaul Walmsley  * @omap2xxx_pwrst: OMAP2xxx hardware power state to convert
757e7fff82SPaul Walmsley  *
767e7fff82SPaul Walmsley  * Return the common power state bits corresponding to the OMAP2xxx
777e7fff82SPaul Walmsley  * hardware power state bits @omap2xxx_pwrst, or -EINVAL upon error.
787e7fff82SPaul Walmsley  */
omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)797e7fff82SPaul Walmsley static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)
807e7fff82SPaul Walmsley {
817e7fff82SPaul Walmsley 	u8 pwrst;
827e7fff82SPaul Walmsley 
837e7fff82SPaul Walmsley 	switch (omap2xxx_pwrst) {
847e7fff82SPaul Walmsley 	case OMAP24XX_PWRDM_POWER_OFF:
857e7fff82SPaul Walmsley 		pwrst = PWRDM_POWER_OFF;
867e7fff82SPaul Walmsley 		break;
877e7fff82SPaul Walmsley 	case OMAP24XX_PWRDM_POWER_RET:
887e7fff82SPaul Walmsley 		pwrst = PWRDM_POWER_RET;
897e7fff82SPaul Walmsley 		break;
907e7fff82SPaul Walmsley 	case OMAP24XX_PWRDM_POWER_ON:
917e7fff82SPaul Walmsley 		pwrst = PWRDM_POWER_ON;
927e7fff82SPaul Walmsley 		break;
937e7fff82SPaul Walmsley 	default:
947e7fff82SPaul Walmsley 		return -EINVAL;
957e7fff82SPaul Walmsley 	}
967e7fff82SPaul Walmsley 
977e7fff82SPaul Walmsley 	return pwrst;
987e7fff82SPaul Walmsley }
997e7fff82SPaul Walmsley 
1007e7fff82SPaul Walmsley /**
101d08cce6aSPaul Walmsley  * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
102d08cce6aSPaul Walmsley  *
103d08cce6aSPaul Walmsley  * Set the DPLL reset bit, which should reboot the SoC.  This is the
104d08cce6aSPaul Walmsley  * recommended way to restart the SoC.  No return value.
105d08cce6aSPaul Walmsley  */
omap2xxx_prm_dpll_reset(void)10661c8621eSTero Kristo static void omap2xxx_prm_dpll_reset(void)
107d08cce6aSPaul Walmsley {
108d08cce6aSPaul Walmsley 	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
109d08cce6aSPaul Walmsley 				   OMAP2_RM_RSTCTRL);
110d08cce6aSPaul Walmsley 	/* OCP barrier */
111d08cce6aSPaul Walmsley 	omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
112d08cce6aSPaul Walmsley }
113d08cce6aSPaul Walmsley 
1146bdc4b44STero Kristo /**
1156bdc4b44STero Kristo  * omap2xxx_prm_clear_mod_irqs - clear wakeup status bits for a module
1166bdc4b44STero Kristo  * @module: PRM module to clear wakeups from
1176bdc4b44STero Kristo  * @regs: register offset to clear
1186bdc4b44STero Kristo  * @wkst_mask: wakeup status mask to clear
1196bdc4b44STero Kristo  *
1206bdc4b44STero Kristo  * Clears wakeup status bits for a given module, so that the device can
1216bdc4b44STero Kristo  * re-enter idle.
1226bdc4b44STero Kristo  */
omap2xxx_prm_clear_mod_irqs(s16 module,u8 regs,u32 wkst_mask)1239cb6d363STero Kristo static int omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
1246bdc4b44STero Kristo {
1256bdc4b44STero Kristo 	u32 wkst;
1266bdc4b44STero Kristo 
1276bdc4b44STero Kristo 	wkst = omap2_prm_read_mod_reg(module, regs);
1286bdc4b44STero Kristo 	wkst &= wkst_mask;
1296bdc4b44STero Kristo 	omap2_prm_write_mod_reg(wkst, module, regs);
1309cb6d363STero Kristo 	return 0;
1316bdc4b44STero Kristo }
1326bdc4b44STero Kristo 
omap2xxx_clkdm_sleep(struct clockdomain * clkdm)1334bd5259eSPaul Walmsley int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
1344bd5259eSPaul Walmsley {
1354bd5259eSPaul Walmsley 	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
1364bd5259eSPaul Walmsley 				   clkdm->pwrdm.ptr->prcm_offs,
1374bd5259eSPaul Walmsley 				   OMAP2_PM_PWSTCTRL);
1384bd5259eSPaul Walmsley 	return 0;
1394bd5259eSPaul Walmsley }
1404bd5259eSPaul Walmsley 
omap2xxx_clkdm_wakeup(struct clockdomain * clkdm)1414bd5259eSPaul Walmsley int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
1424bd5259eSPaul Walmsley {
1434bd5259eSPaul Walmsley 	omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
1444bd5259eSPaul Walmsley 				     clkdm->pwrdm.ptr->prcm_offs,
1454bd5259eSPaul Walmsley 				     OMAP2_PM_PWSTCTRL);
1464bd5259eSPaul Walmsley 	return 0;
1474bd5259eSPaul Walmsley }
1484bd5259eSPaul Walmsley 
omap2xxx_pwrdm_set_next_pwrst(struct powerdomain * pwrdm,u8 pwrst)1497e7fff82SPaul Walmsley static int omap2xxx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
1507e7fff82SPaul Walmsley {
1517e7fff82SPaul Walmsley 	u8 omap24xx_pwrst;
1527e7fff82SPaul Walmsley 
1537e7fff82SPaul Walmsley 	switch (pwrst) {
1547e7fff82SPaul Walmsley 	case PWRDM_POWER_OFF:
1557e7fff82SPaul Walmsley 		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF;
1567e7fff82SPaul Walmsley 		break;
1577e7fff82SPaul Walmsley 	case PWRDM_POWER_RET:
1587e7fff82SPaul Walmsley 		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET;
1597e7fff82SPaul Walmsley 		break;
1607e7fff82SPaul Walmsley 	case PWRDM_POWER_ON:
1617e7fff82SPaul Walmsley 		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON;
1627e7fff82SPaul Walmsley 		break;
1637e7fff82SPaul Walmsley 	default:
1647e7fff82SPaul Walmsley 		return -EINVAL;
1657e7fff82SPaul Walmsley 	}
1667e7fff82SPaul Walmsley 
1677e7fff82SPaul Walmsley 	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
1687e7fff82SPaul Walmsley 				   (omap24xx_pwrst << OMAP_POWERSTATE_SHIFT),
1697e7fff82SPaul Walmsley 				   pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
1707e7fff82SPaul Walmsley 	return 0;
1717e7fff82SPaul Walmsley }
1727e7fff82SPaul Walmsley 
omap2xxx_pwrdm_read_next_pwrst(struct powerdomain * pwrdm)1737e7fff82SPaul Walmsley static int omap2xxx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
1747e7fff82SPaul Walmsley {
1757e7fff82SPaul Walmsley 	u8 omap2xxx_pwrst;
1767e7fff82SPaul Walmsley 
1777e7fff82SPaul Walmsley 	omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
1787e7fff82SPaul Walmsley 						       OMAP2_PM_PWSTCTRL,
1797e7fff82SPaul Walmsley 						       OMAP_POWERSTATE_MASK);
1807e7fff82SPaul Walmsley 
1817e7fff82SPaul Walmsley 	return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
1827e7fff82SPaul Walmsley }
1837e7fff82SPaul Walmsley 
omap2xxx_pwrdm_read_pwrst(struct powerdomain * pwrdm)1847e7fff82SPaul Walmsley static int omap2xxx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
1857e7fff82SPaul Walmsley {
1867e7fff82SPaul Walmsley 	u8 omap2xxx_pwrst;
1877e7fff82SPaul Walmsley 
1887e7fff82SPaul Walmsley 	omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
1897e7fff82SPaul Walmsley 						       OMAP2_PM_PWSTST,
1907e7fff82SPaul Walmsley 						       OMAP_POWERSTATEST_MASK);
1917e7fff82SPaul Walmsley 
1927e7fff82SPaul Walmsley 	return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
1937e7fff82SPaul Walmsley }
1947e7fff82SPaul Walmsley 
19549815399SPaul Walmsley struct pwrdm_ops omap2_pwrdm_operations = {
1967e7fff82SPaul Walmsley 	.pwrdm_set_next_pwrst	= omap2xxx_pwrdm_set_next_pwrst,
1977e7fff82SPaul Walmsley 	.pwrdm_read_next_pwrst	= omap2xxx_pwrdm_read_next_pwrst,
1987e7fff82SPaul Walmsley 	.pwrdm_read_pwrst	= omap2xxx_pwrdm_read_pwrst,
19949815399SPaul Walmsley 	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
20049815399SPaul Walmsley 	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
20149815399SPaul Walmsley 	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
20249815399SPaul Walmsley 	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
20349815399SPaul Walmsley 	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
20449815399SPaul Walmsley 	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
20549815399SPaul Walmsley };
2062bb2a5d3SPaul Walmsley 
2072bb2a5d3SPaul Walmsley /*
2082bb2a5d3SPaul Walmsley  *
2092bb2a5d3SPaul Walmsley  */
2102bb2a5d3SPaul Walmsley 
2112bb2a5d3SPaul Walmsley static struct prm_ll_data omap2xxx_prm_ll_data = {
2122bb2a5d3SPaul Walmsley 	.read_reset_sources = &omap2xxx_prm_read_reset_sources,
213efd44dc3STero Kristo 	.assert_hardreset = &omap2_prm_assert_hardreset,
21437fb59d7STero Kristo 	.deassert_hardreset = &omap2_prm_deassert_hardreset,
2151bc28b34STero Kristo 	.is_hardreset_asserted = &omap2_prm_is_hardreset_asserted,
21661c8621eSTero Kristo 	.reset_system = &omap2xxx_prm_dpll_reset,
2179cb6d363STero Kristo 	.clear_mod_irqs = &omap2xxx_prm_clear_mod_irqs,
2182bb2a5d3SPaul Walmsley };
2192bb2a5d3SPaul Walmsley 
omap2xxx_prm_init(const struct omap_prcm_init_data * data)220ab7b2ffcSTero Kristo int __init omap2xxx_prm_init(const struct omap_prcm_init_data *data)
2212bb2a5d3SPaul Walmsley {
2222bb2a5d3SPaul Walmsley 	return prm_register(&omap2xxx_prm_ll_data);
2232bb2a5d3SPaul Walmsley }
2242bb2a5d3SPaul Walmsley 
omap2xxx_prm_exit(void)2252bb2a5d3SPaul Walmsley static void __exit omap2xxx_prm_exit(void)
2262bb2a5d3SPaul Walmsley {
227d8871cd2STero Kristo 	prm_unregister(&omap2xxx_prm_ll_data);
2282bb2a5d3SPaul Walmsley }
2292bb2a5d3SPaul Walmsley __exitcall(omap2xxx_prm_exit);
230