1*0f336e9cSThomas Zimmermann // SPDX-License-Identifier: MIT 2*0f336e9cSThomas Zimmermann /* 3*0f336e9cSThomas Zimmermann * Copyright 2012 Red Hat Inc. 4*0f336e9cSThomas Zimmermann * 5*0f336e9cSThomas Zimmermann * Permission is hereby granted, free of charge, to any person obtaining a 6*0f336e9cSThomas Zimmermann * copy of this software and associated documentation files (the 7*0f336e9cSThomas Zimmermann * "Software"), to deal in the Software without restriction, including 8*0f336e9cSThomas Zimmermann * without limitation the rights to use, copy, modify, merge, publish, 9*0f336e9cSThomas Zimmermann * distribute, sub license, and/or sell copies of the Software, and to 10*0f336e9cSThomas Zimmermann * permit persons to whom the Software is furnished to do so, subject to 11*0f336e9cSThomas Zimmermann * the following conditions: 12*0f336e9cSThomas Zimmermann * 13*0f336e9cSThomas Zimmermann * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14*0f336e9cSThomas Zimmermann * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15*0f336e9cSThomas Zimmermann * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 16*0f336e9cSThomas Zimmermann * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 17*0f336e9cSThomas Zimmermann * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18*0f336e9cSThomas Zimmermann * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19*0f336e9cSThomas Zimmermann * USE OR OTHER DEALINGS IN THE SOFTWARE. 20*0f336e9cSThomas Zimmermann * 21*0f336e9cSThomas Zimmermann * The above copyright notice and this permission notice (including the 22*0f336e9cSThomas Zimmermann * next paragraph) shall be included in all copies or substantial portions 23*0f336e9cSThomas Zimmermann * of the Software. 24*0f336e9cSThomas Zimmermann */ 25*0f336e9cSThomas Zimmermann /* 26*0f336e9cSThomas Zimmermann * Authors: Dave Airlie <airlied@redhat.com> 27*0f336e9cSThomas Zimmermann */ 28*0f336e9cSThomas Zimmermann 29*0f336e9cSThomas Zimmermann #include <linux/delay.h> 30*0f336e9cSThomas Zimmermann 31*0f336e9cSThomas Zimmermann #include "ast_drv.h" 32*0f336e9cSThomas Zimmermann #include "ast_post.h" 33*0f336e9cSThomas Zimmermann 34*0f336e9cSThomas Zimmermann /* 35*0f336e9cSThomas Zimmermann * POST 36*0f336e9cSThomas Zimmermann */ 37*0f336e9cSThomas Zimmermann 38*0f336e9cSThomas Zimmermann /* AST 2300 DRAM settings */ 39*0f336e9cSThomas Zimmermann #define AST_DDR3 0 40*0f336e9cSThomas Zimmermann #define AST_DDR2 1 41*0f336e9cSThomas Zimmermann 42*0f336e9cSThomas Zimmermann struct ast2300_dram_param { 43*0f336e9cSThomas Zimmermann u32 dram_type; 44*0f336e9cSThomas Zimmermann u32 dram_chipid; 45*0f336e9cSThomas Zimmermann u32 dram_freq; 46*0f336e9cSThomas Zimmermann u32 vram_size; 47*0f336e9cSThomas Zimmermann u32 odt; 48*0f336e9cSThomas Zimmermann u32 wodt; 49*0f336e9cSThomas Zimmermann u32 rodt; 50*0f336e9cSThomas Zimmermann u32 dram_config; 51*0f336e9cSThomas Zimmermann u32 reg_PERIOD; 52*0f336e9cSThomas Zimmermann u32 reg_MADJ; 53*0f336e9cSThomas Zimmermann u32 reg_SADJ; 54*0f336e9cSThomas Zimmermann u32 reg_MRS; 55*0f336e9cSThomas Zimmermann u32 reg_EMRS; 56*0f336e9cSThomas Zimmermann u32 reg_AC1; 57*0f336e9cSThomas Zimmermann u32 reg_AC2; 58*0f336e9cSThomas Zimmermann u32 reg_DQSIC; 59*0f336e9cSThomas Zimmermann u32 reg_DRV; 60*0f336e9cSThomas Zimmermann u32 reg_IOZ; 61*0f336e9cSThomas Zimmermann u32 reg_DQIDLY; 62*0f336e9cSThomas Zimmermann u32 reg_FREQ; 63*0f336e9cSThomas Zimmermann u32 madj_max; 64*0f336e9cSThomas Zimmermann u32 dll2_finetune_step; 65*0f336e9cSThomas Zimmermann }; 66*0f336e9cSThomas Zimmermann 67*0f336e9cSThomas Zimmermann /* 68*0f336e9cSThomas Zimmermann * DQSI DLL CBR Setting 69*0f336e9cSThomas Zimmermann */ 70*0f336e9cSThomas Zimmermann #define CBR_SIZE0 ((1 << 10) - 1) 71*0f336e9cSThomas Zimmermann #define CBR_SIZE1 ((4 << 10) - 1) 72*0f336e9cSThomas Zimmermann #define CBR_SIZE2 ((64 << 10) - 1) 73*0f336e9cSThomas Zimmermann #define CBR_PASSNUM 5 74*0f336e9cSThomas Zimmermann #define CBR_PASSNUM2 5 75*0f336e9cSThomas Zimmermann #define CBR_THRESHOLD 10 76*0f336e9cSThomas Zimmermann #define CBR_THRESHOLD2 10 77*0f336e9cSThomas Zimmermann #define TIMEOUT 5000000 78*0f336e9cSThomas Zimmermann #define CBR_PATNUM 8 79*0f336e9cSThomas Zimmermann 80*0f336e9cSThomas Zimmermann static const u32 pattern[8] = { 81*0f336e9cSThomas Zimmermann 0xFF00FF00, 82*0f336e9cSThomas Zimmermann 0xCC33CC33, 83*0f336e9cSThomas Zimmermann 0xAA55AA55, 84*0f336e9cSThomas Zimmermann 0x88778877, 85*0f336e9cSThomas Zimmermann 0x92CC4D6E, 86*0f336e9cSThomas Zimmermann 0x543D3CDE, 87*0f336e9cSThomas Zimmermann 0xF1E843C7, 88*0f336e9cSThomas Zimmermann 0x7C61D253 89*0f336e9cSThomas Zimmermann }; 90*0f336e9cSThomas Zimmermann 91*0f336e9cSThomas Zimmermann static u32 mmc_test2(struct ast_device *ast, u32 datagen, u8 test_ctl) 92*0f336e9cSThomas Zimmermann { 93*0f336e9cSThomas Zimmermann u32 data, timeout; 94*0f336e9cSThomas Zimmermann 95*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 96*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl); 97*0f336e9cSThomas Zimmermann timeout = 0; 98*0f336e9cSThomas Zimmermann do { 99*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1e6e0070) & 0x1000; 100*0f336e9cSThomas Zimmermann if (++timeout > TIMEOUT) { 101*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e0070, 0x0); 102*0f336e9cSThomas Zimmermann return 0xffffffff; 103*0f336e9cSThomas Zimmermann } 104*0f336e9cSThomas Zimmermann } while (!data); 105*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1e6e0078); 106*0f336e9cSThomas Zimmermann data = (data | (data >> 16)) & 0xffff; 107*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 108*0f336e9cSThomas Zimmermann return data; 109*0f336e9cSThomas Zimmermann } 110*0f336e9cSThomas Zimmermann 111*0f336e9cSThomas Zimmermann static u32 mmc_test_burst2(struct ast_device *ast, u32 datagen) 112*0f336e9cSThomas Zimmermann { 113*0f336e9cSThomas Zimmermann return mmc_test2(ast, datagen, 0x41); 114*0f336e9cSThomas Zimmermann } 115*0f336e9cSThomas Zimmermann 116*0f336e9cSThomas Zimmermann static bool mmc_test_single(struct ast_device *ast, u32 datagen) 117*0f336e9cSThomas Zimmermann { 118*0f336e9cSThomas Zimmermann return mmc_test(ast, datagen, 0xc5); 119*0f336e9cSThomas Zimmermann } 120*0f336e9cSThomas Zimmermann 121*0f336e9cSThomas Zimmermann static u32 mmc_test_single2(struct ast_device *ast, u32 datagen) 122*0f336e9cSThomas Zimmermann { 123*0f336e9cSThomas Zimmermann return mmc_test2(ast, datagen, 0x05); 124*0f336e9cSThomas Zimmermann } 125*0f336e9cSThomas Zimmermann 126*0f336e9cSThomas Zimmermann static int cbr_test(struct ast_device *ast) 127*0f336e9cSThomas Zimmermann { 128*0f336e9cSThomas Zimmermann u32 data; 129*0f336e9cSThomas Zimmermann int i; 130*0f336e9cSThomas Zimmermann 131*0f336e9cSThomas Zimmermann data = mmc_test_single2(ast, 0); 132*0f336e9cSThomas Zimmermann if ((data & 0xff) && (data & 0xff00)) 133*0f336e9cSThomas Zimmermann return 0; 134*0f336e9cSThomas Zimmermann for (i = 0; i < 8; i++) { 135*0f336e9cSThomas Zimmermann data = mmc_test_burst2(ast, i); 136*0f336e9cSThomas Zimmermann if ((data & 0xff) && (data & 0xff00)) 137*0f336e9cSThomas Zimmermann return 0; 138*0f336e9cSThomas Zimmermann } 139*0f336e9cSThomas Zimmermann if (!data) 140*0f336e9cSThomas Zimmermann return 3; 141*0f336e9cSThomas Zimmermann else if (data & 0xff) 142*0f336e9cSThomas Zimmermann return 2; 143*0f336e9cSThomas Zimmermann return 1; 144*0f336e9cSThomas Zimmermann } 145*0f336e9cSThomas Zimmermann 146*0f336e9cSThomas Zimmermann static int cbr_scan(struct ast_device *ast) 147*0f336e9cSThomas Zimmermann { 148*0f336e9cSThomas Zimmermann u32 data, data2, patcnt, loop; 149*0f336e9cSThomas Zimmermann 150*0f336e9cSThomas Zimmermann data2 = 3; 151*0f336e9cSThomas Zimmermann for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 152*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 153*0f336e9cSThomas Zimmermann for (loop = 0; loop < CBR_PASSNUM2; loop++) { 154*0f336e9cSThomas Zimmermann data = cbr_test(ast); 155*0f336e9cSThomas Zimmermann if (data != 0) { 156*0f336e9cSThomas Zimmermann data2 &= data; 157*0f336e9cSThomas Zimmermann if (!data2) 158*0f336e9cSThomas Zimmermann return 0; 159*0f336e9cSThomas Zimmermann break; 160*0f336e9cSThomas Zimmermann } 161*0f336e9cSThomas Zimmermann } 162*0f336e9cSThomas Zimmermann if (loop == CBR_PASSNUM2) 163*0f336e9cSThomas Zimmermann return 0; 164*0f336e9cSThomas Zimmermann } 165*0f336e9cSThomas Zimmermann return data2; 166*0f336e9cSThomas Zimmermann } 167*0f336e9cSThomas Zimmermann 168*0f336e9cSThomas Zimmermann static u32 cbr_test2(struct ast_device *ast) 169*0f336e9cSThomas Zimmermann { 170*0f336e9cSThomas Zimmermann u32 data; 171*0f336e9cSThomas Zimmermann 172*0f336e9cSThomas Zimmermann data = mmc_test_burst2(ast, 0); 173*0f336e9cSThomas Zimmermann if (data == 0xffff) 174*0f336e9cSThomas Zimmermann return 0; 175*0f336e9cSThomas Zimmermann data |= mmc_test_single2(ast, 0); 176*0f336e9cSThomas Zimmermann if (data == 0xffff) 177*0f336e9cSThomas Zimmermann return 0; 178*0f336e9cSThomas Zimmermann 179*0f336e9cSThomas Zimmermann return ~data & 0xffff; 180*0f336e9cSThomas Zimmermann } 181*0f336e9cSThomas Zimmermann 182*0f336e9cSThomas Zimmermann static u32 cbr_scan2(struct ast_device *ast) 183*0f336e9cSThomas Zimmermann { 184*0f336e9cSThomas Zimmermann u32 data, data2, patcnt, loop; 185*0f336e9cSThomas Zimmermann 186*0f336e9cSThomas Zimmermann data2 = 0xffff; 187*0f336e9cSThomas Zimmermann for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 188*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 189*0f336e9cSThomas Zimmermann for (loop = 0; loop < CBR_PASSNUM2; loop++) { 190*0f336e9cSThomas Zimmermann data = cbr_test2(ast); 191*0f336e9cSThomas Zimmermann if (data != 0) { 192*0f336e9cSThomas Zimmermann data2 &= data; 193*0f336e9cSThomas Zimmermann if (!data2) 194*0f336e9cSThomas Zimmermann return 0; 195*0f336e9cSThomas Zimmermann break; 196*0f336e9cSThomas Zimmermann } 197*0f336e9cSThomas Zimmermann } 198*0f336e9cSThomas Zimmermann if (loop == CBR_PASSNUM2) 199*0f336e9cSThomas Zimmermann return 0; 200*0f336e9cSThomas Zimmermann } 201*0f336e9cSThomas Zimmermann return data2; 202*0f336e9cSThomas Zimmermann } 203*0f336e9cSThomas Zimmermann 204*0f336e9cSThomas Zimmermann static bool cbr_test3(struct ast_device *ast) 205*0f336e9cSThomas Zimmermann { 206*0f336e9cSThomas Zimmermann if (!mmc_test_burst(ast, 0)) 207*0f336e9cSThomas Zimmermann return false; 208*0f336e9cSThomas Zimmermann if (!mmc_test_single(ast, 0)) 209*0f336e9cSThomas Zimmermann return false; 210*0f336e9cSThomas Zimmermann return true; 211*0f336e9cSThomas Zimmermann } 212*0f336e9cSThomas Zimmermann 213*0f336e9cSThomas Zimmermann static bool cbr_scan3(struct ast_device *ast) 214*0f336e9cSThomas Zimmermann { 215*0f336e9cSThomas Zimmermann u32 patcnt, loop; 216*0f336e9cSThomas Zimmermann 217*0f336e9cSThomas Zimmermann for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 218*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 219*0f336e9cSThomas Zimmermann for (loop = 0; loop < 2; loop++) { 220*0f336e9cSThomas Zimmermann if (cbr_test3(ast)) 221*0f336e9cSThomas Zimmermann break; 222*0f336e9cSThomas Zimmermann } 223*0f336e9cSThomas Zimmermann if (loop == 2) 224*0f336e9cSThomas Zimmermann return false; 225*0f336e9cSThomas Zimmermann } 226*0f336e9cSThomas Zimmermann return true; 227*0f336e9cSThomas Zimmermann } 228*0f336e9cSThomas Zimmermann 229*0f336e9cSThomas Zimmermann static bool finetuneDQI_L(struct ast_device *ast, struct ast2300_dram_param *param) 230*0f336e9cSThomas Zimmermann { 231*0f336e9cSThomas Zimmermann u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0; 232*0f336e9cSThomas Zimmermann bool status = false; 233*0f336e9cSThomas Zimmermann FINETUNE_START: 234*0f336e9cSThomas Zimmermann for (cnt = 0; cnt < 16; cnt++) { 235*0f336e9cSThomas Zimmermann dllmin[cnt] = 0xff; 236*0f336e9cSThomas Zimmermann dllmax[cnt] = 0x0; 237*0f336e9cSThomas Zimmermann } 238*0f336e9cSThomas Zimmermann passcnt = 0; 239*0f336e9cSThomas Zimmermann for (dlli = 0; dlli < 76; dlli++) { 240*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 241*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1); 242*0f336e9cSThomas Zimmermann data = cbr_scan2(ast); 243*0f336e9cSThomas Zimmermann if (data != 0) { 244*0f336e9cSThomas Zimmermann mask = 0x00010001; 245*0f336e9cSThomas Zimmermann for (cnt = 0; cnt < 16; cnt++) { 246*0f336e9cSThomas Zimmermann if (data & mask) { 247*0f336e9cSThomas Zimmermann if (dllmin[cnt] > dlli) 248*0f336e9cSThomas Zimmermann dllmin[cnt] = dlli; 249*0f336e9cSThomas Zimmermann if (dllmax[cnt] < dlli) 250*0f336e9cSThomas Zimmermann dllmax[cnt] = dlli; 251*0f336e9cSThomas Zimmermann } 252*0f336e9cSThomas Zimmermann mask <<= 1; 253*0f336e9cSThomas Zimmermann } 254*0f336e9cSThomas Zimmermann passcnt++; 255*0f336e9cSThomas Zimmermann } else if (passcnt >= CBR_THRESHOLD2) { 256*0f336e9cSThomas Zimmermann break; 257*0f336e9cSThomas Zimmermann } 258*0f336e9cSThomas Zimmermann } 259*0f336e9cSThomas Zimmermann gold_sadj[0] = 0x0; 260*0f336e9cSThomas Zimmermann passcnt = 0; 261*0f336e9cSThomas Zimmermann for (cnt = 0; cnt < 16; cnt++) { 262*0f336e9cSThomas Zimmermann if ((dllmax[cnt] > dllmin[cnt]) && 263*0f336e9cSThomas Zimmermann ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 264*0f336e9cSThomas Zimmermann gold_sadj[0] += dllmin[cnt]; 265*0f336e9cSThomas Zimmermann passcnt++; 266*0f336e9cSThomas Zimmermann } 267*0f336e9cSThomas Zimmermann } 268*0f336e9cSThomas Zimmermann if (retry++ > 10) 269*0f336e9cSThomas Zimmermann goto FINETUNE_DONE; 270*0f336e9cSThomas Zimmermann if (passcnt != 16) 271*0f336e9cSThomas Zimmermann goto FINETUNE_START; 272*0f336e9cSThomas Zimmermann status = true; 273*0f336e9cSThomas Zimmermann FINETUNE_DONE: 274*0f336e9cSThomas Zimmermann gold_sadj[0] = gold_sadj[0] >> 4; 275*0f336e9cSThomas Zimmermann gold_sadj[1] = gold_sadj[0]; 276*0f336e9cSThomas Zimmermann 277*0f336e9cSThomas Zimmermann data = 0; 278*0f336e9cSThomas Zimmermann for (cnt = 0; cnt < 8; cnt++) { 279*0f336e9cSThomas Zimmermann data >>= 3; 280*0f336e9cSThomas Zimmermann if ((dllmax[cnt] > dllmin[cnt]) && 281*0f336e9cSThomas Zimmermann ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 282*0f336e9cSThomas Zimmermann dlli = dllmin[cnt]; 283*0f336e9cSThomas Zimmermann if (gold_sadj[0] >= dlli) { 284*0f336e9cSThomas Zimmermann dlli = ((gold_sadj[0] - dlli) * 19) >> 5; 285*0f336e9cSThomas Zimmermann if (dlli > 3) 286*0f336e9cSThomas Zimmermann dlli = 3; 287*0f336e9cSThomas Zimmermann } else { 288*0f336e9cSThomas Zimmermann dlli = ((dlli - gold_sadj[0]) * 19) >> 5; 289*0f336e9cSThomas Zimmermann if (dlli > 4) 290*0f336e9cSThomas Zimmermann dlli = 4; 291*0f336e9cSThomas Zimmermann dlli = (8 - dlli) & 0x7; 292*0f336e9cSThomas Zimmermann } 293*0f336e9cSThomas Zimmermann data |= dlli << 21; 294*0f336e9cSThomas Zimmermann } 295*0f336e9cSThomas Zimmermann } 296*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0080, data); 297*0f336e9cSThomas Zimmermann 298*0f336e9cSThomas Zimmermann data = 0; 299*0f336e9cSThomas Zimmermann for (cnt = 8; cnt < 16; cnt++) { 300*0f336e9cSThomas Zimmermann data >>= 3; 301*0f336e9cSThomas Zimmermann if ((dllmax[cnt] > dllmin[cnt]) && 302*0f336e9cSThomas Zimmermann ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 303*0f336e9cSThomas Zimmermann dlli = dllmin[cnt]; 304*0f336e9cSThomas Zimmermann if (gold_sadj[1] >= dlli) { 305*0f336e9cSThomas Zimmermann dlli = ((gold_sadj[1] - dlli) * 19) >> 5; 306*0f336e9cSThomas Zimmermann if (dlli > 3) 307*0f336e9cSThomas Zimmermann dlli = 3; 308*0f336e9cSThomas Zimmermann else 309*0f336e9cSThomas Zimmermann dlli = (dlli - 1) & 0x7; 310*0f336e9cSThomas Zimmermann } else { 311*0f336e9cSThomas Zimmermann dlli = ((dlli - gold_sadj[1]) * 19) >> 5; 312*0f336e9cSThomas Zimmermann dlli += 1; 313*0f336e9cSThomas Zimmermann if (dlli > 4) 314*0f336e9cSThomas Zimmermann dlli = 4; 315*0f336e9cSThomas Zimmermann dlli = (8 - dlli) & 0x7; 316*0f336e9cSThomas Zimmermann } 317*0f336e9cSThomas Zimmermann data |= dlli << 21; 318*0f336e9cSThomas Zimmermann } 319*0f336e9cSThomas Zimmermann } 320*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0084, data); 321*0f336e9cSThomas Zimmermann return status; 322*0f336e9cSThomas Zimmermann } /* finetuneDQI_L */ 323*0f336e9cSThomas Zimmermann 324*0f336e9cSThomas Zimmermann static void finetuneDQSI(struct ast_device *ast) 325*0f336e9cSThomas Zimmermann { 326*0f336e9cSThomas Zimmermann u32 dlli, dqsip, dqidly; 327*0f336e9cSThomas Zimmermann u32 reg_mcr18, reg_mcr0c, passcnt[2], diff; 328*0f336e9cSThomas Zimmermann u32 g_dqidly, g_dqsip, g_margin, g_side; 329*0f336e9cSThomas Zimmermann u16 pass[32][2][2]; 330*0f336e9cSThomas Zimmermann char tag[2][76]; 331*0f336e9cSThomas Zimmermann 332*0f336e9cSThomas Zimmermann /* Disable DQI CBR */ 333*0f336e9cSThomas Zimmermann reg_mcr0c = ast_mindwm(ast, 0x1E6E000C); 334*0f336e9cSThomas Zimmermann reg_mcr18 = ast_mindwm(ast, 0x1E6E0018); 335*0f336e9cSThomas Zimmermann reg_mcr18 &= 0x0000ffff; 336*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, reg_mcr18); 337*0f336e9cSThomas Zimmermann 338*0f336e9cSThomas Zimmermann for (dlli = 0; dlli < 76; dlli++) { 339*0f336e9cSThomas Zimmermann tag[0][dlli] = 0x0; 340*0f336e9cSThomas Zimmermann tag[1][dlli] = 0x0; 341*0f336e9cSThomas Zimmermann } 342*0f336e9cSThomas Zimmermann for (dqidly = 0; dqidly < 32; dqidly++) { 343*0f336e9cSThomas Zimmermann pass[dqidly][0][0] = 0xff; 344*0f336e9cSThomas Zimmermann pass[dqidly][0][1] = 0x0; 345*0f336e9cSThomas Zimmermann pass[dqidly][1][0] = 0xff; 346*0f336e9cSThomas Zimmermann pass[dqidly][1][1] = 0x0; 347*0f336e9cSThomas Zimmermann } 348*0f336e9cSThomas Zimmermann for (dqidly = 0; dqidly < 32; dqidly++) { 349*0f336e9cSThomas Zimmermann passcnt[0] = 0; 350*0f336e9cSThomas Zimmermann passcnt[1] = 0; 351*0f336e9cSThomas Zimmermann for (dqsip = 0; dqsip < 2; dqsip++) { 352*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, 0); 353*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23)); 354*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c); 355*0f336e9cSThomas Zimmermann for (dlli = 0; dlli < 76; dlli++) { 356*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, 357*0f336e9cSThomas Zimmermann 0x00001300 | (dlli << 16) | (dlli << 24)); 358*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0070, 0); 359*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0); 360*0f336e9cSThomas Zimmermann if (cbr_scan3(ast)) { 361*0f336e9cSThomas Zimmermann if (dlli == 0) 362*0f336e9cSThomas Zimmermann break; 363*0f336e9cSThomas Zimmermann passcnt[dqsip]++; 364*0f336e9cSThomas Zimmermann tag[dqsip][dlli] = 'P'; 365*0f336e9cSThomas Zimmermann if (dlli < pass[dqidly][dqsip][0]) 366*0f336e9cSThomas Zimmermann pass[dqidly][dqsip][0] = (u16)dlli; 367*0f336e9cSThomas Zimmermann if (dlli > pass[dqidly][dqsip][1]) 368*0f336e9cSThomas Zimmermann pass[dqidly][dqsip][1] = (u16)dlli; 369*0f336e9cSThomas Zimmermann } else if (passcnt[dqsip] >= 5) { 370*0f336e9cSThomas Zimmermann break; 371*0f336e9cSThomas Zimmermann } else { 372*0f336e9cSThomas Zimmermann pass[dqidly][dqsip][0] = 0xff; 373*0f336e9cSThomas Zimmermann pass[dqidly][dqsip][1] = 0x0; 374*0f336e9cSThomas Zimmermann } 375*0f336e9cSThomas Zimmermann } 376*0f336e9cSThomas Zimmermann } 377*0f336e9cSThomas Zimmermann if (passcnt[0] == 0 && passcnt[1] == 0) 378*0f336e9cSThomas Zimmermann dqidly++; 379*0f336e9cSThomas Zimmermann } 380*0f336e9cSThomas Zimmermann /* Search margin */ 381*0f336e9cSThomas Zimmermann g_dqidly = 0; 382*0f336e9cSThomas Zimmermann g_dqsip = 0; 383*0f336e9cSThomas Zimmermann g_margin = 0; 384*0f336e9cSThomas Zimmermann g_side = 0; 385*0f336e9cSThomas Zimmermann 386*0f336e9cSThomas Zimmermann for (dqidly = 0; dqidly < 32; dqidly++) { 387*0f336e9cSThomas Zimmermann for (dqsip = 0; dqsip < 2; dqsip++) { 388*0f336e9cSThomas Zimmermann if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1]) 389*0f336e9cSThomas Zimmermann continue; 390*0f336e9cSThomas Zimmermann diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0]; 391*0f336e9cSThomas Zimmermann if ((diff + 2) < g_margin) 392*0f336e9cSThomas Zimmermann continue; 393*0f336e9cSThomas Zimmermann passcnt[0] = 0; 394*0f336e9cSThomas Zimmermann passcnt[1] = 0; 395*0f336e9cSThomas Zimmermann for (dlli = pass[dqidly][dqsip][0]; 396*0f336e9cSThomas Zimmermann dlli > 0 && tag[dqsip][dlli] != 0; 397*0f336e9cSThomas Zimmermann dlli--, passcnt[0]++) { 398*0f336e9cSThomas Zimmermann } 399*0f336e9cSThomas Zimmermann for (dlli = pass[dqidly][dqsip][1]; 400*0f336e9cSThomas Zimmermann dlli < 76 && tag[dqsip][dlli] != 0; 401*0f336e9cSThomas Zimmermann dlli++, passcnt[1]++) { 402*0f336e9cSThomas Zimmermann } 403*0f336e9cSThomas Zimmermann if (passcnt[0] > passcnt[1]) 404*0f336e9cSThomas Zimmermann passcnt[0] = passcnt[1]; 405*0f336e9cSThomas Zimmermann passcnt[1] = 0; 406*0f336e9cSThomas Zimmermann if (passcnt[0] > g_side) 407*0f336e9cSThomas Zimmermann passcnt[1] = passcnt[0] - g_side; 408*0f336e9cSThomas Zimmermann if (diff > (g_margin + 1) && (passcnt[1] > 0 || passcnt[0] > 8)) { 409*0f336e9cSThomas Zimmermann g_margin = diff; 410*0f336e9cSThomas Zimmermann g_dqidly = dqidly; 411*0f336e9cSThomas Zimmermann g_dqsip = dqsip; 412*0f336e9cSThomas Zimmermann g_side = passcnt[0]; 413*0f336e9cSThomas Zimmermann } else if (passcnt[1] > 1 && g_side < 8) { 414*0f336e9cSThomas Zimmermann if (diff > g_margin) 415*0f336e9cSThomas Zimmermann g_margin = diff; 416*0f336e9cSThomas Zimmermann g_dqidly = dqidly; 417*0f336e9cSThomas Zimmermann g_dqsip = dqsip; 418*0f336e9cSThomas Zimmermann g_side = passcnt[0]; 419*0f336e9cSThomas Zimmermann } 420*0f336e9cSThomas Zimmermann } 421*0f336e9cSThomas Zimmermann } 422*0f336e9cSThomas Zimmermann reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23); 423*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, reg_mcr18); 424*0f336e9cSThomas Zimmermann } 425*0f336e9cSThomas Zimmermann 426*0f336e9cSThomas Zimmermann static bool cbr_dll2(struct ast_device *ast, struct ast2300_dram_param *param) 427*0f336e9cSThomas Zimmermann { 428*0f336e9cSThomas Zimmermann u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0; 429*0f336e9cSThomas Zimmermann bool status = false; 430*0f336e9cSThomas Zimmermann 431*0f336e9cSThomas Zimmermann finetuneDQSI(ast); 432*0f336e9cSThomas Zimmermann if (finetuneDQI_L(ast, param) == false) 433*0f336e9cSThomas Zimmermann return status; 434*0f336e9cSThomas Zimmermann 435*0f336e9cSThomas Zimmermann CBR_START2: 436*0f336e9cSThomas Zimmermann dllmin[0] = 0xff; 437*0f336e9cSThomas Zimmermann dllmin[1] = 0xff; 438*0f336e9cSThomas Zimmermann dllmax[0] = 0x0; 439*0f336e9cSThomas Zimmermann dllmax[1] = 0x0; 440*0f336e9cSThomas Zimmermann passcnt = 0; 441*0f336e9cSThomas Zimmermann for (dlli = 0; dlli < 76; dlli++) { 442*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24)); 443*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2); 444*0f336e9cSThomas Zimmermann data = cbr_scan(ast); 445*0f336e9cSThomas Zimmermann if (data != 0) { 446*0f336e9cSThomas Zimmermann if (data & 0x1) { 447*0f336e9cSThomas Zimmermann if (dllmin[0] > dlli) 448*0f336e9cSThomas Zimmermann dllmin[0] = dlli; 449*0f336e9cSThomas Zimmermann if (dllmax[0] < dlli) 450*0f336e9cSThomas Zimmermann dllmax[0] = dlli; 451*0f336e9cSThomas Zimmermann } 452*0f336e9cSThomas Zimmermann if (data & 0x2) { 453*0f336e9cSThomas Zimmermann if (dllmin[1] > dlli) 454*0f336e9cSThomas Zimmermann dllmin[1] = dlli; 455*0f336e9cSThomas Zimmermann if (dllmax[1] < dlli) 456*0f336e9cSThomas Zimmermann dllmax[1] = dlli; 457*0f336e9cSThomas Zimmermann } 458*0f336e9cSThomas Zimmermann passcnt++; 459*0f336e9cSThomas Zimmermann } else if (passcnt >= CBR_THRESHOLD) { 460*0f336e9cSThomas Zimmermann break; 461*0f336e9cSThomas Zimmermann } 462*0f336e9cSThomas Zimmermann } 463*0f336e9cSThomas Zimmermann if (retry++ > 10) 464*0f336e9cSThomas Zimmermann goto CBR_DONE2; 465*0f336e9cSThomas Zimmermann if (dllmax[0] == 0 || (dllmax[0] - dllmin[0]) < CBR_THRESHOLD) 466*0f336e9cSThomas Zimmermann goto CBR_START2; 467*0f336e9cSThomas Zimmermann if (dllmax[1] == 0 || (dllmax[1] - dllmin[1]) < CBR_THRESHOLD) 468*0f336e9cSThomas Zimmermann goto CBR_START2; 469*0f336e9cSThomas Zimmermann status = true; 470*0f336e9cSThomas Zimmermann CBR_DONE2: 471*0f336e9cSThomas Zimmermann dlli = (dllmin[1] + dllmax[1]) >> 1; 472*0f336e9cSThomas Zimmermann dlli <<= 8; 473*0f336e9cSThomas Zimmermann dlli += (dllmin[0] + dllmax[0]) >> 1; 474*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16)); 475*0f336e9cSThomas Zimmermann return status; 476*0f336e9cSThomas Zimmermann } /* CBRDLL2 */ 477*0f336e9cSThomas Zimmermann 478*0f336e9cSThomas Zimmermann static void get_ddr3_info(struct ast_device *ast, struct ast2300_dram_param *param) 479*0f336e9cSThomas Zimmermann { 480*0f336e9cSThomas Zimmermann u32 trap, trap_AC2, trap_MRS; 481*0f336e9cSThomas Zimmermann 482*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 483*0f336e9cSThomas Zimmermann 484*0f336e9cSThomas Zimmermann /* Ger trap info */ 485*0f336e9cSThomas Zimmermann trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 486*0f336e9cSThomas Zimmermann trap_AC2 = 0x00020000 + (trap << 16); 487*0f336e9cSThomas Zimmermann trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19); 488*0f336e9cSThomas Zimmermann trap_MRS = 0x00000010 + (trap << 4); 489*0f336e9cSThomas Zimmermann trap_MRS |= ((trap & 0x2) << 18); 490*0f336e9cSThomas Zimmermann 491*0f336e9cSThomas Zimmermann param->reg_MADJ = 0x00034C4C; 492*0f336e9cSThomas Zimmermann param->reg_SADJ = 0x00001800; 493*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F0; 494*0f336e9cSThomas Zimmermann param->reg_PERIOD = param->dram_freq; 495*0f336e9cSThomas Zimmermann param->rodt = 0; 496*0f336e9cSThomas Zimmermann 497*0f336e9cSThomas Zimmermann switch (param->dram_freq) { 498*0f336e9cSThomas Zimmermann case 336: 499*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0190); 500*0f336e9cSThomas Zimmermann param->wodt = 0; 501*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x22202725; 502*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA007613 | trap_AC2; 503*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000BA; 504*0f336e9cSThomas Zimmermann param->reg_MRS = 0x04001400 | trap_MRS; 505*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000000; 506*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000023; 507*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000074; 508*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x00004DC0; 509*0f336e9cSThomas Zimmermann param->madj_max = 96; 510*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 511*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 512*0f336e9cSThomas Zimmermann default: 513*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 514*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 515*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA007613 | trap_AC2; 516*0f336e9cSThomas Zimmermann break; 517*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 518*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA00761C | trap_AC2; 519*0f336e9cSThomas Zimmermann break; 520*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 521*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA007636 | trap_AC2; 522*0f336e9cSThomas Zimmermann break; 523*0f336e9cSThomas Zimmermann } 524*0f336e9cSThomas Zimmermann break; 525*0f336e9cSThomas Zimmermann default: 526*0f336e9cSThomas Zimmermann case 396: 527*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x03F1); 528*0f336e9cSThomas Zimmermann param->wodt = 1; 529*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302825; 530*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC009617 | trap_AC2; 531*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000E2; 532*0f336e9cSThomas Zimmermann param->reg_MRS = 0x04001600 | trap_MRS; 533*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000000; 534*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000034; 535*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000FA; 536*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000089; 537*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x00005040; 538*0f336e9cSThomas Zimmermann param->madj_max = 96; 539*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 4; 540*0f336e9cSThomas Zimmermann 541*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 542*0f336e9cSThomas Zimmermann default: 543*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 544*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 545*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC009617 | trap_AC2; 546*0f336e9cSThomas Zimmermann break; 547*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 548*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC009622 | trap_AC2; 549*0f336e9cSThomas Zimmermann break; 550*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 551*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00963F | trap_AC2; 552*0f336e9cSThomas Zimmermann break; 553*0f336e9cSThomas Zimmermann } 554*0f336e9cSThomas Zimmermann break; 555*0f336e9cSThomas Zimmermann 556*0f336e9cSThomas Zimmermann case 408: 557*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x01F0); 558*0f336e9cSThomas Zimmermann param->wodt = 1; 559*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302825; 560*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC009617 | trap_AC2; 561*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000E2; 562*0f336e9cSThomas Zimmermann param->reg_MRS = 0x04001600 | trap_MRS; 563*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000000; 564*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000023; 565*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000FA; 566*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000089; 567*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000050C0; 568*0f336e9cSThomas Zimmermann param->madj_max = 96; 569*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 4; 570*0f336e9cSThomas Zimmermann 571*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 572*0f336e9cSThomas Zimmermann default: 573*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 574*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 575*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC009617 | trap_AC2; 576*0f336e9cSThomas Zimmermann break; 577*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 578*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC009622 | trap_AC2; 579*0f336e9cSThomas Zimmermann break; 580*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 581*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00963F | trap_AC2; 582*0f336e9cSThomas Zimmermann break; 583*0f336e9cSThomas Zimmermann } 584*0f336e9cSThomas Zimmermann 585*0f336e9cSThomas Zimmermann break; 586*0f336e9cSThomas Zimmermann case 456: 587*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0230); 588*0f336e9cSThomas Zimmermann param->wodt = 0; 589*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302926; 590*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCD44961A; 591*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000FC; 592*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00081830; 593*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000000; 594*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000045; 595*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000097; 596*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000052C0; 597*0f336e9cSThomas Zimmermann param->madj_max = 88; 598*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 4; 599*0f336e9cSThomas Zimmermann break; 600*0f336e9cSThomas Zimmermann case 504: 601*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0270); 602*0f336e9cSThomas Zimmermann param->wodt = 1; 603*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302926; 604*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xDE44A61D; 605*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x00000117; 606*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00081A30; 607*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000000; 608*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x070000BB; 609*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x000000A0; 610*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000054C0; 611*0f336e9cSThomas Zimmermann param->madj_max = 79; 612*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 4; 613*0f336e9cSThomas Zimmermann break; 614*0f336e9cSThomas Zimmermann case 528: 615*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0290); 616*0f336e9cSThomas Zimmermann param->wodt = 1; 617*0f336e9cSThomas Zimmermann param->rodt = 1; 618*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302926; 619*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xEF44B61E; 620*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x00000125; 621*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00081A30; 622*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000040; 623*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F5; 624*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000023; 625*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000088; 626*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000055C0; 627*0f336e9cSThomas Zimmermann param->madj_max = 76; 628*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 629*0f336e9cSThomas Zimmermann break; 630*0f336e9cSThomas Zimmermann case 576: 631*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0140); 632*0f336e9cSThomas Zimmermann param->reg_MADJ = 0x00136868; 633*0f336e9cSThomas Zimmermann param->reg_SADJ = 0x00004534; 634*0f336e9cSThomas Zimmermann param->wodt = 1; 635*0f336e9cSThomas Zimmermann param->rodt = 1; 636*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302A37; 637*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xEF56B61E; 638*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x0000013F; 639*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00101A50; 640*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000040; 641*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000FA; 642*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000023; 643*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000078; 644*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000057C0; 645*0f336e9cSThomas Zimmermann param->madj_max = 136; 646*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 647*0f336e9cSThomas Zimmermann break; 648*0f336e9cSThomas Zimmermann case 600: 649*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x02E1); 650*0f336e9cSThomas Zimmermann param->reg_MADJ = 0x00136868; 651*0f336e9cSThomas Zimmermann param->reg_SADJ = 0x00004534; 652*0f336e9cSThomas Zimmermann param->wodt = 1; 653*0f336e9cSThomas Zimmermann param->rodt = 1; 654*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x32302A37; 655*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xDF56B61F; 656*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x0000014D; 657*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00101A50; 658*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000004; 659*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F5; 660*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000023; 661*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000078; 662*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000058C0; 663*0f336e9cSThomas Zimmermann param->madj_max = 132; 664*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 665*0f336e9cSThomas Zimmermann break; 666*0f336e9cSThomas Zimmermann case 624: 667*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0160); 668*0f336e9cSThomas Zimmermann param->reg_MADJ = 0x00136868; 669*0f336e9cSThomas Zimmermann param->reg_SADJ = 0x00004534; 670*0f336e9cSThomas Zimmermann param->wodt = 1; 671*0f336e9cSThomas Zimmermann param->rodt = 1; 672*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x32302A37; 673*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xEF56B621; 674*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x0000015A; 675*0f336e9cSThomas Zimmermann param->reg_MRS = 0x02101A50; 676*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000004; 677*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F5; 678*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000034; 679*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000078; 680*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000059C0; 681*0f336e9cSThomas Zimmermann param->madj_max = 128; 682*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 683*0f336e9cSThomas Zimmermann break; 684*0f336e9cSThomas Zimmermann } /* switch freq */ 685*0f336e9cSThomas Zimmermann 686*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 687*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 688*0f336e9cSThomas Zimmermann param->dram_config = 0x130; 689*0f336e9cSThomas Zimmermann break; 690*0f336e9cSThomas Zimmermann default: 691*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 692*0f336e9cSThomas Zimmermann param->dram_config = 0x131; 693*0f336e9cSThomas Zimmermann break; 694*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 695*0f336e9cSThomas Zimmermann param->dram_config = 0x132; 696*0f336e9cSThomas Zimmermann break; 697*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 698*0f336e9cSThomas Zimmermann param->dram_config = 0x133; 699*0f336e9cSThomas Zimmermann break; 700*0f336e9cSThomas Zimmermann } /* switch size */ 701*0f336e9cSThomas Zimmermann 702*0f336e9cSThomas Zimmermann switch (param->vram_size) { 703*0f336e9cSThomas Zimmermann default: 704*0f336e9cSThomas Zimmermann case SZ_8M: 705*0f336e9cSThomas Zimmermann param->dram_config |= 0x00; 706*0f336e9cSThomas Zimmermann break; 707*0f336e9cSThomas Zimmermann case SZ_16M: 708*0f336e9cSThomas Zimmermann param->dram_config |= 0x04; 709*0f336e9cSThomas Zimmermann break; 710*0f336e9cSThomas Zimmermann case SZ_32M: 711*0f336e9cSThomas Zimmermann param->dram_config |= 0x08; 712*0f336e9cSThomas Zimmermann break; 713*0f336e9cSThomas Zimmermann case SZ_64M: 714*0f336e9cSThomas Zimmermann param->dram_config |= 0x0c; 715*0f336e9cSThomas Zimmermann break; 716*0f336e9cSThomas Zimmermann } 717*0f336e9cSThomas Zimmermann } 718*0f336e9cSThomas Zimmermann 719*0f336e9cSThomas Zimmermann static void ddr3_init(struct ast_device *ast, struct ast2300_dram_param *param) 720*0f336e9cSThomas Zimmermann { 721*0f336e9cSThomas Zimmermann u32 data, data2, retry = 0; 722*0f336e9cSThomas Zimmermann 723*0f336e9cSThomas Zimmermann ddr3_init_start: 724*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0000, 0xFC600309); 725*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, 0x00000100); 726*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0024, 0x00000000); 727*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0034, 0x00000000); 728*0f336e9cSThomas Zimmermann udelay(10); 729*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 730*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 731*0f336e9cSThomas Zimmermann udelay(10); 732*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 733*0f336e9cSThomas Zimmermann udelay(10); 734*0f336e9cSThomas Zimmermann 735*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0004, param->dram_config); 736*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0008, 0x90040f); 737*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1); 738*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2); 739*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 740*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0080, 0x00000000); 741*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0084, 0x00000000); 742*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 743*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, 0x4000A170); 744*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, 0x00002370); 745*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0038, 0x00000000); 746*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0040, 0xFF444444); 747*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0044, 0x22222222); 748*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0048, 0x22222222); 749*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E004C, 0x00000002); 750*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 751*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 752*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0054, 0); 753*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV); 754*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 755*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 756*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0074, 0x00000000); 757*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0078, 0x00000000); 758*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 759*0f336e9cSThomas Zimmermann /* Wait MCLK2X lock to MCLK */ 760*0f336e9cSThomas Zimmermann do { 761*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 762*0f336e9cSThomas Zimmermann } while (!(data & 0x08000000)); 763*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 764*0f336e9cSThomas Zimmermann data = (data >> 8) & 0xff; 765*0f336e9cSThomas Zimmermann while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 766*0f336e9cSThomas Zimmermann data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 767*0f336e9cSThomas Zimmermann if ((data2 & 0xff) > param->madj_max) 768*0f336e9cSThomas Zimmermann break; 769*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, data2); 770*0f336e9cSThomas Zimmermann if (data2 & 0x00100000) 771*0f336e9cSThomas Zimmermann data2 = ((data2 & 0xff) >> 3) + 3; 772*0f336e9cSThomas Zimmermann else 773*0f336e9cSThomas Zimmermann data2 = ((data2 & 0xff) >> 2) + 5; 774*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff; 775*0f336e9cSThomas Zimmermann data2 += data & 0xff; 776*0f336e9cSThomas Zimmermann data = data | (data2 << 8); 777*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, data); 778*0f336e9cSThomas Zimmermann udelay(10); 779*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000); 780*0f336e9cSThomas Zimmermann udelay(10); 781*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 782*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, data); 783*0f336e9cSThomas Zimmermann data = data | 0x200; 784*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, data); 785*0f336e9cSThomas Zimmermann do { 786*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 787*0f336e9cSThomas Zimmermann } while (!(data & 0x08000000)); 788*0f336e9cSThomas Zimmermann 789*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 790*0f336e9cSThomas Zimmermann data = (data >> 8) & 0xff; 791*0f336e9cSThomas Zimmermann } 792*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff); 793*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0018) | 0xC00; 794*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, data); 795*0f336e9cSThomas Zimmermann 796*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0034, 0x00000001); 797*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, 0x00000040); 798*0f336e9cSThomas Zimmermann udelay(50); 799*0f336e9cSThomas Zimmermann /* Mode Register Setting */ 800*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 801*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 802*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000005); 803*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000007); 804*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 805*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 806*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS); 807*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, 0x00005C08); 808*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 809*0f336e9cSThomas Zimmermann 810*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, 0x00005C01); 811*0f336e9cSThomas Zimmermann data = 0; 812*0f336e9cSThomas Zimmermann if (param->wodt) 813*0f336e9cSThomas Zimmermann data = 0x300; 814*0f336e9cSThomas Zimmermann if (param->rodt) 815*0f336e9cSThomas Zimmermann data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 816*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0034, data | 0x3); 817*0f336e9cSThomas Zimmermann 818*0f336e9cSThomas Zimmermann /* Calibrate the DQSI delay */ 819*0f336e9cSThomas Zimmermann if ((cbr_dll2(ast, param) == false) && (retry++ < 10)) 820*0f336e9cSThomas Zimmermann goto ddr3_init_start; 821*0f336e9cSThomas Zimmermann 822*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 823*0f336e9cSThomas Zimmermann /* ECC Memory Initialization */ 824*0f336e9cSThomas Zimmermann #ifdef ECC 825*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 826*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0070, 0x221); 827*0f336e9cSThomas Zimmermann do { 828*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0070); 829*0f336e9cSThomas Zimmermann } while (!(data & 0x00001000)); 830*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 831*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 832*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 833*0f336e9cSThomas Zimmermann #endif 834*0f336e9cSThomas Zimmermann } 835*0f336e9cSThomas Zimmermann 836*0f336e9cSThomas Zimmermann static void get_ddr2_info(struct ast_device *ast, struct ast2300_dram_param *param) 837*0f336e9cSThomas Zimmermann { 838*0f336e9cSThomas Zimmermann u32 trap, trap_AC2, trap_MRS; 839*0f336e9cSThomas Zimmermann 840*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 841*0f336e9cSThomas Zimmermann 842*0f336e9cSThomas Zimmermann /* Ger trap info */ 843*0f336e9cSThomas Zimmermann trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 844*0f336e9cSThomas Zimmermann trap_AC2 = (trap << 20) | (trap << 16); 845*0f336e9cSThomas Zimmermann trap_AC2 += 0x00110000; 846*0f336e9cSThomas Zimmermann trap_MRS = 0x00000040 | (trap << 4); 847*0f336e9cSThomas Zimmermann 848*0f336e9cSThomas Zimmermann param->reg_MADJ = 0x00034C4C; 849*0f336e9cSThomas Zimmermann param->reg_SADJ = 0x00001800; 850*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F0; 851*0f336e9cSThomas Zimmermann param->reg_PERIOD = param->dram_freq; 852*0f336e9cSThomas Zimmermann param->rodt = 0; 853*0f336e9cSThomas Zimmermann 854*0f336e9cSThomas Zimmermann switch (param->dram_freq) { 855*0f336e9cSThomas Zimmermann case 264: 856*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0130); 857*0f336e9cSThomas Zimmermann param->wodt = 0; 858*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x11101513; 859*0f336e9cSThomas Zimmermann param->reg_AC2 = 0x78117011; 860*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x00000092; 861*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000842; 862*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000000; 863*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F0; 864*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000034; 865*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x0000005A; 866*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x00004AC0; 867*0f336e9cSThomas Zimmermann param->madj_max = 138; 868*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 869*0f336e9cSThomas Zimmermann break; 870*0f336e9cSThomas Zimmermann case 336: 871*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0190); 872*0f336e9cSThomas Zimmermann param->wodt = 1; 873*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x22202613; 874*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA009016 | trap_AC2; 875*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000BA; 876*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000A02 | trap_MRS; 877*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000040; 878*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000FA; 879*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000034; 880*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000074; 881*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x00004DC0; 882*0f336e9cSThomas Zimmermann param->madj_max = 96; 883*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 884*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 885*0f336e9cSThomas Zimmermann default: 886*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 887*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA009012 | trap_AC2; 888*0f336e9cSThomas Zimmermann break; 889*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 890*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA009016 | trap_AC2; 891*0f336e9cSThomas Zimmermann break; 892*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 893*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA009023 | trap_AC2; 894*0f336e9cSThomas Zimmermann break; 895*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 896*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xAA00903B | trap_AC2; 897*0f336e9cSThomas Zimmermann break; 898*0f336e9cSThomas Zimmermann } 899*0f336e9cSThomas Zimmermann break; 900*0f336e9cSThomas Zimmermann default: 901*0f336e9cSThomas Zimmermann case 396: 902*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x03F1); 903*0f336e9cSThomas Zimmermann param->wodt = 1; 904*0f336e9cSThomas Zimmermann param->rodt = 0; 905*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302714; 906*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B01B | trap_AC2; 907*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000E2; 908*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000C02 | trap_MRS; 909*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000040; 910*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000FA; 911*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000034; 912*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000089; 913*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x00005040; 914*0f336e9cSThomas Zimmermann param->madj_max = 96; 915*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 4; 916*0f336e9cSThomas Zimmermann 917*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 918*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 919*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B016 | trap_AC2; 920*0f336e9cSThomas Zimmermann break; 921*0f336e9cSThomas Zimmermann default: 922*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 923*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B01B | trap_AC2; 924*0f336e9cSThomas Zimmermann break; 925*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 926*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B02B | trap_AC2; 927*0f336e9cSThomas Zimmermann break; 928*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 929*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B03F | trap_AC2; 930*0f336e9cSThomas Zimmermann break; 931*0f336e9cSThomas Zimmermann } 932*0f336e9cSThomas Zimmermann 933*0f336e9cSThomas Zimmermann break; 934*0f336e9cSThomas Zimmermann 935*0f336e9cSThomas Zimmermann case 408: 936*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x01F0); 937*0f336e9cSThomas Zimmermann param->wodt = 1; 938*0f336e9cSThomas Zimmermann param->rodt = 0; 939*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302714; 940*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B01B | trap_AC2; 941*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000E2; 942*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000C02 | trap_MRS; 943*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000040; 944*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000FA; 945*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000034; 946*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000089; 947*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000050C0; 948*0f336e9cSThomas Zimmermann param->madj_max = 96; 949*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 4; 950*0f336e9cSThomas Zimmermann 951*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 952*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 953*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B016 | trap_AC2; 954*0f336e9cSThomas Zimmermann break; 955*0f336e9cSThomas Zimmermann default: 956*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 957*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B01B | trap_AC2; 958*0f336e9cSThomas Zimmermann break; 959*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 960*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B02B | trap_AC2; 961*0f336e9cSThomas Zimmermann break; 962*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 963*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCC00B03F | trap_AC2; 964*0f336e9cSThomas Zimmermann break; 965*0f336e9cSThomas Zimmermann } 966*0f336e9cSThomas Zimmermann 967*0f336e9cSThomas Zimmermann break; 968*0f336e9cSThomas Zimmermann case 456: 969*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0230); 970*0f336e9cSThomas Zimmermann param->wodt = 0; 971*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302815; 972*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xCD44B01E; 973*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x000000FC; 974*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000E72; 975*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000000; 976*0f336e9cSThomas Zimmermann param->reg_DRV = 0x00000000; 977*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000034; 978*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x00000097; 979*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000052C0; 980*0f336e9cSThomas Zimmermann param->madj_max = 88; 981*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 982*0f336e9cSThomas Zimmermann break; 983*0f336e9cSThomas Zimmermann case 504: 984*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0261); 985*0f336e9cSThomas Zimmermann param->wodt = 1; 986*0f336e9cSThomas Zimmermann param->rodt = 1; 987*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302815; 988*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xDE44C022; 989*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x00000117; 990*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000E72; 991*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000040; 992*0f336e9cSThomas Zimmermann param->reg_DRV = 0x0000000A; 993*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000045; 994*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x000000A0; 995*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000054C0; 996*0f336e9cSThomas Zimmermann param->madj_max = 79; 997*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 998*0f336e9cSThomas Zimmermann break; 999*0f336e9cSThomas Zimmermann case 528: 1000*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0120); 1001*0f336e9cSThomas Zimmermann param->wodt = 1; 1002*0f336e9cSThomas Zimmermann param->rodt = 1; 1003*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x33302815; 1004*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xEF44D024; 1005*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x00000125; 1006*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000E72; 1007*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000004; 1008*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F9; 1009*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000045; 1010*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x000000A7; 1011*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000055C0; 1012*0f336e9cSThomas Zimmermann param->madj_max = 76; 1013*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 1014*0f336e9cSThomas Zimmermann break; 1015*0f336e9cSThomas Zimmermann case 552: 1016*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x02A1); 1017*0f336e9cSThomas Zimmermann param->wodt = 1; 1018*0f336e9cSThomas Zimmermann param->rodt = 1; 1019*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x43402915; 1020*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xFF44E025; 1021*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x00000132; 1022*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000E72; 1023*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000040; 1024*0f336e9cSThomas Zimmermann param->reg_DRV = 0x0000000A; 1025*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000045; 1026*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x000000AD; 1027*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000056C0; 1028*0f336e9cSThomas Zimmermann param->madj_max = 76; 1029*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 1030*0f336e9cSThomas Zimmermann break; 1031*0f336e9cSThomas Zimmermann case 576: 1032*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E2020, 0x0140); 1033*0f336e9cSThomas Zimmermann param->wodt = 1; 1034*0f336e9cSThomas Zimmermann param->rodt = 1; 1035*0f336e9cSThomas Zimmermann param->reg_AC1 = 0x43402915; 1036*0f336e9cSThomas Zimmermann param->reg_AC2 = 0xFF44E027; 1037*0f336e9cSThomas Zimmermann param->reg_DQSIC = 0x0000013F; 1038*0f336e9cSThomas Zimmermann param->reg_MRS = 0x00000E72; 1039*0f336e9cSThomas Zimmermann param->reg_EMRS = 0x00000004; 1040*0f336e9cSThomas Zimmermann param->reg_DRV = 0x000000F5; 1041*0f336e9cSThomas Zimmermann param->reg_IOZ = 0x00000045; 1042*0f336e9cSThomas Zimmermann param->reg_DQIDLY = 0x000000B3; 1043*0f336e9cSThomas Zimmermann param->reg_FREQ = 0x000057C0; 1044*0f336e9cSThomas Zimmermann param->madj_max = 76; 1045*0f336e9cSThomas Zimmermann param->dll2_finetune_step = 3; 1046*0f336e9cSThomas Zimmermann break; 1047*0f336e9cSThomas Zimmermann } 1048*0f336e9cSThomas Zimmermann 1049*0f336e9cSThomas Zimmermann switch (param->dram_chipid) { 1050*0f336e9cSThomas Zimmermann case AST_DRAM_512Mx16: 1051*0f336e9cSThomas Zimmermann param->dram_config = 0x100; 1052*0f336e9cSThomas Zimmermann break; 1053*0f336e9cSThomas Zimmermann default: 1054*0f336e9cSThomas Zimmermann case AST_DRAM_1Gx16: 1055*0f336e9cSThomas Zimmermann param->dram_config = 0x121; 1056*0f336e9cSThomas Zimmermann break; 1057*0f336e9cSThomas Zimmermann case AST_DRAM_2Gx16: 1058*0f336e9cSThomas Zimmermann param->dram_config = 0x122; 1059*0f336e9cSThomas Zimmermann break; 1060*0f336e9cSThomas Zimmermann case AST_DRAM_4Gx16: 1061*0f336e9cSThomas Zimmermann param->dram_config = 0x123; 1062*0f336e9cSThomas Zimmermann break; 1063*0f336e9cSThomas Zimmermann } /* switch size */ 1064*0f336e9cSThomas Zimmermann 1065*0f336e9cSThomas Zimmermann switch (param->vram_size) { 1066*0f336e9cSThomas Zimmermann default: 1067*0f336e9cSThomas Zimmermann case SZ_8M: 1068*0f336e9cSThomas Zimmermann param->dram_config |= 0x00; 1069*0f336e9cSThomas Zimmermann break; 1070*0f336e9cSThomas Zimmermann case SZ_16M: 1071*0f336e9cSThomas Zimmermann param->dram_config |= 0x04; 1072*0f336e9cSThomas Zimmermann break; 1073*0f336e9cSThomas Zimmermann case SZ_32M: 1074*0f336e9cSThomas Zimmermann param->dram_config |= 0x08; 1075*0f336e9cSThomas Zimmermann break; 1076*0f336e9cSThomas Zimmermann case SZ_64M: 1077*0f336e9cSThomas Zimmermann param->dram_config |= 0x0c; 1078*0f336e9cSThomas Zimmermann break; 1079*0f336e9cSThomas Zimmermann } 1080*0f336e9cSThomas Zimmermann } 1081*0f336e9cSThomas Zimmermann 1082*0f336e9cSThomas Zimmermann static void ddr2_init(struct ast_device *ast, struct ast2300_dram_param *param) 1083*0f336e9cSThomas Zimmermann { 1084*0f336e9cSThomas Zimmermann u32 data, data2, retry = 0; 1085*0f336e9cSThomas Zimmermann 1086*0f336e9cSThomas Zimmermann ddr2_init_start: 1087*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0000, 0xFC600309); 1088*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, 0x00000100); 1089*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0024, 0x00000000); 1090*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 1091*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 1092*0f336e9cSThomas Zimmermann udelay(10); 1093*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 1094*0f336e9cSThomas Zimmermann udelay(10); 1095*0f336e9cSThomas Zimmermann 1096*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0004, param->dram_config); 1097*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0008, 0x90040f); 1098*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1); 1099*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2); 1100*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 1101*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0080, 0x00000000); 1102*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0084, 0x00000000); 1103*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 1104*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, 0x4000A130); 1105*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, 0x00002330); 1106*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0038, 0x00000000); 1107*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0040, 0xFF808000); 1108*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0044, 0x88848466); 1109*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0048, 0x44440008); 1110*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E004C, 0x00000000); 1111*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 1112*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 1113*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0054, 0); 1114*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV); 1115*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 1116*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 1117*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0074, 0x00000000); 1118*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0078, 0x00000000); 1119*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 1120*0f336e9cSThomas Zimmermann 1121*0f336e9cSThomas Zimmermann /* Wait MCLK2X lock to MCLK */ 1122*0f336e9cSThomas Zimmermann do { 1123*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 1124*0f336e9cSThomas Zimmermann } while (!(data & 0x08000000)); 1125*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 1126*0f336e9cSThomas Zimmermann data = (data >> 8) & 0xff; 1127*0f336e9cSThomas Zimmermann while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 1128*0f336e9cSThomas Zimmermann data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 1129*0f336e9cSThomas Zimmermann if ((data2 & 0xff) > param->madj_max) 1130*0f336e9cSThomas Zimmermann break; 1131*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, data2); 1132*0f336e9cSThomas Zimmermann if (data2 & 0x00100000) 1133*0f336e9cSThomas Zimmermann data2 = ((data2 & 0xff) >> 3) + 3; 1134*0f336e9cSThomas Zimmermann else 1135*0f336e9cSThomas Zimmermann data2 = ((data2 & 0xff) >> 2) + 5; 1136*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff; 1137*0f336e9cSThomas Zimmermann data2 += data & 0xff; 1138*0f336e9cSThomas Zimmermann data = data | (data2 << 8); 1139*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0068, data); 1140*0f336e9cSThomas Zimmermann udelay(10); 1141*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000); 1142*0f336e9cSThomas Zimmermann udelay(10); 1143*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 1144*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, data); 1145*0f336e9cSThomas Zimmermann data = data | 0x200; 1146*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, data); 1147*0f336e9cSThomas Zimmermann do { 1148*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 1149*0f336e9cSThomas Zimmermann } while (!(data & 0x08000000)); 1150*0f336e9cSThomas Zimmermann 1151*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E001C); 1152*0f336e9cSThomas Zimmermann data = (data >> 8) & 0xff; 1153*0f336e9cSThomas Zimmermann } 1154*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff); 1155*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0018) | 0xC00; 1156*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0018, data); 1157*0f336e9cSThomas Zimmermann 1158*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0034, 0x00000001); 1159*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, 0x00000000); 1160*0f336e9cSThomas Zimmermann udelay(50); 1161*0f336e9cSThomas Zimmermann /* Mode Register Setting */ 1162*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 1163*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1164*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000005); 1165*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000007); 1166*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 1167*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 1168*0f336e9cSThomas Zimmermann 1169*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, 0x00005C08); 1170*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS); 1171*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 1172*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380); 1173*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 1174*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1175*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 1176*0f336e9cSThomas Zimmermann 1177*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01); 1178*0f336e9cSThomas Zimmermann data = 0; 1179*0f336e9cSThomas Zimmermann if (param->wodt) 1180*0f336e9cSThomas Zimmermann data = 0x500; 1181*0f336e9cSThomas Zimmermann if (param->rodt) 1182*0f336e9cSThomas Zimmermann data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 1183*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0034, data | 0x3); 1184*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 1185*0f336e9cSThomas Zimmermann 1186*0f336e9cSThomas Zimmermann /* Calibrate the DQSI delay */ 1187*0f336e9cSThomas Zimmermann if ((cbr_dll2(ast, param) == false) && (retry++ < 10)) 1188*0f336e9cSThomas Zimmermann goto ddr2_init_start; 1189*0f336e9cSThomas Zimmermann 1190*0f336e9cSThomas Zimmermann /* ECC Memory Initialization */ 1191*0f336e9cSThomas Zimmermann #ifdef ECC 1192*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 1193*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0070, 0x221); 1194*0f336e9cSThomas Zimmermann do { 1195*0f336e9cSThomas Zimmermann data = ast_mindwm(ast, 0x1E6E0070); 1196*0f336e9cSThomas Zimmermann } while (!(data & 0x00001000)); 1197*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 1198*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 1199*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 1200*0f336e9cSThomas Zimmermann #endif 1201*0f336e9cSThomas Zimmermann } 1202*0f336e9cSThomas Zimmermann 1203*0f336e9cSThomas Zimmermann static void ast_post_chip_2300(struct ast_device *ast) 1204*0f336e9cSThomas Zimmermann { 1205*0f336e9cSThomas Zimmermann struct ast2300_dram_param param; 1206*0f336e9cSThomas Zimmermann u32 temp; 1207*0f336e9cSThomas Zimmermann u8 reg; 1208*0f336e9cSThomas Zimmermann 1209*0f336e9cSThomas Zimmermann reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); 1210*0f336e9cSThomas Zimmermann if ((reg & 0x80) == 0) {/* vga only */ 1211*0f336e9cSThomas Zimmermann ast_write32(ast, 0xf004, 0x1e6e0000); 1212*0f336e9cSThomas Zimmermann ast_write32(ast, 0xf000, 0x1); 1213*0f336e9cSThomas Zimmermann ast_write32(ast, 0x12000, 0x1688a8a8); 1214*0f336e9cSThomas Zimmermann do { 1215*0f336e9cSThomas Zimmermann ; 1216*0f336e9cSThomas Zimmermann } while (ast_read32(ast, 0x12000) != 0x1); 1217*0f336e9cSThomas Zimmermann 1218*0f336e9cSThomas Zimmermann ast_write32(ast, 0x10000, 0xfc600309); 1219*0f336e9cSThomas Zimmermann do { 1220*0f336e9cSThomas Zimmermann ; 1221*0f336e9cSThomas Zimmermann } while (ast_read32(ast, 0x10000) != 0x1); 1222*0f336e9cSThomas Zimmermann 1223*0f336e9cSThomas Zimmermann /* Slow down CPU/AHB CLK in VGA only mode */ 1224*0f336e9cSThomas Zimmermann temp = ast_read32(ast, 0x12008); 1225*0f336e9cSThomas Zimmermann temp |= 0x73; 1226*0f336e9cSThomas Zimmermann ast_write32(ast, 0x12008, temp); 1227*0f336e9cSThomas Zimmermann 1228*0f336e9cSThomas Zimmermann param.dram_freq = 396; 1229*0f336e9cSThomas Zimmermann param.dram_type = AST_DDR3; 1230*0f336e9cSThomas Zimmermann temp = ast_mindwm(ast, 0x1e6e2070); 1231*0f336e9cSThomas Zimmermann if (temp & 0x01000000) 1232*0f336e9cSThomas Zimmermann param.dram_type = AST_DDR2; 1233*0f336e9cSThomas Zimmermann switch (temp & 0x18000000) { 1234*0f336e9cSThomas Zimmermann case 0: 1235*0f336e9cSThomas Zimmermann param.dram_chipid = AST_DRAM_512Mx16; 1236*0f336e9cSThomas Zimmermann break; 1237*0f336e9cSThomas Zimmermann default: 1238*0f336e9cSThomas Zimmermann case 0x08000000: 1239*0f336e9cSThomas Zimmermann param.dram_chipid = AST_DRAM_1Gx16; 1240*0f336e9cSThomas Zimmermann break; 1241*0f336e9cSThomas Zimmermann case 0x10000000: 1242*0f336e9cSThomas Zimmermann param.dram_chipid = AST_DRAM_2Gx16; 1243*0f336e9cSThomas Zimmermann break; 1244*0f336e9cSThomas Zimmermann case 0x18000000: 1245*0f336e9cSThomas Zimmermann param.dram_chipid = AST_DRAM_4Gx16; 1246*0f336e9cSThomas Zimmermann break; 1247*0f336e9cSThomas Zimmermann } 1248*0f336e9cSThomas Zimmermann switch (temp & 0x0c) { 1249*0f336e9cSThomas Zimmermann default: 1250*0f336e9cSThomas Zimmermann case 0x00: 1251*0f336e9cSThomas Zimmermann param.vram_size = SZ_8M; 1252*0f336e9cSThomas Zimmermann break; 1253*0f336e9cSThomas Zimmermann case 0x04: 1254*0f336e9cSThomas Zimmermann param.vram_size = SZ_16M; 1255*0f336e9cSThomas Zimmermann break; 1256*0f336e9cSThomas Zimmermann case 0x08: 1257*0f336e9cSThomas Zimmermann param.vram_size = SZ_32M; 1258*0f336e9cSThomas Zimmermann break; 1259*0f336e9cSThomas Zimmermann case 0x0c: 1260*0f336e9cSThomas Zimmermann param.vram_size = SZ_64M; 1261*0f336e9cSThomas Zimmermann break; 1262*0f336e9cSThomas Zimmermann } 1263*0f336e9cSThomas Zimmermann 1264*0f336e9cSThomas Zimmermann if (param.dram_type == AST_DDR3) { 1265*0f336e9cSThomas Zimmermann get_ddr3_info(ast, ¶m); 1266*0f336e9cSThomas Zimmermann ddr3_init(ast, ¶m); 1267*0f336e9cSThomas Zimmermann } else { 1268*0f336e9cSThomas Zimmermann get_ddr2_info(ast, ¶m); 1269*0f336e9cSThomas Zimmermann ddr2_init(ast, ¶m); 1270*0f336e9cSThomas Zimmermann } 1271*0f336e9cSThomas Zimmermann 1272*0f336e9cSThomas Zimmermann temp = ast_mindwm(ast, 0x1e6e2040); 1273*0f336e9cSThomas Zimmermann ast_moutdwm(ast, 0x1e6e2040, temp | 0x40); 1274*0f336e9cSThomas Zimmermann } 1275*0f336e9cSThomas Zimmermann 1276*0f336e9cSThomas Zimmermann /* wait ready */ 1277*0f336e9cSThomas Zimmermann do { 1278*0f336e9cSThomas Zimmermann reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); 1279*0f336e9cSThomas Zimmermann } while ((reg & 0x40) == 0); 1280*0f336e9cSThomas Zimmermann } 1281*0f336e9cSThomas Zimmermann 1282*0f336e9cSThomas Zimmermann int ast_2300_post(struct ast_device *ast) 1283*0f336e9cSThomas Zimmermann { 1284*0f336e9cSThomas Zimmermann if (ast->config_mode == ast_use_p2a) { 1285*0f336e9cSThomas Zimmermann ast_post_chip_2300(ast); 1286*0f336e9cSThomas Zimmermann ast_init_3rdtx(ast); 1287*0f336e9cSThomas Zimmermann } else { 1288*0f336e9cSThomas Zimmermann if (ast->tx_chip == AST_TX_SIL164) { 1289*0f336e9cSThomas Zimmermann /* Enable DVO */ 1290*0f336e9cSThomas Zimmermann ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80); 1291*0f336e9cSThomas Zimmermann } 1292*0f336e9cSThomas Zimmermann } 1293*0f336e9cSThomas Zimmermann 1294*0f336e9cSThomas Zimmermann return 0; 1295*0f336e9cSThomas Zimmermann } 1296