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 34d95618efSBenjamin Herrenschmidt static void ast_post_chip_2300(struct drm_device *dev); 35312fec14SDave Airlie 36d1b98557SBenjamin Herrenschmidt void ast_enable_vga(struct drm_device *dev) 37312fec14SDave Airlie { 38312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 39312fec14SDave Airlie 40d1b98557SBenjamin Herrenschmidt ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01); 41d1b98557SBenjamin Herrenschmidt ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01); 42312fec14SDave Airlie } 43312fec14SDave Airlie 44d1b98557SBenjamin Herrenschmidt void ast_enable_mmio(struct drm_device *dev) 45d1b98557SBenjamin Herrenschmidt { 46d1b98557SBenjamin Herrenschmidt struct ast_private *ast = dev->dev_private; 47d1b98557SBenjamin Herrenschmidt 48d1b98557SBenjamin Herrenschmidt ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04); 49d1b98557SBenjamin Herrenschmidt } 50d1b98557SBenjamin Herrenschmidt 51d1b98557SBenjamin Herrenschmidt 52d1b98557SBenjamin Herrenschmidt bool ast_is_vga_enabled(struct drm_device *dev) 53312fec14SDave Airlie { 54312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 55312fec14SDave Airlie u8 ch; 56312fec14SDave Airlie 57312fec14SDave Airlie if (ast->chip == AST1180) { 58312fec14SDave Airlie /* TODO 1180 */ 59312fec14SDave Airlie } else { 60d1b98557SBenjamin Herrenschmidt ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT); 61312fec14SDave Airlie if (ch) { 62312fec14SDave Airlie ast_open_key(ast); 63312fec14SDave Airlie ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff); 64312fec14SDave Airlie return ch & 0x04; 65312fec14SDave Airlie } 66312fec14SDave Airlie } 67312fec14SDave Airlie return 0; 68312fec14SDave Airlie } 69312fec14SDave Airlie 70312fec14SDave Airlie static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff }; 71312fec14SDave Airlie static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff }; 72312fec14SDave Airlie static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff }; 73312fec14SDave Airlie 74312fec14SDave Airlie static void 75312fec14SDave Airlie ast_set_def_ext_reg(struct drm_device *dev) 76312fec14SDave Airlie { 77312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 78312fec14SDave Airlie u8 i, index, reg; 79312fec14SDave Airlie const u8 *ext_reg_info; 80312fec14SDave Airlie 81312fec14SDave Airlie /* reset scratch */ 82bad09da6SY.C. Chen for (i = 0x81; i <= 0x9f; i++) 83312fec14SDave Airlie ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00); 84312fec14SDave Airlie 851453bf4cSDave Airlie if (ast->chip == AST2300 || ast->chip == AST2400) { 86312fec14SDave Airlie if (dev->pdev->revision >= 0x20) 87312fec14SDave Airlie ext_reg_info = extreginfo_ast2300; 88312fec14SDave Airlie else 89312fec14SDave Airlie ext_reg_info = extreginfo_ast2300a0; 90312fec14SDave Airlie } else 91312fec14SDave Airlie ext_reg_info = extreginfo; 92312fec14SDave Airlie 93312fec14SDave Airlie index = 0xa0; 94312fec14SDave Airlie while (*ext_reg_info != 0xff) { 95312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info); 96312fec14SDave Airlie index++; 97312fec14SDave Airlie ext_reg_info++; 98312fec14SDave Airlie } 99312fec14SDave Airlie 100312fec14SDave Airlie /* disable standard IO/MEM decode if secondary */ 101312fec14SDave Airlie /* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */ 102312fec14SDave Airlie 103312fec14SDave Airlie /* Set Ext. Default */ 104312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01); 105312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00); 106312fec14SDave Airlie 107312fec14SDave Airlie /* Enable RAMDAC for A1 */ 108312fec14SDave Airlie reg = 0x04; 1091453bf4cSDave Airlie if (ast->chip == AST2300 || ast->chip == AST2400) 110312fec14SDave Airlie reg |= 0x20; 111312fec14SDave Airlie ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg); 112312fec14SDave Airlie } 113312fec14SDave Airlie 11483c6620bSDave Airlie u32 ast_mindwm(struct ast_private *ast, u32 r) 115312fec14SDave Airlie { 116318cfa29SDave Airlie uint32_t data; 117318cfa29SDave Airlie 118312fec14SDave Airlie ast_write32(ast, 0xf004, r & 0xffff0000); 119312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 120312fec14SDave Airlie 121318cfa29SDave Airlie do { 122318cfa29SDave Airlie data = ast_read32(ast, 0xf004) & 0xffff0000; 123318cfa29SDave Airlie } while (data != (r & 0xffff0000)); 124312fec14SDave Airlie return ast_read32(ast, 0x10000 + (r & 0x0000ffff)); 125312fec14SDave Airlie } 126312fec14SDave Airlie 12783c6620bSDave Airlie void ast_moutdwm(struct ast_private *ast, u32 r, u32 v) 128312fec14SDave Airlie { 129318cfa29SDave Airlie uint32_t data; 130312fec14SDave Airlie ast_write32(ast, 0xf004, r & 0xffff0000); 131312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 132318cfa29SDave Airlie do { 133318cfa29SDave Airlie data = ast_read32(ast, 0xf004) & 0xffff0000; 134318cfa29SDave Airlie } while (data != (r & 0xffff0000)); 135312fec14SDave Airlie ast_write32(ast, 0x10000 + (r & 0x0000ffff), v); 136312fec14SDave Airlie } 137312fec14SDave Airlie 138312fec14SDave Airlie /* 139312fec14SDave Airlie * AST2100/2150 DLL CBR Setting 140312fec14SDave Airlie */ 141312fec14SDave Airlie #define CBR_SIZE_AST2150 ((16 << 10) - 1) 142312fec14SDave Airlie #define CBR_PASSNUM_AST2150 5 143312fec14SDave Airlie #define CBR_THRESHOLD_AST2150 10 144312fec14SDave Airlie #define CBR_THRESHOLD2_AST2150 10 145312fec14SDave Airlie #define TIMEOUT_AST2150 5000000 146312fec14SDave Airlie 147312fec14SDave Airlie #define CBR_PATNUM_AST2150 8 148312fec14SDave Airlie 149312fec14SDave Airlie static const u32 pattern_AST2150[14] = { 150312fec14SDave Airlie 0xFF00FF00, 151312fec14SDave Airlie 0xCC33CC33, 152312fec14SDave Airlie 0xAA55AA55, 153312fec14SDave Airlie 0xFFFE0001, 154312fec14SDave Airlie 0x683501FE, 155312fec14SDave Airlie 0x0F1929B0, 156312fec14SDave Airlie 0x2D0B4346, 157312fec14SDave Airlie 0x60767F02, 158312fec14SDave Airlie 0x6FBE36A6, 159312fec14SDave Airlie 0x3A253035, 160312fec14SDave Airlie 0x3019686D, 161312fec14SDave Airlie 0x41C6167E, 162312fec14SDave Airlie 0x620152BF, 163312fec14SDave Airlie 0x20F050E0 164312fec14SDave Airlie }; 165312fec14SDave Airlie 166312fec14SDave Airlie static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen) 167312fec14SDave Airlie { 168312fec14SDave Airlie u32 data, timeout; 169312fec14SDave Airlie 1700e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 1710e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3)); 172312fec14SDave Airlie timeout = 0; 173312fec14SDave Airlie do { 1740e5ce924SDave Airlie data = ast_mindwm(ast, 0x1e6e0070) & 0x40; 175312fec14SDave Airlie if (++timeout > TIMEOUT_AST2150) { 1760e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 177312fec14SDave Airlie return 0xffffffff; 178312fec14SDave Airlie } 179312fec14SDave Airlie } while (!data); 1800e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 1810e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3)); 182312fec14SDave Airlie timeout = 0; 183312fec14SDave Airlie do { 1840e5ce924SDave Airlie data = ast_mindwm(ast, 0x1e6e0070) & 0x40; 185312fec14SDave Airlie if (++timeout > TIMEOUT_AST2150) { 1860e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 187312fec14SDave Airlie return 0xffffffff; 188312fec14SDave Airlie } 189312fec14SDave Airlie } while (!data); 1900e5ce924SDave Airlie data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7; 1910e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 192312fec14SDave Airlie return data; 193312fec14SDave Airlie } 194312fec14SDave Airlie 195312fec14SDave Airlie #if 0 /* unused in DDX driver - here for completeness */ 196312fec14SDave Airlie static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen) 197312fec14SDave Airlie { 198312fec14SDave Airlie u32 data, timeout; 199312fec14SDave Airlie 2000e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 2010e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3)); 202312fec14SDave Airlie timeout = 0; 203312fec14SDave Airlie do { 2040e5ce924SDave Airlie data = ast_mindwm(ast, 0x1e6e0070) & 0x40; 205312fec14SDave Airlie if (++timeout > TIMEOUT_AST2150) { 2060e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 207312fec14SDave Airlie return 0xffffffff; 208312fec14SDave Airlie } 209312fec14SDave Airlie } while (!data); 2100e5ce924SDave Airlie data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7; 2110e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 212312fec14SDave Airlie return data; 213312fec14SDave Airlie } 214312fec14SDave Airlie #endif 215312fec14SDave Airlie 216312fec14SDave Airlie static int cbrtest_ast2150(struct ast_private *ast) 217312fec14SDave Airlie { 218312fec14SDave Airlie int i; 219312fec14SDave Airlie 220312fec14SDave Airlie for (i = 0; i < 8; i++) 221312fec14SDave Airlie if (mmctestburst2_ast2150(ast, i)) 222312fec14SDave Airlie return 0; 223312fec14SDave Airlie return 1; 224312fec14SDave Airlie } 225312fec14SDave Airlie 226312fec14SDave Airlie static int cbrscan_ast2150(struct ast_private *ast, int busw) 227312fec14SDave Airlie { 228312fec14SDave Airlie u32 patcnt, loop; 229312fec14SDave Airlie 230312fec14SDave Airlie for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) { 2310e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]); 232312fec14SDave Airlie for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) { 233312fec14SDave Airlie if (cbrtest_ast2150(ast)) 234312fec14SDave Airlie break; 235312fec14SDave Airlie } 236312fec14SDave Airlie if (loop == CBR_PASSNUM_AST2150) 237312fec14SDave Airlie return 0; 238312fec14SDave Airlie } 239312fec14SDave Airlie return 1; 240312fec14SDave Airlie } 241312fec14SDave Airlie 242312fec14SDave Airlie 243312fec14SDave Airlie static void cbrdlli_ast2150(struct ast_private *ast, int busw) 244312fec14SDave Airlie { 245312fec14SDave Airlie u32 dll_min[4], dll_max[4], dlli, data, passcnt; 246312fec14SDave Airlie 247312fec14SDave Airlie cbr_start: 248312fec14SDave Airlie dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff; 249312fec14SDave Airlie dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0; 250312fec14SDave Airlie passcnt = 0; 251312fec14SDave Airlie 252312fec14SDave Airlie for (dlli = 0; dlli < 100; dlli++) { 2530e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 254312fec14SDave Airlie data = cbrscan_ast2150(ast, busw); 255312fec14SDave Airlie if (data != 0) { 256312fec14SDave Airlie if (data & 0x1) { 257312fec14SDave Airlie if (dll_min[0] > dlli) 258312fec14SDave Airlie dll_min[0] = dlli; 259312fec14SDave Airlie if (dll_max[0] < dlli) 260312fec14SDave Airlie dll_max[0] = dlli; 261312fec14SDave Airlie } 262312fec14SDave Airlie passcnt++; 263312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD_AST2150) 264312fec14SDave Airlie goto cbr_start; 265312fec14SDave Airlie } 266312fec14SDave Airlie if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150) 267312fec14SDave Airlie goto cbr_start; 268312fec14SDave Airlie 269312fec14SDave Airlie dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4); 2700e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 271312fec14SDave Airlie } 272312fec14SDave Airlie 273312fec14SDave Airlie 274312fec14SDave Airlie 275312fec14SDave Airlie static void ast_init_dram_reg(struct drm_device *dev) 276312fec14SDave Airlie { 277312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 278312fec14SDave Airlie u8 j; 279312fec14SDave Airlie u32 data, temp, i; 280312fec14SDave Airlie const struct ast_dramstruct *dram_reg_info; 281312fec14SDave Airlie 282312fec14SDave Airlie j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 283312fec14SDave Airlie 284312fec14SDave Airlie if ((j & 0x80) == 0) { /* VGA only */ 285312fec14SDave Airlie if (ast->chip == AST2000) { 286312fec14SDave Airlie dram_reg_info = ast2000_dram_table_data; 287312fec14SDave Airlie ast_write32(ast, 0xf004, 0x1e6e0000); 288312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 289312fec14SDave Airlie ast_write32(ast, 0x10100, 0xa8); 290312fec14SDave Airlie 291312fec14SDave Airlie do { 292312fec14SDave Airlie ; 293312fec14SDave Airlie } while (ast_read32(ast, 0x10100) != 0xa8); 294312fec14SDave Airlie } else {/* AST2100/1100 */ 295312fec14SDave Airlie if (ast->chip == AST2100 || ast->chip == 2200) 296312fec14SDave Airlie dram_reg_info = ast2100_dram_table_data; 297312fec14SDave Airlie else 298312fec14SDave Airlie dram_reg_info = ast1100_dram_table_data; 299312fec14SDave Airlie 300312fec14SDave Airlie ast_write32(ast, 0xf004, 0x1e6e0000); 301312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 302312fec14SDave Airlie ast_write32(ast, 0x12000, 0x1688A8A8); 303312fec14SDave Airlie do { 304312fec14SDave Airlie ; 305312fec14SDave Airlie } while (ast_read32(ast, 0x12000) != 0x01); 306312fec14SDave Airlie 307312fec14SDave Airlie ast_write32(ast, 0x10000, 0xfc600309); 308312fec14SDave Airlie do { 309312fec14SDave Airlie ; 310312fec14SDave Airlie } while (ast_read32(ast, 0x10000) != 0x01); 311312fec14SDave Airlie } 312312fec14SDave Airlie 313312fec14SDave Airlie while (dram_reg_info->index != 0xffff) { 314312fec14SDave Airlie if (dram_reg_info->index == 0xff00) {/* delay fn */ 315312fec14SDave Airlie for (i = 0; i < 15; i++) 316312fec14SDave Airlie udelay(dram_reg_info->data); 317312fec14SDave Airlie } else if (dram_reg_info->index == 0x4 && ast->chip != AST2000) { 318312fec14SDave Airlie data = dram_reg_info->data; 319312fec14SDave Airlie if (ast->dram_type == AST_DRAM_1Gx16) 320312fec14SDave Airlie data = 0x00000d89; 321312fec14SDave Airlie else if (ast->dram_type == AST_DRAM_1Gx32) 322312fec14SDave Airlie data = 0x00000c8d; 323312fec14SDave Airlie 324312fec14SDave Airlie temp = ast_read32(ast, 0x12070); 325312fec14SDave Airlie temp &= 0xc; 326312fec14SDave Airlie temp <<= 2; 327312fec14SDave Airlie ast_write32(ast, 0x10000 + dram_reg_info->index, data | temp); 328312fec14SDave Airlie } else 329312fec14SDave Airlie ast_write32(ast, 0x10000 + dram_reg_info->index, dram_reg_info->data); 330312fec14SDave Airlie dram_reg_info++; 331312fec14SDave Airlie } 332312fec14SDave Airlie 333312fec14SDave Airlie /* AST 2100/2150 DRAM calibration */ 334312fec14SDave Airlie data = ast_read32(ast, 0x10120); 335312fec14SDave Airlie if (data == 0x5061) { /* 266Mhz */ 336312fec14SDave Airlie data = ast_read32(ast, 0x10004); 337312fec14SDave Airlie if (data & 0x40) 338312fec14SDave Airlie cbrdlli_ast2150(ast, 16); /* 16 bits */ 339312fec14SDave Airlie else 340312fec14SDave Airlie cbrdlli_ast2150(ast, 32); /* 32 bits */ 341312fec14SDave Airlie } 342312fec14SDave Airlie 343312fec14SDave Airlie switch (ast->chip) { 344312fec14SDave Airlie case AST2000: 345312fec14SDave Airlie temp = ast_read32(ast, 0x10140); 346312fec14SDave Airlie ast_write32(ast, 0x10140, temp | 0x40); 347312fec14SDave Airlie break; 348312fec14SDave Airlie case AST1100: 349312fec14SDave Airlie case AST2100: 350312fec14SDave Airlie case AST2200: 351312fec14SDave Airlie case AST2150: 352312fec14SDave Airlie temp = ast_read32(ast, 0x1200c); 353312fec14SDave Airlie ast_write32(ast, 0x1200c, temp & 0xfffffffd); 354312fec14SDave Airlie temp = ast_read32(ast, 0x12040); 355312fec14SDave Airlie ast_write32(ast, 0x12040, temp | 0x40); 356312fec14SDave Airlie break; 357312fec14SDave Airlie default: 358312fec14SDave Airlie break; 359312fec14SDave Airlie } 360312fec14SDave Airlie } 361312fec14SDave Airlie 362312fec14SDave Airlie /* wait ready */ 363312fec14SDave Airlie do { 364312fec14SDave Airlie j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 365312fec14SDave Airlie } while ((j & 0x40) == 0); 366312fec14SDave Airlie } 367312fec14SDave Airlie 368312fec14SDave Airlie void ast_post_gpu(struct drm_device *dev) 369312fec14SDave Airlie { 370312fec14SDave Airlie u32 reg; 371312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 372312fec14SDave Airlie 373312fec14SDave Airlie pci_read_config_dword(ast->dev->pdev, 0x04, ®); 374312fec14SDave Airlie reg |= 0x3; 375312fec14SDave Airlie pci_write_config_dword(ast->dev->pdev, 0x04, reg); 376312fec14SDave Airlie 377312fec14SDave Airlie ast_enable_vga(dev); 378d1b98557SBenjamin Herrenschmidt ast_enable_mmio(dev); 379312fec14SDave Airlie ast_open_key(ast); 380312fec14SDave Airlie ast_set_def_ext_reg(dev); 381312fec14SDave Airlie 38271f677a9SRussell Currey if (ast->config_mode == ast_use_p2a) { 3831453bf4cSDave Airlie if (ast->chip == AST2300 || ast->chip == AST2400) 384d95618efSBenjamin Herrenschmidt ast_post_chip_2300(dev); 385312fec14SDave Airlie else 386312fec14SDave Airlie ast_init_dram_reg(dev); 38783c6620bSDave Airlie 38883c6620bSDave Airlie ast_init_3rdtx(dev); 38971f677a9SRussell Currey } else { 3906c971c09SY.C. Chen if (ast->tx_chip_type != AST_TX_NONE) 3916c971c09SY.C. Chen ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */ 3926c971c09SY.C. Chen } 3936c971c09SY.C. Chen } 394312fec14SDave Airlie 395312fec14SDave Airlie /* AST 2300 DRAM settings */ 396312fec14SDave Airlie #define AST_DDR3 0 397312fec14SDave Airlie #define AST_DDR2 1 398312fec14SDave Airlie 399312fec14SDave Airlie struct ast2300_dram_param { 400312fec14SDave Airlie u32 dram_type; 401312fec14SDave Airlie u32 dram_chipid; 402312fec14SDave Airlie u32 dram_freq; 403312fec14SDave Airlie u32 vram_size; 404312fec14SDave Airlie u32 odt; 405312fec14SDave Airlie u32 wodt; 406312fec14SDave Airlie u32 rodt; 407312fec14SDave Airlie u32 dram_config; 408312fec14SDave Airlie u32 reg_PERIOD; 409312fec14SDave Airlie u32 reg_MADJ; 410312fec14SDave Airlie u32 reg_SADJ; 411312fec14SDave Airlie u32 reg_MRS; 412312fec14SDave Airlie u32 reg_EMRS; 413312fec14SDave Airlie u32 reg_AC1; 414312fec14SDave Airlie u32 reg_AC2; 415312fec14SDave Airlie u32 reg_DQSIC; 416312fec14SDave Airlie u32 reg_DRV; 417312fec14SDave Airlie u32 reg_IOZ; 418312fec14SDave Airlie u32 reg_DQIDLY; 419312fec14SDave Airlie u32 reg_FREQ; 420312fec14SDave Airlie u32 madj_max; 421312fec14SDave Airlie u32 dll2_finetune_step; 422312fec14SDave Airlie }; 423312fec14SDave Airlie 424312fec14SDave Airlie /* 425312fec14SDave Airlie * DQSI DLL CBR Setting 426312fec14SDave Airlie */ 427318cfa29SDave Airlie #define CBR_SIZE0 ((1 << 10) - 1) 428312fec14SDave Airlie #define CBR_SIZE1 ((4 << 10) - 1) 429312fec14SDave Airlie #define CBR_SIZE2 ((64 << 10) - 1) 430312fec14SDave Airlie #define CBR_PASSNUM 5 431312fec14SDave Airlie #define CBR_PASSNUM2 5 432312fec14SDave Airlie #define CBR_THRESHOLD 10 433312fec14SDave Airlie #define CBR_THRESHOLD2 10 434312fec14SDave Airlie #define TIMEOUT 5000000 435312fec14SDave Airlie #define CBR_PATNUM 8 436312fec14SDave Airlie 437312fec14SDave Airlie static const u32 pattern[8] = { 438312fec14SDave Airlie 0xFF00FF00, 439312fec14SDave Airlie 0xCC33CC33, 440312fec14SDave Airlie 0xAA55AA55, 441312fec14SDave Airlie 0x88778877, 442312fec14SDave Airlie 0x92CC4D6E, 443312fec14SDave Airlie 0x543D3CDE, 444312fec14SDave Airlie 0xF1E843C7, 445312fec14SDave Airlie 0x7C61D253 446312fec14SDave Airlie }; 447312fec14SDave Airlie 448b368e53aSBenjamin Herrenschmidt static bool mmc_test(struct ast_private *ast, u32 datagen, u8 test_ctl) 449312fec14SDave Airlie { 450312fec14SDave Airlie u32 data, timeout; 451312fec14SDave Airlie 4520e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 453b368e53aSBenjamin Herrenschmidt ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl); 454312fec14SDave Airlie timeout = 0; 455312fec14SDave Airlie do { 4560e5ce924SDave Airlie data = ast_mindwm(ast, 0x1e6e0070) & 0x3000; 457312fec14SDave Airlie if (data & 0x2000) 458b368e53aSBenjamin Herrenschmidt return false; 459312fec14SDave Airlie if (++timeout > TIMEOUT) { 460b368e53aSBenjamin Herrenschmidt ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 461b368e53aSBenjamin Herrenschmidt return false; 462312fec14SDave Airlie } 463312fec14SDave Airlie } while (!data); 4640e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x0); 465b368e53aSBenjamin Herrenschmidt return true; 466312fec14SDave Airlie } 467312fec14SDave Airlie 468b368e53aSBenjamin Herrenschmidt static u32 mmc_test2(struct ast_private *ast, u32 datagen, u8 test_ctl) 469312fec14SDave Airlie { 470312fec14SDave Airlie u32 data, timeout; 471312fec14SDave Airlie 4720e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 473b368e53aSBenjamin Herrenschmidt ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl); 474312fec14SDave Airlie timeout = 0; 475312fec14SDave Airlie do { 4760e5ce924SDave Airlie data = ast_mindwm(ast, 0x1e6e0070) & 0x1000; 477312fec14SDave Airlie if (++timeout > TIMEOUT) { 4780e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e0070, 0x0); 479b368e53aSBenjamin Herrenschmidt return 0xffffffff; 480312fec14SDave Airlie } 481312fec14SDave Airlie } while (!data); 4820e5ce924SDave Airlie data = ast_mindwm(ast, 0x1e6e0078); 483312fec14SDave Airlie data = (data | (data >> 16)) & 0xffff; 484b368e53aSBenjamin Herrenschmidt ast_moutdwm(ast, 0x1e6e0070, 0x00000000); 485312fec14SDave Airlie return data; 486312fec14SDave Airlie } 487312fec14SDave Airlie 488b368e53aSBenjamin Herrenschmidt 489b368e53aSBenjamin Herrenschmidt static bool mmc_test_burst(struct ast_private *ast, u32 datagen) 490b368e53aSBenjamin Herrenschmidt { 491b368e53aSBenjamin Herrenschmidt return mmc_test(ast, datagen, 0xc1); 492b368e53aSBenjamin Herrenschmidt } 493b368e53aSBenjamin Herrenschmidt 494b368e53aSBenjamin Herrenschmidt static u32 mmc_test_burst2(struct ast_private *ast, u32 datagen) 495b368e53aSBenjamin Herrenschmidt { 496b368e53aSBenjamin Herrenschmidt return mmc_test2(ast, datagen, 0x41); 497b368e53aSBenjamin Herrenschmidt } 498b368e53aSBenjamin Herrenschmidt 499b368e53aSBenjamin Herrenschmidt static bool mmc_test_single(struct ast_private *ast, u32 datagen) 500b368e53aSBenjamin Herrenschmidt { 501b368e53aSBenjamin Herrenschmidt return mmc_test(ast, datagen, 0xc5); 502b368e53aSBenjamin Herrenschmidt } 503b368e53aSBenjamin Herrenschmidt 504b368e53aSBenjamin Herrenschmidt static u32 mmc_test_single2(struct ast_private *ast, u32 datagen) 505b368e53aSBenjamin Herrenschmidt { 506b368e53aSBenjamin Herrenschmidt return mmc_test2(ast, datagen, 0x05); 507b368e53aSBenjamin Herrenschmidt } 508b368e53aSBenjamin Herrenschmidt 509312fec14SDave Airlie static int cbr_test(struct ast_private *ast) 510312fec14SDave Airlie { 511312fec14SDave Airlie u32 data; 512312fec14SDave Airlie int i; 513312fec14SDave Airlie data = mmc_test_single2(ast, 0); 514312fec14SDave Airlie if ((data & 0xff) && (data & 0xff00)) 515312fec14SDave Airlie return 0; 516312fec14SDave Airlie for (i = 0; i < 8; i++) { 517312fec14SDave Airlie data = mmc_test_burst2(ast, i); 518312fec14SDave Airlie if ((data & 0xff) && (data & 0xff00)) 519312fec14SDave Airlie return 0; 520312fec14SDave Airlie } 521312fec14SDave Airlie if (!data) 522312fec14SDave Airlie return 3; 523312fec14SDave Airlie else if (data & 0xff) 524312fec14SDave Airlie return 2; 525312fec14SDave Airlie return 1; 526312fec14SDave Airlie } 527312fec14SDave Airlie 528312fec14SDave Airlie static int cbr_scan(struct ast_private *ast) 529312fec14SDave Airlie { 530312fec14SDave Airlie u32 data, data2, patcnt, loop; 531312fec14SDave Airlie 532312fec14SDave Airlie data2 = 3; 533312fec14SDave Airlie for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 5340e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 535312fec14SDave Airlie for (loop = 0; loop < CBR_PASSNUM2; loop++) { 536312fec14SDave Airlie if ((data = cbr_test(ast)) != 0) { 537312fec14SDave Airlie data2 &= data; 538312fec14SDave Airlie if (!data2) 539312fec14SDave Airlie return 0; 540312fec14SDave Airlie break; 541312fec14SDave Airlie } 542312fec14SDave Airlie } 543312fec14SDave Airlie if (loop == CBR_PASSNUM2) 544312fec14SDave Airlie return 0; 545312fec14SDave Airlie } 546312fec14SDave Airlie return data2; 547312fec14SDave Airlie } 548312fec14SDave Airlie 549312fec14SDave Airlie static u32 cbr_test2(struct ast_private *ast) 550312fec14SDave Airlie { 551312fec14SDave Airlie u32 data; 552312fec14SDave Airlie 553312fec14SDave Airlie data = mmc_test_burst2(ast, 0); 554312fec14SDave Airlie if (data == 0xffff) 555312fec14SDave Airlie return 0; 556312fec14SDave Airlie data |= mmc_test_single2(ast, 0); 557312fec14SDave Airlie if (data == 0xffff) 558312fec14SDave Airlie return 0; 559312fec14SDave Airlie 560312fec14SDave Airlie return ~data & 0xffff; 561312fec14SDave Airlie } 562312fec14SDave Airlie 563312fec14SDave Airlie static u32 cbr_scan2(struct ast_private *ast) 564312fec14SDave Airlie { 565312fec14SDave Airlie u32 data, data2, patcnt, loop; 566312fec14SDave Airlie 567312fec14SDave Airlie data2 = 0xffff; 568312fec14SDave Airlie for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 5690e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 570312fec14SDave Airlie for (loop = 0; loop < CBR_PASSNUM2; loop++) { 571312fec14SDave Airlie if ((data = cbr_test2(ast)) != 0) { 572312fec14SDave Airlie data2 &= data; 573a82049b1SDave Airlie if (!data2) 574312fec14SDave Airlie return 0; 575312fec14SDave Airlie break; 576312fec14SDave Airlie } 577312fec14SDave Airlie } 578312fec14SDave Airlie if (loop == CBR_PASSNUM2) 579312fec14SDave Airlie return 0; 580312fec14SDave Airlie } 581312fec14SDave Airlie return data2; 582312fec14SDave Airlie } 583312fec14SDave Airlie 584b368e53aSBenjamin Herrenschmidt static bool cbr_test3(struct ast_private *ast) 585312fec14SDave Airlie { 586318cfa29SDave Airlie if (!mmc_test_burst(ast, 0)) 587b368e53aSBenjamin Herrenschmidt return false; 588318cfa29SDave Airlie if (!mmc_test_single(ast, 0)) 589b368e53aSBenjamin Herrenschmidt return false; 590b368e53aSBenjamin Herrenschmidt return true; 591318cfa29SDave Airlie } 592312fec14SDave Airlie 593b368e53aSBenjamin Herrenschmidt static bool cbr_scan3(struct ast_private *ast) 594318cfa29SDave Airlie { 595318cfa29SDave Airlie u32 patcnt, loop; 596312fec14SDave Airlie 597318cfa29SDave Airlie for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 5980e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 599318cfa29SDave Airlie for (loop = 0; loop < 2; loop++) { 600318cfa29SDave Airlie if (cbr_test3(ast)) 601312fec14SDave Airlie break; 602312fec14SDave Airlie } 603318cfa29SDave Airlie if (loop == 2) 604b368e53aSBenjamin Herrenschmidt return false; 605312fec14SDave Airlie } 606b368e53aSBenjamin Herrenschmidt return true; 607312fec14SDave Airlie } 608312fec14SDave Airlie 609318cfa29SDave Airlie static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param) 610312fec14SDave Airlie { 611318cfa29SDave Airlie u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0; 612318cfa29SDave Airlie bool status = false; 613312fec14SDave Airlie FINETUNE_START: 614312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 615312fec14SDave Airlie dllmin[cnt] = 0xff; 616312fec14SDave Airlie dllmax[cnt] = 0x0; 617312fec14SDave Airlie } 618312fec14SDave Airlie passcnt = 0; 619312fec14SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 6200e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 6210e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1); 622312fec14SDave Airlie data = cbr_scan2(ast); 623312fec14SDave Airlie if (data != 0) { 624312fec14SDave Airlie mask = 0x00010001; 625312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 626312fec14SDave Airlie if (data & mask) { 627312fec14SDave Airlie if (dllmin[cnt] > dlli) { 628312fec14SDave Airlie dllmin[cnt] = dlli; 629312fec14SDave Airlie } 630312fec14SDave Airlie if (dllmax[cnt] < dlli) { 631312fec14SDave Airlie dllmax[cnt] = dlli; 632312fec14SDave Airlie } 633312fec14SDave Airlie } 634312fec14SDave Airlie mask <<= 1; 635312fec14SDave Airlie } 636312fec14SDave Airlie passcnt++; 637312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD2) { 638312fec14SDave Airlie break; 639312fec14SDave Airlie } 640312fec14SDave Airlie } 641312fec14SDave Airlie gold_sadj[0] = 0x0; 642312fec14SDave Airlie passcnt = 0; 643312fec14SDave Airlie for (cnt = 0; cnt < 16; cnt++) { 644312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 645312fec14SDave Airlie gold_sadj[0] += dllmin[cnt]; 646312fec14SDave Airlie passcnt++; 647312fec14SDave Airlie } 648312fec14SDave Airlie } 649318cfa29SDave Airlie if (retry++ > 10) 650318cfa29SDave Airlie goto FINETUNE_DONE; 651312fec14SDave Airlie if (passcnt != 16) { 652312fec14SDave Airlie goto FINETUNE_START; 653312fec14SDave Airlie } 654318cfa29SDave Airlie status = true; 655318cfa29SDave Airlie FINETUNE_DONE: 656312fec14SDave Airlie gold_sadj[0] = gold_sadj[0] >> 4; 657312fec14SDave Airlie gold_sadj[1] = gold_sadj[0]; 658312fec14SDave Airlie 659312fec14SDave Airlie data = 0; 660312fec14SDave Airlie for (cnt = 0; cnt < 8; cnt++) { 661312fec14SDave Airlie data >>= 3; 662312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 663312fec14SDave Airlie dlli = dllmin[cnt]; 664312fec14SDave Airlie if (gold_sadj[0] >= dlli) { 665312fec14SDave Airlie dlli = ((gold_sadj[0] - dlli) * 19) >> 5; 666312fec14SDave Airlie if (dlli > 3) { 667312fec14SDave Airlie dlli = 3; 668312fec14SDave Airlie } 669312fec14SDave Airlie } else { 670312fec14SDave Airlie dlli = ((dlli - gold_sadj[0]) * 19) >> 5; 671312fec14SDave Airlie if (dlli > 4) { 672312fec14SDave Airlie dlli = 4; 673312fec14SDave Airlie } 674312fec14SDave Airlie dlli = (8 - dlli) & 0x7; 675312fec14SDave Airlie } 676312fec14SDave Airlie data |= dlli << 21; 677312fec14SDave Airlie } 678312fec14SDave Airlie } 6790e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0080, data); 680312fec14SDave Airlie 681312fec14SDave Airlie data = 0; 682312fec14SDave Airlie for (cnt = 8; cnt < 16; cnt++) { 683312fec14SDave Airlie data >>= 3; 684312fec14SDave Airlie if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 685312fec14SDave Airlie dlli = dllmin[cnt]; 686312fec14SDave Airlie if (gold_sadj[1] >= dlli) { 687312fec14SDave Airlie dlli = ((gold_sadj[1] - dlli) * 19) >> 5; 688312fec14SDave Airlie if (dlli > 3) { 689312fec14SDave Airlie dlli = 3; 690312fec14SDave Airlie } else { 691312fec14SDave Airlie dlli = (dlli - 1) & 0x7; 692312fec14SDave Airlie } 693312fec14SDave Airlie } else { 694312fec14SDave Airlie dlli = ((dlli - gold_sadj[1]) * 19) >> 5; 695312fec14SDave Airlie dlli += 1; 696312fec14SDave Airlie if (dlli > 4) { 697312fec14SDave Airlie dlli = 4; 698312fec14SDave Airlie } 699312fec14SDave Airlie dlli = (8 - dlli) & 0x7; 700312fec14SDave Airlie } 701312fec14SDave Airlie data |= dlli << 21; 702312fec14SDave Airlie } 703312fec14SDave Airlie } 7040e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0084, data); 705318cfa29SDave Airlie return status; 706312fec14SDave Airlie } /* finetuneDQI_L */ 707312fec14SDave Airlie 708318cfa29SDave Airlie static void finetuneDQSI(struct ast_private *ast) 709312fec14SDave Airlie { 710318cfa29SDave Airlie u32 dlli, dqsip, dqidly; 711318cfa29SDave Airlie u32 reg_mcr18, reg_mcr0c, passcnt[2], diff; 712318cfa29SDave Airlie u32 g_dqidly, g_dqsip, g_margin, g_side; 713318cfa29SDave Airlie u16 pass[32][2][2]; 714318cfa29SDave Airlie char tag[2][76]; 715312fec14SDave Airlie 716318cfa29SDave Airlie /* Disable DQI CBR */ 7170e5ce924SDave Airlie reg_mcr0c = ast_mindwm(ast, 0x1E6E000C); 7180e5ce924SDave Airlie reg_mcr18 = ast_mindwm(ast, 0x1E6E0018); 719318cfa29SDave Airlie reg_mcr18 &= 0x0000ffff; 7200e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, reg_mcr18); 721318cfa29SDave Airlie 722312fec14SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 723318cfa29SDave Airlie tag[0][dlli] = 0x0; 724318cfa29SDave Airlie tag[1][dlli] = 0x0; 725312fec14SDave Airlie } 726318cfa29SDave Airlie for (dqidly = 0; dqidly < 32; dqidly++) { 727318cfa29SDave Airlie pass[dqidly][0][0] = 0xff; 728318cfa29SDave Airlie pass[dqidly][0][1] = 0x0; 729318cfa29SDave Airlie pass[dqidly][1][0] = 0xff; 730318cfa29SDave Airlie pass[dqidly][1][1] = 0x0; 731312fec14SDave Airlie } 732318cfa29SDave Airlie for (dqidly = 0; dqidly < 32; dqidly++) { 733318cfa29SDave Airlie passcnt[0] = passcnt[1] = 0; 734318cfa29SDave Airlie for (dqsip = 0; dqsip < 2; dqsip++) { 7350e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, 0); 7360e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23)); 7370e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c); 738318cfa29SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 7390e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24)); 7400e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0070, 0); 7410e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0); 742318cfa29SDave Airlie if (cbr_scan3(ast)) { 743318cfa29SDave Airlie if (dlli == 0) 744312fec14SDave Airlie break; 745318cfa29SDave Airlie passcnt[dqsip]++; 746318cfa29SDave Airlie tag[dqsip][dlli] = 'P'; 747318cfa29SDave Airlie if (dlli < pass[dqidly][dqsip][0]) 748318cfa29SDave Airlie pass[dqidly][dqsip][0] = (u16) dlli; 749318cfa29SDave Airlie if (dlli > pass[dqidly][dqsip][1]) 750318cfa29SDave Airlie pass[dqidly][dqsip][1] = (u16) dlli; 751318cfa29SDave Airlie } else if (passcnt[dqsip] >= 5) 752318cfa29SDave Airlie break; 753318cfa29SDave Airlie else { 754318cfa29SDave Airlie pass[dqidly][dqsip][0] = 0xff; 755318cfa29SDave Airlie pass[dqidly][dqsip][1] = 0x0; 756312fec14SDave Airlie } 757312fec14SDave Airlie } 758312fec14SDave Airlie } 759318cfa29SDave Airlie if (passcnt[0] == 0 && passcnt[1] == 0) 760318cfa29SDave Airlie dqidly++; 761318cfa29SDave Airlie } 762318cfa29SDave Airlie /* Search margin */ 763318cfa29SDave Airlie g_dqidly = g_dqsip = g_margin = g_side = 0; 764312fec14SDave Airlie 765318cfa29SDave Airlie for (dqidly = 0; dqidly < 32; dqidly++) { 766318cfa29SDave Airlie for (dqsip = 0; dqsip < 2; dqsip++) { 767318cfa29SDave Airlie if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1]) 768318cfa29SDave Airlie continue; 769318cfa29SDave Airlie diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0]; 770318cfa29SDave Airlie if ((diff+2) < g_margin) 771318cfa29SDave Airlie continue; 772318cfa29SDave Airlie passcnt[0] = passcnt[1] = 0; 773318cfa29SDave Airlie for (dlli = pass[dqidly][dqsip][0]; dlli > 0 && tag[dqsip][dlli] != 0; dlli--, passcnt[0]++); 774318cfa29SDave Airlie for (dlli = pass[dqidly][dqsip][1]; dlli < 76 && tag[dqsip][dlli] != 0; dlli++, passcnt[1]++); 775318cfa29SDave Airlie if (passcnt[0] > passcnt[1]) 776318cfa29SDave Airlie passcnt[0] = passcnt[1]; 777318cfa29SDave Airlie passcnt[1] = 0; 778318cfa29SDave Airlie if (passcnt[0] > g_side) 779318cfa29SDave Airlie passcnt[1] = passcnt[0] - g_side; 780318cfa29SDave Airlie if (diff > (g_margin+1) && (passcnt[1] > 0 || passcnt[0] > 8)) { 781318cfa29SDave Airlie g_margin = diff; 782318cfa29SDave Airlie g_dqidly = dqidly; 783318cfa29SDave Airlie g_dqsip = dqsip; 784318cfa29SDave Airlie g_side = passcnt[0]; 785318cfa29SDave Airlie } else if (passcnt[1] > 1 && g_side < 8) { 786318cfa29SDave Airlie if (diff > g_margin) 787318cfa29SDave Airlie g_margin = diff; 788318cfa29SDave Airlie g_dqidly = dqidly; 789318cfa29SDave Airlie g_dqsip = dqsip; 790318cfa29SDave Airlie g_side = passcnt[0]; 791312fec14SDave Airlie } 792312fec14SDave Airlie } 793312fec14SDave Airlie } 794318cfa29SDave Airlie reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23); 7950e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, reg_mcr18); 796312fec14SDave Airlie 797312fec14SDave Airlie } 798318cfa29SDave Airlie static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param) 799312fec14SDave Airlie { 800318cfa29SDave Airlie u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0; 801318cfa29SDave Airlie bool status = false; 802312fec14SDave Airlie 803318cfa29SDave Airlie finetuneDQSI(ast); 804318cfa29SDave Airlie if (finetuneDQI_L(ast, param) == false) 805318cfa29SDave Airlie return status; 806312fec14SDave Airlie 807312fec14SDave Airlie CBR_START2: 808312fec14SDave Airlie dllmin[0] = dllmin[1] = 0xff; 809312fec14SDave Airlie dllmax[0] = dllmax[1] = 0x0; 810312fec14SDave Airlie passcnt = 0; 811312fec14SDave Airlie for (dlli = 0; dlli < 76; dlli++) { 8120e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24)); 8130e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2); 814312fec14SDave Airlie data = cbr_scan(ast); 815312fec14SDave Airlie if (data != 0) { 816312fec14SDave Airlie if (data & 0x1) { 817312fec14SDave Airlie if (dllmin[0] > dlli) { 818312fec14SDave Airlie dllmin[0] = dlli; 819312fec14SDave Airlie } 820312fec14SDave Airlie if (dllmax[0] < dlli) { 821312fec14SDave Airlie dllmax[0] = dlli; 822312fec14SDave Airlie } 823312fec14SDave Airlie } 824312fec14SDave Airlie if (data & 0x2) { 825312fec14SDave Airlie if (dllmin[1] > dlli) { 826312fec14SDave Airlie dllmin[1] = dlli; 827312fec14SDave Airlie } 828312fec14SDave Airlie if (dllmax[1] < dlli) { 829312fec14SDave Airlie dllmax[1] = dlli; 830312fec14SDave Airlie } 831312fec14SDave Airlie } 832312fec14SDave Airlie passcnt++; 833312fec14SDave Airlie } else if (passcnt >= CBR_THRESHOLD) { 834312fec14SDave Airlie break; 835312fec14SDave Airlie } 836312fec14SDave Airlie } 837318cfa29SDave Airlie if (retry++ > 10) 838318cfa29SDave Airlie goto CBR_DONE2; 839312fec14SDave Airlie if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) { 840312fec14SDave Airlie goto CBR_START2; 841312fec14SDave Airlie } 842312fec14SDave Airlie if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) { 843312fec14SDave Airlie goto CBR_START2; 844312fec14SDave Airlie } 845318cfa29SDave Airlie status = true; 846318cfa29SDave Airlie CBR_DONE2: 847312fec14SDave Airlie dlli = (dllmin[1] + dllmax[1]) >> 1; 848312fec14SDave Airlie dlli <<= 8; 849312fec14SDave Airlie dlli += (dllmin[0] + dllmax[0]) >> 1; 8500e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16)); 851318cfa29SDave Airlie return status; 852312fec14SDave Airlie } /* CBRDLL2 */ 853312fec14SDave Airlie 854312fec14SDave Airlie static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param) 855312fec14SDave Airlie { 856312fec14SDave Airlie u32 trap, trap_AC2, trap_MRS; 857312fec14SDave Airlie 8580e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 859312fec14SDave Airlie 860312fec14SDave Airlie /* Ger trap info */ 8610e5ce924SDave Airlie trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 862312fec14SDave Airlie trap_AC2 = 0x00020000 + (trap << 16); 863312fec14SDave Airlie trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19); 864312fec14SDave Airlie trap_MRS = 0x00000010 + (trap << 4); 865312fec14SDave Airlie trap_MRS |= ((trap & 0x2) << 18); 866312fec14SDave Airlie 867312fec14SDave Airlie param->reg_MADJ = 0x00034C4C; 868312fec14SDave Airlie param->reg_SADJ = 0x00001800; 869312fec14SDave Airlie param->reg_DRV = 0x000000F0; 870312fec14SDave Airlie param->reg_PERIOD = param->dram_freq; 871312fec14SDave Airlie param->rodt = 0; 872312fec14SDave Airlie 873312fec14SDave Airlie switch (param->dram_freq) { 874312fec14SDave Airlie case 336: 8750e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0190); 876312fec14SDave Airlie param->wodt = 0; 877312fec14SDave Airlie param->reg_AC1 = 0x22202725; 878312fec14SDave Airlie param->reg_AC2 = 0xAA007613 | trap_AC2; 879312fec14SDave Airlie param->reg_DQSIC = 0x000000BA; 880312fec14SDave Airlie param->reg_MRS = 0x04001400 | trap_MRS; 881312fec14SDave Airlie param->reg_EMRS = 0x00000000; 882318cfa29SDave Airlie param->reg_IOZ = 0x00000023; 883312fec14SDave Airlie param->reg_DQIDLY = 0x00000074; 884312fec14SDave Airlie param->reg_FREQ = 0x00004DC0; 885312fec14SDave Airlie param->madj_max = 96; 886312fec14SDave Airlie param->dll2_finetune_step = 3; 887318cfa29SDave Airlie switch (param->dram_chipid) { 888318cfa29SDave Airlie default: 889318cfa29SDave Airlie case AST_DRAM_512Mx16: 890318cfa29SDave Airlie case AST_DRAM_1Gx16: 891318cfa29SDave Airlie param->reg_AC2 = 0xAA007613 | trap_AC2; 892318cfa29SDave Airlie break; 893318cfa29SDave Airlie case AST_DRAM_2Gx16: 894318cfa29SDave Airlie param->reg_AC2 = 0xAA00761C | trap_AC2; 895318cfa29SDave Airlie break; 896318cfa29SDave Airlie case AST_DRAM_4Gx16: 897318cfa29SDave Airlie param->reg_AC2 = 0xAA007636 | trap_AC2; 898318cfa29SDave Airlie break; 899318cfa29SDave Airlie } 900312fec14SDave Airlie break; 901312fec14SDave Airlie default: 902312fec14SDave Airlie case 396: 9030e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x03F1); 904312fec14SDave Airlie param->wodt = 1; 905312fec14SDave Airlie param->reg_AC1 = 0x33302825; 906312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 907312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 908312fec14SDave Airlie param->reg_MRS = 0x04001600 | trap_MRS; 909312fec14SDave Airlie param->reg_EMRS = 0x00000000; 910312fec14SDave Airlie param->reg_IOZ = 0x00000034; 911312fec14SDave Airlie param->reg_DRV = 0x000000FA; 912312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 913318cfa29SDave Airlie param->reg_FREQ = 0x00005040; 914312fec14SDave Airlie param->madj_max = 96; 915312fec14SDave Airlie param->dll2_finetune_step = 4; 916312fec14SDave Airlie 917312fec14SDave Airlie switch (param->dram_chipid) { 918312fec14SDave Airlie default: 919312fec14SDave Airlie case AST_DRAM_512Mx16: 920312fec14SDave Airlie case AST_DRAM_1Gx16: 921312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 922312fec14SDave Airlie break; 923312fec14SDave Airlie case AST_DRAM_2Gx16: 924312fec14SDave Airlie param->reg_AC2 = 0xCC009622 | trap_AC2; 925312fec14SDave Airlie break; 926312fec14SDave Airlie case AST_DRAM_4Gx16: 927312fec14SDave Airlie param->reg_AC2 = 0xCC00963F | trap_AC2; 928312fec14SDave Airlie break; 929312fec14SDave Airlie } 930312fec14SDave Airlie break; 931312fec14SDave Airlie 932312fec14SDave Airlie case 408: 9330e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x01F0); 934312fec14SDave Airlie param->wodt = 1; 935312fec14SDave Airlie param->reg_AC1 = 0x33302825; 936312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 937312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 938312fec14SDave Airlie param->reg_MRS = 0x04001600 | trap_MRS; 939312fec14SDave Airlie param->reg_EMRS = 0x00000000; 940318cfa29SDave Airlie param->reg_IOZ = 0x00000023; 941312fec14SDave Airlie param->reg_DRV = 0x000000FA; 942312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 943312fec14SDave Airlie param->reg_FREQ = 0x000050C0; 944312fec14SDave Airlie param->madj_max = 96; 945312fec14SDave Airlie param->dll2_finetune_step = 4; 946312fec14SDave Airlie 947312fec14SDave Airlie switch (param->dram_chipid) { 948312fec14SDave Airlie default: 949312fec14SDave Airlie case AST_DRAM_512Mx16: 950312fec14SDave Airlie case AST_DRAM_1Gx16: 951312fec14SDave Airlie param->reg_AC2 = 0xCC009617 | trap_AC2; 952312fec14SDave Airlie break; 953312fec14SDave Airlie case AST_DRAM_2Gx16: 954312fec14SDave Airlie param->reg_AC2 = 0xCC009622 | trap_AC2; 955312fec14SDave Airlie break; 956312fec14SDave Airlie case AST_DRAM_4Gx16: 957312fec14SDave Airlie param->reg_AC2 = 0xCC00963F | trap_AC2; 958312fec14SDave Airlie break; 959312fec14SDave Airlie } 960312fec14SDave Airlie 961312fec14SDave Airlie break; 962312fec14SDave Airlie case 456: 9630e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0230); 964312fec14SDave Airlie param->wodt = 0; 965312fec14SDave Airlie param->reg_AC1 = 0x33302926; 966312fec14SDave Airlie param->reg_AC2 = 0xCD44961A; 967312fec14SDave Airlie param->reg_DQSIC = 0x000000FC; 968312fec14SDave Airlie param->reg_MRS = 0x00081830; 969312fec14SDave Airlie param->reg_EMRS = 0x00000000; 970312fec14SDave Airlie param->reg_IOZ = 0x00000045; 971312fec14SDave Airlie param->reg_DQIDLY = 0x00000097; 972312fec14SDave Airlie param->reg_FREQ = 0x000052C0; 973312fec14SDave Airlie param->madj_max = 88; 974312fec14SDave Airlie param->dll2_finetune_step = 4; 975312fec14SDave Airlie break; 976312fec14SDave Airlie case 504: 9770e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0270); 978312fec14SDave Airlie param->wodt = 1; 979312fec14SDave Airlie param->reg_AC1 = 0x33302926; 980312fec14SDave Airlie param->reg_AC2 = 0xDE44A61D; 981312fec14SDave Airlie param->reg_DQSIC = 0x00000117; 982312fec14SDave Airlie param->reg_MRS = 0x00081A30; 983312fec14SDave Airlie param->reg_EMRS = 0x00000000; 984312fec14SDave Airlie param->reg_IOZ = 0x070000BB; 985312fec14SDave Airlie param->reg_DQIDLY = 0x000000A0; 986312fec14SDave Airlie param->reg_FREQ = 0x000054C0; 987312fec14SDave Airlie param->madj_max = 79; 988312fec14SDave Airlie param->dll2_finetune_step = 4; 989312fec14SDave Airlie break; 990312fec14SDave Airlie case 528: 9910e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0290); 992312fec14SDave Airlie param->wodt = 1; 993312fec14SDave Airlie param->rodt = 1; 994312fec14SDave Airlie param->reg_AC1 = 0x33302926; 995312fec14SDave Airlie param->reg_AC2 = 0xEF44B61E; 996312fec14SDave Airlie param->reg_DQSIC = 0x00000125; 997312fec14SDave Airlie param->reg_MRS = 0x00081A30; 998312fec14SDave Airlie param->reg_EMRS = 0x00000040; 999312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1000312fec14SDave Airlie param->reg_IOZ = 0x00000023; 1001312fec14SDave Airlie param->reg_DQIDLY = 0x00000088; 1002312fec14SDave Airlie param->reg_FREQ = 0x000055C0; 1003312fec14SDave Airlie param->madj_max = 76; 1004312fec14SDave Airlie param->dll2_finetune_step = 3; 1005312fec14SDave Airlie break; 1006312fec14SDave Airlie case 576: 10070e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0140); 1008312fec14SDave Airlie param->reg_MADJ = 0x00136868; 1009312fec14SDave Airlie param->reg_SADJ = 0x00004534; 1010312fec14SDave Airlie param->wodt = 1; 1011312fec14SDave Airlie param->rodt = 1; 1012312fec14SDave Airlie param->reg_AC1 = 0x33302A37; 1013312fec14SDave Airlie param->reg_AC2 = 0xEF56B61E; 1014312fec14SDave Airlie param->reg_DQSIC = 0x0000013F; 1015312fec14SDave Airlie param->reg_MRS = 0x00101A50; 1016312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1017312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1018312fec14SDave Airlie param->reg_IOZ = 0x00000023; 1019312fec14SDave Airlie param->reg_DQIDLY = 0x00000078; 1020312fec14SDave Airlie param->reg_FREQ = 0x000057C0; 1021312fec14SDave Airlie param->madj_max = 136; 1022312fec14SDave Airlie param->dll2_finetune_step = 3; 1023312fec14SDave Airlie break; 1024312fec14SDave Airlie case 600: 10250e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x02E1); 1026312fec14SDave Airlie param->reg_MADJ = 0x00136868; 1027312fec14SDave Airlie param->reg_SADJ = 0x00004534; 1028312fec14SDave Airlie param->wodt = 1; 1029312fec14SDave Airlie param->rodt = 1; 1030312fec14SDave Airlie param->reg_AC1 = 0x32302A37; 1031312fec14SDave Airlie param->reg_AC2 = 0xDF56B61F; 1032312fec14SDave Airlie param->reg_DQSIC = 0x0000014D; 1033312fec14SDave Airlie param->reg_MRS = 0x00101A50; 1034312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1035312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1036312fec14SDave Airlie param->reg_IOZ = 0x00000023; 1037312fec14SDave Airlie param->reg_DQIDLY = 0x00000078; 1038312fec14SDave Airlie param->reg_FREQ = 0x000058C0; 1039312fec14SDave Airlie param->madj_max = 132; 1040312fec14SDave Airlie param->dll2_finetune_step = 3; 1041312fec14SDave Airlie break; 1042312fec14SDave Airlie case 624: 10430e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0160); 1044312fec14SDave Airlie param->reg_MADJ = 0x00136868; 1045312fec14SDave Airlie param->reg_SADJ = 0x00004534; 1046312fec14SDave Airlie param->wodt = 1; 1047312fec14SDave Airlie param->rodt = 1; 1048312fec14SDave Airlie param->reg_AC1 = 0x32302A37; 1049312fec14SDave Airlie param->reg_AC2 = 0xEF56B621; 1050312fec14SDave Airlie param->reg_DQSIC = 0x0000015A; 1051312fec14SDave Airlie param->reg_MRS = 0x02101A50; 1052312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1053312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1054312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1055312fec14SDave Airlie param->reg_DQIDLY = 0x00000078; 1056312fec14SDave Airlie param->reg_FREQ = 0x000059C0; 1057312fec14SDave Airlie param->madj_max = 128; 1058312fec14SDave Airlie param->dll2_finetune_step = 3; 1059312fec14SDave Airlie break; 1060312fec14SDave Airlie } /* switch freq */ 1061312fec14SDave Airlie 1062312fec14SDave Airlie switch (param->dram_chipid) { 1063312fec14SDave Airlie case AST_DRAM_512Mx16: 1064312fec14SDave Airlie param->dram_config = 0x130; 1065312fec14SDave Airlie break; 1066312fec14SDave Airlie default: 1067312fec14SDave Airlie case AST_DRAM_1Gx16: 1068312fec14SDave Airlie param->dram_config = 0x131; 1069312fec14SDave Airlie break; 1070312fec14SDave Airlie case AST_DRAM_2Gx16: 1071312fec14SDave Airlie param->dram_config = 0x132; 1072312fec14SDave Airlie break; 1073312fec14SDave Airlie case AST_DRAM_4Gx16: 1074312fec14SDave Airlie param->dram_config = 0x133; 1075312fec14SDave Airlie break; 107610d9b4edSDamien Lespiau } /* switch size */ 1077312fec14SDave Airlie 1078312fec14SDave Airlie switch (param->vram_size) { 1079312fec14SDave Airlie default: 1080312fec14SDave Airlie case AST_VIDMEM_SIZE_8M: 1081312fec14SDave Airlie param->dram_config |= 0x00; 1082312fec14SDave Airlie break; 1083312fec14SDave Airlie case AST_VIDMEM_SIZE_16M: 1084312fec14SDave Airlie param->dram_config |= 0x04; 1085312fec14SDave Airlie break; 1086312fec14SDave Airlie case AST_VIDMEM_SIZE_32M: 1087312fec14SDave Airlie param->dram_config |= 0x08; 1088312fec14SDave Airlie break; 1089312fec14SDave Airlie case AST_VIDMEM_SIZE_64M: 1090312fec14SDave Airlie param->dram_config |= 0x0c; 1091312fec14SDave Airlie break; 1092312fec14SDave Airlie } 1093312fec14SDave Airlie 1094312fec14SDave Airlie } 1095312fec14SDave Airlie 1096312fec14SDave Airlie static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param) 1097312fec14SDave Airlie { 1098318cfa29SDave Airlie u32 data, data2, retry = 0; 1099312fec14SDave Airlie 1100318cfa29SDave Airlie ddr3_init_start: 11010e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0000, 0xFC600309); 11020e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, 0x00000100); 11030e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0024, 0x00000000); 11040e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0034, 0x00000000); 1105312fec14SDave Airlie udelay(10); 11060e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 11070e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 1108312fec14SDave Airlie udelay(10); 11090e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 1110312fec14SDave Airlie udelay(10); 1111312fec14SDave Airlie 11120e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0004, param->dram_config); 11130e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0008, 0x90040f); 11140e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1); 11150e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2); 11160e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 11170e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0080, 0x00000000); 11180e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0084, 0x00000000); 11190e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 11200e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, 0x4000A170); 11210e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, 0x00002370); 11220e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0038, 0x00000000); 11230e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0040, 0xFF444444); 11240e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0044, 0x22222222); 11250e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0048, 0x22222222); 11260e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E004C, 0x00000002); 11270e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 11280e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 11290e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0054, 0); 11300e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV); 11310e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 11320e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 11330e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0074, 0x00000000); 11340e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0078, 0x00000000); 11350e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 1136312fec14SDave Airlie /* Wait MCLK2X lock to MCLK */ 1137312fec14SDave Airlie do { 11380e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1139312fec14SDave Airlie } while (!(data & 0x08000000)); 11400e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1141312fec14SDave Airlie data = (data >> 8) & 0xff; 1142312fec14SDave Airlie while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 11430e5ce924SDave Airlie data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 1144312fec14SDave Airlie if ((data2 & 0xff) > param->madj_max) { 1145312fec14SDave Airlie break; 1146312fec14SDave Airlie } 11470e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, data2); 1148312fec14SDave Airlie if (data2 & 0x00100000) { 1149312fec14SDave Airlie data2 = ((data2 & 0xff) >> 3) + 3; 1150312fec14SDave Airlie } else { 1151312fec14SDave Airlie data2 = ((data2 & 0xff) >> 2) + 5; 1152312fec14SDave Airlie } 11530e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff; 1154312fec14SDave Airlie data2 += data & 0xff; 1155312fec14SDave Airlie data = data | (data2 << 8); 11560e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, data); 1157312fec14SDave Airlie udelay(10); 11580e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000); 1159312fec14SDave Airlie udelay(10); 11600e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 11610e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, data); 1162312fec14SDave Airlie data = data | 0x200; 11630e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, data); 1164312fec14SDave Airlie do { 11650e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1166312fec14SDave Airlie } while (!(data & 0x08000000)); 1167312fec14SDave Airlie 11680e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1169312fec14SDave Airlie data = (data >> 8) & 0xff; 1170312fec14SDave Airlie } 11710e5ce924SDave Airlie ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff); 11720e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0018) | 0xC00; 11730e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, data); 1174312fec14SDave Airlie 11750e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0034, 0x00000001); 11760e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, 0x00000040); 1177312fec14SDave Airlie udelay(50); 1178312fec14SDave Airlie /* Mode Register Setting */ 11790e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 11800e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 11810e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000005); 11820e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000007); 11830e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 11840e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 11850e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS); 11860e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, 0x00005C08); 11870e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 1188312fec14SDave Airlie 11890e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, 0x00005C01); 1190312fec14SDave Airlie data = 0; 1191312fec14SDave Airlie if (param->wodt) { 1192312fec14SDave Airlie data = 0x300; 1193312fec14SDave Airlie } 1194312fec14SDave Airlie if (param->rodt) { 1195312fec14SDave Airlie data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 1196312fec14SDave Airlie } 11970e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0034, data | 0x3); 1198312fec14SDave Airlie 1199312fec14SDave Airlie /* Calibrate the DQSI delay */ 1200318cfa29SDave Airlie if ((cbr_dll2(ast, param) == false) && (retry++ < 10)) 1201318cfa29SDave Airlie goto ddr3_init_start; 1202312fec14SDave Airlie 12030e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 1204312fec14SDave Airlie /* ECC Memory Initialization */ 1205312fec14SDave Airlie #ifdef ECC 12060e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 12070e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0070, 0x221); 1208312fec14SDave Airlie do { 12090e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0070); 1210312fec14SDave Airlie } while (!(data & 0x00001000)); 12110e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 12120e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 12130e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 1214312fec14SDave Airlie #endif 1215312fec14SDave Airlie 1216312fec14SDave Airlie 1217312fec14SDave Airlie } 1218312fec14SDave Airlie 1219312fec14SDave Airlie static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param) 1220312fec14SDave Airlie { 1221312fec14SDave Airlie u32 trap, trap_AC2, trap_MRS; 1222312fec14SDave Airlie 12230e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 1224312fec14SDave Airlie 1225312fec14SDave Airlie /* Ger trap info */ 12260e5ce924SDave Airlie trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 1227312fec14SDave Airlie trap_AC2 = (trap << 20) | (trap << 16); 1228312fec14SDave Airlie trap_AC2 += 0x00110000; 1229312fec14SDave Airlie trap_MRS = 0x00000040 | (trap << 4); 1230312fec14SDave Airlie 1231312fec14SDave Airlie 1232312fec14SDave Airlie param->reg_MADJ = 0x00034C4C; 1233312fec14SDave Airlie param->reg_SADJ = 0x00001800; 1234312fec14SDave Airlie param->reg_DRV = 0x000000F0; 1235312fec14SDave Airlie param->reg_PERIOD = param->dram_freq; 1236312fec14SDave Airlie param->rodt = 0; 1237312fec14SDave Airlie 1238312fec14SDave Airlie switch (param->dram_freq) { 1239312fec14SDave Airlie case 264: 12400e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0130); 1241312fec14SDave Airlie param->wodt = 0; 1242312fec14SDave Airlie param->reg_AC1 = 0x11101513; 1243312fec14SDave Airlie param->reg_AC2 = 0x78117011; 1244312fec14SDave Airlie param->reg_DQSIC = 0x00000092; 1245312fec14SDave Airlie param->reg_MRS = 0x00000842; 1246312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1247312fec14SDave Airlie param->reg_DRV = 0x000000F0; 1248312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1249312fec14SDave Airlie param->reg_DQIDLY = 0x0000005A; 1250312fec14SDave Airlie param->reg_FREQ = 0x00004AC0; 1251312fec14SDave Airlie param->madj_max = 138; 1252312fec14SDave Airlie param->dll2_finetune_step = 3; 1253312fec14SDave Airlie break; 1254312fec14SDave Airlie case 336: 12550e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0190); 1256312fec14SDave Airlie param->wodt = 1; 1257312fec14SDave Airlie param->reg_AC1 = 0x22202613; 1258312fec14SDave Airlie param->reg_AC2 = 0xAA009016 | trap_AC2; 1259312fec14SDave Airlie param->reg_DQSIC = 0x000000BA; 1260312fec14SDave Airlie param->reg_MRS = 0x00000A02 | trap_MRS; 1261312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1262312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1263312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1264312fec14SDave Airlie param->reg_DQIDLY = 0x00000074; 1265312fec14SDave Airlie param->reg_FREQ = 0x00004DC0; 1266312fec14SDave Airlie param->madj_max = 96; 1267312fec14SDave Airlie param->dll2_finetune_step = 3; 1268318cfa29SDave Airlie switch (param->dram_chipid) { 1269318cfa29SDave Airlie default: 1270318cfa29SDave Airlie case AST_DRAM_512Mx16: 1271318cfa29SDave Airlie param->reg_AC2 = 0xAA009012 | trap_AC2; 1272318cfa29SDave Airlie break; 1273318cfa29SDave Airlie case AST_DRAM_1Gx16: 1274318cfa29SDave Airlie param->reg_AC2 = 0xAA009016 | trap_AC2; 1275318cfa29SDave Airlie break; 1276318cfa29SDave Airlie case AST_DRAM_2Gx16: 1277318cfa29SDave Airlie param->reg_AC2 = 0xAA009023 | trap_AC2; 1278318cfa29SDave Airlie break; 1279318cfa29SDave Airlie case AST_DRAM_4Gx16: 1280318cfa29SDave Airlie param->reg_AC2 = 0xAA00903B | trap_AC2; 1281318cfa29SDave Airlie break; 1282318cfa29SDave Airlie } 1283312fec14SDave Airlie break; 1284312fec14SDave Airlie default: 1285312fec14SDave Airlie case 396: 12860e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x03F1); 1287312fec14SDave Airlie param->wodt = 1; 1288312fec14SDave Airlie param->rodt = 0; 1289312fec14SDave Airlie param->reg_AC1 = 0x33302714; 1290312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1291312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 1292312fec14SDave Airlie param->reg_MRS = 0x00000C02 | trap_MRS; 1293312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1294312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1295312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1296312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 1297318cfa29SDave Airlie param->reg_FREQ = 0x00005040; 1298312fec14SDave Airlie param->madj_max = 96; 1299312fec14SDave Airlie param->dll2_finetune_step = 4; 1300312fec14SDave Airlie 1301312fec14SDave Airlie switch (param->dram_chipid) { 1302312fec14SDave Airlie case AST_DRAM_512Mx16: 1303312fec14SDave Airlie param->reg_AC2 = 0xCC00B016 | trap_AC2; 1304312fec14SDave Airlie break; 1305312fec14SDave Airlie default: 1306312fec14SDave Airlie case AST_DRAM_1Gx16: 1307312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1308312fec14SDave Airlie break; 1309312fec14SDave Airlie case AST_DRAM_2Gx16: 1310312fec14SDave Airlie param->reg_AC2 = 0xCC00B02B | trap_AC2; 1311312fec14SDave Airlie break; 1312312fec14SDave Airlie case AST_DRAM_4Gx16: 1313312fec14SDave Airlie param->reg_AC2 = 0xCC00B03F | trap_AC2; 1314312fec14SDave Airlie break; 1315312fec14SDave Airlie } 1316312fec14SDave Airlie 1317312fec14SDave Airlie break; 1318312fec14SDave Airlie 1319312fec14SDave Airlie case 408: 13200e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x01F0); 1321312fec14SDave Airlie param->wodt = 1; 1322312fec14SDave Airlie param->rodt = 0; 1323312fec14SDave Airlie param->reg_AC1 = 0x33302714; 1324312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1325312fec14SDave Airlie param->reg_DQSIC = 0x000000E2; 1326312fec14SDave Airlie param->reg_MRS = 0x00000C02 | trap_MRS; 1327312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1328312fec14SDave Airlie param->reg_DRV = 0x000000FA; 1329312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1330312fec14SDave Airlie param->reg_DQIDLY = 0x00000089; 1331312fec14SDave Airlie param->reg_FREQ = 0x000050C0; 1332312fec14SDave Airlie param->madj_max = 96; 1333312fec14SDave Airlie param->dll2_finetune_step = 4; 1334312fec14SDave Airlie 1335312fec14SDave Airlie switch (param->dram_chipid) { 1336312fec14SDave Airlie case AST_DRAM_512Mx16: 1337312fec14SDave Airlie param->reg_AC2 = 0xCC00B016 | trap_AC2; 1338312fec14SDave Airlie break; 1339312fec14SDave Airlie default: 1340312fec14SDave Airlie case AST_DRAM_1Gx16: 1341312fec14SDave Airlie param->reg_AC2 = 0xCC00B01B | trap_AC2; 1342312fec14SDave Airlie break; 1343312fec14SDave Airlie case AST_DRAM_2Gx16: 1344312fec14SDave Airlie param->reg_AC2 = 0xCC00B02B | trap_AC2; 1345312fec14SDave Airlie break; 1346312fec14SDave Airlie case AST_DRAM_4Gx16: 1347312fec14SDave Airlie param->reg_AC2 = 0xCC00B03F | trap_AC2; 1348312fec14SDave Airlie break; 1349312fec14SDave Airlie } 1350312fec14SDave Airlie 1351312fec14SDave Airlie break; 1352312fec14SDave Airlie case 456: 13530e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0230); 1354312fec14SDave Airlie param->wodt = 0; 1355312fec14SDave Airlie param->reg_AC1 = 0x33302815; 1356312fec14SDave Airlie param->reg_AC2 = 0xCD44B01E; 1357312fec14SDave Airlie param->reg_DQSIC = 0x000000FC; 1358312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1359312fec14SDave Airlie param->reg_EMRS = 0x00000000; 1360312fec14SDave Airlie param->reg_DRV = 0x00000000; 1361312fec14SDave Airlie param->reg_IOZ = 0x00000034; 1362312fec14SDave Airlie param->reg_DQIDLY = 0x00000097; 1363312fec14SDave Airlie param->reg_FREQ = 0x000052C0; 1364312fec14SDave Airlie param->madj_max = 88; 1365312fec14SDave Airlie param->dll2_finetune_step = 3; 1366312fec14SDave Airlie break; 1367312fec14SDave Airlie case 504: 13680e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0261); 1369312fec14SDave Airlie param->wodt = 1; 1370312fec14SDave Airlie param->rodt = 1; 1371312fec14SDave Airlie param->reg_AC1 = 0x33302815; 1372312fec14SDave Airlie param->reg_AC2 = 0xDE44C022; 1373312fec14SDave Airlie param->reg_DQSIC = 0x00000117; 1374312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1375312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1376312fec14SDave Airlie param->reg_DRV = 0x0000000A; 1377312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1378312fec14SDave Airlie param->reg_DQIDLY = 0x000000A0; 1379312fec14SDave Airlie param->reg_FREQ = 0x000054C0; 1380312fec14SDave Airlie param->madj_max = 79; 1381312fec14SDave Airlie param->dll2_finetune_step = 3; 1382312fec14SDave Airlie break; 1383312fec14SDave Airlie case 528: 13840e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0120); 1385312fec14SDave Airlie param->wodt = 1; 1386312fec14SDave Airlie param->rodt = 1; 1387312fec14SDave Airlie param->reg_AC1 = 0x33302815; 1388312fec14SDave Airlie param->reg_AC2 = 0xEF44D024; 1389312fec14SDave Airlie param->reg_DQSIC = 0x00000125; 1390312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1391312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1392312fec14SDave Airlie param->reg_DRV = 0x000000F9; 1393312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1394312fec14SDave Airlie param->reg_DQIDLY = 0x000000A7; 1395312fec14SDave Airlie param->reg_FREQ = 0x000055C0; 1396312fec14SDave Airlie param->madj_max = 76; 1397312fec14SDave Airlie param->dll2_finetune_step = 3; 1398312fec14SDave Airlie break; 1399312fec14SDave Airlie case 552: 14000e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x02A1); 1401312fec14SDave Airlie param->wodt = 1; 1402312fec14SDave Airlie param->rodt = 1; 1403312fec14SDave Airlie param->reg_AC1 = 0x43402915; 1404312fec14SDave Airlie param->reg_AC2 = 0xFF44E025; 1405312fec14SDave Airlie param->reg_DQSIC = 0x00000132; 1406312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1407312fec14SDave Airlie param->reg_EMRS = 0x00000040; 1408312fec14SDave Airlie param->reg_DRV = 0x0000000A; 1409312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1410312fec14SDave Airlie param->reg_DQIDLY = 0x000000AD; 1411312fec14SDave Airlie param->reg_FREQ = 0x000056C0; 1412312fec14SDave Airlie param->madj_max = 76; 1413312fec14SDave Airlie param->dll2_finetune_step = 3; 1414312fec14SDave Airlie break; 1415312fec14SDave Airlie case 576: 14160e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E2020, 0x0140); 1417312fec14SDave Airlie param->wodt = 1; 1418312fec14SDave Airlie param->rodt = 1; 1419312fec14SDave Airlie param->reg_AC1 = 0x43402915; 1420312fec14SDave Airlie param->reg_AC2 = 0xFF44E027; 1421312fec14SDave Airlie param->reg_DQSIC = 0x0000013F; 1422312fec14SDave Airlie param->reg_MRS = 0x00000E72; 1423312fec14SDave Airlie param->reg_EMRS = 0x00000004; 1424312fec14SDave Airlie param->reg_DRV = 0x000000F5; 1425312fec14SDave Airlie param->reg_IOZ = 0x00000045; 1426312fec14SDave Airlie param->reg_DQIDLY = 0x000000B3; 1427312fec14SDave Airlie param->reg_FREQ = 0x000057C0; 1428312fec14SDave Airlie param->madj_max = 76; 1429312fec14SDave Airlie param->dll2_finetune_step = 3; 1430312fec14SDave Airlie break; 1431312fec14SDave Airlie } 1432312fec14SDave Airlie 1433312fec14SDave Airlie switch (param->dram_chipid) { 1434312fec14SDave Airlie case AST_DRAM_512Mx16: 1435312fec14SDave Airlie param->dram_config = 0x100; 1436312fec14SDave Airlie break; 1437312fec14SDave Airlie default: 1438312fec14SDave Airlie case AST_DRAM_1Gx16: 1439312fec14SDave Airlie param->dram_config = 0x121; 1440312fec14SDave Airlie break; 1441312fec14SDave Airlie case AST_DRAM_2Gx16: 1442312fec14SDave Airlie param->dram_config = 0x122; 1443312fec14SDave Airlie break; 1444312fec14SDave Airlie case AST_DRAM_4Gx16: 1445312fec14SDave Airlie param->dram_config = 0x123; 1446312fec14SDave Airlie break; 144710d9b4edSDamien Lespiau } /* switch size */ 1448312fec14SDave Airlie 1449312fec14SDave Airlie switch (param->vram_size) { 1450312fec14SDave Airlie default: 1451312fec14SDave Airlie case AST_VIDMEM_SIZE_8M: 1452312fec14SDave Airlie param->dram_config |= 0x00; 1453312fec14SDave Airlie break; 1454312fec14SDave Airlie case AST_VIDMEM_SIZE_16M: 1455312fec14SDave Airlie param->dram_config |= 0x04; 1456312fec14SDave Airlie break; 1457312fec14SDave Airlie case AST_VIDMEM_SIZE_32M: 1458312fec14SDave Airlie param->dram_config |= 0x08; 1459312fec14SDave Airlie break; 1460312fec14SDave Airlie case AST_VIDMEM_SIZE_64M: 1461312fec14SDave Airlie param->dram_config |= 0x0c; 1462312fec14SDave Airlie break; 1463312fec14SDave Airlie } 1464312fec14SDave Airlie } 1465312fec14SDave Airlie 1466312fec14SDave Airlie static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param) 1467312fec14SDave Airlie { 1468318cfa29SDave Airlie u32 data, data2, retry = 0; 1469312fec14SDave Airlie 1470318cfa29SDave Airlie ddr2_init_start: 14710e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0000, 0xFC600309); 14720e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, 0x00000100); 14730e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0024, 0x00000000); 14740e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 14750e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 1476312fec14SDave Airlie udelay(10); 14770e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 1478312fec14SDave Airlie udelay(10); 1479312fec14SDave Airlie 14800e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0004, param->dram_config); 14810e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0008, 0x90040f); 14820e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1); 14830e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2); 14840e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 14850e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0080, 0x00000000); 14860e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0084, 0x00000000); 14870e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 14880e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, 0x4000A130); 14890e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, 0x00002330); 14900e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0038, 0x00000000); 14910e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0040, 0xFF808000); 14920e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0044, 0x88848466); 14930e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0048, 0x44440008); 14940e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E004C, 0x00000000); 14950e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 14960e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 14970e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0054, 0); 14980e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV); 14990e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 15000e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 15010e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0074, 0x00000000); 15020e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0078, 0x00000000); 15030e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 1504312fec14SDave Airlie 1505312fec14SDave Airlie /* Wait MCLK2X lock to MCLK */ 1506312fec14SDave Airlie do { 15070e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1508312fec14SDave Airlie } while (!(data & 0x08000000)); 15090e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1510312fec14SDave Airlie data = (data >> 8) & 0xff; 1511312fec14SDave Airlie while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 15120e5ce924SDave Airlie data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 1513312fec14SDave Airlie if ((data2 & 0xff) > param->madj_max) { 1514312fec14SDave Airlie break; 1515312fec14SDave Airlie } 15160e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, data2); 1517312fec14SDave Airlie if (data2 & 0x00100000) { 1518312fec14SDave Airlie data2 = ((data2 & 0xff) >> 3) + 3; 1519312fec14SDave Airlie } else { 1520312fec14SDave Airlie data2 = ((data2 & 0xff) >> 2) + 5; 1521312fec14SDave Airlie } 15220e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff; 1523312fec14SDave Airlie data2 += data & 0xff; 1524312fec14SDave Airlie data = data | (data2 << 8); 15250e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0068, data); 1526312fec14SDave Airlie udelay(10); 15270e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000); 1528312fec14SDave Airlie udelay(10); 15290e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 15300e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, data); 1531312fec14SDave Airlie data = data | 0x200; 15320e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, data); 1533312fec14SDave Airlie do { 15340e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1535312fec14SDave Airlie } while (!(data & 0x08000000)); 1536312fec14SDave Airlie 15370e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E001C); 1538312fec14SDave Airlie data = (data >> 8) & 0xff; 1539312fec14SDave Airlie } 15400e5ce924SDave Airlie ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff); 15410e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0018) | 0xC00; 15420e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0018, data); 1543312fec14SDave Airlie 15440e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0034, 0x00000001); 15450e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, 0x00000000); 1546312fec14SDave Airlie udelay(50); 1547312fec14SDave Airlie /* Mode Register Setting */ 15480e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 15490e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 15500e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000005); 15510e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000007); 15520e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 15530e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 1554312fec14SDave Airlie 15550e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, 0x00005C08); 15560e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS); 15570e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000001); 15580e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380); 15590e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 15600e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 15610e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0028, 0x00000003); 1562312fec14SDave Airlie 15630e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01); 1564312fec14SDave Airlie data = 0; 1565312fec14SDave Airlie if (param->wodt) { 1566312fec14SDave Airlie data = 0x500; 1567312fec14SDave Airlie } 1568312fec14SDave Airlie if (param->rodt) { 1569312fec14SDave Airlie data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 1570312fec14SDave Airlie } 15710e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0034, data | 0x3); 15720e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 1573312fec14SDave Airlie 1574312fec14SDave Airlie /* Calibrate the DQSI delay */ 1575318cfa29SDave Airlie if ((cbr_dll2(ast, param) == false) && (retry++ < 10)) 1576318cfa29SDave Airlie goto ddr2_init_start; 1577312fec14SDave Airlie 1578312fec14SDave Airlie /* ECC Memory Initialization */ 1579312fec14SDave Airlie #ifdef ECC 15800e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E007C, 0x00000000); 15810e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0070, 0x221); 1582312fec14SDave Airlie do { 15830e5ce924SDave Airlie data = ast_mindwm(ast, 0x1E6E0070); 1584312fec14SDave Airlie } while (!(data & 0x00001000)); 15850e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0070, 0x00000000); 15860e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x80000000); 15870e5ce924SDave Airlie ast_moutdwm(ast, 0x1E6E0050, 0x00000000); 1588312fec14SDave Airlie #endif 1589312fec14SDave Airlie 1590312fec14SDave Airlie } 1591312fec14SDave Airlie 1592d95618efSBenjamin Herrenschmidt static void ast_post_chip_2300(struct drm_device *dev) 1593312fec14SDave Airlie { 1594312fec14SDave Airlie struct ast_private *ast = dev->dev_private; 1595312fec14SDave Airlie struct ast2300_dram_param param; 1596312fec14SDave Airlie u32 temp; 1597312fec14SDave Airlie u8 reg; 1598312fec14SDave Airlie 1599312fec14SDave Airlie reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 1600312fec14SDave Airlie if ((reg & 0x80) == 0) {/* vga only */ 1601312fec14SDave Airlie ast_write32(ast, 0xf004, 0x1e6e0000); 1602312fec14SDave Airlie ast_write32(ast, 0xf000, 0x1); 1603312fec14SDave Airlie ast_write32(ast, 0x12000, 0x1688a8a8); 1604312fec14SDave Airlie do { 1605312fec14SDave Airlie ; 1606312fec14SDave Airlie } while (ast_read32(ast, 0x12000) != 0x1); 1607312fec14SDave Airlie 1608312fec14SDave Airlie ast_write32(ast, 0x10000, 0xfc600309); 1609312fec14SDave Airlie do { 1610312fec14SDave Airlie ; 1611312fec14SDave Airlie } while (ast_read32(ast, 0x10000) != 0x1); 1612312fec14SDave Airlie 1613312fec14SDave Airlie /* Slow down CPU/AHB CLK in VGA only mode */ 1614312fec14SDave Airlie temp = ast_read32(ast, 0x12008); 1615312fec14SDave Airlie temp |= 0x73; 1616312fec14SDave Airlie ast_write32(ast, 0x12008, temp); 1617312fec14SDave Airlie 16183856081eSY.C. Chen param.dram_freq = 396; 1619312fec14SDave Airlie param.dram_type = AST_DDR3; 16203856081eSY.C. Chen temp = ast_mindwm(ast, 0x1e6e2070); 1621312fec14SDave Airlie if (temp & 0x01000000) 1622312fec14SDave Airlie param.dram_type = AST_DDR2; 16233856081eSY.C. Chen switch (temp & 0x18000000) { 16243856081eSY.C. Chen case 0: 16253856081eSY.C. Chen param.dram_chipid = AST_DRAM_512Mx16; 16263856081eSY.C. Chen break; 16273856081eSY.C. Chen default: 16283856081eSY.C. Chen case 0x08000000: 16293856081eSY.C. Chen param.dram_chipid = AST_DRAM_1Gx16; 16303856081eSY.C. Chen break; 16313856081eSY.C. Chen case 0x10000000: 16323856081eSY.C. Chen param.dram_chipid = AST_DRAM_2Gx16; 16333856081eSY.C. Chen break; 16343856081eSY.C. Chen case 0x18000000: 16353856081eSY.C. Chen param.dram_chipid = AST_DRAM_4Gx16; 16363856081eSY.C. Chen break; 16373856081eSY.C. Chen } 16383856081eSY.C. Chen switch (temp & 0x0c) { 16393856081eSY.C. Chen default: 16403856081eSY.C. Chen case 0x00: 16413856081eSY.C. Chen param.vram_size = AST_VIDMEM_SIZE_8M; 16423856081eSY.C. Chen break; 16433856081eSY.C. Chen 16443856081eSY.C. Chen case 0x04: 16453856081eSY.C. Chen param.vram_size = AST_VIDMEM_SIZE_16M; 16463856081eSY.C. Chen break; 16473856081eSY.C. Chen 16483856081eSY.C. Chen case 0x08: 16493856081eSY.C. Chen param.vram_size = AST_VIDMEM_SIZE_32M; 16503856081eSY.C. Chen break; 16513856081eSY.C. Chen 16523856081eSY.C. Chen case 0x0c: 16533856081eSY.C. Chen param.vram_size = AST_VIDMEM_SIZE_64M; 16543856081eSY.C. Chen break; 16553856081eSY.C. Chen } 1656312fec14SDave Airlie 1657312fec14SDave Airlie if (param.dram_type == AST_DDR3) { 1658312fec14SDave Airlie get_ddr3_info(ast, ¶m); 1659312fec14SDave Airlie ddr3_init(ast, ¶m); 1660312fec14SDave Airlie } else { 1661312fec14SDave Airlie get_ddr2_info(ast, ¶m); 1662312fec14SDave Airlie ddr2_init(ast, ¶m); 1663312fec14SDave Airlie } 1664312fec14SDave Airlie 16650e5ce924SDave Airlie temp = ast_mindwm(ast, 0x1e6e2040); 16660e5ce924SDave Airlie ast_moutdwm(ast, 0x1e6e2040, temp | 0x40); 1667312fec14SDave Airlie } 1668312fec14SDave Airlie 1669312fec14SDave Airlie /* wait ready */ 1670312fec14SDave Airlie do { 1671312fec14SDave Airlie reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 1672312fec14SDave Airlie } while ((reg & 0x40) == 0); 1673312fec14SDave Airlie } 1674312fec14SDave Airlie 1675