~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

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