| 1 | /* |
|---|
| 2 | * This file is part of the coreboot project. |
|---|
| 3 | * |
|---|
| 4 | * Copyright (C) 2007 Advanced Micro Devices, Inc. |
|---|
| 5 | * |
|---|
| 6 | * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | * it under the terms of the GNU General Public License version 2 as |
|---|
| 8 | * published by the Free Software Foundation. |
|---|
| 9 | * |
|---|
| 10 | * This program is distributed in the hope that it will be useful, |
|---|
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | * GNU General Public License for more details. |
|---|
| 14 | * |
|---|
| 15 | * You should have received a copy of the GNU General Public License |
|---|
| 16 | * along with this program; if not, write to the Free Software |
|---|
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 18 | */ |
|---|
| 19 | |
|---|
| 20 | #define ASSEMBLY 1 |
|---|
| 21 | |
|---|
| 22 | #include <stdint.h> |
|---|
| 23 | #include <spd.h> |
|---|
| 24 | #include <device/pci_def.h> |
|---|
| 25 | #include <arch/io.h> |
|---|
| 26 | #include <device/pnp_def.h> |
|---|
| 27 | #include <arch/romcc_io.h> |
|---|
| 28 | #include <arch/hlt.h> |
|---|
| 29 | #include "pc80/serial.c" |
|---|
| 30 | #include "arch/i386/lib/console.c" |
|---|
| 31 | #include "ram/ramtest.c" |
|---|
| 32 | #include "cpu/x86/bist.h" |
|---|
| 33 | #include "cpu/x86/msr.h" |
|---|
| 34 | #include <cpu/amd/lxdef.h> |
|---|
| 35 | #include <cpu/amd/geode_post_code.h> |
|---|
| 36 | #include "southbridge/amd/cs5536/cs5536.h" |
|---|
| 37 | |
|---|
| 38 | #define POST_CODE(x) outb(x, 0x80) |
|---|
| 39 | #define SERIAL_DEV PNP_DEV(0x2e, W83627HF_SP1) |
|---|
| 40 | |
|---|
| 41 | /* The ALIX1.C has no SMBus; the setup is hard-wired. */ |
|---|
| 42 | void cs5536_enable_smbus(void) |
|---|
| 43 | { |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | #include "southbridge/amd/cs5536/cs5536_early_setup.c" |
|---|
| 47 | #include "superio/winbond/w83627hf/w83627hf_early_serial.c" |
|---|
| 48 | |
|---|
| 49 | /* The part is a Hynix hy5du121622ctp-d43. |
|---|
| 50 | * |
|---|
| 51 | * HY 5D U 12 16 2 2 C <blank> T <blank> P D43 |
|---|
| 52 | * Hynix |
|---|
| 53 | * DDR SDRAM (5D) |
|---|
| 54 | * VDD 2.5 VDDQ 2.5 (U) |
|---|
| 55 | * 512M 8K REFRESH (12) |
|---|
| 56 | * x16 (16) |
|---|
| 57 | * 4banks (2) |
|---|
| 58 | * SSTL_2 (2) |
|---|
| 59 | * 4th GEN die (C) |
|---|
| 60 | * Normal Power Consumption (<blank> ) |
|---|
| 61 | * TSOP (T) |
|---|
| 62 | * Single Die (<blank>) |
|---|
| 63 | * Lead Free (P) |
|---|
| 64 | * DDR400 3-3-3 (D43) |
|---|
| 65 | */ |
|---|
| 66 | /* SPD array */ |
|---|
| 67 | static const u8 spdbytes[] = { |
|---|
| 68 | [SPD_ACCEPTABLE_CAS_LATENCIES] = 0x10, |
|---|
| 69 | [SPD_BANK_DENSITY] = 0x40, |
|---|
| 70 | [SPD_DEVICE_ATTRIBUTES_GENERAL] = 0xff, |
|---|
| 71 | [SPD_MEMORY_TYPE] = 7, |
|---|
| 72 | [SPD_MIN_CYCLE_TIME_AT_CAS_MAX] = 10, /* A guess for the tRAC value */ |
|---|
| 73 | [SPD_MODULE_ATTRIBUTES] = 0xff, /* FIXME later when we figure out. */ |
|---|
| 74 | [SPD_NUM_BANKS_PER_SDRAM] = 4, |
|---|
| 75 | [SPD_PRIMARY_SDRAM_WIDTH] = 8, |
|---|
| 76 | [SPD_NUM_DIMM_BANKS] = 1, /* ALIX1.C is 1 bank. */ |
|---|
| 77 | [SPD_NUM_COLUMNS] = 0xa, |
|---|
| 78 | [SPD_NUM_ROWS] = 3, |
|---|
| 79 | [SPD_REFRESH] = 0x3a, |
|---|
| 80 | [SPD_SDRAM_CYCLE_TIME_2ND] = 60, |
|---|
| 81 | [SPD_SDRAM_CYCLE_TIME_3RD] = 75, |
|---|
| 82 | [SPD_tRAS] = 40, |
|---|
| 83 | [SPD_tRCD] = 15, |
|---|
| 84 | [SPD_tRFC] = 70, |
|---|
| 85 | [SPD_tRP] = 15, |
|---|
| 86 | [SPD_tRRD] = 10, |
|---|
| 87 | }; |
|---|
| 88 | |
|---|
| 89 | static u8 spd_read_byte(u8 device, u8 address) |
|---|
| 90 | { |
|---|
| 91 | print_debug("spd_read_byte dev "); |
|---|
| 92 | print_debug_hex8(device); |
|---|
| 93 | |
|---|
| 94 | if (device != (0x50 << 1)) { |
|---|
| 95 | print_debug(" returns 0xff\n"); |
|---|
| 96 | return 0xff; |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | print_debug(" addr "); |
|---|
| 100 | print_debug_hex8(address); |
|---|
| 101 | print_debug(" returns "); |
|---|
| 102 | print_debug_hex8(spdbytes[address]); |
|---|
| 103 | print_debug("\r\n"); |
|---|
| 104 | |
|---|
| 105 | return spdbytes[address]; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | #define ManualConf 0 /* Do automatic strapped PLL config */ |
|---|
| 109 | #define PLLMSRhi 0x00001490 /* Manual settings for the PLL */ |
|---|
| 110 | #define PLLMSRlo 0x02000030 |
|---|
| 111 | |
|---|
| 112 | #define DIMM0 0xa0 |
|---|
| 113 | #define DIMM1 0xa2 |
|---|
| 114 | |
|---|
| 115 | #include "northbridge/amd/lx/raminit.h" |
|---|
| 116 | #include "northbridge/amd/lx/pll_reset.c" |
|---|
| 117 | #include "northbridge/amd/lx/raminit.c" |
|---|
| 118 | #include "sdram/generic_sdram.c" |
|---|
| 119 | #include "cpu/amd/model_lx/cpureginit.c" |
|---|
| 120 | #include "cpu/amd/model_lx/syspreinit.c" |
|---|
| 121 | |
|---|
| 122 | static void msr_init(void) |
|---|
| 123 | { |
|---|
| 124 | msr_t msr; |
|---|
| 125 | |
|---|
| 126 | /* Setup access to the MC for under 1MB. Note MC not setup yet. */ |
|---|
| 127 | msr.hi = 0x24fffc02; |
|---|
| 128 | msr.lo = 0x10010000; |
|---|
| 129 | wrmsr(CPU_RCONF_DEFAULT, msr); |
|---|
| 130 | |
|---|
| 131 | msr.hi = 0x20000000; |
|---|
| 132 | msr.lo = 0xfff00; |
|---|
| 133 | wrmsr(MSR_GLIU0 + 0x20, msr); |
|---|
| 134 | |
|---|
| 135 | msr.hi = 0x20000000; |
|---|
| 136 | msr.lo = 0xfff00; |
|---|
| 137 | wrmsr(MSR_GLIU1 + 0x20, msr); |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | /** Early mainboard specific GPIO setup. */ |
|---|
| 141 | static void mb_gpio_init(void) |
|---|
| 142 | { |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | void cache_as_ram_main(void) |
|---|
| 146 | { |
|---|
| 147 | static const struct mem_controller memctrl[] = { |
|---|
| 148 | {.channel0 = {0x50}}, |
|---|
| 149 | }; |
|---|
| 150 | |
|---|
| 151 | extern void RestartCAR(); |
|---|
| 152 | |
|---|
| 153 | POST_CODE(0x01); |
|---|
| 154 | |
|---|
| 155 | SystemPreInit(); |
|---|
| 156 | msr_init(); |
|---|
| 157 | |
|---|
| 158 | cs5536_early_setup(); |
|---|
| 159 | |
|---|
| 160 | /* NOTE: Must do this AFTER cs5536_early_setup()! |
|---|
| 161 | * It is counting on some early MSR setup for the CS5536. |
|---|
| 162 | */ |
|---|
| 163 | cs5536_disable_internal_uart(); |
|---|
| 164 | w83627hf_enable_serial(SERIAL_DEV, TTYS0_BASE); |
|---|
| 165 | mb_gpio_init(); |
|---|
| 166 | uart_init(); |
|---|
| 167 | console_init(); |
|---|
| 168 | |
|---|
| 169 | pll_reset(ManualConf); |
|---|
| 170 | |
|---|
| 171 | cpuRegInit(); |
|---|
| 172 | |
|---|
| 173 | sdram_initialize(1, memctrl); |
|---|
| 174 | |
|---|
| 175 | /* Check memory */ |
|---|
| 176 | /* Enable this only if you are having questions. */ |
|---|
| 177 | /* ram_check(0, 640 * 1024); */ |
|---|
| 178 | |
|---|
| 179 | /* Switch from Cache as RAM to real RAM. |
|---|
| 180 | * |
|---|
| 181 | * There are two ways we could think about this. |
|---|
| 182 | * |
|---|
| 183 | * 1. If we are using the auto.inc ROMCC way, the stack is |
|---|
| 184 | * going to be re-setup in the code following this code. Just |
|---|
| 185 | * wbinvd the stack to clear the cache tags. We don't care |
|---|
| 186 | * where the stack used to be. |
|---|
| 187 | * |
|---|
| 188 | * 2. This file is built as a normal .c -> .o and linked in |
|---|
| 189 | * etc. The stack might be used to return etc. That means we |
|---|
| 190 | * care about what is in the stack. If we are smart we set |
|---|
| 191 | * the CAR stack to the same location as the rest of |
|---|
| 192 | * coreboot. If that is the case we can just do a wbinvd. |
|---|
| 193 | * The stack will be written into real RAM that is now setup |
|---|
| 194 | * and we continue like nothing happened. If the stack is |
|---|
| 195 | * located somewhere other than where LB would like it, you |
|---|
| 196 | * need to write some code to do a copy from cache to RAM |
|---|
| 197 | * |
|---|
| 198 | * We use method 1 on Norwich and on this board too. |
|---|
| 199 | */ |
|---|
| 200 | POST_CODE(0x02); |
|---|
| 201 | print_err("POST 02\n"); |
|---|
| 202 | __asm__("wbinvd\n"); |
|---|
| 203 | print_err("Past wbinvd\n"); |
|---|
| 204 | |
|---|
| 205 | /* We are finding the return does not work on this board. Explicitly |
|---|
| 206 | * call the label that is after the call to us. This is gross, but |
|---|
| 207 | * sometimes at this level it is the only way out. |
|---|
| 208 | */ |
|---|
| 209 | done_cache_as_ram_main(); |
|---|
| 210 | } |
|---|