1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * (C) Copyright 2009, Texas Instruments, Inc. http://www.ti.com/ 4 */ 5 6/* replicated define because linux/bitops.h cannot be included in assembly */ 7#define BIT(nr) (1 << (nr)) 8 9#include <linux/linkage.h> 10#include <asm/assembler.h> 11#include "psc.h" 12#include "ddr2.h" 13 14#include "clock.h" 15 16/* Arbitrary, hardware currently does not update PHYRDY correctly */ 17#define PHYRDY_CYCLES 0x1000 18 19/* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */ 20#define PLL_BYPASS_CYCLES (PLL_BYPASS_TIME * 25) 21#define PLL_RESET_CYCLES (PLL_RESET_TIME * 25) 22#define PLL_LOCK_CYCLES (PLL_LOCK_TIME * 25) 23 24#define DEEPSLEEP_SLEEPENABLE_BIT BIT(31) 25 26 .text 27/* 28 * Move DaVinci into deep sleep state 29 * 30 * Note: This code is copied to internal SRAM by PM code. When the DaVinci 31 * wakes up it continues execution at the point it went to sleep. 32 * Register Usage: 33 * r0: contains virtual base for DDR2 controller 34 * r1: contains virtual base for DDR2 Power and Sleep controller (PSC) 35 * r2: contains PSC number for DDR2 36 * r3: contains virtual base DDR2 PLL controller 37 * r4: contains virtual address of the DEEPSLEEP register 38 */ 39ENTRY(davinci_cpu_suspend) 40 stmfd sp!, {r0-r12, lr} @ save registers on stack 41 42 ldr ip, CACHE_FLUSH 43 blx ip 44 45 ldmia r0, {r0-r4} 46 47 /* 48 * Switch DDR to self-refresh mode. 49 */ 50 51 /* calculate SDRCR address */ 52 ldr ip, [r0, #DDR2_SDRCR_OFFSET] 53 bic ip, ip, #DDR2_SRPD_BIT 54 orr ip, ip, #DDR2_LPMODEN_BIT 55 str ip, [r0, #DDR2_SDRCR_OFFSET] 56 57 ldr ip, [r0, #DDR2_SDRCR_OFFSET] 58 orr ip, ip, #DDR2_MCLKSTOPEN_BIT 59 str ip, [r0, #DDR2_SDRCR_OFFSET] 60 61 mov ip, #PHYRDY_CYCLES 621: subs ip, ip, #0x1 63 bne 1b 64 65 /* Disable DDR2 LPSC */ 66 mov r7, r0 67 mov r0, #0x2 68 bl davinci_ddr_psc_config 69 mov r0, r7 70 71 /* Disable clock to DDR PHY */ 72 ldr ip, [r3, #PLLDIV1] 73 bic ip, ip, #PLLDIV_EN 74 str ip, [r3, #PLLDIV1] 75 76 /* Put the DDR PLL in bypass and power down */ 77 ldr ip, [r3, #PLLCTL] 78 bic ip, ip, #PLLCTL_PLLENSRC 79 bic ip, ip, #PLLCTL_PLLEN 80 str ip, [r3, #PLLCTL] 81 82 /* Wait for PLL to switch to bypass */ 83 mov ip, #PLL_BYPASS_CYCLES 842: subs ip, ip, #0x1 85 bne 2b 86 87 /* Power down the PLL */ 88 ldr ip, [r3, #PLLCTL] 89 orr ip, ip, #PLLCTL_PLLPWRDN 90 str ip, [r3, #PLLCTL] 91 92 /* Go to deep sleep */ 93 ldr ip, [r4] 94 orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT 95 /* System goes to sleep beyond after this instruction */ 96 str ip, [r4] 97 98 /* Wake up from sleep */ 99 100 /* Clear sleep enable */ 101 ldr ip, [r4] 102 bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT 103 str ip, [r4] 104 105 /* initialize the DDR PLL controller */ 106 107 /* Put PLL in reset */ 108 ldr ip, [r3, #PLLCTL] 109 bic ip, ip, #PLLCTL_PLLRST 110 str ip, [r3, #PLLCTL] 111 112 /* Clear PLL power down */ 113 ldr ip, [r3, #PLLCTL] 114 bic ip, ip, #PLLCTL_PLLPWRDN 115 str ip, [r3, #PLLCTL] 116 117 mov ip, #PLL_RESET_CYCLES 1183: subs ip, ip, #0x1 119 bne 3b 120 121 /* Bring PLL out of reset */ 122 ldr ip, [r3, #PLLCTL] 123 orr ip, ip, #PLLCTL_PLLRST 124 str ip, [r3, #PLLCTL] 125 126 /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */ 127 mov ip, #PLL_LOCK_CYCLES 1284: subs ip, ip, #0x1 129 bne 4b 130 131 /* Remove PLL from bypass mode */ 132 ldr ip, [r3, #PLLCTL] 133 bic ip, ip, #PLLCTL_PLLENSRC 134 orr ip, ip, #PLLCTL_PLLEN 135 str ip, [r3, #PLLCTL] 136 137 /* Start 2x clock to DDR2 */ 138 139 ldr ip, [r3, #PLLDIV1] 140 orr ip, ip, #PLLDIV_EN 141 str ip, [r3, #PLLDIV1] 142 143 /* Enable VCLK */ 144 145 /* Enable DDR2 LPSC */ 146 mov r7, r0 147 mov r0, #0x3 148 bl davinci_ddr_psc_config 149 mov r0, r7 150 151 /* clear MCLKSTOPEN */ 152 153 ldr ip, [r0, #DDR2_SDRCR_OFFSET] 154 bic ip, ip, #DDR2_MCLKSTOPEN_BIT 155 str ip, [r0, #DDR2_SDRCR_OFFSET] 156 157 ldr ip, [r0, #DDR2_SDRCR_OFFSET] 158 bic ip, ip, #DDR2_LPMODEN_BIT 159 str ip, [r0, #DDR2_SDRCR_OFFSET] 160 161 /* Restore registers and return */ 162 ldmfd sp!, {r0-r12, pc} 163 164ENDPROC(davinci_cpu_suspend) 165 166/* 167 * Disables or Enables DDR2 LPSC 168 * Register Usage: 169 * r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC 170 * r1: contains virtual base for DDR2 Power and Sleep controller (PSC) 171 * r2: contains PSC number for DDR2 172 */ 173ENTRY(davinci_ddr_psc_config) 174 /* Set next state in mdctl for DDR2 */ 175 mov r6, #MDCTL 176 add r6, r6, r2, lsl #2 177 ldr ip, [r1, r6] 178 bic ip, ip, #MDSTAT_STATE_MASK 179 orr ip, ip, r0 180 str ip, [r1, r6] 181 182 /* Enable the Power Domain Transition Command */ 183 ldr ip, [r1, #PTCMD] 184 orr ip, ip, #0x1 185 str ip, [r1, #PTCMD] 186 187 /* Check for Transition Complete (PTSTAT) */ 188ptstat_done: 189 ldr ip, [r1, #PTSTAT] 190 and ip, ip, #0x1 191 cmp ip, #0x0 192 bne ptstat_done 193 194 /* Check for DDR2 clock disable completion; */ 195 mov r6, #MDSTAT 196 add r6, r6, r2, lsl #2 197ddr2clk_stop_done: 198 ldr ip, [r1, r6] 199 and ip, ip, #MDSTAT_STATE_MASK 200 cmp ip, r0 201 bne ddr2clk_stop_done 202 203 ret lr 204ENDPROC(davinci_ddr_psc_config) 205 206CACHE_FLUSH: 207#ifdef CONFIG_CPU_V6 208 .word v6_flush_kern_cache_all 209#else 210 .word arm926_flush_kern_cache_all 211#endif 212 213ENTRY(davinci_cpu_suspend_sz) 214 .word . - davinci_cpu_suspend 215ENDPROC(davinci_cpu_suspend_sz) 216