Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * AM33XX PRM functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2011-2012 Texas Instruments Incorporated - https://www.ti.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * modify it under the terms of the GNU General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * published by the Free Software Foundation version 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * kind, whether express or implied; without even the implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include "powerdomain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "prm33xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include "prm-regbits-33xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define AM33XX_PRM_RSTCTRL_OFFSET		0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define AM33XX_RST_GLOBAL_WARM_SW_MASK		(1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) /* Read a register in a PRM instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static u32 am33xx_prm_read_reg(s16 inst, u16 idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	return readl_relaxed(prm_base.va + inst + idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) /* Write into a register in a PRM instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	writel_relaxed(val, prm_base.va + inst + idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) /* Read-modify-write a register in PRM. Caller must lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	v = am33xx_prm_read_reg(inst, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	v &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	v |= bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	am33xx_prm_write_reg(v, inst, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * am33xx_prm_is_hardreset_asserted - read the HW reset line state of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * submodules contained in the hwmod module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * @shift: register bit shift corresponding to the reset line to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * @part: PRM partition, ignored for AM33xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * @inst: CM instance register offset (*_INST macro)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * @rstctrl_offs: RM_RSTCTRL register address offset for this module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * Returns 1 if the (sub)module hardreset line is currently asserted,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * 0 if the (sub)module hardreset line is not currently asserted, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * -EINVAL upon parameter error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static int am33xx_prm_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 					    u16 rstctrl_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	v = am33xx_prm_read_reg(inst, rstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	v &= 1 << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	v >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * am33xx_prm_assert_hardreset - assert the HW reset line of a submodule
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * @shift: register bit shift corresponding to the reset line to assert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * @part: CM partition, ignored for AM33xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * @inst: CM instance register offset (*_INST macro)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * @rstctrl_reg: RM_RSTCTRL register address for this module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * Some IPs like dsp, ipu or iva contain processors that require an HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * reset line to be asserted / deasserted in order to fully enable the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * IP.  These modules may have multiple hard-reset lines that reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * different 'submodules' inside the IP block.  This function will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  * place the submodule into reset.  Returns 0 upon success or -EINVAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * upon an argument error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) static int am33xx_prm_assert_hardreset(u8 shift, u8 part, s16 inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				       u16 rstctrl_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	u32 mask = 1 << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	am33xx_prm_rmw_reg_bits(mask, mask, inst, rstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)  * am33xx_prm_deassert_hardreset - deassert a submodule hardreset line and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)  * wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * @shift: register bit shift corresponding to the reset line to deassert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * @st_shift: reset status register bit shift corresponding to the reset line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * @part: PRM partition, not used for AM33xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * @inst: CM instance register offset (*_INST macro)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  * @rstctrl_reg: RM_RSTCTRL register address for this module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * @rstst_reg: RM_RSTST register address for this module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * Some IPs like dsp, ipu or iva contain processors that require an HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * reset line to be asserted / deasserted in order to fully enable the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * IP.  These modules may have multiple hard-reset lines that reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * different 'submodules' inside the IP block.  This function will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * take the submodule out of reset and wait until the PRCM indicates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  * that the reset has completed before returning.  Returns 0 upon success or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  * of reset, or -EBUSY if the submodule did not exit reset promptly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, u8 part,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 					 s16 inst, u16 rstctrl_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 					 u16 rstst_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	u32 mask = 1 << st_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	/* Check the current status to avoid  de-asserting the line twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (am33xx_prm_is_hardreset_asserted(shift, 0, inst, rstctrl_offs) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	/* Clear the reset status by writing 1 to the status bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	am33xx_prm_rmw_reg_bits(0xffffffff, mask, inst, rstst_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	/* de-assert the reset control line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	mask = 1 << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	/* wait the status to be set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	omap_test_timeout(am33xx_prm_is_hardreset_asserted(st_shift, 0, inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 							   rstst_offs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			  MAX_MODULE_HARDRESET_WAIT, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 				(pwrst << OMAP_POWERSTATE_SHIFT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	v = am33xx_prm_read_reg(pwrdm->prcm_offs,  pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	v &= OMAP_POWERSTATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	v >>= OMAP_POWERSTATE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	v &= OMAP_POWERSTATEST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	v >>= OMAP_POWERSTATEST_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 				(1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 				AM33XX_LASTPOWERSTATEENTERED_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 				pwrdm->prcm_offs, pwrdm->pwrstst_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	u32 m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	m = pwrdm->logicretstate_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	v &= AM33XX_LOGICSTATEST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	v >>= AM33XX_LOGICSTATEST_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	u32 v, m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	m = pwrdm->logicretstate_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	v &= m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	v >>= __ffs(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	u32 m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	m = pwrdm->mem_on_mask[bank];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 					u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	u32 m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	m = pwrdm->mem_ret_mask[bank];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	m = pwrdm->mem_pwrst_mask[bank];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	v &= m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	v >>= __ffs(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	m = pwrdm->mem_retst_mask[bank];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	v &= m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	v >>= __ffs(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	u32 c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	 * REVISIT: pwrdm_wait_transition() may be better implemented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	 * via a callback and a periodic timer check -- how long do we expect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	 * powerdomain transitions to take?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	/* XXX Is this udelay() value meaningful? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			& OMAP_INTRANSITION_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 			(c++ < PWRDM_TRANSITION_BAILOUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (c > PWRDM_TRANSITION_BAILOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		pr_err("powerdomain: %s: waited too long to complete transition\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		       pwrdm->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	pr_debug("powerdomain: completed transition in %d loops\n", c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int am33xx_check_vcvp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	/* No VC/VP on am33xx devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  * am33xx_prm_global_warm_sw_reset - reboot the device via warm reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  * Immediately reboots the device through warm reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void am33xx_prm_global_warm_sw_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 				AM33XX_RST_GLOBAL_WARM_SW_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 				AM33XX_PRM_DEVICE_MOD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 				AM33XX_PRM_RSTCTRL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	/* OCP barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	(void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 				  AM33XX_PRM_RSTCTRL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	pwrdm->context = am33xx_prm_read_reg(pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 						pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	 * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	 * reading back a 1 indicates a request in progress.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	pwrdm->context &= ~AM33XX_LOWPOWERSTATECHANGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	int st, ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	st = am33xx_prm_read_reg(pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 				 pwrdm->pwrstst_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	am33xx_prm_write_reg(pwrdm->context, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			     pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	/* Make sure we only wait for a transition if there is one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	st &= OMAP_POWERSTATEST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (st != ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		am33xx_pwrdm_wait_transition(pwrdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct pwrdm_ops am33xx_pwrdm_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	.pwrdm_set_next_pwrst		= am33xx_pwrdm_set_next_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	.pwrdm_read_next_pwrst		= am33xx_pwrdm_read_next_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	.pwrdm_read_pwrst		= am33xx_pwrdm_read_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	.pwrdm_set_logic_retst		= am33xx_pwrdm_set_logic_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	.pwrdm_read_logic_pwrst		= am33xx_pwrdm_read_logic_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	.pwrdm_read_logic_retst		= am33xx_pwrdm_read_logic_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	.pwrdm_clear_all_prev_pwrst	= am33xx_pwrdm_clear_all_prev_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	.pwrdm_set_lowpwrstchange	= am33xx_pwrdm_set_lowpwrstchange,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	.pwrdm_read_mem_pwrst		= am33xx_pwrdm_read_mem_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	.pwrdm_read_mem_retst		= am33xx_pwrdm_read_mem_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	.pwrdm_set_mem_onst		= am33xx_pwrdm_set_mem_onst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	.pwrdm_set_mem_retst		= am33xx_pwrdm_set_mem_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	.pwrdm_wait_transition		= am33xx_pwrdm_wait_transition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	.pwrdm_has_voltdm		= am33xx_check_vcvp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	.pwrdm_save_context		= am33xx_pwrdm_save_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	.pwrdm_restore_context		= am33xx_pwrdm_restore_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static struct prm_ll_data am33xx_prm_ll_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	.assert_hardreset		= am33xx_prm_assert_hardreset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	.deassert_hardreset		= am33xx_prm_deassert_hardreset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	.is_hardreset_asserted		= am33xx_prm_is_hardreset_asserted,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	.reset_system			= am33xx_prm_global_warm_sw_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int __init am33xx_prm_init(const struct omap_prcm_init_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	return prm_register(&am33xx_prm_ll_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static void __exit am33xx_prm_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	prm_unregister(&am33xx_prm_ll_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) __exitcall(am33xx_prm_exit);