Loading...
1/*
2 * Copyright (C) 2014-2015 Altera Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include <linux/linkage.h>
17#include <asm/assembler.h>
18
19#define MAX_LOOP_COUNT 1000
20
21/* Register offset */
22#define SDR_CTRLGRP_LOWPWREQ_ADDR 0x54
23#define SDR_CTRLGRP_LOWPWRACK_ADDR 0x58
24
25/* Bitfield positions */
26#define SELFRSHREQ_POS 3
27#define SELFRSHREQ_MASK 0x8
28
29#define SELFRFSHACK_POS 1
30#define SELFRFSHACK_MASK 0x2
31
32 /*
33 * This code assumes that when the bootloader configured
34 * the sdram controller for the DDR on the board it
35 * configured the following fields depending on the DDR
36 * vendor/configuration:
37 *
38 * sdr.ctrlcfg.lowpwreq.selfrfshmask
39 * sdr.ctrlcfg.lowpwrtiming.clkdisablecycles
40 * sdr.ctrlcfg.dramtiming4.selfrfshexit
41 */
42
43 .arch armv7-a
44 .text
45 .align 3
46
47 /*
48 * socfpga_sdram_self_refresh
49 *
50 * r0 : sdr_ctl_base_addr
51 * r1 : temp storage of return value
52 * r2 : temp storage of register values
53 * r3 : loop counter
54 *
55 * return value: lower 16 bits: loop count going into self refresh
56 * upper 16 bits: loop count exiting self refresh
57 */
58ENTRY(socfpga_sdram_self_refresh)
59 /* Enable dynamic clock gating in the Power Control Register. */
60 mrc p15, 0, r2, c15, c0, 0
61 orr r2, r2, #1
62 mcr p15, 0, r2, c15, c0, 0
63
64 /* Enable self refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 1 */
65 ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
66 orr r2, r2, #SELFRSHREQ_MASK
67 str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
68
69 /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 1 or hit max loops */
70 mov r3, #0
71while_ack_0:
72 ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR]
73 and r2, r2, #SELFRFSHACK_MASK
74 cmp r2, #SELFRFSHACK_MASK
75 beq ack_1
76
77 add r3, #1
78 cmp r3, #MAX_LOOP_COUNT
79 bne while_ack_0
80
81ack_1:
82 mov r1, r3
83
84 /*
85 * Execute an ISB instruction to ensure that all of the
86 * CP15 register changes have been committed.
87 */
88 isb
89
90 /*
91 * Execute a barrier instruction to ensure that all cache,
92 * TLB and branch predictor maintenance operations issued
93 * by any CPU in the cluster have completed.
94 */
95 dsb
96 dmb
97
98 wfi
99
100 /* Disable self-refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 0 */
101 ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
102 bic r2, r2, #SELFRSHREQ_MASK
103 str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
104
105 /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 0 or hit max loops */
106 mov r3, #0
107while_ack_1:
108 ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR]
109 and r2, r2, #SELFRFSHACK_MASK
110 cmp r2, #SELFRFSHACK_MASK
111 bne ack_0
112
113 add r3, #1
114 cmp r3, #MAX_LOOP_COUNT
115 bne while_ack_1
116
117ack_0:
118 /*
119 * Prepare return value:
120 * Shift loop count for exiting self refresh into upper 16 bits.
121 * Leave loop count for requesting self refresh in lower 16 bits.
122 */
123 mov r3, r3, lsl #16
124 add r1, r1, r3
125
126 /* Disable dynamic clock gating in the Power Control Register. */
127 mrc p15, 0, r2, c15, c0, 0
128 bic r2, r2, #1
129 mcr p15, 0, r2, c15, c0, 0
130
131 mov r0, r1 @ return value
132 bx lr @ return
133
134ENDPROC(socfpga_sdram_self_refresh)
135ENTRY(socfpga_sdram_self_refresh_sz)
136 .word . - socfpga_sdram_self_refresh
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2014-2015 Altera Corporation. All rights reserved.
4 */
5#include <linux/linkage.h>
6#include <asm/assembler.h>
7
8#define MAX_LOOP_COUNT 1000
9
10/* Register offset */
11#define SDR_CTRLGRP_LOWPWREQ_ADDR 0x54
12#define SDR_CTRLGRP_LOWPWRACK_ADDR 0x58
13
14/* Bitfield positions */
15#define SELFRSHREQ_POS 3
16#define SELFRSHREQ_MASK 0x8
17
18#define SELFRFSHACK_POS 1
19#define SELFRFSHACK_MASK 0x2
20
21 /*
22 * This code assumes that when the bootloader configured
23 * the sdram controller for the DDR on the board it
24 * configured the following fields depending on the DDR
25 * vendor/configuration:
26 *
27 * sdr.ctrlcfg.lowpwreq.selfrfshmask
28 * sdr.ctrlcfg.lowpwrtiming.clkdisablecycles
29 * sdr.ctrlcfg.dramtiming4.selfrfshexit
30 */
31
32 .arch armv7-a
33 .text
34 .align 3
35
36 /*
37 * socfpga_sdram_self_refresh
38 *
39 * r0 : sdr_ctl_base_addr
40 * r1 : temp storage of return value
41 * r2 : temp storage of register values
42 * r3 : loop counter
43 *
44 * return value: lower 16 bits: loop count going into self refresh
45 * upper 16 bits: loop count exiting self refresh
46 */
47ENTRY(socfpga_sdram_self_refresh)
48 /* Enable dynamic clock gating in the Power Control Register. */
49 mrc p15, 0, r2, c15, c0, 0
50 orr r2, r2, #1
51 mcr p15, 0, r2, c15, c0, 0
52
53 /* Enable self refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 1 */
54 ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
55 orr r2, r2, #SELFRSHREQ_MASK
56 str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
57
58 /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 1 or hit max loops */
59 mov r3, #0
60while_ack_0:
61 ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR]
62 and r2, r2, #SELFRFSHACK_MASK
63 cmp r2, #SELFRFSHACK_MASK
64 beq ack_1
65
66 add r3, #1
67 cmp r3, #MAX_LOOP_COUNT
68 bne while_ack_0
69
70ack_1:
71 mov r1, r3
72
73 /*
74 * Execute an ISB instruction to ensure that all of the
75 * CP15 register changes have been committed.
76 */
77 isb
78
79 /*
80 * Execute a barrier instruction to ensure that all cache,
81 * TLB and branch predictor maintenance operations issued
82 * by any CPU in the cluster have completed.
83 */
84 dsb
85 dmb
86
87 wfi
88
89 /* Disable self-refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 0 */
90 ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
91 bic r2, r2, #SELFRSHREQ_MASK
92 str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
93
94 /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 0 or hit max loops */
95 mov r3, #0
96while_ack_1:
97 ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR]
98 and r2, r2, #SELFRFSHACK_MASK
99 cmp r2, #SELFRFSHACK_MASK
100 bne ack_0
101
102 add r3, #1
103 cmp r3, #MAX_LOOP_COUNT
104 bne while_ack_1
105
106ack_0:
107 /*
108 * Prepare return value:
109 * Shift loop count for exiting self refresh into upper 16 bits.
110 * Leave loop count for requesting self refresh in lower 16 bits.
111 */
112 mov r3, r3, lsl #16
113 add r1, r1, r3
114
115 /* Disable dynamic clock gating in the Power Control Register. */
116 mrc p15, 0, r2, c15, c0, 0
117 bic r2, r2, #1
118 mcr p15, 0, r2, c15, c0, 0
119
120 mov r0, r1 @ return value
121 bx lr @ return
122
123ENDPROC(socfpga_sdram_self_refresh)
124ENTRY(socfpga_sdram_self_refresh_sz)
125 .word . - socfpga_sdram_self_refresh