root/arch/arm/mach-socfpga/self-refresh.S

/* [<][>][^][v][top][bottom][index][help] */
   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          */
  47 ENTRY(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
  60 while_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 
  70 ack_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
  96 while_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 
 106 ack_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 
 123 ENDPROC(socfpga_sdram_self_refresh)
 124 ENTRY(socfpga_sdram_self_refresh_sz)
 125         .word   . - socfpga_sdram_self_refresh

/* [<][>][^][v][top][bottom][index][help] */