1 /* 2 * Keystone: PSC configuration module 3 * 4 * (C) Copyright 2012-2014 5 * Texas Instruments Incorporated, <www.ti.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <asm-generic/errno.h> 12 #include <asm/io.h> 13 #include <asm/processor.h> 14 #include <asm/arch/psc_defs.h> 15 16 int psc_delay(void) 17 { 18 udelay(10); 19 return 10; 20 } 21 22 /* 23 * FUNCTION PURPOSE: Wait for end of transitional state 24 * 25 * DESCRIPTION: Polls pstat for the selected domain and waits for transitions 26 * to be complete. 27 * 28 * Since this is boot loader code it is *ASSUMED* that interrupts 29 * are disabled and no other core is mucking around with the psc 30 * at the same time. 31 * 32 * Returns 0 when the domain is free. Returns -1 if a timeout 33 * occurred waiting for the completion. 34 */ 35 int psc_wait(u32 domain_num) 36 { 37 u32 retry; 38 u32 ptstat; 39 40 /* 41 * Do nothing if the power domain is in transition. This should never 42 * happen since the boot code is the only software accesses psc. 43 * It's still remotely possible that the hardware state machines 44 * initiate transitions. 45 * Don't trap if the domain (or a module in this domain) is 46 * stuck in transition. 47 */ 48 retry = 0; 49 50 do { 51 ptstat = __raw_readl(KS2_PSC_BASE + PSC_REG_PSTAT); 52 ptstat = ptstat & (1 << domain_num); 53 } while ((ptstat != 0) && ((retry += psc_delay()) < 54 PSC_PTSTAT_TIMEOUT_LIMIT)); 55 56 if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT) 57 return -1; 58 59 return 0; 60 } 61 62 u32 psc_get_domain_num(u32 mod_num) 63 { 64 u32 domain_num; 65 66 /* Get the power domain associated with the module number */ 67 domain_num = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num)); 68 domain_num = PSC_REG_MDCFG_GET_PD(domain_num); 69 70 return domain_num; 71 } 72 73 /* 74 * FUNCTION PURPOSE: Power up/down a module 75 * 76 * DESCRIPTION: Powers up/down the requested module and the associated power 77 * domain if required. No action is taken it the module is 78 * already powered up/down. 79 * 80 * This only controls modules. The domain in which the module 81 * resides will be left in the power on state. Multiple modules 82 * can exist in a power domain, so powering down the domain based 83 * on a single module is not done. 84 * 85 * Returns 0 on success, -1 if the module can't be powered up, or 86 * if there is a timeout waiting for the transition. 87 */ 88 int psc_set_state(u32 mod_num, u32 state) 89 { 90 u32 domain_num; 91 u32 pdctl; 92 u32 mdctl; 93 u32 ptcmd; 94 u32 reset_iso; 95 u32 v; 96 97 /* 98 * Get the power domain associated with the module number, and reset 99 * isolation functionality 100 */ 101 v = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num)); 102 domain_num = PSC_REG_MDCFG_GET_PD(v); 103 reset_iso = PSC_REG_MDCFG_GET_RESET_ISO(v); 104 105 /* Wait for the status of the domain/module to be non-transitional */ 106 if (psc_wait(domain_num) != 0) 107 return -1; 108 109 /* 110 * Perform configuration even if the current status matches the 111 * existing state 112 * 113 * Set the next state of the power domain to on. It's OK if the domain 114 * is always on. This code will not ever power down a domain, so no 115 * change is made if the new state is power down. 116 */ 117 if (state == PSC_REG_VAL_MDCTL_NEXT_ON) { 118 pdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num)); 119 pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, 120 PSC_REG_VAL_PDCTL_NEXT_ON); 121 __raw_writel(pdctl, KS2_PSC_BASE + PSC_REG_PDCTL(domain_num)); 122 } 123 124 /* Set the next state for the module to enabled/disabled */ 125 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); 126 mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, state); 127 mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, reset_iso); 128 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); 129 130 /* Trigger the enable */ 131 ptcmd = __raw_readl(KS2_PSC_BASE + PSC_REG_PTCMD); 132 ptcmd |= (u32)(1<<domain_num); 133 __raw_writel(ptcmd, KS2_PSC_BASE + PSC_REG_PTCMD); 134 135 /* Wait on the complete */ 136 return psc_wait(domain_num); 137 } 138 139 /* 140 * FUNCTION PURPOSE: Power up a module 141 * 142 * DESCRIPTION: Powers up the requested module and the associated power domain 143 * if required. No action is taken it the module is already 144 * powered up. 145 * 146 * Returns 0 on success, -1 if the module can't be powered up, or 147 * if there is a timeout waiting for the transition. 148 */ 149 int psc_enable_module(u32 mod_num) 150 { 151 u32 mdctl; 152 153 /* Set the bit to apply reset */ 154 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); 155 if ((mdctl & 0x3f) == PSC_REG_VAL_MDSTAT_STATE_ON) 156 return 0; 157 158 return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_ON); 159 } 160 161 /* 162 * FUNCTION PURPOSE: Power down a module 163 * 164 * DESCRIPTION: Powers down the requested module. 165 * 166 * Returns 0 on success, -1 on failure or timeout. 167 */ 168 int psc_disable_module(u32 mod_num) 169 { 170 u32 mdctl; 171 172 /* Set the bit to apply reset */ 173 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); 174 if ((mdctl & 0x3f) == 0) 175 return 0; 176 mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0); 177 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); 178 179 return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE); 180 } 181 182 /* 183 * FUNCTION PURPOSE: Set the reset isolation bit in mdctl 184 * 185 * DESCRIPTION: The reset isolation enable bit is set. The state of the module 186 * is not changed. Returns 0 if the module config showed that 187 * reset isolation is supported. Returns 1 otherwise. This is not 188 * an error, but setting the bit in mdctl has no effect. 189 */ 190 int psc_set_reset_iso(u32 mod_num) 191 { 192 u32 v; 193 u32 mdctl; 194 195 /* Set the reset isolation bit */ 196 mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); 197 mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, 1); 198 __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); 199 200 v = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num)); 201 if (PSC_REG_MDCFG_GET_RESET_ISO(v) == 1) 202 return 0; 203 204 return 1; 205 } 206 207 /* 208 * FUNCTION PURPOSE: Disable a power domain 209 * 210 * DESCRIPTION: The power domain is disabled 211 */ 212 int psc_disable_domain(u32 domain_num) 213 { 214 u32 pdctl; 215 u32 ptcmd; 216 217 pdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num)); 218 pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF); 219 pdctl = PSC_REG_PDCTL_SET_PDMODE(pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP); 220 __raw_writel(pdctl, KS2_PSC_BASE + PSC_REG_PDCTL(domain_num)); 221 222 ptcmd = __raw_readl(KS2_PSC_BASE + PSC_REG_PTCMD); 223 ptcmd |= (u32)(1 << domain_num); 224 __raw_writel(ptcmd, KS2_PSC_BASE + PSC_REG_PTCMD); 225 226 return psc_wait(domain_num); 227 } 228