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 126