18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * (C) Copyright 2009, Texas Instruments, Inc. https://www.ti.com/ 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/* replicated define because linux/bitops.h cannot be included in assembly */ 78c2ecf20Sopenharmony_ci#define BIT(nr) (1 << (nr)) 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/linkage.h> 108c2ecf20Sopenharmony_ci#include <asm/assembler.h> 118c2ecf20Sopenharmony_ci#include "psc.h" 128c2ecf20Sopenharmony_ci#include "ddr2.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "clock.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* Arbitrary, hardware currently does not update PHYRDY correctly */ 178c2ecf20Sopenharmony_ci#define PHYRDY_CYCLES 0x1000 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */ 208c2ecf20Sopenharmony_ci#define PLL_BYPASS_CYCLES (PLL_BYPASS_TIME * 25) 218c2ecf20Sopenharmony_ci#define PLL_RESET_CYCLES (PLL_RESET_TIME * 25) 228c2ecf20Sopenharmony_ci#define PLL_LOCK_CYCLES (PLL_LOCK_TIME * 25) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define DEEPSLEEP_SLEEPENABLE_BIT BIT(31) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci .text 278c2ecf20Sopenharmony_ci .arch armv5te 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * Move DaVinci into deep sleep state 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * Note: This code is copied to internal SRAM by PM code. When the DaVinci 328c2ecf20Sopenharmony_ci * wakes up it continues execution at the point it went to sleep. 338c2ecf20Sopenharmony_ci * Register Usage: 348c2ecf20Sopenharmony_ci * r0: contains virtual base for DDR2 controller 358c2ecf20Sopenharmony_ci * r1: contains virtual base for DDR2 Power and Sleep controller (PSC) 368c2ecf20Sopenharmony_ci * r2: contains PSC number for DDR2 378c2ecf20Sopenharmony_ci * r3: contains virtual base DDR2 PLL controller 388c2ecf20Sopenharmony_ci * r4: contains virtual address of the DEEPSLEEP register 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ciENTRY(davinci_cpu_suspend) 418c2ecf20Sopenharmony_ci stmfd sp!, {r0-r12, lr} @ save registers on stack 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci ldr ip, CACHE_FLUSH 448c2ecf20Sopenharmony_ci blx ip 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci ldmia r0, {r0-r4} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* 498c2ecf20Sopenharmony_ci * Switch DDR to self-refresh mode. 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* calculate SDRCR address */ 538c2ecf20Sopenharmony_ci ldr ip, [r0, #DDR2_SDRCR_OFFSET] 548c2ecf20Sopenharmony_ci bic ip, ip, #DDR2_SRPD_BIT 558c2ecf20Sopenharmony_ci orr ip, ip, #DDR2_LPMODEN_BIT 568c2ecf20Sopenharmony_ci str ip, [r0, #DDR2_SDRCR_OFFSET] 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci ldr ip, [r0, #DDR2_SDRCR_OFFSET] 598c2ecf20Sopenharmony_ci orr ip, ip, #DDR2_MCLKSTOPEN_BIT 608c2ecf20Sopenharmony_ci str ip, [r0, #DDR2_SDRCR_OFFSET] 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci mov ip, #PHYRDY_CYCLES 638c2ecf20Sopenharmony_ci1: subs ip, ip, #0x1 648c2ecf20Sopenharmony_ci bne 1b 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* Disable DDR2 LPSC */ 678c2ecf20Sopenharmony_ci mov r7, r0 688c2ecf20Sopenharmony_ci mov r0, #0x2 698c2ecf20Sopenharmony_ci bl davinci_ddr_psc_config 708c2ecf20Sopenharmony_ci mov r0, r7 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* Disable clock to DDR PHY */ 738c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLDIV1] 748c2ecf20Sopenharmony_ci bic ip, ip, #PLLDIV_EN 758c2ecf20Sopenharmony_ci str ip, [r3, #PLLDIV1] 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* Put the DDR PLL in bypass and power down */ 788c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLCTL] 798c2ecf20Sopenharmony_ci bic ip, ip, #PLLCTL_PLLENSRC 808c2ecf20Sopenharmony_ci bic ip, ip, #PLLCTL_PLLEN 818c2ecf20Sopenharmony_ci str ip, [r3, #PLLCTL] 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* Wait for PLL to switch to bypass */ 848c2ecf20Sopenharmony_ci mov ip, #PLL_BYPASS_CYCLES 858c2ecf20Sopenharmony_ci2: subs ip, ip, #0x1 868c2ecf20Sopenharmony_ci bne 2b 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* Power down the PLL */ 898c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLCTL] 908c2ecf20Sopenharmony_ci orr ip, ip, #PLLCTL_PLLPWRDN 918c2ecf20Sopenharmony_ci str ip, [r3, #PLLCTL] 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Go to deep sleep */ 948c2ecf20Sopenharmony_ci ldr ip, [r4] 958c2ecf20Sopenharmony_ci orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT 968c2ecf20Sopenharmony_ci /* System goes to sleep beyond after this instruction */ 978c2ecf20Sopenharmony_ci str ip, [r4] 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* Wake up from sleep */ 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* Clear sleep enable */ 1028c2ecf20Sopenharmony_ci ldr ip, [r4] 1038c2ecf20Sopenharmony_ci bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT 1048c2ecf20Sopenharmony_ci str ip, [r4] 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* initialize the DDR PLL controller */ 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* Put PLL in reset */ 1098c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLCTL] 1108c2ecf20Sopenharmony_ci bic ip, ip, #PLLCTL_PLLRST 1118c2ecf20Sopenharmony_ci str ip, [r3, #PLLCTL] 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* Clear PLL power down */ 1148c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLCTL] 1158c2ecf20Sopenharmony_ci bic ip, ip, #PLLCTL_PLLPWRDN 1168c2ecf20Sopenharmony_ci str ip, [r3, #PLLCTL] 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci mov ip, #PLL_RESET_CYCLES 1198c2ecf20Sopenharmony_ci3: subs ip, ip, #0x1 1208c2ecf20Sopenharmony_ci bne 3b 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* Bring PLL out of reset */ 1238c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLCTL] 1248c2ecf20Sopenharmony_ci orr ip, ip, #PLLCTL_PLLRST 1258c2ecf20Sopenharmony_ci str ip, [r3, #PLLCTL] 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */ 1288c2ecf20Sopenharmony_ci mov ip, #PLL_LOCK_CYCLES 1298c2ecf20Sopenharmony_ci4: subs ip, ip, #0x1 1308c2ecf20Sopenharmony_ci bne 4b 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* Remove PLL from bypass mode */ 1338c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLCTL] 1348c2ecf20Sopenharmony_ci bic ip, ip, #PLLCTL_PLLENSRC 1358c2ecf20Sopenharmony_ci orr ip, ip, #PLLCTL_PLLEN 1368c2ecf20Sopenharmony_ci str ip, [r3, #PLLCTL] 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* Start 2x clock to DDR2 */ 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci ldr ip, [r3, #PLLDIV1] 1418c2ecf20Sopenharmony_ci orr ip, ip, #PLLDIV_EN 1428c2ecf20Sopenharmony_ci str ip, [r3, #PLLDIV1] 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* Enable VCLK */ 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* Enable DDR2 LPSC */ 1478c2ecf20Sopenharmony_ci mov r7, r0 1488c2ecf20Sopenharmony_ci mov r0, #0x3 1498c2ecf20Sopenharmony_ci bl davinci_ddr_psc_config 1508c2ecf20Sopenharmony_ci mov r0, r7 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* clear MCLKSTOPEN */ 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci ldr ip, [r0, #DDR2_SDRCR_OFFSET] 1558c2ecf20Sopenharmony_ci bic ip, ip, #DDR2_MCLKSTOPEN_BIT 1568c2ecf20Sopenharmony_ci str ip, [r0, #DDR2_SDRCR_OFFSET] 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci ldr ip, [r0, #DDR2_SDRCR_OFFSET] 1598c2ecf20Sopenharmony_ci bic ip, ip, #DDR2_LPMODEN_BIT 1608c2ecf20Sopenharmony_ci str ip, [r0, #DDR2_SDRCR_OFFSET] 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* Restore registers and return */ 1638c2ecf20Sopenharmony_ci ldmfd sp!, {r0-r12, pc} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciENDPROC(davinci_cpu_suspend) 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* 1688c2ecf20Sopenharmony_ci * Disables or Enables DDR2 LPSC 1698c2ecf20Sopenharmony_ci * Register Usage: 1708c2ecf20Sopenharmony_ci * r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC 1718c2ecf20Sopenharmony_ci * r1: contains virtual base for DDR2 Power and Sleep controller (PSC) 1728c2ecf20Sopenharmony_ci * r2: contains PSC number for DDR2 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_ciENTRY(davinci_ddr_psc_config) 1758c2ecf20Sopenharmony_ci /* Set next state in mdctl for DDR2 */ 1768c2ecf20Sopenharmony_ci mov r6, #MDCTL 1778c2ecf20Sopenharmony_ci add r6, r6, r2, lsl #2 1788c2ecf20Sopenharmony_ci ldr ip, [r1, r6] 1798c2ecf20Sopenharmony_ci bic ip, ip, #MDSTAT_STATE_MASK 1808c2ecf20Sopenharmony_ci orr ip, ip, r0 1818c2ecf20Sopenharmony_ci str ip, [r1, r6] 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci /* Enable the Power Domain Transition Command */ 1848c2ecf20Sopenharmony_ci ldr ip, [r1, #PTCMD] 1858c2ecf20Sopenharmony_ci orr ip, ip, #0x1 1868c2ecf20Sopenharmony_ci str ip, [r1, #PTCMD] 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci /* Check for Transition Complete (PTSTAT) */ 1898c2ecf20Sopenharmony_ciptstat_done: 1908c2ecf20Sopenharmony_ci ldr ip, [r1, #PTSTAT] 1918c2ecf20Sopenharmony_ci and ip, ip, #0x1 1928c2ecf20Sopenharmony_ci cmp ip, #0x0 1938c2ecf20Sopenharmony_ci bne ptstat_done 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci /* Check for DDR2 clock disable completion; */ 1968c2ecf20Sopenharmony_ci mov r6, #MDSTAT 1978c2ecf20Sopenharmony_ci add r6, r6, r2, lsl #2 1988c2ecf20Sopenharmony_ciddr2clk_stop_done: 1998c2ecf20Sopenharmony_ci ldr ip, [r1, r6] 2008c2ecf20Sopenharmony_ci and ip, ip, #MDSTAT_STATE_MASK 2018c2ecf20Sopenharmony_ci cmp ip, r0 2028c2ecf20Sopenharmony_ci bne ddr2clk_stop_done 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci ret lr 2058c2ecf20Sopenharmony_ciENDPROC(davinci_ddr_psc_config) 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ciCACHE_FLUSH: 2088c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_V6 2098c2ecf20Sopenharmony_ci .word v6_flush_kern_cache_all 2108c2ecf20Sopenharmony_ci#else 2118c2ecf20Sopenharmony_ci .word arm926_flush_kern_cache_all 2128c2ecf20Sopenharmony_ci#endif 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ciENTRY(davinci_cpu_suspend_sz) 2158c2ecf20Sopenharmony_ci .word . - davinci_cpu_suspend 2168c2ecf20Sopenharmony_ciENDPROC(davinci_cpu_suspend_sz) 217