1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2022 StarFive Technology Co., Ltd. 4 * Author: Yanhong Wang<yanhong.wang@starfivetech.com> 5 */ 6 7#include <common.h> 8#include <asm/io.h> 9#include <asm/arch/regs.h> 10#include <linux/delay.h> 11#include <wait_bit.h> 12 13#include "starfive_ddr.h" 14 15#define REGOFFSET(offset) ((offset) / 4) 16 17static const struct ddr_reg_cfg ddr_csr_cfg[] = { 18 {0x0, 0x0, 0x00000001, REGSETALL}, 19 {0xf00, 0x0, 0x40001030, (OFFSET_SEL | F_SET | REG4G | REG8G)}, 20 {0xf00, 0x0, 0x40001030, (OFFSET_SEL | F_SET | REG2G)}, 21 {0xf04, 0x0, 0x00000001, (OFFSET_SEL | F_SET | REG4G | REG8G)}, 22 {0xf04, 0x0, 0x00800001, (OFFSET_SEL | F_SET | REG2G)}, 23 {0xf10, 0x0, 0x00400000, (OFFSET_SEL | REGSETALL)}, 24 {0xf14, 0x0, 0x043fffff, (OFFSET_SEL | REGSETALL)}, 25 {0xf18, 0x0, 0x00000000, (OFFSET_SEL | REGSETALL)}, 26 {0xf30, 0x0, 0x1f000041, (OFFSET_SEL | REGSETALL)}, 27 {0xf34, 0x0, 0x1f000041, (OFFSET_SEL | F_SET | REG4G | REG8G)}, 28 {0x110, 0x0, 0xc0000001, (OFFSET_SEL | REGSETALL)}, 29 {0x114, 0x0, 0xffffffff, (OFFSET_SEL | REGSETALL)}, 30 {0x10c, 0x0, 0x00000505, REGSETALL}, 31 {0x11c, 0x0, 0x00000000, REGSETALL}, 32 {0x500, 0x0, 0x00000201, REGSETALL}, 33 {0x514, 0x0, 0x00000100, REGSETALL}, 34 {0x6a8, 0x0, 0x00040000, REGSETALL}, 35 {0xea8, 0x0, 0x00040000, REGSETALL}, 36 {0x504, 0x0, 0x40000000, REGSETALL} 37}; 38 39static const struct ddr_reg_cfg ddr_csr_cfg1[] = { 40 {0x310, 0x0, 0x00020000, REGSETALL}, 41 {0x310, 0x0, 0x00020001, REGSETALL}, 42 {0x600, 0x0, 0x002e0176, REGSETALL}, 43 {0x604, 0x0, 0x002e0176, REGSETALL}, 44 {0x608, 0x0, 0x001700bb, REGSETALL}, 45 {0x60c, 0x0, 0x000b005d, REGSETALL}, 46 {0x610, 0x0, 0x0005002e, REGSETALL}, 47 {0x614, 0x0, 0x00020017, REGSETALL}, 48 {0x618, 0x0, 0x00020017, REGSETALL}, 49 {0x61c, 0x0, 0x00020017, REGSETALL}, 50 {0x678, 0x0, 0x00000019, REGSETALL}, 51 {0x100, 0x0, 0x000000f8, REGSETALL}, 52 {0x620, 0x0, 0x03030404, REGSETALL}, 53 {0x624, 0x0, 0x04030505, REGSETALL}, 54 {0x628, 0x0, 0x07030884, REGSETALL}, 55 {0x62c, 0x0, 0x13150401, REGSETALL}, 56 {0x630, 0x0, 0x17150604, REGSETALL}, 57 {0x634, 0x0, 0x00110000, REGSETALL}, 58 {0x638, 0x0, 0x200a0a08, REGSETALL}, 59 {0x63c, 0x0, 0x1730f803, REGSETALL}, 60 {0x640, 0x0, 0x000a0c00, REGSETALL}, 61 {0x644, 0x0, 0xa005000a, REGSETALL}, 62 {0x648, 0x0, 0x00000000, REGSETALL}, 63 {0x64c, 0x0, 0x00081306, REGSETALL}, 64 {0x650, 0x0, 0x04070304, REGSETALL}, 65 {0x654, 0x0, 0x00000404, REGSETALL}, 66 {0x658, 0x0, 0x00000060, REGSETALL}, 67 {0x65c, 0x0, 0x00030008, REGSETALL}, 68 {0x660, 0x0, 0x00000000, REGSETALL}, 69 {0x680, 0x0, 0x00000603, REGSETALL}, 70 {0x684, 0x0, 0x01000202, REGSETALL}, 71 {0x688, 0x0, 0x0413040d, REGSETALL}, 72 {0x68c, 0x0, 0x20002420, REGSETALL}, 73 {0x690, 0x0, 0x00140000, REGSETALL}, 74 {0x69c, 0x0, 0x01240074, REGSETALL}, 75 {0x6a0, 0x0, 0x00000000, REGSETALL}, 76 {0x6a4, 0x0, 0x20240c00, REGSETALL}, 77 {0x6a8, 0x0, 0x00040000, REGSETALL}, 78 {0x4, 0x0, 0x30010006, (F_SET | REG4G | REG8G)}, 79 {0x4, 0x0, 0x10010006, (F_SET | REG2G)}, 80 {0xc, 0x0, 0x00000002, REGSETALL}, 81 {0x4, 0x0, 0x30020000, (F_SET | REG4G | REG8G)}, 82 {0x4, 0x0, 0x10020000, (F_SET | REG2G)}, 83 {0xc, 0x0, 0x00000002, REGSETALL}, 84 {0x4, 0x0, 0x30030031, (F_SET | REG4G | REG8G)}, 85 {0x4, 0x0, 0x10030031, (F_SET | REG2G)}, 86 {0xc, 0x0, 0x00000002, REGSETALL}, 87 {0x4, 0x0, 0x300b0033, (F_SET | REG4G | REG8G)}, 88 {0x4, 0x0, 0x100b0033, (F_SET | REG2G)}, 89 {0xc, 0x0, 0x00000002, REGSETALL}, 90 {0x4, 0x0, 0x30160016, (F_SET | REG4G | REG8G)}, 91 {0x4, 0x0, 0x10160016, (F_SET | REG2G)}, 92 {0xc, 0x0, 0x00000002, REGSETALL}, 93 {0x10, 0x0, 0x00000010, REGSETALL}, 94 {0x14, 0x0, 0x00000001, REGSETALL}, 95}; 96 97static const struct ddr_reg_cfg ddr_csr_cfg2[] = { 98 {0xb8, 0xf0ffffff, 0x3000000, REGCLRSETALL}, 99 {0x84, 0xFEFFFFFF, 0x0, REGCLRSETALL}, 100 {0xb0, 0xFFFEFFFF, 0x0, REGCLRSETALL}, 101 {0xb0, 0xFEFFFFFF, 0x0, REGCLRSETALL}, 102 {0xb4, 0xffffffff, 0x1, REGCLRSETALL}, 103 {0x248, 0xffffffff, 0x3000000, REGCLRSETALL}, 104 {0x24c, 0xffffffff, 0x300, REGCLRSETALL}, 105 {0x24c, 0xffffffff, 0x3000000, REGCLRSETALL}, 106 {0xb0, 0xffffffff, 0x100, REGCLRSETALL}, 107 {0xb8, 0xFFF0FFFF, 0x30000, REGCLRSETALL}, 108 {0x84, 0xFFFEFFFF, 0x0, REGCLRSETALL}, 109 {0xac, 0xFFFEFFFF, 0x0, REGCLRSETALL}, 110 {0xac, 0xFEFFFFFF, 0x0, REGCLRSETALL}, 111 {0xb0, 0xffffffff, 0x1, REGCLRSETALL}, 112 {0x248, 0xffffffff, 0x30000, REGCLRSETALL}, 113 {0x24c, 0xffffffff, 0x3, REGCLRSETALL}, 114 {0x24c, 0xffffffff, 0x30000, REGCLRSETALL}, 115 {0x250, 0xffffffff, 0x3000000, REGCLRSETALL}, 116 {0x254, 0xffffffff, 0x3000000, REGCLRSETALL}, 117 {0x258, 0xffffffff, 0x3000000, REGCLRSETALL}, 118 {0xac, 0xffffffff, 0x100, REGCLRSETALL}, 119 {0x10c, 0xFFFFF0FF, 0x300, REGCLRSETALL}, 120 {0x110, 0xFFFFFEFF, 0x0, REGCLRSETALL}, 121 {0x11c, 0xFFFEFFFF, 0x0, REGCLRSETALL}, 122 {0x11c, 0xFEFFFFFF, 0x0, REGCLRSETALL}, 123 {0x120, 0xffffffff, 0x100, REGCLRSETALL}, 124 {0x2d0, 0xffffffff, 0x300, REGCLRSETALL}, 125 {0x2dc, 0xffffffff, 0x300, REGCLRSETALL}, 126 {0x2e8, 0xffffffff, 0x300, REGCLRSETALL}, 127}; 128 129static const struct ddr_reg_cfg ddr_csr_cfg3[] = { 130 {0x100, 0x0, 0x000000e0, REGSETALL}, 131 {0x620, 0x0, 0x04041417, REGSETALL}, 132 {0x624, 0x0, 0x09110609, REGSETALL}, 133 {0x628, 0x0, 0x442d0994, REGSETALL}, 134 {0x62c, 0x0, 0x271e102b, REGSETALL}, 135 {0x630, 0x0, 0x291b140a, REGSETALL}, 136 {0x634, 0x0, 0x001c0000, REGSETALL}, 137 {0x638, 0x0, 0x200f0f08, REGSETALL}, 138 {0x63c, 0x0, 0x29420a06, REGSETALL}, 139 {0x640, 0x0, 0x019e1fc1, REGSETALL}, 140 {0x644, 0x0, 0x10cb0196, REGSETALL}, 141 {0x648, 0x0, 0x00000000, REGSETALL}, 142 {0x64c, 0x0, 0x00082714, REGSETALL}, 143 {0x650, 0x0, 0x16442f0d, REGSETALL}, 144 {0x654, 0x0, 0x00001916, REGSETALL}, 145 {0x658, 0x0, 0x00000060, REGSETALL}, 146 {0x65c, 0x0, 0x00600020, REGSETALL}, 147 {0x660, 0x0, 0x00000000, REGSETALL}, 148 {0x680, 0x0, 0x0c00040f, REGSETALL}, 149 {0x684, 0x0, 0x03000604, REGSETALL}, 150 {0x688, 0x0, 0x0515040d, REGSETALL}, 151 {0x68c, 0x0, 0x20002c20, REGSETALL}, 152 {0x690, 0x0, 0x00140000, REGSETALL}, 153 {0x69c, 0x0, 0x01240074, REGSETALL}, 154 {0x6a0, 0x0, 0x00000000, REGSETALL}, 155 {0x6a4, 0x0, 0x202c0c00, REGSETALL}, 156 {0x6a8, 0x0, 0x00040000, REGSETALL}, 157 {0x4, 0x0, 0x30010036, (F_SET | REG4G | REG8G)}, 158 {0x4, 0x0, 0x10010036, (F_SET | REG2G)}, 159 {0xc, 0x0, 0x00000002, REGSETALL}, 160 {0x4, 0x0, 0x3002001b, (F_SET | REG4G | REG8G)}, 161 {0x4, 0x0, 0x10010036, (F_SET | REG2G)}, 162 {0xc, 0x0, 0x00000002, REGSETALL}, 163 {0x4, 0x0, 0x30030031, (F_SET | REG4G | REG8G)}, 164 {0x4, 0x0, 0x10030031, (F_SET | REG2G)}, 165 {0xc, 0x0, 0x00000002, REGSETALL}, 166 {0x4, 0x0, 0x300b0066, (F_SET | REG4G)}, 167 {0x4, 0x0, 0x300b0036, (F_SET | REG8G)}, 168 {0x4, 0x0, 0x100b0066, (F_SET | REG2G)}, 169 {0xc, 0x0, 0x00000002, REGSETALL}, 170 {0x4, 0x0, 0x30160016, (F_SET | REG4G | REG8G)}, 171 {0x4, 0x0, 0x10160016, (F_SET | REG2G)}, 172 {0xc, 0x0, 0x00000002, REGSETALL}, 173 {0x410, 0x0, 0x00101010, REGSETALL}, 174 {0x420, 0x0, 0x0c181006, REGSETALL}, 175 {0x424, 0x0, 0x20200820, REGSETALL}, 176 {0x428, 0x0, 0x80000020, REGSETALL}, 177 {0x0, 0x0, 0x00000001, REGSETALL}, 178 {0x108, 0x0, 0x00003000, REGSETALL}, 179 {0x704, 0x0, 0x00000007, REGSETALL | OFFSET_SEL}, 180 {0x330, 0x0, 0x09313fff, (F_SET | REG4G | REG8G)}, 181 {0x330, 0x0, 0x09311fff, (F_SET | REG2G)}, 182 {0x508, 0x0, 0x00000033, (F_SET | REG4G | REG8G)}, 183 {0x508, 0x0, 0x00000013, (F_SET | REG2G)}, 184 {0x324, 0x0, 0x00002000, REGSETALL}, 185 {0x104, 0x0, 0x90000000, REGSETALL}, 186 {0x510, 0x0, 0x00000100, REGSETALL}, 187 {0x514, 0x0, 0x00000000, REGSETALL}, 188 {0x700, 0x0, 0x00000003, REGSETALL | OFFSET_SEL}, 189 {0x514, 0x0, 0x00000600, REGSETALL}, 190 {0x20, 0x0, 0x00000001, REGSETALL}, 191}; 192 193static void ddr_csr_set(u32 *csrreg, u32 *secreg, const struct ddr_reg_cfg *data, 194 u32 len, u32 mask) 195{ 196 u32 *addr; 197 u32 i; 198 199 for (i = 0; i < len; i++) { 200 if (!(data[i].flag & mask)) 201 continue; 202 203 if (data[i].flag & OFFSET_SEL) 204 addr = secreg + REGOFFSET(data[i].offset); 205 else 206 addr = csrreg + REGOFFSET(data[i].offset); 207 208 if (data[i].flag & F_CLRSET) 209 DDR_REG_TRIGGER(addr, data[i].mask, data[i].val); 210 else 211 out_le32(addr, data[i].val); 212 } 213} 214 215void ddrcsr_boot(u32 *csrreg, u32 *secreg, u32 *phyreg, enum ddr_size_t size) 216{ 217 u32 len; 218 u32 val; 219 u32 mask; 220 int ret; 221 222 switch (size) { 223 case DDR_SIZE_2G: 224 mask = REG2G; 225 break; 226 227 case DDR_SIZE_4G: 228 mask = REG4G; 229 break; 230 231 case DDR_SIZE_8G: 232 mask = REG8G; 233 break; 234 235 case DDR_SIZE_16G: 236 default: 237 return; 238 }; 239 240 len = ARRAY_SIZE(ddr_csr_cfg); 241 ddr_csr_set(csrreg, secreg, ddr_csr_cfg, len, mask); 242 243 ret = wait_for_bit_le32(csrreg + REGOFFSET(0x504), BIT(31), 244 true, 1000, false); 245 if (ret) 246 return; 247 248 out_le32(csrreg + REGOFFSET(0x504), 0x0); 249 out_le32(csrreg + REGOFFSET(0x50c), 0x0); 250 udelay(300); 251 out_le32(csrreg + REGOFFSET(0x50c), 0x1); 252 mdelay(3); 253 254 switch (size) { 255 case DDR_SIZE_2G: 256 out_le32(csrreg + REGOFFSET(0x10), 0x1c); 257 break; 258 259 case DDR_SIZE_8G: 260 case DDR_SIZE_4G: 261 out_le32(csrreg + REGOFFSET(0x10), 0x3c); 262 break; 263 264 case DDR_SIZE_16G: 265 default: 266 break; 267 }; 268 269 out_le32(csrreg + REGOFFSET(0x14), 0x1); 270 udelay(4); 271 272 len = ARRAY_SIZE(ddr_csr_cfg1); 273 ddr_csr_set(csrreg, secreg, ddr_csr_cfg1, len, mask); 274 275 udelay(4); 276 out_le32(csrreg + REGOFFSET(0x10), 0x11); 277 out_le32(csrreg + REGOFFSET(0x14), 0x1); 278 279 switch (size) { 280 case DDR_SIZE_4G: 281 case DDR_SIZE_8G: 282 out_le32(csrreg + REGOFFSET(0x10), 0x20); 283 out_le32(csrreg + REGOFFSET(0x14), 0x1); 284 udelay(4); 285 out_le32(csrreg + REGOFFSET(0x10), 0x21); 286 out_le32(csrreg + REGOFFSET(0x14), 0x1); 287 break; 288 289 case DDR_SIZE_2G: 290 case DDR_SIZE_16G: 291 default: 292 break; 293 }; 294 295 out_le32(csrreg + REGOFFSET(0x514), 0x0); 296 ret = wait_for_bit_le32(csrreg + REGOFFSET(0x518), BIT(1), 297 true, 1000, false); 298 if (ret) 299 return; 300 301 val = in_le32(csrreg + REGOFFSET(0x518)); 302 while ((val & 0x2) != 0x0) { 303 val = in_le32(phyreg + 1); 304 305 if ((val & 0x20) == 0x20) { 306 switch (val & 0x1f) { 307 case 0: /* ddrc_clock=12M */ 308 DDR_REG_SET(BUS, DDR_BUS_OSC_DIV2); 309 break; 310 case 1: /* ddrc_clock=200M */ 311 DDR_REG_SET(BUS, DDR_BUS_PLL1_DIV8); 312 break; 313 case 2: /* ddrc_clock=800M */ 314 DDR_REG_SET(BUS, DDR_BUS_PLL1_DIV2); 315 break; 316 default: 317 break; 318 }; 319 320 out_le32(phyreg + 2, 0x1); 321 ret = wait_for_bit_le32(phyreg + 2, BIT(0), false, 1000, false); 322 if (ret) 323 return; 324 } 325 326 udelay(1); 327 val = in_le32(csrreg + REGOFFSET(0x518)); 328 }; 329 330 val = in_le32(phyreg + 2048 + 83); 331 val = in_le32(phyreg + 2048 + 84); 332 out_le32(phyreg + 2048 + 84, val & 0xF8000000); 333 334 len = ARRAY_SIZE(ddr_csr_cfg2); 335 ddr_csr_set(phyreg + PHY_BASE_ADDR, secreg, ddr_csr_cfg2, len, mask); 336 337 len = ARRAY_SIZE(ddr_csr_cfg3); 338 ddr_csr_set(csrreg, secreg, ddr_csr_cfg3, len, mask); 339} 340