]>
Commit | Line | Data |
---|---|---|
5894ca00 | 1 | /* |
f6e7f07c | 2 | * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com> |
5894ca00 MY |
3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
323d1f9d | 8 | #include <linux/err.h> |
f6e7f07c | 9 | #include <linux/io.h> |
323d1f9d | 10 | #include <linux/sizes.h> |
107b3fb4 MY |
11 | |
12 | #include "../init.h" | |
13 | #include "ddrphy-regs.h" | |
14 | #include "umc-regs.h" | |
5894ca00 | 15 | |
ee94ee34 | 16 | static void umc_start_ssif(void __iomem *ssif_base) |
5894ca00 MY |
17 | { |
18 | writel(0x00000000, ssif_base + 0x0000b004); | |
19 | writel(0xffffffff, ssif_base + 0x0000c004); | |
20 | writel(0x000fffcf, ssif_base + 0x0000c008); | |
21 | writel(0x00000001, ssif_base + 0x0000b000); | |
22 | writel(0x00000001, ssif_base + 0x0000c000); | |
23 | writel(0x03010101, ssif_base + UMC_MDMCHSEL); | |
24 | writel(0x03010100, ssif_base + UMC_DMDCHSEL); | |
25 | ||
26 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_FETCH); | |
27 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE0); | |
28 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC0); | |
29 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC0); | |
30 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE1); | |
31 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC1); | |
32 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC1); | |
33 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_WC); | |
34 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_RC); | |
35 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_DST); | |
36 | ||
37 | writel(0x00000001, ssif_base + UMC_CPURST); | |
38 | writel(0x00000001, ssif_base + UMC_IDSRST); | |
39 | writel(0x00000001, ssif_base + UMC_IXMRST); | |
40 | writel(0x00000001, ssif_base + UMC_MDMRST); | |
41 | writel(0x00000001, ssif_base + UMC_MDDRST); | |
42 | writel(0x00000001, ssif_base + UMC_SIORST); | |
43 | writel(0x00000001, ssif_base + UMC_VIORST); | |
44 | writel(0x00000001, ssif_base + UMC_FRCRST); | |
45 | writel(0x00000001, ssif_base + UMC_RGLRST); | |
46 | writel(0x00000001, ssif_base + UMC_AIORST); | |
47 | writel(0x00000001, ssif_base + UMC_DMDRST); | |
48 | } | |
49 | ||
ec79c798 MY |
50 | static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, |
51 | int size, int freq) | |
5894ca00 MY |
52 | { |
53 | if (freq == 1333) { | |
54 | writel(0x45990b11, dramcont + UMC_CMDCTLA); | |
55 | writel(0x16958924, dramcont + UMC_CMDCTLB); | |
56 | writel(0x5101046A, dramcont + UMC_INITCTLA); | |
57 | ||
58 | if (size == 1) | |
59 | writel(0x27028B0A, dramcont + UMC_INITCTLB); | |
60 | else if (size == 2) | |
61 | writel(0x38028B0A, dramcont + UMC_INITCTLB); | |
62 | ||
63 | writel(0x000FF0FF, dramcont + UMC_INITCTLC); | |
64 | writel(0x00000b51, dramcont + UMC_DRMMR0); | |
65 | } else if (freq == 1600) { | |
66 | writel(0x36BB0F17, dramcont + UMC_CMDCTLA); | |
67 | writel(0x18C6AA24, dramcont + UMC_CMDCTLB); | |
68 | writel(0x5101387F, dramcont + UMC_INITCTLA); | |
69 | ||
70 | if (size == 1) | |
71 | writel(0x2F030D3F, dramcont + UMC_INITCTLB); | |
72 | else if (size == 2) | |
73 | writel(0x43030D3F, dramcont + UMC_INITCTLB); | |
74 | ||
75 | writel(0x00FF00FF, dramcont + UMC_INITCTLC); | |
76 | writel(0x00000d71, dramcont + UMC_DRMMR0); | |
77 | } | |
78 | ||
79 | writel(0x00000006, dramcont + UMC_DRMMR1); | |
80 | ||
81 | if (freq == 1333) | |
82 | writel(0x00000290, dramcont + UMC_DRMMR2); | |
83 | else if (freq == 1600) | |
84 | writel(0x00000298, dramcont + UMC_DRMMR2); | |
85 | ||
86 | writel(0x00000800, dramcont + UMC_DRMMR3); | |
87 | ||
88 | if (freq == 1333) { | |
89 | if (size == 1) | |
90 | writel(0x00240512, dramcont + UMC_SPCCTLA); | |
91 | else if (size == 2) | |
92 | writel(0x00350512, dramcont + UMC_SPCCTLA); | |
93 | ||
94 | writel(0x00ff0006, dramcont + UMC_SPCCTLB); | |
95 | writel(0x000a00ac, dramcont + UMC_RDATACTL_D0); | |
96 | } else if (freq == 1600) { | |
97 | if (size == 1) | |
98 | writel(0x002B0617, dramcont + UMC_SPCCTLA); | |
99 | else if (size == 2) | |
100 | writel(0x003F0617, dramcont + UMC_SPCCTLA); | |
101 | ||
102 | writel(0x00ff0008, dramcont + UMC_SPCCTLB); | |
103 | writel(0x000c00ae, dramcont + UMC_RDATACTL_D0); | |
104 | } | |
105 | ||
106 | writel(0x04060806, dramcont + UMC_WDATACTL_D0); | |
107 | writel(0x04a02000, dramcont + UMC_DATASET); | |
108 | writel(0x00000000, ca_base + 0x2300); | |
109 | writel(0x00400020, dramcont + UMC_DCCGCTL); | |
110 | writel(0x00000003, dramcont + 0x7000); | |
111 | writel(0x0000000f, dramcont + 0x8000); | |
112 | writel(0x000000c3, dramcont + 0x8004); | |
113 | writel(0x00000071, dramcont + 0x8008); | |
114 | writel(0x0000003b, dramcont + UMC_DICGCTLA); | |
115 | writel(0x020a0808, dramcont + UMC_DICGCTLB); | |
116 | writel(0x00000004, dramcont + UMC_FLOWCTLG); | |
117 | writel(0x80000201, ca_base + 0xc20); | |
118 | writel(0x0801e01e, dramcont + UMC_FLOWCTLA); | |
119 | writel(0x00200000, dramcont + UMC_FLOWCTLB); | |
120 | writel(0x00004444, dramcont + UMC_FLOWCTLC); | |
121 | writel(0x200a0a00, dramcont + UMC_SPCSETB); | |
122 | writel(0x00000000, dramcont + UMC_SPCSETD); | |
123 | writel(0x00000520, dramcont + UMC_DFICUPDCTLA); | |
124 | } | |
125 | ||
ee94ee34 | 126 | static int umc_init_sub(int freq, int size_ch0, int size_ch1) |
5894ca00 MY |
127 | { |
128 | void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE; | |
129 | void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); | |
130 | void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); | |
131 | void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); | |
132 | void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); | |
b614e16c MY |
133 | void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); |
134 | void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); | |
5894ca00 MY |
135 | |
136 | umc_dram_init_start(dramcont0); | |
137 | umc_dram_init_start(dramcont1); | |
138 | umc_dram_init_poll(dramcont0); | |
139 | umc_dram_init_poll(dramcont1); | |
140 | ||
141 | writel(0x00000101, dramcont0 + UMC_DIOCTLA); | |
142 | ||
323d1f9d | 143 | ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0); |
b614e16c MY |
144 | |
145 | ddrphy_prepare_training(phy0_0, 0); | |
146 | ddrphy_training(phy0_0); | |
147 | ||
5894ca00 MY |
148 | writel(0x00000101, dramcont1 + UMC_DIOCTLA); |
149 | ||
323d1f9d | 150 | ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1); |
b614e16c MY |
151 | |
152 | ddrphy_prepare_training(phy1_0, 1); | |
153 | ddrphy_training(phy1_0); | |
154 | ||
5894ca00 MY |
155 | umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); |
156 | umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); | |
157 | ||
158 | umc_start_ssif(ssif_base); | |
159 | ||
160 | return 0; | |
161 | } | |
162 | ||
323d1f9d | 163 | int ph1_ld4_umc_init(const struct uniphier_board_data *bd) |
5894ca00 | 164 | { |
323d1f9d MY |
165 | if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) && |
166 | (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) && | |
167 | (bd->dram_freq == 1333 || bd->dram_freq == 1600) && | |
168 | bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) { | |
169 | return umc_init_sub(bd->dram_freq, | |
170 | bd->dram_ch0_size / SZ_128M, | |
171 | bd->dram_ch1_size / SZ_128M); | |
172 | } else { | |
173 | pr_err("Unsupported DDR configuration\n"); | |
174 | return -EINVAL; | |
175 | } | |
5894ca00 | 176 | } |