blob: 9342e0d83f5e88aad3ac72991c9e52315a560b32 [file] [log] [blame]
/*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/linkage.h>
#include "hardware.h"
#define DDRC_MSTR 0x0
#define DDRC_STAT 0x4
#define DDRC_MRCTRL0 0x10
#define DDRC_MRCTRL1 0x14
#define DDRC_MRSTAT 0x18
#define DDRC_PWRCTL 0x30
#define DDRC_RFSHCTL3 0x60
#define DDRC_RFSHTMG 0x64
#define DDRC_DBG1 0x304
#define DDRC_SWCTL 0x320
#define DDRC_SWSTAT 0x324
#define DDRC_PSTAT 0x3fc
#define DDRC_PCTRL_0 0x490
#define DDRC_ZQCTL0 0x180
#define DDRC_DFIMISC 0x1b0
#define DDRC_DBGCAM 0x308
#define DDRPHY_LP_CON0 0x18
#define IOMUXC_GPR8 0x20
#define DDRPHY_MDLL_CON0 0xb0
#define DDRPHY_MDLL_CON1 0xb4
#define DDRPHY_OFFSETD_CON0 0x50
#define DDRPHY_OFFSETR_CON0 0x20
#define DDRPHY_OFFSETR_CON1 0x24
#define DDRPHY_OFFSETR_CON2 0x28
#define DDRPHY_OFFSETW_CON0 0x30
#define DDRPHY_OFFSETW_CON1 0x34
#define DDRPHY_OFFSETW_CON2 0x38
#define DDRPHY_CA_WLDSKEW_CON0 0x6c
#define DDRPHY_CA_DSKEW_CON0 0x7c
#define DDRPHY_CA_DSKEW_CON1 0x80
#define DDRPHY_CA_DSKEW_CON2 0x84
#define ANADIG_DIGPROG 0x800
.align 3
.macro switch_to_below_100m
ldr r7, =0x2
str r7, [r4, #DDRC_DBG1]
ldr r6, =0x36000000
1:
ldr r7, [r4, #DDRC_DBGCAM]
and r7, r7, r6
cmp r7, r6
bne 1b
ldr r6, =0x1
2:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 2b
ldr r7, =0x10f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x0
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800010f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r6, =0x1
3:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 3b
ldr r7, =0x20f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x8
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800020f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r6, =0x1
4:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 4b
ldr r7, =0x10f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x1
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800010f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x20
str r7, [r4, #DDRC_PWRCTL]
ldr r6, =0x23
5:
ldr r7, [r4, #DDRC_STAT]
and r7, r7, r6
cmp r7, r6
bne 5b
ldr r7, =0x0
str r7, [r4, #DDRC_SWCTL]
ldr r7, =0x03048001
str r7, [r4, #DDRC_MSTR]
ldr r7, =0x1
str r7, [r4, #DDRC_SWCTL]
ldr r6, =0x1
6:
ldr r7, [r4, #DDRC_SWSTAT]
and r7, r7, r6
cmp r7, r6
bne 6b
ldr r7, =0x10010100
str r7, [r5, #0x4]
ldr r6, =24000000
cmp r0, r6
beq 25f
ldr r7, =0x000B000D
str r7,[r4, #DDRC_RFSHTMG]
b 7f
25:
ldr r7, =0x00030004
str r7,[r4, #DDRC_RFSHTMG]
/* dram alt sel set to OSC */
ldr r7, =0x10000000
ldr r8, =0xa080
str r7, [r2, r8]
/* dram root set to from dram alt, div by 1 */
ldr r7, =0x11000000
ldr r8, =0x9880
str r7, [r2, r8]
b 8f
7:
/* dram alt sel set to pfd0_392m */
ldr r7, =0x15000000
ldr r8, =0xa080
str r7, [r2, r8]
/* dram root set to from dram alt, div by 4 */
ldr r7, =0x11000003
ldr r8, =0x9880
str r7, [r2, r8]
8:
ldr r7, =0x202ffd0
str r7, [r5, #DDRPHY_MDLL_CON0]
ldr r7, =0x1000007f
str r7, [r5, #DDRPHY_OFFSETD_CON0]
ldr r7, =0x7f7f7f7f
str r7, [r5, #DDRPHY_OFFSETR_CON0]
str r7, [r5, #DDRPHY_OFFSETR_CON1]
ldr r7, =0x7f
str r7, [r5, #DDRPHY_OFFSETR_CON2]
ldr r7, =0x7f7f7f7f
str r7, [r5, #DDRPHY_OFFSETW_CON0]
str r7, [r5, #DDRPHY_OFFSETW_CON1]
ldr r7, =0x7f
str r7, [r5, #DDRPHY_OFFSETW_CON2]
ldr r7, [r9, #ANADIG_DIGPROG]
and r7, r7, #0x11
cmp r7, #0x11
bne 20f
ldr r7, =0x0
str r7, [r5, #DDRPHY_CA_WLDSKEW_CON0]
ldr r7, =0x60606060
str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
ldr r7, =0x00006060
str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
b 21f
20:
ldr r7, =0x0
str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
21:
ldr r7, =0x1100007f
str r7, [r5, #DDRPHY_OFFSETD_CON0]
ldr r7, =0x1000007f
str r7, [r5, #DDRPHY_OFFSETD_CON0]
ldr r7, =0x0
str r7, [r4, #DDRC_PWRCTL]
ldr r6, =0x1
9:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 9b
ldr r7, =0xf0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x820
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800000f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r6, =0x1
10:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 10b
ldr r7, =0x800020
str r7, [r4, #DDRC_ZQCTL0]
ldr r7, =0x0
str r7, [r4, #DDRC_DBG1]
/* enable auto self-refresh */
ldr r7, [r4, #DDRC_PWRCTL]
orr r7, r7, #(1 << 0)
str r7, [r4, #DDRC_PWRCTL]
.endm
.macro switch_to_533m
ldr r7, =0x2
str r7, [r4, #DDRC_DBG1]
ldr r7, =0x78
str r7, [r3, #IOMUXC_GPR8]
orr r7, r7, #0x100
str r7, [r3, #IOMUXC_GPR8]
ldr r6, =0x30000000
11:
ldr r7, [r4, #DDRC_DBGCAM]
and r7, r7, r6
cmp r7, r6
bne 11b
ldr r6, =0x1
12:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 12b
ldr r7, =0x10f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x1
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800010f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x20
str r7, [r4, #DDRC_PWRCTL]
ldr r6, =0x23
13:
ldr r7, [r4, #DDRC_STAT]
and r7, r7, r6
cmp r7, r6
bne 13b
ldr r7, =0x03040001
str r7, [r4, #DDRC_MSTR]
ldr r7, =0x40800020
str r7, [r4, #DDRC_ZQCTL0]
ldr r7, =0x10210100
str r7, [r5, #0x4]
ldr r7, =0x00040046
str r7, [r4, #DDRC_RFSHTMG]
/* dram root set to from dram main, div by 2 */
ldr r7, =0x10000001
ldr r8, =0x9880
str r7, [r2, r8]
ldr r7, =0x1010007e
str r7, [r5, #DDRPHY_MDLL_CON0]
ldr r7, =0x10000008
str r7, [r5, #DDRPHY_OFFSETD_CON0]
ldr r7, =0x08080808
str r7, [r5, #DDRPHY_OFFSETR_CON0]
str r7, [r5, #DDRPHY_OFFSETR_CON1]
ldr r7, =0x8
str r7, [r5, #DDRPHY_OFFSETR_CON2]
ldr r7, =0x08080808
str r7, [r5, #DDRPHY_OFFSETW_CON0]
str r7, [r5, #DDRPHY_OFFSETW_CON1]
ldr r7, =0x8
str r7, [r5, #DDRPHY_OFFSETW_CON2]
ldr r7, [r9, #ANADIG_DIGPROG]
and r7, r7, #0x11
cmp r7, #0x11
bne 22f
ldr r7, =0x40404040
str r7, [r5, #DDRPHY_CA_WLDSKEW_CON0]
ldr r7, =0x18181818
str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
ldr r7, =0x40401818
str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
b 23f
22:
ldr r7, =0x0
str r7, [r5, #DDRPHY_CA_DSKEW_CON0]
str r7, [r5, #DDRPHY_CA_DSKEW_CON1]
str r7, [r5, #DDRPHY_CA_DSKEW_CON2]
23:
ldr r7, =0x11000008
str r7, [r5, #DDRPHY_OFFSETD_CON0]
ldr r7, =0x10000008
str r7, [r5, #DDRPHY_OFFSETD_CON0]
ldr r6, =0x4
14:
ldr r7, [r5, #DDRPHY_MDLL_CON1]
and r7, r7, r6
cmp r7, r6
bne 14b
ldr r7, =0x1
str r7, [r4, #DDRC_RFSHCTL3]
ldr r7, =0x3
str r7, [r4, #DDRC_RFSHCTL3]
ldr r7, =0x0
str r7, [r4, #DDRC_PWRCTL]
ldr r6, =0x1
15:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 15b
ldr r7, =0x10f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x0
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800010f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r6, =0x1
16:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 16b
ldr r7, =0xf0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x930
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800000f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x0
str r7, [r4, #DDRC_RFSHCTL3]
ldr r7, =0x2
str r7, [r4, #DDRC_RFSHCTL3]
ldr r6, =0x1
17:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 17b
ldr r7, =0xf0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x930
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800000f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r6, =0x1
18:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 18b
ldr r7, =0x20f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x408
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800020f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r6, =0x1
19:
ldr r7, [r4, #DDRC_MRSTAT]
and r7, r7, r6
cmp r7, r6
beq 19b
ldr r7, =0x10f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x4
str r7, [r4, #DDRC_MRCTRL1]
ldr r7, =0x800010f0
str r7, [r4, #DDRC_MRCTRL0]
ldr r7, =0x0
str r7, [r4, #DDRC_DBG1]
/* enable auto self-refresh */
ldr r7, [r4, #DDRC_PWRCTL]
orr r7, r7, #(1 << 0)
str r7, [r4, #DDRC_PWRCTL]
.endm
ENTRY(imx7d_ddr3_freq_change)
push {r2 - r9}
/*
* To ensure no page table walks occur in DDR, we
* have a another page table stored in IRAM that only
* contains entries pointing to IRAM, AIPS1 and AIPS2.
* We need to set the TTBR1 to the new IRAM TLB.
* Do the following steps:
* 1. Flush the Branch Target Address Cache (BTAC)
* 2. Set TTBR1 to point to IRAM page table.
* 3. Disable page table walks in TTBR0 (PD0 = 1)
* 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
* and 2-4G is translated by TTBR1.
*/
ldr r6, =0x0
mcr p15, 0, r6, c8, c3, 0
ldr r6, =iram_tlb_phys_addr
ldr r7, [r6]
/* Disable Branch Prediction, Z bit in SCTLR. */
mrc p15, 0, r6, c1, c0, 0
bic r6, r6, #0x800
mcr p15, 0, r6, c1, c0, 0
/* Flush the Branch Target Address Cache (BTAC) */
ldr r6, =0x0
mcr p15, 0, r6, c7, c1, 6
dsb
isb
/* Store the IRAM table in TTBR1 */
mcr p15, 0, r7, c2, c0, 1
/* Read TTBCR and set PD0=1, N = 1 */
mrc p15, 0, r6, c2, c0, 2
orr r6, r6, #0x11
mcr p15, 0, r6, c2, c0, 2
dsb
isb
/* flush the TLB */
ldr r6, =0x0
mcr p15, 0, r6, c8, c3, 0
dsb
isb
ldr r2, =IMX_IO_P2V(MX7D_CCM_BASE_ADDR)
ldr r3, =IMX_IO_P2V(MX7D_IOMUXC_GPR_BASE_ADDR)
ldr r4, =IMX_IO_P2V(MX7D_DDRC_BASE_ADDR)
ldr r5, =IMX_IO_P2V(MX7D_DDRC_PHY_BASE_ADDR)
ldr r9, =IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR)
ldr r6, =100000000
cmp r0, r6
bgt set_to_533m
set_to_below_100m:
switch_to_below_100m
b done
set_to_533m:
switch_to_533m
b done
done:
/* Enable L1 data cache. */
mrc p15, 0, r6, c1, c0, 0
orr r6, r6, #0x4
mcr p15, 0, r6, c1, c0, 0
/* Restore the TTBCR */
dsb
isb
/* Read TTBCR and set PD0=0, N = 0 */
mrc p15, 0, r6, c2, c0, 2
bic r6, r6, #0x11
mcr p15, 0, r6, c2, c0, 2
dsb
isb
/* flush the TLB */
ldr r6, =0x0
mcr p15, 0, r6, c8, c3, 0
dsb
isb
/* Enable Branch Prediction, Z bit in SCTLR. */
mrc p15, 0, r6, c1, c0, 0
orr r6, r6, #0x800
mcr p15, 0, r6, c1, c0, 0
/* Flush the Branch Target Address Cache (BTAC) */
ldr r6, =0x0
mcr p15, 0, r6, c7, c1, 6
dsb
isb
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
/* Restore registers */
pop {r2 - r9}
mov pc, lr
.ltorg
ENDPROC(imx7d_ddr3_freq_change)