xref: /openbmc/linux/arch/arm/mach-omap2/prm2xxx.c (revision d8871cd2)
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 "powerdomain.h"
224bd5259eSPaul Walmsley #include "clockdomain.h"
2349815399SPaul Walmsley #include "prm2xxx.h"
2449815399SPaul Walmsley #include "cm2xxx_3xxx.h"
2549815399SPaul Walmsley #include "prm-regbits-24xx.h"
2649815399SPaul Walmsley 
272bb2a5d3SPaul Walmsley /*
287e7fff82SPaul Walmsley  * OMAP24xx PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED bits -
297e7fff82SPaul Walmsley  * these are reversed from the bits used on OMAP3+
307e7fff82SPaul Walmsley  */
317e7fff82SPaul Walmsley #define OMAP24XX_PWRDM_POWER_ON			0x0
327e7fff82SPaul Walmsley #define OMAP24XX_PWRDM_POWER_RET		0x1
337e7fff82SPaul Walmsley #define OMAP24XX_PWRDM_POWER_OFF		0x3
347e7fff82SPaul Walmsley 
357e7fff82SPaul Walmsley /*
362bb2a5d3SPaul Walmsley  * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
372bb2a5d3SPaul Walmsley  *   hardware register (which are specific to the OMAP2xxx SoCs) to
382bb2a5d3SPaul Walmsley  *   reset source ID bit shifts (which is an OMAP SoC-independent
392bb2a5d3SPaul Walmsley  *   enumeration)
402bb2a5d3SPaul Walmsley  */
412bb2a5d3SPaul Walmsley static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
422bb2a5d3SPaul Walmsley 	{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
432bb2a5d3SPaul Walmsley 	{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
442bb2a5d3SPaul Walmsley 	{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
452bb2a5d3SPaul Walmsley 	{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
462bb2a5d3SPaul Walmsley 	{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
472bb2a5d3SPaul Walmsley 	{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
482bb2a5d3SPaul Walmsley 	{ -1, -1 },
492bb2a5d3SPaul Walmsley };
502bb2a5d3SPaul Walmsley 
512bb2a5d3SPaul Walmsley /**
522bb2a5d3SPaul Walmsley  * omap2xxx_prm_read_reset_sources - return the last SoC reset source
532bb2a5d3SPaul Walmsley  *
542bb2a5d3SPaul Walmsley  * Return a u32 representing the last reset sources of the SoC.  The
552bb2a5d3SPaul Walmsley  * returned reset source bits are standardized across OMAP SoCs.
562bb2a5d3SPaul Walmsley  */
572bb2a5d3SPaul Walmsley static u32 omap2xxx_prm_read_reset_sources(void)
582bb2a5d3SPaul Walmsley {
592bb2a5d3SPaul Walmsley 	struct prm_reset_src_map *p;
602bb2a5d3SPaul Walmsley 	u32 r = 0;
612bb2a5d3SPaul Walmsley 	u32 v;
622bb2a5d3SPaul Walmsley 
632bb2a5d3SPaul Walmsley 	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
642bb2a5d3SPaul Walmsley 
652bb2a5d3SPaul Walmsley 	p = omap2xxx_prm_reset_src_map;
662bb2a5d3SPaul Walmsley 	while (p->reg_shift >= 0 && p->std_shift >= 0) {
672bb2a5d3SPaul Walmsley 		if (v & (1 << p->reg_shift))
682bb2a5d3SPaul Walmsley 			r |= 1 << p->std_shift;
692bb2a5d3SPaul Walmsley 		p++;
702bb2a5d3SPaul Walmsley 	}
712bb2a5d3SPaul Walmsley 
722bb2a5d3SPaul Walmsley 	return r;
732bb2a5d3SPaul Walmsley }
742bb2a5d3SPaul Walmsley 
75d08cce6aSPaul Walmsley /**
767e7fff82SPaul Walmsley  * omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst
777e7fff82SPaul Walmsley  * @omap2xxx_pwrst: OMAP2xxx hardware power state to convert
787e7fff82SPaul Walmsley  *
797e7fff82SPaul Walmsley  * Return the common power state bits corresponding to the OMAP2xxx
807e7fff82SPaul Walmsley  * hardware power state bits @omap2xxx_pwrst, or -EINVAL upon error.
817e7fff82SPaul Walmsley  */
827e7fff82SPaul Walmsley static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)
837e7fff82SPaul Walmsley {
847e7fff82SPaul Walmsley 	u8 pwrst;
857e7fff82SPaul Walmsley 
867e7fff82SPaul Walmsley 	switch (omap2xxx_pwrst) {
877e7fff82SPaul Walmsley 	case OMAP24XX_PWRDM_POWER_OFF:
887e7fff82SPaul Walmsley 		pwrst = PWRDM_POWER_OFF;
897e7fff82SPaul Walmsley 		break;
907e7fff82SPaul Walmsley 	case OMAP24XX_PWRDM_POWER_RET:
917e7fff82SPaul Walmsley 		pwrst = PWRDM_POWER_RET;
927e7fff82SPaul Walmsley 		break;
937e7fff82SPaul Walmsley 	case OMAP24XX_PWRDM_POWER_ON:
947e7fff82SPaul Walmsley 		pwrst = PWRDM_POWER_ON;
957e7fff82SPaul Walmsley 		break;
967e7fff82SPaul Walmsley 	default:
977e7fff82SPaul Walmsley 		return -EINVAL;
987e7fff82SPaul Walmsley 	}
997e7fff82SPaul Walmsley 
1007e7fff82SPaul Walmsley 	return pwrst;
1017e7fff82SPaul Walmsley }
1027e7fff82SPaul Walmsley 
1037e7fff82SPaul Walmsley /**
104d08cce6aSPaul Walmsley  * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
105d08cce6aSPaul Walmsley  *
106d08cce6aSPaul Walmsley  * Set the DPLL reset bit, which should reboot the SoC.  This is the
107d08cce6aSPaul Walmsley  * recommended way to restart the SoC.  No return value.
108d08cce6aSPaul Walmsley  */
109d08cce6aSPaul Walmsley void omap2xxx_prm_dpll_reset(void)
110d08cce6aSPaul Walmsley {
111d08cce6aSPaul Walmsley 	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
112d08cce6aSPaul Walmsley 				   OMAP2_RM_RSTCTRL);
113d08cce6aSPaul Walmsley 	/* OCP barrier */
114d08cce6aSPaul Walmsley 	omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
115d08cce6aSPaul Walmsley }
116d08cce6aSPaul Walmsley 
1174bd5259eSPaul Walmsley int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
1184bd5259eSPaul Walmsley {
1194bd5259eSPaul Walmsley 	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
1204bd5259eSPaul Walmsley 				   clkdm->pwrdm.ptr->prcm_offs,
1214bd5259eSPaul Walmsley 				   OMAP2_PM_PWSTCTRL);
1224bd5259eSPaul Walmsley 	return 0;
1234bd5259eSPaul Walmsley }
1244bd5259eSPaul Walmsley 
1254bd5259eSPaul Walmsley int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
1264bd5259eSPaul Walmsley {
1274bd5259eSPaul Walmsley 	omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
1284bd5259eSPaul Walmsley 				     clkdm->pwrdm.ptr->prcm_offs,
1294bd5259eSPaul Walmsley 				     OMAP2_PM_PWSTCTRL);
1304bd5259eSPaul Walmsley 	return 0;
1314bd5259eSPaul Walmsley }
1324bd5259eSPaul Walmsley 
1337e7fff82SPaul Walmsley static int omap2xxx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
1347e7fff82SPaul Walmsley {
1357e7fff82SPaul Walmsley 	u8 omap24xx_pwrst;
1367e7fff82SPaul Walmsley 
1377e7fff82SPaul Walmsley 	switch (pwrst) {
1387e7fff82SPaul Walmsley 	case PWRDM_POWER_OFF:
1397e7fff82SPaul Walmsley 		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF;
1407e7fff82SPaul Walmsley 		break;
1417e7fff82SPaul Walmsley 	case PWRDM_POWER_RET:
1427e7fff82SPaul Walmsley 		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET;
1437e7fff82SPaul Walmsley 		break;
1447e7fff82SPaul Walmsley 	case PWRDM_POWER_ON:
1457e7fff82SPaul Walmsley 		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON;
1467e7fff82SPaul Walmsley 		break;
1477e7fff82SPaul Walmsley 	default:
1487e7fff82SPaul Walmsley 		return -EINVAL;
1497e7fff82SPaul Walmsley 	}
1507e7fff82SPaul Walmsley 
1517e7fff82SPaul Walmsley 	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
1527e7fff82SPaul Walmsley 				   (omap24xx_pwrst << OMAP_POWERSTATE_SHIFT),
1537e7fff82SPaul Walmsley 				   pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
1547e7fff82SPaul Walmsley 	return 0;
1557e7fff82SPaul Walmsley }
1567e7fff82SPaul Walmsley 
1577e7fff82SPaul Walmsley static int omap2xxx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
1587e7fff82SPaul Walmsley {
1597e7fff82SPaul Walmsley 	u8 omap2xxx_pwrst;
1607e7fff82SPaul Walmsley 
1617e7fff82SPaul Walmsley 	omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
1627e7fff82SPaul Walmsley 						       OMAP2_PM_PWSTCTRL,
1637e7fff82SPaul Walmsley 						       OMAP_POWERSTATE_MASK);
1647e7fff82SPaul Walmsley 
1657e7fff82SPaul Walmsley 	return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
1667e7fff82SPaul Walmsley }
1677e7fff82SPaul Walmsley 
1687e7fff82SPaul Walmsley static int omap2xxx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
1697e7fff82SPaul Walmsley {
1707e7fff82SPaul Walmsley 	u8 omap2xxx_pwrst;
1717e7fff82SPaul Walmsley 
1727e7fff82SPaul Walmsley 	omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
1737e7fff82SPaul Walmsley 						       OMAP2_PM_PWSTST,
1747e7fff82SPaul Walmsley 						       OMAP_POWERSTATEST_MASK);
1757e7fff82SPaul Walmsley 
1767e7fff82SPaul Walmsley 	return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
1777e7fff82SPaul Walmsley }
1787e7fff82SPaul Walmsley 
17949815399SPaul Walmsley struct pwrdm_ops omap2_pwrdm_operations = {
1807e7fff82SPaul Walmsley 	.pwrdm_set_next_pwrst	= omap2xxx_pwrdm_set_next_pwrst,
1817e7fff82SPaul Walmsley 	.pwrdm_read_next_pwrst	= omap2xxx_pwrdm_read_next_pwrst,
1827e7fff82SPaul Walmsley 	.pwrdm_read_pwrst	= omap2xxx_pwrdm_read_pwrst,
18349815399SPaul Walmsley 	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
18449815399SPaul Walmsley 	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
18549815399SPaul Walmsley 	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
18649815399SPaul Walmsley 	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
18749815399SPaul Walmsley 	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
18849815399SPaul Walmsley 	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
18949815399SPaul Walmsley };
1902bb2a5d3SPaul Walmsley 
1912bb2a5d3SPaul Walmsley /*
1922bb2a5d3SPaul Walmsley  *
1932bb2a5d3SPaul Walmsley  */
1942bb2a5d3SPaul Walmsley 
1952bb2a5d3SPaul Walmsley static struct prm_ll_data omap2xxx_prm_ll_data = {
1962bb2a5d3SPaul Walmsley 	.read_reset_sources = &omap2xxx_prm_read_reset_sources,
1972bb2a5d3SPaul Walmsley };
1982bb2a5d3SPaul Walmsley 
19963a293e0SPaul Walmsley int __init omap2xxx_prm_init(void)
2002bb2a5d3SPaul Walmsley {
2012bb2a5d3SPaul Walmsley 	return prm_register(&omap2xxx_prm_ll_data);
2022bb2a5d3SPaul Walmsley }
2032bb2a5d3SPaul Walmsley 
2042bb2a5d3SPaul Walmsley static void __exit omap2xxx_prm_exit(void)
2052bb2a5d3SPaul Walmsley {
206d8871cd2STero Kristo 	prm_unregister(&omap2xxx_prm_ll_data);
2072bb2a5d3SPaul Walmsley }
2082bb2a5d3SPaul Walmsley __exitcall(omap2xxx_prm_exit);
209