1312fec14SDave Airlie /* 2312fec14SDave Airlie * Copyright 2012 Red Hat Inc. 3312fec14SDave Airlie * 4312fec14SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 5312fec14SDave Airlie * copy of this software and associated documentation files (the 6312fec14SDave Airlie * "Software"), to deal in the Software without restriction, including 7312fec14SDave Airlie * without limitation the rights to use, copy, modify, merge, publish, 8312fec14SDave Airlie * distribute, sub license, and/or sell copies of the Software, and to 9312fec14SDave Airlie * permit persons to whom the Software is furnished to do so, subject to 10312fec14SDave Airlie * the following conditions: 11312fec14SDave Airlie * 12312fec14SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13312fec14SDave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14312fec14SDave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 15312fec14SDave Airlie * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 16312fec14SDave Airlie * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 17312fec14SDave Airlie * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 18312fec14SDave Airlie * USE OR OTHER DEALINGS IN THE SOFTWARE. 19312fec14SDave Airlie * 20312fec14SDave Airlie * The above copyright notice and this permission notice (including the 21312fec14SDave Airlie * next paragraph) shall be included in all copies or substantial portions 22312fec14SDave Airlie * of the Software. 23312fec14SDave Airlie * 24312fec14SDave Airlie */ 25312fec14SDave Airlie /* 26312fec14SDave Airlie * Authors: Dave Airlie <airlied@redhat.com> 27312fec14SDave Airlie */ 28312fec14SDave Airlie 29760285e7SDavid Howells #include <drm/drmP.h> 30312fec14SDave Airlie #include "ast_drv.h" 31312fec14SDave Airlie 32312fec14SDave Airlie #include "ast_dram_tables.h" 33312fec14SDave Airlie 34312fec14SDave Airlie static void ast_init_dram_2300(struct drm_device *dev); 35312fec14SDave Airlie 36312fec14SDave Airlie static void 37312fec14SDave Airlie ast_enable_vga(struct drm_device *dev) 38312fec14SDave Airlie { 39312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 40312fec14SDave Airlie 41312fec14SDave Airlie ast_io_write8(ast, 0x43, 0x01); 42312fec14SDave Airlie ast_io_write8(ast, 0x42, 0x01); 43312fec14SDave Airlie } 44312fec14SDave Airlie 45312fec14SDave Airlie #if 0 /* will use later */ 46312fec14SDave Airlie static bool 47312fec14SDave Airlie ast_is_vga_enabled(struct drm_device *dev) 48312fec14SDave Airlie { 49312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 50312fec14SDave Airlie u8 ch; 51312fec14SDave Airlie 52312fec14SDave Airlie if (ast->chip == AST1180) { 53312fec14SDave Airlie /* TODO 1180 */ 54312fec14SDave Airlie } else { 55312fec14SDave Airlie ch = ast_io_read8(ast, 0x43); 56312fec14SDave Airlie if (ch) { 57312fec14SDave Airlie ast_open_key(ast); 58312fec14SDave Airlie ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff); 59312fec14SDave Airlie return ch & 0x04; 60312fec14SDave Airlie } 61312fec14SDave Airlie } 62312fec14SDave Airlie return 0; 63312fec14SDave Airlie } 64312fec14SDave Airlie #endif 65312fec14SDave Airlie 66312fec14SDave Airlie static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff }; 67312fec14SDave Airlie static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff }; 68312fec14SDave Airlie static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff }; 69312fec14SDave Airlie 70312fec14SDave Airlie static void 71312fec14SDave Airlie ast_set_def_ext_reg(struct drm_device *dev) 72312fec14SDave Airlie { 73312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 74312fec14SDave Airlie u8 i, index, reg; 75312fec14SDave Airlie const u8 *ext_reg_info; 76312fec14SDave Airlie 77312fec14SDave Airlie /* reset scratch */ 78312fec14SDave Airlie for (i = 0x81; i <= 0x8f; i++) 79312fec14SDave Airlie ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00); 80312fec14SDave Airlie 811453bf4cSDave Airlie if (ast->chip == AST2300 || ast->chip == AST2400) { 82312fec14SDave Airlie if (dev->pdev->revision >= 0x20) 83312fec14SDave Airlie ext_reg_info = extreginfo_ast2300; 84312fec14SDave Airlie else 85312fec14SDave Airlie ext_reg_info = extreginfo_ast2300a0; 86312fec14SDave Airlie } else 87312fec14SDave Airlie ext_reg_info = extreginfo; 88312fec14SDave Airlie 89312fec14SDave Airlie index = 0xa0; 90312fec14SDave Airlie while (*ext_reg_info != 0xff) { 91312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info); 92312fec14SDave Airlie index++; 93312fec14SDave Airlie ext_reg_info++; 94312fec14SDave Airlie } 95312fec14SDave Airlie 96312fec14SDave Airlie /* disable standard IO/MEM decode if secondary */ 97312fec14SDave Airlie /* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */ 98312fec14SDave Airlie 99312fec14SDave Airlie /* Set Ext. Default */ 100312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01); 101312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00); 102312fec14SDave Airlie 103312fec14SDave Airlie /* Enable RAMDAC for A1 */ 104312fec14SDave Airlie reg = 0x04; 1051453bf4cSDave Airlie if (ast->chip == AST2300 || ast->chip == AST2400) 106312fec14SDave Airlie reg |= 0x20; 107312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg); 108312fec14SDave Airlie } 109312fec14SDave Airlie 110312fec14SDave Airlie static inline u32 mindwm(struct ast_private *ast, u32 r) 111312fec14SDave Airlie { 112312fec14SDave Airlie ast_write32(ast, 0xf004, r & 0xffff0000); 113312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 114312fec14SDave Airlie 115312fec14SDave Airlie return ast_read32(ast, 0x10000 + (r & 0x0000ffff)); 116312fec14SDave Airlie } 117312fec14SDave Airlie 118312fec14SDave Airlie static inline void moutdwm(struct ast_private *ast, u32 r, u32 v) 119312fec14SDave Airlie { 120312fec14SDave Airlie ast_write32(ast, 0xf004, r & 0xffff0000); 121312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 122312fec14SDave Airlie ast_write32(ast, 0x10000 + (r & 0x0000ffff), v); 123312fec14SDave Airlie } 124312fec14SDave Airlie 125312fec14SDave Airlie /* 126312fec14SDave Airlie * AST2100/2150 DLL CBR Setting 127312fec14SDave Airlie */ 128312fec14SDave Airlie #define CBR_SIZE_AST2150 ((16 << 10) - 1) 129312fec14SDave Airlie #define CBR_PASSNUM_AST2150 5 130312fec14SDave Airlie #define CBR_THRESHOLD_AST2150 10 131312fec14SDave Airlie #define CBR_THRESHOLD2_AST2150 10 132312fec14SDave Airlie #define TIMEOUT_AST2150 5000000 133312fec14SDave Airlie 134312fec14SDave Airlie #define CBR_PATNUM_AST2150 8 135312fec14SDave Airlie 136312fec14SDave Airlie static const u32 pattern_AST2150[14] = { 137312fec14SDave Airlie 0xFF00FF00, 138312fec14SDave Airlie 0xCC33CC33, 139312fec14SDave Airlie 0xAA55AA55, 140312fec14SDave Airlie 0xFFFE0001, 141312fec14SDave Airlie 0x683501FE, 142312fec14SDave Airlie 0x0F1929B0, 143312fec14SDave Airlie 0x2D0B4346, 144312fec14SDave Airlie 0x60767F02, 145312fec14SDave Airlie 0x6FBE36A6, 146312fec14SDave Airlie 0x3A253035, 147312fec14SDave Airlie 0x3019686D, 148312fec14SDave Airlie 0x41C6167E, 149312fec14SDave Airlie 0x620152BF, 150312fec14SDave Airlie 0x20F050E0 151312fec14SDave Airlie }; 152312fec14SDave Airlie 153312fec14SDave Airlie static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen) 154312fec14SDave Airlie { 155312fec14SDave Airlie u32 data, timeout; 156312fec14SDave Airlie 157312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 158312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3)); 159312fec14SDave Airlie timeout = 0; 160312fec14SDave Airlie do { 161312fec14SDave Airlie data = mindwm(ast, 0x1e6e0070) & 0x40; 162312fec14SDave Airlie if (++timeout > TIMEOUT_AST2150) { 163312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 164312fec14SDave Airlie return 0xffffffff; 165312fec14SDave Airlie } 166312fec14SDave Airlie } while (!data); 167312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 168312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3)); 169312fec14SDave Airlie timeout = 0; 170312fec14SDave Airlie do { 171312fec14SDave Airlie data = mindwm(ast, 0x1e6e0070) & 0x40; 172312fec14SDave Airlie if (++timeout > TIMEOUT_AST2150) { 173312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 174312fec14SDave Airlie return 0xffffffff; 175312fec14SDave Airlie } 176312fec14SDave Airlie } while (!data); 177312fec14SDave Airlie data = (mindwm(ast, 0x1e6e0070) & 0x80) >> 7; 178312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 179312fec14SDave Airlie return data; 180312fec14SDave Airlie } 181312fec14SDave Airlie 182312fec14SDave Airlie #if 0 /* unused in DDX driver - here for completeness */ 183312fec14SDave Airlie static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen) 184312fec14SDave Airlie { 185312fec14SDave Airlie u32 data, timeout; 186312fec14SDave Airlie 187312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 188312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3)); 189312fec14SDave Airlie timeout = 0; 190312fec14SDave Airlie do { 191312fec14SDave Airlie data = mindwm(ast, 0x1e6e0070) & 0x40; 192312fec14SDave Airlie if (++timeout > TIMEOUT_AST2150) { 193312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 194312fec14SDave Airlie return 0xffffffff; 195312fec14SDave Airlie } 196312fec14SDave Airlie } while (!data); 197312fec14SDave Airlie data = (mindwm(ast, 0x1e6e0070) & 0x80) >> 7; 198312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 199312fec14SDave Airlie return data; 200312fec14SDave Airlie } 201312fec14SDave Airlie #endif 202312fec14SDave Airlie 203312fec14SDave Airlie static int cbrtest_ast2150(struct ast_private *ast) 204312fec14SDave Airlie { 205312fec14SDave Airlie int i; 206312fec14SDave Airlie 207312fec14SDave Airlie for (i = 0; i < 8; i++) 208312fec14SDave Airlie if (mmctestburst2_ast2150(ast, i)) 209312fec14SDave Airlie return 0; 210312fec14SDave Airlie return 1; 211312fec14SDave Airlie } 212312fec14SDave Airlie 213312fec14SDave Airlie static int cbrscan_ast2150(struct ast_private *ast, int busw) 214312fec14SDave Airlie { 215312fec14SDave Airlie u32 patcnt, loop; 216312fec14SDave Airlie 217312fec14SDave Airlie for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) { 218312fec14SDave Airlie moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]); 219312fec14SDave Airlie for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) { 220312fec14SDave Airlie if (cbrtest_ast2150(ast)) 221312fec14SDave Airlie break; 222312fec14SDave Airlie } 223312fec14SDave Airlie if (loop == CBR_PASSNUM_AST2150) 224312fec14SDave Airlie return 0; 225312fec14SDave Airlie } 226312fec14SDave Airlie return 1; 227312fec14SDave Airlie } 228312fec14SDave Airlie 229312fec14SDave Airlie 230312fec14SDave Airlie static void cbrdlli_ast2150(struct ast_private *ast, int busw) 231312fec14SDave Airlie { 232312fec14SDave Airlie u32 dll_min[4], dll_max[4], dlli, data, passcnt; 233312fec14SDave Airlie 234312fec14SDave Airlie cbr_start: 235312fec14SDave Airlie dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff; 236312fec14SDave Airlie dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0; 237312fec14SDave Airlie passcnt = 0; 238312fec14SDave Airlie 239312fec14SDave Airlie for (dlli = 0; dlli < 100; dlli++) { 240312fec14SDave Airlie moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 241312fec14SDave Airlie data = cbrscan_ast2150(ast, busw); 242312fec14SDave Airlie if (data != 0) { 243312fec14SDave Airlie if (data & 0x1) { 244312fec14SDave Airlie if (dll_min[0] > dlli) 245312fec14SDave Airlie dll_min[0] = dlli; 246312fec14SDave Airlie if (dll_max[0] < dlli) 247312fec14SDave Airlie dll_max[0] = dlli; 248312fec14SDave Airlie } 249312fec14SDave Airlie passcnt++; 250312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD_AST2150) 251312fec14SDave Airlie goto cbr_start; 252312fec14SDave Airlie } 253312fec14SDave Airlie if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150) 254312fec14SDave Airlie goto cbr_start; 255312fec14SDave Airlie 256312fec14SDave Airlie dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4); 257312fec14SDave Airlie moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 258312fec14SDave Airlie } 259312fec14SDave Airlie 260312fec14SDave Airlie 261312fec14SDave Airlie 262312fec14SDave Airlie static void ast_init_dram_reg(struct drm_device *dev) 263312fec14SDave Airlie { 264312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 265312fec14SDave Airlie u8 j; 266312fec14SDave Airlie u32 data, temp, i; 267312fec14SDave Airlie const struct ast_dramstruct *dram_reg_info; 268312fec14SDave Airlie 269312fec14SDave Airlie j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 270312fec14SDave Airlie 271312fec14SDave Airlie if ((j & 0x80) == 0) { /* VGA only */ 272312fec14SDave Airlie if (ast->chip == AST2000) { 273312fec14SDave Airlie dram_reg_info = ast2000_dram_table_data; 274312fec14SDave Airlie ast_write32(ast, 0xf004, 0x1e6e0000); 275312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 276312fec14SDave Airlie ast_write32(ast, 0x10100, 0xa8); 277312fec14SDave Airlie 278312fec14SDave Airlie do { 279312fec14SDave Airlie ; 280312fec14SDave Airlie } while (ast_read32(ast, 0x10100) != 0xa8); 281312fec14SDave Airlie } else {/* AST2100/1100 */ 282312fec14SDave Airlie if (ast->chip == AST2100 || ast->chip == 2200) 283312fec14SDave Airlie dram_reg_info = ast2100_dram_table_data; 284312fec14SDave Airlie else 285312fec14SDave Airlie dram_reg_info = ast1100_dram_table_data; 286312fec14SDave Airlie 287312fec14SDave Airlie ast_write32(ast, 0xf004, 0x1e6e0000); 288312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 289312fec14SDave Airlie ast_write32(ast, 0x12000, 0x1688A8A8); 290312fec14SDave Airlie do { 291312fec14SDave Airlie ; 292312fec14SDave Airlie } while (ast_read32(ast, 0x12000) != 0x01); 293312fec14SDave Airlie 294312fec14SDave Airlie ast_write32(ast, 0x10000, 0xfc600309); 295312fec14SDave Airlie do { 296312fec14SDave Airlie ; 297312fec14SDave Airlie } while (ast_read32(ast, 0x10000) != 0x01); 298312fec14SDave Airlie } 299312fec14SDave Airlie 300312fec14SDave Airlie while (dram_reg_info->index != 0xffff) { 301312fec14SDave Airlie if (dram_reg_info->index == 0xff00) {/* delay fn */ 302312fec14SDave Airlie for (i = 0; i < 15; i++) 303312fec14SDave Airlie udelay(dram_reg_info->data); 304312fec14SDave Airlie } else if (dram_reg_info->index == 0x4 && ast->chip != AST2000) { 305312fec14SDave Airlie data = dram_reg_info->data; 306312fec14SDave Airlie if (ast->dram_type == AST_DRAM_1Gx16) 307312fec14SDave Airlie data = 0x00000d89; 308312fec14SDave Airlie else if (ast->dram_type == AST_DRAM_1Gx32) 309312fec14SDave Airlie data = 0x00000c8d; 310312fec14SDave Airlie 311312fec14SDave Airlie temp = ast_read32(ast, 0x12070); 312312fec14SDave Airlie temp &= 0xc; 313312fec14SDave Airlie temp <<= 2; 314312fec14SDave Airlie ast_write32(ast, 0x10000 + dram_reg_info->index, data | temp); 315312fec14SDave Airlie } else 316312fec14SDave Airlie ast_write32(ast, 0x10000 + dram_reg_info->index, dram_reg_info->data); 317312fec14SDave Airlie dram_reg_info++; 318312fec14SDave Airlie } 319312fec14SDave Airlie 320312fec14SDave Airlie /* AST 2100/2150 DRAM calibration */ 321312fec14SDave Airlie data = ast_read32(ast, 0x10120); 322312fec14SDave Airlie if (data == 0x5061) { /* 266Mhz */ 323312fec14SDave Airlie data = ast_read32(ast, 0x10004); 324312fec14SDave Airlie if (data & 0x40) 325312fec14SDave Airlie cbrdlli_ast2150(ast, 16); /* 16 bits */ 326312fec14SDave Airlie else 327312fec14SDave Airlie cbrdlli_ast2150(ast, 32); /* 32 bits */ 328312fec14SDave Airlie } 329312fec14SDave Airlie 330312fec14SDave Airlie switch (ast->chip) { 331312fec14SDave Airlie case AST2000: 332312fec14SDave Airlie temp = ast_read32(ast, 0x10140); 333312fec14SDave Airlie ast_write32(ast, 0x10140, temp | 0x40); 334312fec14SDave Airlie break; 335312fec14SDave Airlie case AST1100: 336312fec14SDave Airlie case AST2100: 337312fec14SDave Airlie case AST2200: 338312fec14SDave Airlie case AST2150: 339312fec14SDave Airlie temp = ast_read32(ast, 0x1200c); 340312fec14SDave Airlie ast_write32(ast, 0x1200c, temp & 0xfffffffd); 341312fec14SDave Airlie temp = ast_read32(ast, 0x12040); 342312fec14SDave Airlie ast_write32(ast, 0x12040, temp | 0x40); 343312fec14SDave Airlie break; 344312fec14SDave Airlie default: 345312fec14SDave Airlie break; 346312fec14SDave Airlie } 347312fec14SDave Airlie } 348312fec14SDave Airlie 349312fec14SDave Airlie /* wait ready */ 350312fec14SDave Airlie do { 351312fec14SDave Airlie j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 352312fec14SDave Airlie } while ((j & 0x40) == 0); 353312fec14SDave Airlie } 354312fec14SDave Airlie 355312fec14SDave Airlie void ast_post_gpu(struct drm_device *dev) 356312fec14SDave Airlie { 357312fec14SDave Airlie u32 reg; 358312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 359312fec14SDave Airlie 360312fec14SDave Airlie pci_read_config_dword(ast->dev->pdev, 0x04, ®); 361312fec14SDave Airlie reg |= 0x3; 362312fec14SDave Airlie pci_write_config_dword(ast->dev->pdev, 0x04, reg); 363312fec14SDave Airlie 364312fec14SDave Airlie ast_enable_vga(dev); 365312fec14SDave Airlie ast_open_key(ast); 366312fec14SDave Airlie ast_set_def_ext_reg(dev); 367312fec14SDave Airlie 3681453bf4cSDave Airlie if (ast->chip == AST2300 || ast->chip == AST2400) 369312fec14SDave Airlie ast_init_dram_2300(dev); 370312fec14SDave Airlie else 371312fec14SDave Airlie ast_init_dram_reg(dev); 372312fec14SDave Airlie } 373312fec14SDave Airlie 374312fec14SDave Airlie /* AST 2300 DRAM settings */ 375312fec14SDave Airlie #define AST_DDR3 0 376312fec14SDave Airlie #define AST_DDR2 1 377312fec14SDave Airlie 378312fec14SDave Airlie struct ast2300_dram_param { 379312fec14SDave Airlie u32 dram_type; 380312fec14SDave Airlie u32 dram_chipid; 381312fec14SDave Airlie u32 dram_freq; 382312fec14SDave Airlie u32 vram_size; 383312fec14SDave Airlie u32 odt; 384312fec14SDave Airlie u32 wodt; 385312fec14SDave Airlie u32 rodt; 386312fec14SDave Airlie u32 dram_config; 387312fec14SDave Airlie u32 reg_PERIOD; 388312fec14SDave Airlie u32 reg_MADJ; 389312fec14SDave Airlie u32 reg_SADJ; 390312fec14SDave Airlie u32 reg_MRS; 391312fec14SDave Airlie u32 reg_EMRS; 392312fec14SDave Airlie u32 reg_AC1; 393312fec14SDave Airlie u32 reg_AC2; 394312fec14SDave Airlie u32 reg_DQSIC; 395312fec14SDave Airlie u32 reg_DRV; 396312fec14SDave Airlie u32 reg_IOZ; 397312fec14SDave Airlie u32 reg_DQIDLY; 398312fec14SDave Airlie u32 reg_FREQ; 399312fec14SDave Airlie u32 madj_max; 400312fec14SDave Airlie u32 dll2_finetune_step; 401312fec14SDave Airlie }; 402312fec14SDave Airlie 403312fec14SDave Airlie /* 404312fec14SDave Airlie * DQSI DLL CBR Setting 405312fec14SDave Airlie */ 406312fec14SDave Airlie #define CBR_SIZE1 ((4 << 10) - 1) 407312fec14SDave Airlie #define CBR_SIZE2 ((64 << 10) - 1) 408312fec14SDave Airlie #define CBR_PASSNUM 5 409312fec14SDave Airlie #define CBR_PASSNUM2 5 410312fec14SDave Airlie #define CBR_THRESHOLD 10 411312fec14SDave Airlie #define CBR_THRESHOLD2 10 412312fec14SDave Airlie #define TIMEOUT 5000000 413312fec14SDave Airlie #define CBR_PATNUM 8 414312fec14SDave Airlie 415312fec14SDave Airlie static const u32 pattern[8] = { 416312fec14SDave Airlie 0xFF00FF00, 417312fec14SDave Airlie 0xCC33CC33, 418312fec14SDave Airlie 0xAA55AA55, 419312fec14SDave Airlie 0x88778877, 420312fec14SDave Airlie 0x92CC4D6E, 421312fec14SDave Airlie 0x543D3CDE, 422312fec14SDave Airlie 0xF1E843C7, 423312fec14SDave Airlie 0x7C61D253 424312fec14SDave Airlie }; 425312fec14SDave Airlie 426312fec14SDave Airlie #if 0 /* unused in DDX, included for completeness */ 427312fec14SDave Airlie static int mmc_test_burst(struct ast_private *ast, u32 datagen) 428312fec14SDave Airlie { 429312fec14SDave Airlie u32 data, timeout; 430312fec14SDave Airlie 431312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 432312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x000000c1 | (datagen << 3)); 433312fec14SDave Airlie timeout = 0; 434312fec14SDave Airlie do { 435312fec14SDave Airlie data = mindwm(ast, 0x1e6e0070) & 0x3000; 436312fec14SDave Airlie if (data & 0x2000) { 437312fec14SDave Airlie return 0; 438312fec14SDave Airlie } 439312fec14SDave Airlie if (++timeout > TIMEOUT) { 440312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 441312fec14SDave Airlie return 0; 442312fec14SDave Airlie } 443312fec14SDave Airlie } while (!data); 444312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 445312fec14SDave Airlie return 1; 446312fec14SDave Airlie } 447312fec14SDave Airlie #endif 448312fec14SDave Airlie 449312fec14SDave Airlie static int mmc_test_burst2(struct ast_private *ast, u32 datagen) 450312fec14SDave Airlie { 451312fec14SDave Airlie u32 data, timeout; 452312fec14SDave Airlie 453312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 454312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000041 | (datagen << 3)); 455312fec14SDave Airlie timeout = 0; 456312fec14SDave Airlie do { 457312fec14SDave Airlie data = mindwm(ast, 0x1e6e0070) & 0x1000; 458312fec14SDave Airlie if (++timeout > TIMEOUT) { 459312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x0); 460312fec14SDave Airlie return -1; 461312fec14SDave Airlie } 462312fec14SDave Airlie } while (!data); 463312fec14SDave Airlie data = mindwm(ast, 0x1e6e0078); 464312fec14SDave Airlie data = (data | (data >> 16)) & 0xffff; 465312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x0); 466312fec14SDave Airlie return data; 467312fec14SDave Airlie } 468312fec14SDave Airlie 469312fec14SDave Airlie #if 0 /* Unused in DDX here for completeness */ 470312fec14SDave Airlie static int mmc_test_single(struct ast_private *ast, u32 datagen) 471312fec14SDave Airlie { 472312fec14SDave Airlie u32 data, timeout; 473312fec14SDave Airlie 474312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 475312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x000000c5 | (datagen << 3)); 476312fec14SDave Airlie timeout = 0; 477312fec14SDave Airlie do { 478312fec14SDave Airlie data = mindwm(ast, 0x1e6e0070) & 0x3000; 479312fec14SDave Airlie if (data & 0x2000) 480312fec14SDave Airlie return 0; 481312fec14SDave Airlie if (++timeout > TIMEOUT) { 482312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x0); 483312fec14SDave Airlie return 0; 484312fec14SDave Airlie } 485312fec14SDave Airlie } while (!data); 486312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x0); 487312fec14SDave Airlie return 1; 488312fec14SDave Airlie } 489312fec14SDave Airlie #endif 490312fec14SDave Airlie 491312fec14SDave Airlie static int mmc_test_single2(struct ast_private *ast, u32 datagen) 492312fec14SDave Airlie { 493312fec14SDave Airlie u32 data, timeout; 494312fec14SDave Airlie 495312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000000); 496312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3)); 497312fec14SDave Airlie timeout = 0; 498312fec14SDave Airlie do { 499312fec14SDave Airlie data = mindwm(ast, 0x1e6e0070) & 0x1000; 500312fec14SDave Airlie if (++timeout > TIMEOUT) { 501312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x0); 502312fec14SDave Airlie return -1; 503312fec14SDave Airlie } 504312fec14SDave Airlie } while (!data); 505312fec14SDave Airlie data = mindwm(ast, 0x1e6e0078); 506312fec14SDave Airlie data = (data | (data >> 16)) & 0xffff; 507312fec14SDave Airlie moutdwm(ast, 0x1e6e0070, 0x0); 508312fec14SDave Airlie return data; 509312fec14SDave Airlie } 510312fec14SDave Airlie 511312fec14SDave Airlie static int cbr_test(struct ast_private *ast) 512312fec14SDave Airlie { 513312fec14SDave Airlie u32 data; 514312fec14SDave Airlie int i; 515312fec14SDave Airlie data = mmc_test_single2(ast, 0); 516312fec14SDave Airlie if ((data & 0xff) && (data & 0xff00)) 517312fec14SDave Airlie return 0; 518312fec14SDave Airlie for (i = 0; i < 8; i++) { 519312fec14SDave Airlie data = mmc_test_burst2(ast, i); 520312fec14SDave Airlie if ((data & 0xff) && (data & 0xff00)) 521312fec14SDave Airlie return 0; 522312fec14SDave Airlie } 523312fec14SDave Airlie if (!data) 524312fec14SDave Airlie return 3; 525312fec14SDave Airlie else if (data & 0xff) 526312fec14SDave Airlie return 2; 527312fec14SDave Airlie return 1; 528312fec14SDave Airlie } 529312fec14SDave Airlie 530312fec14SDave Airlie static int cbr_scan(struct ast_private *ast) 531312fec14SDave Airlie { 532312fec14SDave Airlie u32 data, data2, patcnt, loop; 533312fec14SDave Airlie 534312fec14SDave Airlie data2 = 3; 535312fec14SDave Airlie for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 536312fec14SDave Airlie moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 537312fec14SDave Airlie for (loop = 0; loop < CBR_PASSNUM2; loop++) { 538312fec14SDave Airlie if ((data = cbr_test(ast)) != 0) { 539312fec14SDave Airlie data2 &= data; 540312fec14SDave Airlie if (!data2) 541312fec14SDave Airlie return 0; 542312fec14SDave Airlie break; 543312fec14SDave Airlie } 544312fec14SDave Airlie } 545312fec14SDave Airlie if (loop == CBR_PASSNUM2) 546312fec14SDave Airlie return 0; 547312fec14SDave Airlie } 548312fec14SDave Airlie return data2; 549312fec14SDave Airlie } 550312fec14SDave Airlie 551312fec14SDave Airlie static u32 cbr_test2(struct ast_private *ast) 552312fec14SDave Airlie { 553312fec14SDave Airlie u32 data; 554312fec14SDave Airlie 555312fec14SDave Airlie data = mmc_test_burst2(ast, 0); 556312fec14SDave Airlie if (data == 0xffff) 557312fec14SDave Airlie return 0; 558312fec14SDave Airlie data |= mmc_test_single2(ast, 0); 559312fec14SDave Airlie if (data == 0xffff) 560312fec14SDave Airlie return 0; 561312fec14SDave Airlie 562312fec14SDave Airlie return ~data & 0xffff; 563312fec14SDave Airlie } 564312fec14SDave Airlie 565312fec14SDave Airlie static u32 cbr_scan2(struct ast_private *ast) 566312fec14SDave Airlie { 567312fec14SDave Airlie u32 data, data2, patcnt, loop; 568312fec14SDave Airlie 569312fec14SDave Airlie data2 = 0xffff; 570312fec14SDave Airlie for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 571312fec14SDave Airlie moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 572312fec14SDave Airlie for (loop = 0; loop < CBR_PASSNUM2; loop++) { 573312fec14SDave Airlie if ((data = cbr_test2(ast)) != 0) { 574312fec14SDave Airlie data2 &= data; 575312fec14SDave Airlie if (!data) 576312fec14SDave Airlie return 0; 577312fec14SDave Airlie break; 578312fec14SDave Airlie } 579312fec14SDave Airlie } 580312fec14SDave Airlie if (loop == CBR_PASSNUM2) 581312fec14SDave Airlie return 0; 582312fec14SDave Airlie } 583312fec14SDave Airlie return data2; 584312fec14SDave Airlie } 585312fec14SDave Airlie 586312fec14SDave Airlie #if 0 /* unused in DDX - added for completeness */ 587312fec14SDave Airlie static void finetuneDQI(struct ast_private *ast, struct ast2300_dram_param *param) 588312fec14SDave Airlie { 589312fec14SDave Airlie u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt; 590312fec14SDave Airlie 591312fec14SDave Airlie gold_sadj[0] = (mindwm(ast, 0x1E6E0024) >> 16) & 0xffff; 592312fec14SDave Airlie gold_sadj[1] = gold_sadj[0] >> 8; 593312fec14SDave Airlie gold_sadj[0] = gold_sadj[0] & 0xff; 594312fec14SDave Airlie gold_sadj[0] = (gold_sadj[0] + gold_sadj[1]) >> 1; 595312fec14SDave Airlie gold_sadj[1] = gold_sadj[0]; 596312fec14SDave Airlie 597312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 598312fec14SDave Airlie dllmin[cnt] = 0xff; 599312fec14SDave Airlie dllmax[cnt] = 0x0; 600312fec14SDave Airlie } 601312fec14SDave Airlie passcnt = 0; 602312fec14SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 603312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 604312fec14SDave Airlie /* Wait DQSI latch phase calibration */ 605312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, 0x00000010); 606312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000003); 607312fec14SDave Airlie do { 608312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 609312fec14SDave Airlie } while (!(data & 0x00001000)); 610312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 611312fec14SDave Airlie 612312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, CBR_SIZE1); 613312fec14SDave Airlie data = cbr_scan2(ast); 614312fec14SDave Airlie if (data != 0) { 615312fec14SDave Airlie mask = 0x00010001; 616312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 617312fec14SDave Airlie if (data & mask) { 618312fec14SDave Airlie if (dllmin[cnt] > dlli) { 619312fec14SDave Airlie dllmin[cnt] = dlli; 620312fec14SDave Airlie } 621312fec14SDave Airlie if (dllmax[cnt] < dlli) { 622312fec14SDave Airlie dllmax[cnt] = dlli; 623312fec14SDave Airlie } 624312fec14SDave Airlie } 625312fec14SDave Airlie mask <<= 1; 626312fec14SDave Airlie } 627312fec14SDave Airlie passcnt++; 628312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD) { 629312fec14SDave Airlie break; 630312fec14SDave Airlie } 631312fec14SDave Airlie } 632312fec14SDave Airlie data = 0; 633312fec14SDave Airlie for (cnt = 0; cnt < 8; cnt++) { 634312fec14SDave Airlie data >>= 3; 635312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD)) { 636312fec14SDave Airlie dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 637312fec14SDave Airlie if (gold_sadj[0] >= dlli) { 638312fec14SDave Airlie dlli = (gold_sadj[0] - dlli) >> 1; 639312fec14SDave Airlie if (dlli > 3) { 640312fec14SDave Airlie dlli = 3; 641312fec14SDave Airlie } 642312fec14SDave Airlie } else { 643312fec14SDave Airlie dlli = (dlli - gold_sadj[0]) >> 1; 644312fec14SDave Airlie if (dlli > 4) { 645312fec14SDave Airlie dlli = 4; 646312fec14SDave Airlie } 647312fec14SDave Airlie dlli = (8 - dlli) & 0x7; 648312fec14SDave Airlie } 649312fec14SDave Airlie data |= dlli << 21; 650312fec14SDave Airlie } 651312fec14SDave Airlie } 652312fec14SDave Airlie moutdwm(ast, 0x1E6E0080, data); 653312fec14SDave Airlie 654312fec14SDave Airlie data = 0; 655312fec14SDave Airlie for (cnt = 8; cnt < 16; cnt++) { 656312fec14SDave Airlie data >>= 3; 657312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD)) { 658312fec14SDave Airlie dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 659312fec14SDave Airlie if (gold_sadj[1] >= dlli) { 660312fec14SDave Airlie dlli = (gold_sadj[1] - dlli) >> 1; 661312fec14SDave Airlie if (dlli > 3) { 662312fec14SDave Airlie dlli = 3; 663312fec14SDave Airlie } else { 664312fec14SDave Airlie dlli = (dlli - 1) & 0x7; 665312fec14SDave Airlie } 666312fec14SDave Airlie } else { 667312fec14SDave Airlie dlli = (dlli - gold_sadj[1]) >> 1; 668312fec14SDave Airlie dlli += 1; 669312fec14SDave Airlie if (dlli > 4) { 670312fec14SDave Airlie dlli = 4; 671312fec14SDave Airlie } 672312fec14SDave Airlie dlli = (8 - dlli) & 0x7; 673312fec14SDave Airlie } 674312fec14SDave Airlie data |= dlli << 21; 675312fec14SDave Airlie } 676312fec14SDave Airlie } 677312fec14SDave Airlie moutdwm(ast, 0x1E6E0084, data); 678312fec14SDave Airlie 679312fec14SDave Airlie } /* finetuneDQI */ 680312fec14SDave Airlie #endif 681312fec14SDave Airlie 682312fec14SDave Airlie static void finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param) 683312fec14SDave Airlie { 684312fec14SDave Airlie u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt; 685312fec14SDave Airlie 686312fec14SDave Airlie FINETUNE_START: 687312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 688312fec14SDave Airlie dllmin[cnt] = 0xff; 689312fec14SDave Airlie dllmax[cnt] = 0x0; 690312fec14SDave Airlie } 691312fec14SDave Airlie passcnt = 0; 692312fec14SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 693312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 694312fec14SDave Airlie /* Wait DQSI latch phase calibration */ 695312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, 0x00000010); 696312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000003); 697312fec14SDave Airlie do { 698312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 699312fec14SDave Airlie } while (!(data & 0x00001000)); 700312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 701312fec14SDave Airlie 702312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, CBR_SIZE1); 703312fec14SDave Airlie data = cbr_scan2(ast); 704312fec14SDave Airlie if (data != 0) { 705312fec14SDave Airlie mask = 0x00010001; 706312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 707312fec14SDave Airlie if (data & mask) { 708312fec14SDave Airlie if (dllmin[cnt] > dlli) { 709312fec14SDave Airlie dllmin[cnt] = dlli; 710312fec14SDave Airlie } 711312fec14SDave Airlie if (dllmax[cnt] < dlli) { 712312fec14SDave Airlie dllmax[cnt] = dlli; 713312fec14SDave Airlie } 714312fec14SDave Airlie } 715312fec14SDave Airlie mask <<= 1; 716312fec14SDave Airlie } 717312fec14SDave Airlie passcnt++; 718312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD2) { 719312fec14SDave Airlie break; 720312fec14SDave Airlie } 721312fec14SDave Airlie } 722312fec14SDave Airlie gold_sadj[0] = 0x0; 723312fec14SDave Airlie passcnt = 0; 724312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 725312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 726312fec14SDave Airlie gold_sadj[0] += dllmin[cnt]; 727312fec14SDave Airlie passcnt++; 728312fec14SDave Airlie } 729312fec14SDave Airlie } 730312fec14SDave Airlie if (passcnt != 16) { 731312fec14SDave Airlie goto FINETUNE_START; 732312fec14SDave Airlie } 733312fec14SDave Airlie gold_sadj[0] = gold_sadj[0] >> 4; 734312fec14SDave Airlie gold_sadj[1] = gold_sadj[0]; 735312fec14SDave Airlie 736312fec14SDave Airlie data = 0; 737312fec14SDave Airlie for (cnt = 0; cnt < 8; cnt++) { 738312fec14SDave Airlie data >>= 3; 739312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 740312fec14SDave Airlie dlli = dllmin[cnt]; 741312fec14SDave Airlie if (gold_sadj[0] >= dlli) { 742312fec14SDave Airlie dlli = ((gold_sadj[0] - dlli) * 19) >> 5; 743312fec14SDave Airlie if (dlli > 3) { 744312fec14SDave Airlie dlli = 3; 745312fec14SDave Airlie } 746312fec14SDave Airlie } else { 747312fec14SDave Airlie dlli = ((dlli - gold_sadj[0]) * 19) >> 5; 748312fec14SDave Airlie if (dlli > 4) { 749312fec14SDave Airlie dlli = 4; 750312fec14SDave Airlie } 751312fec14SDave Airlie dlli = (8 - dlli) & 0x7; 752312fec14SDave Airlie } 753312fec14SDave Airlie data |= dlli << 21; 754312fec14SDave Airlie } 755312fec14SDave Airlie } 756312fec14SDave Airlie moutdwm(ast, 0x1E6E0080, data); 757312fec14SDave Airlie 758312fec14SDave Airlie data = 0; 759312fec14SDave Airlie for (cnt = 8; cnt < 16; cnt++) { 760312fec14SDave Airlie data >>= 3; 761312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 762312fec14SDave Airlie dlli = dllmin[cnt]; 763312fec14SDave Airlie if (gold_sadj[1] >= dlli) { 764312fec14SDave Airlie dlli = ((gold_sadj[1] - dlli) * 19) >> 5; 765312fec14SDave Airlie if (dlli > 3) { 766312fec14SDave Airlie dlli = 3; 767312fec14SDave Airlie } else { 768312fec14SDave Airlie dlli = (dlli - 1) & 0x7; 769312fec14SDave Airlie } 770312fec14SDave Airlie } else { 771312fec14SDave Airlie dlli = ((dlli - gold_sadj[1]) * 19) >> 5; 772312fec14SDave Airlie dlli += 1; 773312fec14SDave Airlie if (dlli > 4) { 774312fec14SDave Airlie dlli = 4; 775312fec14SDave Airlie } 776312fec14SDave Airlie dlli = (8 - dlli) & 0x7; 777312fec14SDave Airlie } 778312fec14SDave Airlie data |= dlli << 21; 779312fec14SDave Airlie } 780312fec14SDave Airlie } 781312fec14SDave Airlie moutdwm(ast, 0x1E6E0084, data); 782312fec14SDave Airlie 783312fec14SDave Airlie } /* finetuneDQI_L */ 784312fec14SDave Airlie 785312fec14SDave Airlie static void finetuneDQI_L2(struct ast_private *ast, struct ast2300_dram_param *param) 786312fec14SDave Airlie { 787312fec14SDave Airlie u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, data2; 788312fec14SDave Airlie 789312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 790312fec14SDave Airlie dllmin[cnt] = 0xff; 791312fec14SDave Airlie dllmax[cnt] = 0x0; 792312fec14SDave Airlie } 793312fec14SDave Airlie passcnt = 0; 794312fec14SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 795312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 796312fec14SDave Airlie /* Wait DQSI latch phase calibration */ 797312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, 0x00000010); 798312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000003); 799312fec14SDave Airlie do { 800312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 801312fec14SDave Airlie } while (!(data & 0x00001000)); 802312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 803312fec14SDave Airlie 804312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, CBR_SIZE2); 805312fec14SDave Airlie data = cbr_scan2(ast); 806312fec14SDave Airlie if (data != 0) { 807312fec14SDave Airlie mask = 0x00010001; 808312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 809312fec14SDave Airlie if (data & mask) { 810312fec14SDave Airlie if (dllmin[cnt] > dlli) { 811312fec14SDave Airlie dllmin[cnt] = dlli; 812312fec14SDave Airlie } 813312fec14SDave Airlie if (dllmax[cnt] < dlli) { 814312fec14SDave Airlie dllmax[cnt] = dlli; 815312fec14SDave Airlie } 816312fec14SDave Airlie } 817312fec14SDave Airlie mask <<= 1; 818312fec14SDave Airlie } 819312fec14SDave Airlie passcnt++; 820312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD2) { 821312fec14SDave Airlie break; 822312fec14SDave Airlie } 823312fec14SDave Airlie } 824312fec14SDave Airlie gold_sadj[0] = 0x0; 825312fec14SDave Airlie gold_sadj[1] = 0xFF; 826312fec14SDave Airlie for (cnt = 0; cnt < 8; cnt++) { 827312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 828312fec14SDave Airlie if (gold_sadj[0] < dllmin[cnt]) { 829312fec14SDave Airlie gold_sadj[0] = dllmin[cnt]; 830312fec14SDave Airlie } 831312fec14SDave Airlie if (gold_sadj[1] > dllmax[cnt]) { 832312fec14SDave Airlie gold_sadj[1] = dllmax[cnt]; 833312fec14SDave Airlie } 834312fec14SDave Airlie } 835312fec14SDave Airlie } 836312fec14SDave Airlie gold_sadj[0] = (gold_sadj[1] + gold_sadj[0]) >> 1; 837312fec14SDave Airlie gold_sadj[1] = mindwm(ast, 0x1E6E0080); 838312fec14SDave Airlie 839312fec14SDave Airlie data = 0; 840312fec14SDave Airlie for (cnt = 0; cnt < 8; cnt++) { 841312fec14SDave Airlie data >>= 3; 842312fec14SDave Airlie data2 = gold_sadj[1] & 0x7; 843312fec14SDave Airlie gold_sadj[1] >>= 3; 844312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 845312fec14SDave Airlie dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 846312fec14SDave Airlie if (gold_sadj[0] >= dlli) { 847312fec14SDave Airlie dlli = (gold_sadj[0] - dlli) >> 1; 848312fec14SDave Airlie if (dlli > 0) { 849312fec14SDave Airlie dlli = 1; 850312fec14SDave Airlie } 851312fec14SDave Airlie if (data2 != 3) { 852312fec14SDave Airlie data2 = (data2 + dlli) & 0x7; 853312fec14SDave Airlie } 854312fec14SDave Airlie } else { 855312fec14SDave Airlie dlli = (dlli - gold_sadj[0]) >> 1; 856312fec14SDave Airlie if (dlli > 0) { 857312fec14SDave Airlie dlli = 1; 858312fec14SDave Airlie } 859312fec14SDave Airlie if (data2 != 4) { 860312fec14SDave Airlie data2 = (data2 - dlli) & 0x7; 861312fec14SDave Airlie } 862312fec14SDave Airlie } 863312fec14SDave Airlie } 864312fec14SDave Airlie data |= data2 << 21; 865312fec14SDave Airlie } 866312fec14SDave Airlie moutdwm(ast, 0x1E6E0080, data); 867312fec14SDave Airlie 868312fec14SDave Airlie gold_sadj[0] = 0x0; 869312fec14SDave Airlie gold_sadj[1] = 0xFF; 870312fec14SDave Airlie for (cnt = 8; cnt < 16; cnt++) { 871312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 872312fec14SDave Airlie if (gold_sadj[0] < dllmin[cnt]) { 873312fec14SDave Airlie gold_sadj[0] = dllmin[cnt]; 874312fec14SDave Airlie } 875312fec14SDave Airlie if (gold_sadj[1] > dllmax[cnt]) { 876312fec14SDave Airlie gold_sadj[1] = dllmax[cnt]; 877312fec14SDave Airlie } 878312fec14SDave Airlie } 879312fec14SDave Airlie } 880312fec14SDave Airlie gold_sadj[0] = (gold_sadj[1] + gold_sadj[0]) >> 1; 881312fec14SDave Airlie gold_sadj[1] = mindwm(ast, 0x1E6E0084); 882312fec14SDave Airlie 883312fec14SDave Airlie data = 0; 884312fec14SDave Airlie for (cnt = 8; cnt < 16; cnt++) { 885312fec14SDave Airlie data >>= 3; 886312fec14SDave Airlie data2 = gold_sadj[1] & 0x7; 887312fec14SDave Airlie gold_sadj[1] >>= 3; 888312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 889312fec14SDave Airlie dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 890312fec14SDave Airlie if (gold_sadj[0] >= dlli) { 891312fec14SDave Airlie dlli = (gold_sadj[0] - dlli) >> 1; 892312fec14SDave Airlie if (dlli > 0) { 893312fec14SDave Airlie dlli = 1; 894312fec14SDave Airlie } 895312fec14SDave Airlie if (data2 != 3) { 896312fec14SDave Airlie data2 = (data2 + dlli) & 0x7; 897312fec14SDave Airlie } 898312fec14SDave Airlie } else { 899312fec14SDave Airlie dlli = (dlli - gold_sadj[0]) >> 1; 900312fec14SDave Airlie if (dlli > 0) { 901312fec14SDave Airlie dlli = 1; 902312fec14SDave Airlie } 903312fec14SDave Airlie if (data2 != 4) { 904312fec14SDave Airlie data2 = (data2 - dlli) & 0x7; 905312fec14SDave Airlie } 906312fec14SDave Airlie } 907312fec14SDave Airlie } 908312fec14SDave Airlie data |= data2 << 21; 909312fec14SDave Airlie } 910312fec14SDave Airlie moutdwm(ast, 0x1E6E0084, data); 911312fec14SDave Airlie 912312fec14SDave Airlie } /* finetuneDQI_L2 */ 913312fec14SDave Airlie 914312fec14SDave Airlie static void cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param) 915312fec14SDave Airlie { 916312fec14SDave Airlie u32 dllmin[2], dllmax[2], dlli, data, data2, passcnt; 917312fec14SDave Airlie 918312fec14SDave Airlie 919312fec14SDave Airlie finetuneDQI_L(ast, param); 920312fec14SDave Airlie finetuneDQI_L2(ast, param); 921312fec14SDave Airlie 922312fec14SDave Airlie CBR_START2: 923312fec14SDave Airlie dllmin[0] = dllmin[1] = 0xff; 924312fec14SDave Airlie dllmax[0] = dllmax[1] = 0x0; 925312fec14SDave Airlie passcnt = 0; 926312fec14SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 927312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24)); 928312fec14SDave Airlie /* Wait DQSI latch phase calibration */ 929312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, 0x00000010); 930312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000003); 931312fec14SDave Airlie do { 932312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 933312fec14SDave Airlie } while (!(data & 0x00001000)); 934312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 935312fec14SDave Airlie 936312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, CBR_SIZE2); 937312fec14SDave Airlie data = cbr_scan(ast); 938312fec14SDave Airlie if (data != 0) { 939312fec14SDave Airlie if (data & 0x1) { 940312fec14SDave Airlie if (dllmin[0] > dlli) { 941312fec14SDave Airlie dllmin[0] = dlli; 942312fec14SDave Airlie } 943312fec14SDave Airlie if (dllmax[0] < dlli) { 944312fec14SDave Airlie dllmax[0] = dlli; 945312fec14SDave Airlie } 946312fec14SDave Airlie } 947312fec14SDave Airlie if (data & 0x2) { 948312fec14SDave Airlie if (dllmin[1] > dlli) { 949312fec14SDave Airlie dllmin[1] = dlli; 950312fec14SDave Airlie } 951312fec14SDave Airlie if (dllmax[1] < dlli) { 952312fec14SDave Airlie dllmax[1] = dlli; 953312fec14SDave Airlie } 954312fec14SDave Airlie } 955312fec14SDave Airlie passcnt++; 956312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD) { 957312fec14SDave Airlie break; 958312fec14SDave Airlie } 959312fec14SDave Airlie } 960312fec14SDave Airlie if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) { 961312fec14SDave Airlie goto CBR_START2; 962312fec14SDave Airlie } 963312fec14SDave Airlie if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) { 964312fec14SDave Airlie goto CBR_START2; 965312fec14SDave Airlie } 966312fec14SDave Airlie dlli = (dllmin[1] + dllmax[1]) >> 1; 967312fec14SDave Airlie dlli <<= 8; 968312fec14SDave Airlie dlli += (dllmin[0] + dllmax[0]) >> 1; 969312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, (mindwm(ast, 0x1E6E0068) & 0xFFFF) | (dlli << 16)); 970312fec14SDave Airlie 971312fec14SDave Airlie data = (mindwm(ast, 0x1E6E0080) >> 24) & 0x1F; 972312fec14SDave Airlie data2 = (mindwm(ast, 0x1E6E0018) & 0xff80ffff) | (data << 16); 973312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, data2); 974312fec14SDave Airlie moutdwm(ast, 0x1E6E0024, 0x8001 | (data << 1) | (param->dll2_finetune_step << 8)); 975312fec14SDave Airlie 976312fec14SDave Airlie /* Wait DQSI latch phase calibration */ 977312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, 0x00000010); 978312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000003); 979312fec14SDave Airlie do { 980312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 981312fec14SDave Airlie } while (!(data & 0x00001000)); 982312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 983312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000003); 984312fec14SDave Airlie do { 985312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 986312fec14SDave Airlie } while (!(data & 0x00001000)); 987312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 988312fec14SDave Airlie } /* CBRDLL2 */ 989312fec14SDave Airlie 990312fec14SDave Airlie static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param) 991312fec14SDave Airlie { 992312fec14SDave Airlie u32 trap, trap_AC2, trap_MRS; 993312fec14SDave Airlie 994312fec14SDave Airlie moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 995312fec14SDave Airlie 996312fec14SDave Airlie /* Ger trap info */ 997312fec14SDave Airlie trap = (mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 998312fec14SDave Airlie trap_AC2 = 0x00020000 + (trap << 16); 999312fec14SDave Airlie trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19); 1000312fec14SDave Airlie trap_MRS = 0x00000010 + (trap << 4); 1001312fec14SDave Airlie trap_MRS |= ((trap & 0x2) << 18); 1002312fec14SDave Airlie 1003312fec14SDave Airlie param->reg_MADJ = 0x00034C4C; 1004312fec14SDave Airlie param->reg_SADJ = 0x00001800; 1005312fec14SDave Airlie param->reg_DRV = 0x000000F0; 1006312fec14SDave Airlie param->reg_PERIOD = param->dram_freq; 1007312fec14SDave Airlie param->rodt = 0; 1008312fec14SDave Airlie 1009312fec14SDave Airlie switch (param->dram_freq) { 1010312fec14SDave Airlie case 336: 1011312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0190); 1012312fec14SDave Airlie param->wodt = 0; 1013312fec14SDave Airlie param->reg_AC1 = 0x22202725; 1014312fec14SDave Airlie param->reg_AC2 = 0xAA007613 | trap_AC2; 1015312fec14SDave Airlie param->reg_DQSIC = 0x000000BA; 1016312fec14SDave Airlie param->reg_MRS = 0x04001400 | trap_MRS; 1017312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1018312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1019312fec14SDave Airlie param->reg_DQIDLY = 0x00000074; 1020312fec14SDave Airlie param->reg_FREQ = 0x00004DC0; 1021312fec14SDave Airlie param->madj_max = 96; 1022312fec14SDave Airlie param->dll2_finetune_step = 3; 1023312fec14SDave Airlie break; 1024312fec14SDave Airlie default: 1025312fec14SDave Airlie case 396: 1026312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x03F1); 1027312fec14SDave Airlie param->wodt = 1; 1028312fec14SDave Airlie param->reg_AC1 = 0x33302825; 1029312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 1030312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 1031312fec14SDave Airlie param->reg_MRS = 0x04001600 | trap_MRS; 1032312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1033312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1034312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1035312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 1036312fec14SDave Airlie param->reg_FREQ = 0x000050C0; 1037312fec14SDave Airlie param->madj_max = 96; 1038312fec14SDave Airlie param->dll2_finetune_step = 4; 1039312fec14SDave Airlie 1040312fec14SDave Airlie switch (param->dram_chipid) { 1041312fec14SDave Airlie default: 1042312fec14SDave Airlie case AST_DRAM_512Mx16: 1043312fec14SDave Airlie case AST_DRAM_1Gx16: 1044312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 1045312fec14SDave Airlie break; 1046312fec14SDave Airlie case AST_DRAM_2Gx16: 1047312fec14SDave Airlie param->reg_AC2 = 0xCC009622 | trap_AC2; 1048312fec14SDave Airlie break; 1049312fec14SDave Airlie case AST_DRAM_4Gx16: 1050312fec14SDave Airlie param->reg_AC2 = 0xCC00963F | trap_AC2; 1051312fec14SDave Airlie break; 1052312fec14SDave Airlie } 1053312fec14SDave Airlie break; 1054312fec14SDave Airlie 1055312fec14SDave Airlie case 408: 1056312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x01F0); 1057312fec14SDave Airlie param->wodt = 1; 1058312fec14SDave Airlie param->reg_AC1 = 0x33302825; 1059312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 1060312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 1061312fec14SDave Airlie param->reg_MRS = 0x04001600 | trap_MRS; 1062312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1063312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1064312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1065312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 1066312fec14SDave Airlie param->reg_FREQ = 0x000050C0; 1067312fec14SDave Airlie param->madj_max = 96; 1068312fec14SDave Airlie param->dll2_finetune_step = 4; 1069312fec14SDave Airlie 1070312fec14SDave Airlie switch (param->dram_chipid) { 1071312fec14SDave Airlie default: 1072312fec14SDave Airlie case AST_DRAM_512Mx16: 1073312fec14SDave Airlie case AST_DRAM_1Gx16: 1074312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 1075312fec14SDave Airlie break; 1076312fec14SDave Airlie case AST_DRAM_2Gx16: 1077312fec14SDave Airlie param->reg_AC2 = 0xCC009622 | trap_AC2; 1078312fec14SDave Airlie break; 1079312fec14SDave Airlie case AST_DRAM_4Gx16: 1080312fec14SDave Airlie param->reg_AC2 = 0xCC00963F | trap_AC2; 1081312fec14SDave Airlie break; 1082312fec14SDave Airlie } 1083312fec14SDave Airlie 1084312fec14SDave Airlie break; 1085312fec14SDave Airlie case 456: 1086312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0230); 1087312fec14SDave Airlie param->wodt = 0; 1088312fec14SDave Airlie param->reg_AC1 = 0x33302926; 1089312fec14SDave Airlie param->reg_AC2 = 0xCD44961A; 1090312fec14SDave Airlie param->reg_DQSIC = 0x000000FC; 1091312fec14SDave Airlie param->reg_MRS = 0x00081830; 1092312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1093312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1094312fec14SDave Airlie param->reg_DQIDLY = 0x00000097; 1095312fec14SDave Airlie param->reg_FREQ = 0x000052C0; 1096312fec14SDave Airlie param->madj_max = 88; 1097312fec14SDave Airlie param->dll2_finetune_step = 4; 1098312fec14SDave Airlie break; 1099312fec14SDave Airlie case 504: 1100312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0270); 1101312fec14SDave Airlie param->wodt = 1; 1102312fec14SDave Airlie param->reg_AC1 = 0x33302926; 1103312fec14SDave Airlie param->reg_AC2 = 0xDE44A61D; 1104312fec14SDave Airlie param->reg_DQSIC = 0x00000117; 1105312fec14SDave Airlie param->reg_MRS = 0x00081A30; 1106312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1107312fec14SDave Airlie param->reg_IOZ = 0x070000BB; 1108312fec14SDave Airlie param->reg_DQIDLY = 0x000000A0; 1109312fec14SDave Airlie param->reg_FREQ = 0x000054C0; 1110312fec14SDave Airlie param->madj_max = 79; 1111312fec14SDave Airlie param->dll2_finetune_step = 4; 1112312fec14SDave Airlie break; 1113312fec14SDave Airlie case 528: 1114312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0290); 1115312fec14SDave Airlie param->wodt = 1; 1116312fec14SDave Airlie param->rodt = 1; 1117312fec14SDave Airlie param->reg_AC1 = 0x33302926; 1118312fec14SDave Airlie param->reg_AC2 = 0xEF44B61E; 1119312fec14SDave Airlie param->reg_DQSIC = 0x00000125; 1120312fec14SDave Airlie param->reg_MRS = 0x00081A30; 1121312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1122312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1123312fec14SDave Airlie param->reg_IOZ = 0x00000023; 1124312fec14SDave Airlie param->reg_DQIDLY = 0x00000088; 1125312fec14SDave Airlie param->reg_FREQ = 0x000055C0; 1126312fec14SDave Airlie param->madj_max = 76; 1127312fec14SDave Airlie param->dll2_finetune_step = 3; 1128312fec14SDave Airlie break; 1129312fec14SDave Airlie case 576: 1130312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0140); 1131312fec14SDave Airlie param->reg_MADJ = 0x00136868; 1132312fec14SDave Airlie param->reg_SADJ = 0x00004534; 1133312fec14SDave Airlie param->wodt = 1; 1134312fec14SDave Airlie param->rodt = 1; 1135312fec14SDave Airlie param->reg_AC1 = 0x33302A37; 1136312fec14SDave Airlie param->reg_AC2 = 0xEF56B61E; 1137312fec14SDave Airlie param->reg_DQSIC = 0x0000013F; 1138312fec14SDave Airlie param->reg_MRS = 0x00101A50; 1139312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1140312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1141312fec14SDave Airlie param->reg_IOZ = 0x00000023; 1142312fec14SDave Airlie param->reg_DQIDLY = 0x00000078; 1143312fec14SDave Airlie param->reg_FREQ = 0x000057C0; 1144312fec14SDave Airlie param->madj_max = 136; 1145312fec14SDave Airlie param->dll2_finetune_step = 3; 1146312fec14SDave Airlie break; 1147312fec14SDave Airlie case 600: 1148312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x02E1); 1149312fec14SDave Airlie param->reg_MADJ = 0x00136868; 1150312fec14SDave Airlie param->reg_SADJ = 0x00004534; 1151312fec14SDave Airlie param->wodt = 1; 1152312fec14SDave Airlie param->rodt = 1; 1153312fec14SDave Airlie param->reg_AC1 = 0x32302A37; 1154312fec14SDave Airlie param->reg_AC2 = 0xDF56B61F; 1155312fec14SDave Airlie param->reg_DQSIC = 0x0000014D; 1156312fec14SDave Airlie param->reg_MRS = 0x00101A50; 1157312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1158312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1159312fec14SDave Airlie param->reg_IOZ = 0x00000023; 1160312fec14SDave Airlie param->reg_DQIDLY = 0x00000078; 1161312fec14SDave Airlie param->reg_FREQ = 0x000058C0; 1162312fec14SDave Airlie param->madj_max = 132; 1163312fec14SDave Airlie param->dll2_finetune_step = 3; 1164312fec14SDave Airlie break; 1165312fec14SDave Airlie case 624: 1166312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0160); 1167312fec14SDave Airlie param->reg_MADJ = 0x00136868; 1168312fec14SDave Airlie param->reg_SADJ = 0x00004534; 1169312fec14SDave Airlie param->wodt = 1; 1170312fec14SDave Airlie param->rodt = 1; 1171312fec14SDave Airlie param->reg_AC1 = 0x32302A37; 1172312fec14SDave Airlie param->reg_AC2 = 0xEF56B621; 1173312fec14SDave Airlie param->reg_DQSIC = 0x0000015A; 1174312fec14SDave Airlie param->reg_MRS = 0x02101A50; 1175312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1176312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1177312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1178312fec14SDave Airlie param->reg_DQIDLY = 0x00000078; 1179312fec14SDave Airlie param->reg_FREQ = 0x000059C0; 1180312fec14SDave Airlie param->madj_max = 128; 1181312fec14SDave Airlie param->dll2_finetune_step = 3; 1182312fec14SDave Airlie break; 1183312fec14SDave Airlie } /* switch freq */ 1184312fec14SDave Airlie 1185312fec14SDave Airlie switch (param->dram_chipid) { 1186312fec14SDave Airlie case AST_DRAM_512Mx16: 1187312fec14SDave Airlie param->dram_config = 0x130; 1188312fec14SDave Airlie break; 1189312fec14SDave Airlie default: 1190312fec14SDave Airlie case AST_DRAM_1Gx16: 1191312fec14SDave Airlie param->dram_config = 0x131; 1192312fec14SDave Airlie break; 1193312fec14SDave Airlie case AST_DRAM_2Gx16: 1194312fec14SDave Airlie param->dram_config = 0x132; 1195312fec14SDave Airlie break; 1196312fec14SDave Airlie case AST_DRAM_4Gx16: 1197312fec14SDave Airlie param->dram_config = 0x133; 1198312fec14SDave Airlie break; 1199312fec14SDave Airlie }; /* switch size */ 1200312fec14SDave Airlie 1201312fec14SDave Airlie switch (param->vram_size) { 1202312fec14SDave Airlie default: 1203312fec14SDave Airlie case AST_VIDMEM_SIZE_8M: 1204312fec14SDave Airlie param->dram_config |= 0x00; 1205312fec14SDave Airlie break; 1206312fec14SDave Airlie case AST_VIDMEM_SIZE_16M: 1207312fec14SDave Airlie param->dram_config |= 0x04; 1208312fec14SDave Airlie break; 1209312fec14SDave Airlie case AST_VIDMEM_SIZE_32M: 1210312fec14SDave Airlie param->dram_config |= 0x08; 1211312fec14SDave Airlie break; 1212312fec14SDave Airlie case AST_VIDMEM_SIZE_64M: 1213312fec14SDave Airlie param->dram_config |= 0x0c; 1214312fec14SDave Airlie break; 1215312fec14SDave Airlie } 1216312fec14SDave Airlie 1217312fec14SDave Airlie } 1218312fec14SDave Airlie 1219312fec14SDave Airlie static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param) 1220312fec14SDave Airlie { 1221312fec14SDave Airlie u32 data, data2; 1222312fec14SDave Airlie 1223312fec14SDave Airlie moutdwm(ast, 0x1E6E0000, 0xFC600309); 1224312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, 0x00000100); 1225312fec14SDave Airlie moutdwm(ast, 0x1E6E0024, 0x00000000); 1226312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000000); 1227312fec14SDave Airlie udelay(10); 1228312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 1229312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 1230312fec14SDave Airlie udelay(10); 1231312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 1232312fec14SDave Airlie udelay(10); 1233312fec14SDave Airlie 1234312fec14SDave Airlie moutdwm(ast, 0x1E6E0004, param->dram_config); 1235312fec14SDave Airlie moutdwm(ast, 0x1E6E0008, 0x90040f); 1236312fec14SDave Airlie moutdwm(ast, 0x1E6E0010, param->reg_AC1); 1237312fec14SDave Airlie moutdwm(ast, 0x1E6E0014, param->reg_AC2); 1238312fec14SDave Airlie moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 1239312fec14SDave Airlie moutdwm(ast, 0x1E6E0080, 0x00000000); 1240312fec14SDave Airlie moutdwm(ast, 0x1E6E0084, 0x00000000); 1241312fec14SDave Airlie moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 1242312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, 0x4040A170); 1243312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, 0x20402370); 1244312fec14SDave Airlie moutdwm(ast, 0x1E6E0038, 0x00000000); 1245312fec14SDave Airlie moutdwm(ast, 0x1E6E0040, 0xFF444444); 1246312fec14SDave Airlie moutdwm(ast, 0x1E6E0044, 0x22222222); 1247312fec14SDave Airlie moutdwm(ast, 0x1E6E0048, 0x22222222); 1248312fec14SDave Airlie moutdwm(ast, 0x1E6E004C, 0x00000002); 1249312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x80000000); 1250312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x00000000); 1251312fec14SDave Airlie moutdwm(ast, 0x1E6E0054, 0); 1252312fec14SDave Airlie moutdwm(ast, 0x1E6E0060, param->reg_DRV); 1253312fec14SDave Airlie moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 1254312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 1255312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, 0x00000000); 1256312fec14SDave Airlie moutdwm(ast, 0x1E6E0078, 0x00000000); 1257312fec14SDave Airlie moutdwm(ast, 0x1E6E007C, 0x00000000); 1258312fec14SDave Airlie /* Wait MCLK2X lock to MCLK */ 1259312fec14SDave Airlie do { 1260312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1261312fec14SDave Airlie } while (!(data & 0x08000000)); 1262312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000001); 1263312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00005C04); 1264312fec14SDave Airlie udelay(10); 1265312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00000000); 1266312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000000); 1267312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1268312fec14SDave Airlie data = (data >> 8) & 0xff; 1269312fec14SDave Airlie while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 1270312fec14SDave Airlie data2 = (mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 1271312fec14SDave Airlie if ((data2 & 0xff) > param->madj_max) { 1272312fec14SDave Airlie break; 1273312fec14SDave Airlie } 1274312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, data2); 1275312fec14SDave Airlie if (data2 & 0x00100000) { 1276312fec14SDave Airlie data2 = ((data2 & 0xff) >> 3) + 3; 1277312fec14SDave Airlie } else { 1278312fec14SDave Airlie data2 = ((data2 & 0xff) >> 2) + 5; 1279312fec14SDave Airlie } 1280312fec14SDave Airlie data = mindwm(ast, 0x1E6E0068) & 0xffff00ff; 1281312fec14SDave Airlie data2 += data & 0xff; 1282312fec14SDave Airlie data = data | (data2 << 8); 1283312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, data); 1284312fec14SDave Airlie udelay(10); 1285312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, mindwm(ast, 0x1E6E0064) | 0xC0000); 1286312fec14SDave Airlie udelay(10); 1287312fec14SDave Airlie data = mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 1288312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, data); 1289312fec14SDave Airlie data = data | 0x200; 1290312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, data); 1291312fec14SDave Airlie do { 1292312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1293312fec14SDave Airlie } while (!(data & 0x08000000)); 1294312fec14SDave Airlie 1295312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000001); 1296312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00005C04); 1297312fec14SDave Airlie udelay(10); 1298312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00000000); 1299312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000000); 1300312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1301312fec14SDave Airlie data = (data >> 8) & 0xff; 1302312fec14SDave Airlie } 1303312fec14SDave Airlie data = mindwm(ast, 0x1E6E0018) | 0xC00; 1304312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, data); 1305312fec14SDave Airlie 1306312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000001); 1307312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00000040); 1308312fec14SDave Airlie udelay(50); 1309312fec14SDave Airlie /* Mode Register Setting */ 1310312fec14SDave Airlie moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 1311312fec14SDave Airlie moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1312312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000005); 1313312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000007); 1314312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000003); 1315312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000001); 1316312fec14SDave Airlie moutdwm(ast, 0x1E6E002C, param->reg_MRS); 1317312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00005C08); 1318312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000001); 1319312fec14SDave Airlie 1320312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x7FFF5C01); 1321312fec14SDave Airlie data = 0; 1322312fec14SDave Airlie if (param->wodt) { 1323312fec14SDave Airlie data = 0x300; 1324312fec14SDave Airlie } 1325312fec14SDave Airlie if (param->rodt) { 1326312fec14SDave Airlie data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 1327312fec14SDave Airlie } 1328312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, data | 0x3); 1329312fec14SDave Airlie 1330312fec14SDave Airlie /* Wait DQI delay lock */ 1331312fec14SDave Airlie do { 1332312fec14SDave Airlie data = mindwm(ast, 0x1E6E0080); 1333312fec14SDave Airlie } while (!(data & 0x40000000)); 1334312fec14SDave Airlie /* Wait DQSI delay lock */ 1335312fec14SDave Airlie do { 1336312fec14SDave Airlie data = mindwm(ast, 0x1E6E0020); 1337312fec14SDave Airlie } while (!(data & 0x00000800)); 1338312fec14SDave Airlie /* Calibrate the DQSI delay */ 1339312fec14SDave Airlie cbr_dll2(ast, param); 1340312fec14SDave Airlie 1341312fec14SDave Airlie moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 1342312fec14SDave Airlie /* ECC Memory Initialization */ 1343312fec14SDave Airlie #ifdef ECC 1344312fec14SDave Airlie moutdwm(ast, 0x1E6E007C, 0x00000000); 1345312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x221); 1346312fec14SDave Airlie do { 1347312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 1348312fec14SDave Airlie } while (!(data & 0x00001000)); 1349312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 1350312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x80000000); 1351312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x00000000); 1352312fec14SDave Airlie #endif 1353312fec14SDave Airlie 1354312fec14SDave Airlie 1355312fec14SDave Airlie } 1356312fec14SDave Airlie 1357312fec14SDave Airlie static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param) 1358312fec14SDave Airlie { 1359312fec14SDave Airlie u32 trap, trap_AC2, trap_MRS; 1360312fec14SDave Airlie 1361312fec14SDave Airlie moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 1362312fec14SDave Airlie 1363312fec14SDave Airlie /* Ger trap info */ 1364312fec14SDave Airlie trap = (mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 1365312fec14SDave Airlie trap_AC2 = (trap << 20) | (trap << 16); 1366312fec14SDave Airlie trap_AC2 += 0x00110000; 1367312fec14SDave Airlie trap_MRS = 0x00000040 | (trap << 4); 1368312fec14SDave Airlie 1369312fec14SDave Airlie 1370312fec14SDave Airlie param->reg_MADJ = 0x00034C4C; 1371312fec14SDave Airlie param->reg_SADJ = 0x00001800; 1372312fec14SDave Airlie param->reg_DRV = 0x000000F0; 1373312fec14SDave Airlie param->reg_PERIOD = param->dram_freq; 1374312fec14SDave Airlie param->rodt = 0; 1375312fec14SDave Airlie 1376312fec14SDave Airlie switch (param->dram_freq) { 1377312fec14SDave Airlie case 264: 1378312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0130); 1379312fec14SDave Airlie param->wodt = 0; 1380312fec14SDave Airlie param->reg_AC1 = 0x11101513; 1381312fec14SDave Airlie param->reg_AC2 = 0x78117011; 1382312fec14SDave Airlie param->reg_DQSIC = 0x00000092; 1383312fec14SDave Airlie param->reg_MRS = 0x00000842; 1384312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1385312fec14SDave Airlie param->reg_DRV = 0x000000F0; 1386312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1387312fec14SDave Airlie param->reg_DQIDLY = 0x0000005A; 1388312fec14SDave Airlie param->reg_FREQ = 0x00004AC0; 1389312fec14SDave Airlie param->madj_max = 138; 1390312fec14SDave Airlie param->dll2_finetune_step = 3; 1391312fec14SDave Airlie break; 1392312fec14SDave Airlie case 336: 1393312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0190); 1394312fec14SDave Airlie param->wodt = 1; 1395312fec14SDave Airlie param->reg_AC1 = 0x22202613; 1396312fec14SDave Airlie param->reg_AC2 = 0xAA009016 | trap_AC2; 1397312fec14SDave Airlie param->reg_DQSIC = 0x000000BA; 1398312fec14SDave Airlie param->reg_MRS = 0x00000A02 | trap_MRS; 1399312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1400312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1401312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1402312fec14SDave Airlie param->reg_DQIDLY = 0x00000074; 1403312fec14SDave Airlie param->reg_FREQ = 0x00004DC0; 1404312fec14SDave Airlie param->madj_max = 96; 1405312fec14SDave Airlie param->dll2_finetune_step = 3; 1406312fec14SDave Airlie break; 1407312fec14SDave Airlie default: 1408312fec14SDave Airlie case 396: 1409312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x03F1); 1410312fec14SDave Airlie param->wodt = 1; 1411312fec14SDave Airlie param->rodt = 0; 1412312fec14SDave Airlie param->reg_AC1 = 0x33302714; 1413312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1414312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 1415312fec14SDave Airlie param->reg_MRS = 0x00000C02 | trap_MRS; 1416312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1417312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1418312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1419312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 1420312fec14SDave Airlie param->reg_FREQ = 0x000050C0; 1421312fec14SDave Airlie param->madj_max = 96; 1422312fec14SDave Airlie param->dll2_finetune_step = 4; 1423312fec14SDave Airlie 1424312fec14SDave Airlie switch (param->dram_chipid) { 1425312fec14SDave Airlie case AST_DRAM_512Mx16: 1426312fec14SDave Airlie param->reg_AC2 = 0xCC00B016 | trap_AC2; 1427312fec14SDave Airlie break; 1428312fec14SDave Airlie default: 1429312fec14SDave Airlie case AST_DRAM_1Gx16: 1430312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1431312fec14SDave Airlie break; 1432312fec14SDave Airlie case AST_DRAM_2Gx16: 1433312fec14SDave Airlie param->reg_AC2 = 0xCC00B02B | trap_AC2; 1434312fec14SDave Airlie break; 1435312fec14SDave Airlie case AST_DRAM_4Gx16: 1436312fec14SDave Airlie param->reg_AC2 = 0xCC00B03F | trap_AC2; 1437312fec14SDave Airlie break; 1438312fec14SDave Airlie } 1439312fec14SDave Airlie 1440312fec14SDave Airlie break; 1441312fec14SDave Airlie 1442312fec14SDave Airlie case 408: 1443312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x01F0); 1444312fec14SDave Airlie param->wodt = 1; 1445312fec14SDave Airlie param->rodt = 0; 1446312fec14SDave Airlie param->reg_AC1 = 0x33302714; 1447312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1448312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 1449312fec14SDave Airlie param->reg_MRS = 0x00000C02 | trap_MRS; 1450312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1451312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1452312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1453312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 1454312fec14SDave Airlie param->reg_FREQ = 0x000050C0; 1455312fec14SDave Airlie param->madj_max = 96; 1456312fec14SDave Airlie param->dll2_finetune_step = 4; 1457312fec14SDave Airlie 1458312fec14SDave Airlie switch (param->dram_chipid) { 1459312fec14SDave Airlie case AST_DRAM_512Mx16: 1460312fec14SDave Airlie param->reg_AC2 = 0xCC00B016 | trap_AC2; 1461312fec14SDave Airlie break; 1462312fec14SDave Airlie default: 1463312fec14SDave Airlie case AST_DRAM_1Gx16: 1464312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1465312fec14SDave Airlie break; 1466312fec14SDave Airlie case AST_DRAM_2Gx16: 1467312fec14SDave Airlie param->reg_AC2 = 0xCC00B02B | trap_AC2; 1468312fec14SDave Airlie break; 1469312fec14SDave Airlie case AST_DRAM_4Gx16: 1470312fec14SDave Airlie param->reg_AC2 = 0xCC00B03F | trap_AC2; 1471312fec14SDave Airlie break; 1472312fec14SDave Airlie } 1473312fec14SDave Airlie 1474312fec14SDave Airlie break; 1475312fec14SDave Airlie case 456: 1476312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0230); 1477312fec14SDave Airlie param->wodt = 0; 1478312fec14SDave Airlie param->reg_AC1 = 0x33302815; 1479312fec14SDave Airlie param->reg_AC2 = 0xCD44B01E; 1480312fec14SDave Airlie param->reg_DQSIC = 0x000000FC; 1481312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1482312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1483312fec14SDave Airlie param->reg_DRV = 0x00000000; 1484312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1485312fec14SDave Airlie param->reg_DQIDLY = 0x00000097; 1486312fec14SDave Airlie param->reg_FREQ = 0x000052C0; 1487312fec14SDave Airlie param->madj_max = 88; 1488312fec14SDave Airlie param->dll2_finetune_step = 3; 1489312fec14SDave Airlie break; 1490312fec14SDave Airlie case 504: 1491312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0261); 1492312fec14SDave Airlie param->wodt = 1; 1493312fec14SDave Airlie param->rodt = 1; 1494312fec14SDave Airlie param->reg_AC1 = 0x33302815; 1495312fec14SDave Airlie param->reg_AC2 = 0xDE44C022; 1496312fec14SDave Airlie param->reg_DQSIC = 0x00000117; 1497312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1498312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1499312fec14SDave Airlie param->reg_DRV = 0x0000000A; 1500312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1501312fec14SDave Airlie param->reg_DQIDLY = 0x000000A0; 1502312fec14SDave Airlie param->reg_FREQ = 0x000054C0; 1503312fec14SDave Airlie param->madj_max = 79; 1504312fec14SDave Airlie param->dll2_finetune_step = 3; 1505312fec14SDave Airlie break; 1506312fec14SDave Airlie case 528: 1507312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0120); 1508312fec14SDave Airlie param->wodt = 1; 1509312fec14SDave Airlie param->rodt = 1; 1510312fec14SDave Airlie param->reg_AC1 = 0x33302815; 1511312fec14SDave Airlie param->reg_AC2 = 0xEF44D024; 1512312fec14SDave Airlie param->reg_DQSIC = 0x00000125; 1513312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1514312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1515312fec14SDave Airlie param->reg_DRV = 0x000000F9; 1516312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1517312fec14SDave Airlie param->reg_DQIDLY = 0x000000A7; 1518312fec14SDave Airlie param->reg_FREQ = 0x000055C0; 1519312fec14SDave Airlie param->madj_max = 76; 1520312fec14SDave Airlie param->dll2_finetune_step = 3; 1521312fec14SDave Airlie break; 1522312fec14SDave Airlie case 552: 1523312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x02A1); 1524312fec14SDave Airlie param->wodt = 1; 1525312fec14SDave Airlie param->rodt = 1; 1526312fec14SDave Airlie param->reg_AC1 = 0x43402915; 1527312fec14SDave Airlie param->reg_AC2 = 0xFF44E025; 1528312fec14SDave Airlie param->reg_DQSIC = 0x00000132; 1529312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1530312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1531312fec14SDave Airlie param->reg_DRV = 0x0000000A; 1532312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1533312fec14SDave Airlie param->reg_DQIDLY = 0x000000AD; 1534312fec14SDave Airlie param->reg_FREQ = 0x000056C0; 1535312fec14SDave Airlie param->madj_max = 76; 1536312fec14SDave Airlie param->dll2_finetune_step = 3; 1537312fec14SDave Airlie break; 1538312fec14SDave Airlie case 576: 1539312fec14SDave Airlie moutdwm(ast, 0x1E6E2020, 0x0140); 1540312fec14SDave Airlie param->wodt = 1; 1541312fec14SDave Airlie param->rodt = 1; 1542312fec14SDave Airlie param->reg_AC1 = 0x43402915; 1543312fec14SDave Airlie param->reg_AC2 = 0xFF44E027; 1544312fec14SDave Airlie param->reg_DQSIC = 0x0000013F; 1545312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1546312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1547312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1548312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1549312fec14SDave Airlie param->reg_DQIDLY = 0x000000B3; 1550312fec14SDave Airlie param->reg_FREQ = 0x000057C0; 1551312fec14SDave Airlie param->madj_max = 76; 1552312fec14SDave Airlie param->dll2_finetune_step = 3; 1553312fec14SDave Airlie break; 1554312fec14SDave Airlie } 1555312fec14SDave Airlie 1556312fec14SDave Airlie switch (param->dram_chipid) { 1557312fec14SDave Airlie case AST_DRAM_512Mx16: 1558312fec14SDave Airlie param->dram_config = 0x100; 1559312fec14SDave Airlie break; 1560312fec14SDave Airlie default: 1561312fec14SDave Airlie case AST_DRAM_1Gx16: 1562312fec14SDave Airlie param->dram_config = 0x121; 1563312fec14SDave Airlie break; 1564312fec14SDave Airlie case AST_DRAM_2Gx16: 1565312fec14SDave Airlie param->dram_config = 0x122; 1566312fec14SDave Airlie break; 1567312fec14SDave Airlie case AST_DRAM_4Gx16: 1568312fec14SDave Airlie param->dram_config = 0x123; 1569312fec14SDave Airlie break; 1570312fec14SDave Airlie }; /* switch size */ 1571312fec14SDave Airlie 1572312fec14SDave Airlie switch (param->vram_size) { 1573312fec14SDave Airlie default: 1574312fec14SDave Airlie case AST_VIDMEM_SIZE_8M: 1575312fec14SDave Airlie param->dram_config |= 0x00; 1576312fec14SDave Airlie break; 1577312fec14SDave Airlie case AST_VIDMEM_SIZE_16M: 1578312fec14SDave Airlie param->dram_config |= 0x04; 1579312fec14SDave Airlie break; 1580312fec14SDave Airlie case AST_VIDMEM_SIZE_32M: 1581312fec14SDave Airlie param->dram_config |= 0x08; 1582312fec14SDave Airlie break; 1583312fec14SDave Airlie case AST_VIDMEM_SIZE_64M: 1584312fec14SDave Airlie param->dram_config |= 0x0c; 1585312fec14SDave Airlie break; 1586312fec14SDave Airlie } 1587312fec14SDave Airlie } 1588312fec14SDave Airlie 1589312fec14SDave Airlie static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param) 1590312fec14SDave Airlie { 1591312fec14SDave Airlie u32 data, data2; 1592312fec14SDave Airlie 1593312fec14SDave Airlie moutdwm(ast, 0x1E6E0000, 0xFC600309); 1594312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, 0x00000100); 1595312fec14SDave Airlie moutdwm(ast, 0x1E6E0024, 0x00000000); 1596312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 1597312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 1598312fec14SDave Airlie udelay(10); 1599312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 1600312fec14SDave Airlie udelay(10); 1601312fec14SDave Airlie 1602312fec14SDave Airlie moutdwm(ast, 0x1E6E0004, param->dram_config); 1603312fec14SDave Airlie moutdwm(ast, 0x1E6E0008, 0x90040f); 1604312fec14SDave Airlie moutdwm(ast, 0x1E6E0010, param->reg_AC1); 1605312fec14SDave Airlie moutdwm(ast, 0x1E6E0014, param->reg_AC2); 1606312fec14SDave Airlie moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 1607312fec14SDave Airlie moutdwm(ast, 0x1E6E0080, 0x00000000); 1608312fec14SDave Airlie moutdwm(ast, 0x1E6E0084, 0x00000000); 1609312fec14SDave Airlie moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 1610312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, 0x4040A130); 1611312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, 0x20402330); 1612312fec14SDave Airlie moutdwm(ast, 0x1E6E0038, 0x00000000); 1613312fec14SDave Airlie moutdwm(ast, 0x1E6E0040, 0xFF808000); 1614312fec14SDave Airlie moutdwm(ast, 0x1E6E0044, 0x88848466); 1615312fec14SDave Airlie moutdwm(ast, 0x1E6E0048, 0x44440008); 1616312fec14SDave Airlie moutdwm(ast, 0x1E6E004C, 0x00000000); 1617312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x80000000); 1618312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x00000000); 1619312fec14SDave Airlie moutdwm(ast, 0x1E6E0054, 0); 1620312fec14SDave Airlie moutdwm(ast, 0x1E6E0060, param->reg_DRV); 1621312fec14SDave Airlie moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 1622312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 1623312fec14SDave Airlie moutdwm(ast, 0x1E6E0074, 0x00000000); 1624312fec14SDave Airlie moutdwm(ast, 0x1E6E0078, 0x00000000); 1625312fec14SDave Airlie moutdwm(ast, 0x1E6E007C, 0x00000000); 1626312fec14SDave Airlie 1627312fec14SDave Airlie /* Wait MCLK2X lock to MCLK */ 1628312fec14SDave Airlie do { 1629312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1630312fec14SDave Airlie } while (!(data & 0x08000000)); 1631312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000001); 1632312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00005C04); 1633312fec14SDave Airlie udelay(10); 1634312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00000000); 1635312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000000); 1636312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1637312fec14SDave Airlie data = (data >> 8) & 0xff; 1638312fec14SDave Airlie while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 1639312fec14SDave Airlie data2 = (mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 1640312fec14SDave Airlie if ((data2 & 0xff) > param->madj_max) { 1641312fec14SDave Airlie break; 1642312fec14SDave Airlie } 1643312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, data2); 1644312fec14SDave Airlie if (data2 & 0x00100000) { 1645312fec14SDave Airlie data2 = ((data2 & 0xff) >> 3) + 3; 1646312fec14SDave Airlie } else { 1647312fec14SDave Airlie data2 = ((data2 & 0xff) >> 2) + 5; 1648312fec14SDave Airlie } 1649312fec14SDave Airlie data = mindwm(ast, 0x1E6E0068) & 0xffff00ff; 1650312fec14SDave Airlie data2 += data & 0xff; 1651312fec14SDave Airlie data = data | (data2 << 8); 1652312fec14SDave Airlie moutdwm(ast, 0x1E6E0068, data); 1653312fec14SDave Airlie udelay(10); 1654312fec14SDave Airlie moutdwm(ast, 0x1E6E0064, mindwm(ast, 0x1E6E0064) | 0xC0000); 1655312fec14SDave Airlie udelay(10); 1656312fec14SDave Airlie data = mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 1657312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, data); 1658312fec14SDave Airlie data = data | 0x200; 1659312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, data); 1660312fec14SDave Airlie do { 1661312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1662312fec14SDave Airlie } while (!(data & 0x08000000)); 1663312fec14SDave Airlie 1664312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000001); 1665312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00005C04); 1666312fec14SDave Airlie udelay(10); 1667312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00000000); 1668312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000000); 1669312fec14SDave Airlie data = mindwm(ast, 0x1E6E001C); 1670312fec14SDave Airlie data = (data >> 8) & 0xff; 1671312fec14SDave Airlie } 1672312fec14SDave Airlie data = mindwm(ast, 0x1E6E0018) | 0xC00; 1673312fec14SDave Airlie moutdwm(ast, 0x1E6E0018, data); 1674312fec14SDave Airlie 1675312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, 0x00000001); 1676312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00000000); 1677312fec14SDave Airlie udelay(50); 1678312fec14SDave Airlie /* Mode Register Setting */ 1679312fec14SDave Airlie moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 1680312fec14SDave Airlie moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1681312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000005); 1682312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000007); 1683312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000003); 1684312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000001); 1685312fec14SDave Airlie 1686312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x00005C08); 1687312fec14SDave Airlie moutdwm(ast, 0x1E6E002C, param->reg_MRS); 1688312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000001); 1689312fec14SDave Airlie moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380); 1690312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000003); 1691312fec14SDave Airlie moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1692312fec14SDave Airlie moutdwm(ast, 0x1E6E0028, 0x00000003); 1693312fec14SDave Airlie 1694312fec14SDave Airlie moutdwm(ast, 0x1E6E000C, 0x7FFF5C01); 1695312fec14SDave Airlie data = 0; 1696312fec14SDave Airlie if (param->wodt) { 1697312fec14SDave Airlie data = 0x500; 1698312fec14SDave Airlie } 1699312fec14SDave Airlie if (param->rodt) { 1700312fec14SDave Airlie data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 1701312fec14SDave Airlie } 1702312fec14SDave Airlie moutdwm(ast, 0x1E6E0034, data | 0x3); 1703312fec14SDave Airlie moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 1704312fec14SDave Airlie 1705312fec14SDave Airlie /* Wait DQI delay lock */ 1706312fec14SDave Airlie do { 1707312fec14SDave Airlie data = mindwm(ast, 0x1E6E0080); 1708312fec14SDave Airlie } while (!(data & 0x40000000)); 1709312fec14SDave Airlie /* Wait DQSI delay lock */ 1710312fec14SDave Airlie do { 1711312fec14SDave Airlie data = mindwm(ast, 0x1E6E0020); 1712312fec14SDave Airlie } while (!(data & 0x00000800)); 1713312fec14SDave Airlie /* Calibrate the DQSI delay */ 1714312fec14SDave Airlie cbr_dll2(ast, param); 1715312fec14SDave Airlie 1716312fec14SDave Airlie /* ECC Memory Initialization */ 1717312fec14SDave Airlie #ifdef ECC 1718312fec14SDave Airlie moutdwm(ast, 0x1E6E007C, 0x00000000); 1719312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x221); 1720312fec14SDave Airlie do { 1721312fec14SDave Airlie data = mindwm(ast, 0x1E6E0070); 1722312fec14SDave Airlie } while (!(data & 0x00001000)); 1723312fec14SDave Airlie moutdwm(ast, 0x1E6E0070, 0x00000000); 1724312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x80000000); 1725312fec14SDave Airlie moutdwm(ast, 0x1E6E0050, 0x00000000); 1726312fec14SDave Airlie #endif 1727312fec14SDave Airlie 1728312fec14SDave Airlie } 1729312fec14SDave Airlie 1730312fec14SDave Airlie static void ast_init_dram_2300(struct drm_device *dev) 1731312fec14SDave Airlie { 1732312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 1733312fec14SDave Airlie struct ast2300_dram_param param; 1734312fec14SDave Airlie u32 temp; 1735312fec14SDave Airlie u8 reg; 1736312fec14SDave Airlie 1737312fec14SDave Airlie reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 1738312fec14SDave Airlie if ((reg & 0x80) == 0) {/* vga only */ 1739312fec14SDave Airlie ast_write32(ast, 0xf004, 0x1e6e0000); 1740312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 1741312fec14SDave Airlie ast_write32(ast, 0x12000, 0x1688a8a8); 1742312fec14SDave Airlie do { 1743312fec14SDave Airlie ; 1744312fec14SDave Airlie } while (ast_read32(ast, 0x12000) != 0x1); 1745312fec14SDave Airlie 1746312fec14SDave Airlie ast_write32(ast, 0x10000, 0xfc600309); 1747312fec14SDave Airlie do { 1748312fec14SDave Airlie ; 1749312fec14SDave Airlie } while (ast_read32(ast, 0x10000) != 0x1); 1750312fec14SDave Airlie 1751312fec14SDave Airlie /* Slow down CPU/AHB CLK in VGA only mode */ 1752312fec14SDave Airlie temp = ast_read32(ast, 0x12008); 1753312fec14SDave Airlie temp |= 0x73; 1754312fec14SDave Airlie ast_write32(ast, 0x12008, temp); 1755312fec14SDave Airlie 1756312fec14SDave Airlie param.dram_type = AST_DDR3; 1757312fec14SDave Airlie if (temp & 0x01000000) 1758312fec14SDave Airlie param.dram_type = AST_DDR2; 1759312fec14SDave Airlie param.dram_chipid = ast->dram_type; 1760312fec14SDave Airlie param.dram_freq = ast->mclk; 1761312fec14SDave Airlie param.vram_size = ast->vram_size; 1762312fec14SDave Airlie 1763312fec14SDave Airlie if (param.dram_type == AST_DDR3) { 1764312fec14SDave Airlie get_ddr3_info(ast, ¶m); 1765312fec14SDave Airlie ddr3_init(ast, ¶m); 1766312fec14SDave Airlie } else { 1767312fec14SDave Airlie get_ddr2_info(ast, ¶m); 1768312fec14SDave Airlie ddr2_init(ast, ¶m); 1769312fec14SDave Airlie } 1770312fec14SDave Airlie 1771312fec14SDave Airlie temp = mindwm(ast, 0x1e6e2040); 1772312fec14SDave Airlie moutdwm(ast, 0x1e6e2040, temp | 0x40); 1773312fec14SDave Airlie } 1774312fec14SDave Airlie 1775312fec14SDave Airlie /* wait ready */ 1776312fec14SDave Airlie do { 1777312fec14SDave Airlie reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 1778312fec14SDave Airlie } while ((reg & 0x40) == 0); 1779312fec14SDave Airlie } 1780312fec14SDave Airlie 1781