blob: b8997415f9db120fbdeffd25d70887decc251113 [file] [log] [blame]
Lee Leahy9fd08952016-02-02 07:17:06 -08001/** @file
2 *
3 * Copyright (C) 2015-2016, Intel Corporation
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of Intel Corporation nor the names of its contributors may
14 * be used to endorse or promote products derived from this software without
15 * specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGE.
28 *
29**/
30
31#include <cpu/x86/cr.h>
32#include <soc/QuarkNcSocId.h>
33
34.macro RET32
35 jmp *%esp
36.endm
37
38/* ROM/SPI/MEMORY Definitions */
39.equ QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000) /* Memory Base Address = 0 */
40.equ QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000) /* DDR3 Memory Size = 2GB */
41.equ QUARK_ESRAM_MEM_BASE_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS \
42 + QUARK_MAX_DDR3_MEM_SIZE_BYTES) /* eSRAM Memory above DDR3 */
43.equ QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000) /* eSRAM Memory Size = 512K */
44.equ QUARK_STACK_SIZE_BYTES, (0x008000) /* Quark stack size = 32K */
45.equ QUARK_STACK_BASE_ADDRESS, (QUARK_ESRAM_MEM_BASE_ADDRESS \
46 + QUARK_ESRAM_MEM_SIZE_BYTES \
47 - QUARK_STACK_SIZE_BYTES) /* Top of eSRAM - stack size */
48.equ QUARK_CMH_SIZE_BYTES, (0x0400) /* Quark Module Header size */
49.equ QUARK_ESRAM_STAGE1_BASE_ADDRESS, (QUARK_ESRAM_MEM_BASE_ADDRESS \
50 + QUARK_CMH_SIZE_BYTES) /* Start of Stage1 code in eSRAM */
51
52/* RTC/CMOS definitions */
53.equ RTC_INDEX, (0x70)
54.equ NMI_DISABLE, (0x80) /* Bit7=1 disables NMI */
55.equ RTC_DATA, (0x71)
56
57/* PCI Configuration definitions (Datasheet 5.5.1) */
58.equ PCI_CFG, (0x80000000) /* PCI configuration access mechanism */
59.equ PCI_ADDRESS_PORT, (0xCF8)
60.equ PCI_DATA_PORT, (0xCFC)
61
62/* Quark PCI devices */
63.equ HOST_BRIDGE_PFA, (0 << 11) /* B0:D0:F0 (Host Bridge) */
64.equ ILB_PFA, (0x1F << 11) /* B0:D31:F0 (Legacy Block) */
65
66/* ILB PCI Config Registers */
67.equ BDE, (0x0D4) /* BIOS Decode Enable register */
68.equ DECODE_ALL_REGIONS_ENABLE, (0xFF000000) /* Decode all BIOS ranges */
69
70/* iLB Reset Register */
71.equ ILB_RESET_REG, (0x0CF9)
72.equ CF9_WARM_RESET, (0x02)
73.equ CF9_COLD_RESET, (0x08)
74
75/* Memory Arbiter Config Registers */
76.equ AEC_CTRL_OFFSET, (0x00)
77
78/* Host Bridge Config Registers */
79.equ HMBOUND_OFFSET, (0x08)
80.equ HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS \
81 + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
82.equ HECREG_OFFSET, (0x09)
83.equ EC_BASE, (0xE0000000)
84.equ EC_ENABLE, (0x01)
85
86/* Memory Manager Config Registers */
87.equ ESRAM_ADDRESS_2G, (0x10000080)
88.equ BIMRVCTL_OFFSET, (0x19)
89.equ ENABLE_IMR_INTERRUPT, (0x80000000)
90
91/* SOC UNIT Debug Registers */
92.equ CFGSTICKY_W1_OFFSET, (0x50)
93.equ FORCE_COLD_RESET, (0x00000001)
94.equ CFGSTICKY_RW_OFFSET, (0x51)
95.equ RESET_FOR_ESRAM_LOCK, (0x00000020)
96.equ RESET_FOR_HMBOUND_LOCK, (0x00000040)
97.equ CFGNONSTICKY_W1_OFFSET, (0x52)
98.equ FORCE_WARM_RESET, (0x00000001)
99
100verify_bist:
101 cmp $0, %eax
102 je setup_esram
103 mov $POST_DEAD_CODE, %eax
104#if IS_ENABLED(CONFIG_POST_IO)
105 outb %al, $CONFIG_POST_IO_PORT
106#else
107 post_code(POST_DEAD_CODE)
108#endif
109 jmp .
110
111setup_esram:
112 /* Ensure cache is disabled. */
113 movl %cr0, %eax
114 orl $(CR0_CD | CR0_NW), %eax
115 invd
116 movl %eax, %cr0
117
118 /*
119 * Disable NMI operation
120 * Good convention suggests you should read back RTC data port after
121 * accessing the RTC index port.
122 */
123 movb $(NMI_DISABLE), %al
124 movw $(RTC_INDEX), %dx
125 outb %al, %dx
126 movw $(RTC_DATA), %dx
127 inb %dx, %al
128
129 /* Disable SMI (Disables SMI wire, not SMI messages) */
130 movl $((QUARK_OPCODE_READ << QNC_MCR_OP_OFFSET) \
131 | (QUARK_NC_HOST_BRIDGE_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
132 | (QNC_MSG_FSBIC_REG_HMISC << QNC_MCR_REG_OFFSET)), %ecx
133 leal L1, %esp
134 jmp stackless_SideBand_Read
135L1:
136 andl $(~SMI_EN), %eax
137 movl $((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
138 | (QUARK_NC_HOST_BRIDGE_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
139 | (QNC_MSG_FSBIC_REG_HMISC << QNC_MCR_REG_OFFSET)), %ecx
140 leal L2, %esp
141 jmp stackless_SideBand_Write
142L2:
143
144 /*
145 * Before we get going, check SOC Unit Registers to see if we are
146 * required to issue a warm/cold reset
147 */
148 movl $((QUARK_ALT_OPCODE_READ << QNC_MCR_OP_OFFSET) \
149 | (QUARK_SCSS_SOC_UNIT_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
150 | (CFGNONSTICKY_W1_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
151 leal L3, %esp
152 jmp stackless_SideBand_Read
153L3:
154 andl $(FORCE_WARM_RESET), %eax
155 jz TestForceColdReset /* No warm reset - branch */
156 jmp IssueWarmReset
157
158TestForceColdReset:
159 movl $((QUARK_ALT_OPCODE_READ << QNC_MCR_OP_OFFSET) \
160 | (QUARK_SCSS_SOC_UNIT_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
161 | (CFGNONSTICKY_W1_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
162 leal L4, %esp
163 jmp stackless_SideBand_Read
164L4:
165 andl $(FORCE_COLD_RESET), %eax
166 jz TestHmboundLock /* No cold reset - branch */
167 jmp IssueColdReset
168
169 /* Before setting HMBOUND, check it's not locked */
170TestHmboundLock:
171 movl $((QUARK_OPCODE_READ << QNC_MCR_OP_OFFSET) \
172 | (QUARK_NC_HOST_BRIDGE_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
173 | (HMBOUND_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
174 leal L5, %esp
175 jmp stackless_SideBand_Read
176L5:
177 andl $(HMBOUND_LOCK), %eax
178 jz ConfigHmbound /* Good configuration - branch */
179
180 /* Failed to config - store sticky bit debug */
181 movl $((QUARK_ALT_OPCODE_READ << QNC_MCR_OP_OFFSET) \
182 | (QUARK_SCSS_SOC_UNIT_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
183 | (CFGSTICKY_RW_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
184 leal L6, %esp
185 jmp stackless_SideBand_Read
186L6:
187 orl $(RESET_FOR_HMBOUND_LOCK), %eax
188 movl $((QUARK_ALT_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
189 | (QUARK_SCSS_SOC_UNIT_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
190 | (CFGSTICKY_RW_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
191 leal L7, %esp
192 jmp stackless_SideBand_Write
193L7:
194 jmp IssueWarmReset
195
196 /* Set up the HMBOUND register */
197ConfigHmbound:
198 movl $(HMBOUND_ADDRESS), %eax /* Data (Set HMBOUND location) */
199 movl $((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
200 | (QUARK_NC_HOST_BRIDGE_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
201 | (HMBOUND_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
202 leal L8, %esp
203 jmp stackless_SideBand_Write
204L8:
205
206 /*
207 * Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND
208 * violation occurs.
209 */
210 movl $(ENABLE_IMR_INTERRUPT), %eax /* Set interrupt enable mask */
211 movl $((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
212 | (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
213 | (BIMRVCTL_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
214 leal L9, %esp
215 jmp stackless_SideBand_Write
216L9:
217
218 /* Move eSRAM memory to 2GB */
219 movl $(ESRAM_ADDRESS_2G), %eax /* Data (Set eSRAM location) */
220 movl $((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
221 | (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
222 | (QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK \
223 << QNC_MCR_REG_OFFSET)), %ecx
224 leal L10, %esp
225 jmp stackless_SideBand_Write
226L10:
227
228 /* Check that we're not blocked from setting the config that we want. */
229 movl $((QUARK_OPCODE_READ << QNC_MCR_OP_OFFSET) \
230 | (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
231 | (QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK \
232 << QNC_MCR_REG_OFFSET)), %ecx
233 leal L11, %esp
234 jmp stackless_SideBand_Read
235L11:
236 andl $(BLOCK_ENABLE_PG), %eax
237 jnz ConfigPci /* Good configuration - branch */
238
239 /* Failed to config - store sticky bit debug */
240 movl $((QUARK_ALT_OPCODE_READ << QNC_MCR_OP_OFFSET) \
241 | (QUARK_SCSS_SOC_UNIT_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
242 | (CFGSTICKY_RW_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
243 leal L12, %esp
244 jmp stackless_SideBand_Read
245L12:
246 orl $(RESET_FOR_ESRAM_LOCK), %eax
247 movl $((QUARK_ALT_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
248 | (QUARK_SCSS_SOC_UNIT_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
249 | (CFGSTICKY_RW_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
250 leal L13, %esp
251 jmp stackless_SideBand_Write
252L13:
253 jmp IssueWarmReset
254
255 /* Enable PCIEXBAR */
256ConfigPci:
257 movl $(EC_BASE + EC_ENABLE), %eax /* Data */
258 movl $((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
259 | (QUARK_NC_MEMORY_ARBITER_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
260 | (AEC_CTRL_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
261 leal L14, %esp
262 jmp stackless_SideBand_Write
263L14:
264
265 movl $(EC_BASE + EC_ENABLE), %eax /* Data */
266 movl $((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) \
267 | (QUARK_NC_HOST_BRIDGE_SB_PORT_ID << QNC_MCR_PORT_OFFSET) \
268 | (HECREG_OFFSET << QNC_MCR_REG_OFFSET)), %ecx
269 leal L15, %esp
270 jmp stackless_SideBand_Write
271L15:
272
273 /* Open up full 8MB SPI decode */
274 movl $(PCI_CFG | ILB_PFA | BDE), %ebx /* PCI config address */
275 movl $(DECODE_ALL_REGIONS_ENABLE), %eax
276 leal L16, %esp
277 jmp stackless_PCIConfig_Write
278L16:
279
280 jmp esram_init_done
281
282IssueWarmReset:
283 /* Issue Warm Reset request to Remote Management Unit via iLB */
284 movw $(CF9_WARM_RESET), %ax
285 movw $(ILB_RESET_REG), %dx
286 outw %ax, %dx
287 jmp . /* Stay here until we are reset. */
288
289IssueColdReset:
290 /* Issue Cold Reset request to Remote Management Unit via iLB */
291 movw $(CF9_COLD_RESET), %ax
292 movw $(ILB_RESET_REG), %dx
293 outw %ax, %dx
294 jmp . /* Stay here until we are reset. */
295
296/*
297 *----------------------------------------------------------------------------
298 *
299 * Procedure: stackless_SideBand_Read
300 *
301 * Input: esp - return address
302 * ecx[15:8] - Register offset
303 * ecx[23:16] - Port ID
304 * ecx[31:24] - Opcode
305 *
306 * Output: eax - Data read
307 *
308 * Destroys: eax
309 * ebx
310 * cl
311 * esi
312 *
313 * Description:
314 * Perform requested sideband read
315 *----------------------------------------------------------------------------
316 */
317
318stackless_SideBand_Read:
319
320 movl %esp, %esi /* Save the return address */
321
322 /* Load the SideBand Packet Register to generate the transaction */
323 movl $(PCI_CFG | HOST_BRIDGE_PFA | QNC_ACCESS_PORT_MCR), %ebx
324 movb $QNC_MCR_BYTE_ENABLES, %cl /* Set all Byte Enable bits */
325 xchgl %ecx, %eax
326 leal L17, %esp
327 jmp stackless_PCIConfig_Write
328L17:
329 xchgl %ecx, %eax
330
331 /* Read the SideBand Data Register */
332 movl $(PCI_CFG | HOST_BRIDGE_PFA | (QNC_ACCESS_PORT_MDR)), %ebx
333 leal L18, %esp
334 jmp stackless_PCIConfig_Read
335L18:
336
337 movl %esi, %esp /* Restore the return address */
338 RET32
339
340/*
341 *----------------------------------------------------------------------------
342 *
343 * Procedure: stackless_SideBand_Write
344 *
345 * Input: esp - return address
346 * eax - Data
347 * ecx[15:8] - Register offset
348 * ecx[23:16] - Port ID
349 * ecx[31:24] - Opcode
350 *
351 * Output: None
352 *
353 * Destroys: ebx
354 * cl
355 * esi
356 *
357 * Description:
358 * Perform requested sideband write
359 *
360 *----------------------------------------------------------------------------
361 */
362
363stackless_SideBand_Write:
364
365 movl %esp, %esi /* Save the return address */
366
367 /* Load the SideBand Data Register with the data */
368 movl $(PCI_CFG | HOST_BRIDGE_PFA | QNC_ACCESS_PORT_MDR), %ebx
369 leal L19, %esp
370 jmp stackless_PCIConfig_Write
371L19:
372
373 /* Load the SideBand Packet Register to generate the transaction */
374 movl $(PCI_CFG | HOST_BRIDGE_PFA | QNC_ACCESS_PORT_MCR), %ebx
375 movb $QNC_MCR_BYTE_ENABLES, %cl /* Set all Byte Enable bits */
376 xchgl %ecx, %eax
377 leal L20, %esp
378 jmp stackless_PCIConfig_Write
379L20:
380 xchgl %ecx, %eax
381
382 movl %esi, %esp /* Restore the return address */
383 RET32
384
385/*
386 *----------------------------------------------------------------------------
387 *
388 * Procedure: stackless_PCIConfig_Write
389 *
390 * Input: esp - return address
391 * eax - Data to write
392 * ebx - PCI Config Address
393 *
394 * Output: None
395 *
396 * Destroys: dx
397 *
398 * Description:
399 * Perform a DWORD PCI Configuration write
400 *
401 *----------------------------------------------------------------------------
402 */
403
404stackless_PCIConfig_Write:
405
406 /* Write the PCI Config Address to the address port */
407 xchgl %ebx, %eax
408 movw $(PCI_ADDRESS_PORT), %dx
409 outl %eax, %dx
410 xchgl %ebx, %eax
411
412 /* Write the PCI DWORD Data to the data port */
413 movw $(PCI_DATA_PORT), %dx
414 outl %eax, %dx
415
416 RET32
417
418/*
419 *----------------------------------------------------------------------------
420 *
421 * Procedure: stackless_PCIConfig_Read
422 *
423 * Input: esp - return address
424 * ebx - PCI Config Address
425 *
426 * Output: eax - Data read
427 *
428 * Destroys: eax
429 * dx
430 *
431 * Description:
432 * Perform a DWORD PCI Configuration read
433 *
434 *----------------------------------------------------------------------------
435 */
436
437stackless_PCIConfig_Read:
438
439 /* Write the PCI Config Address to the address port */
440 xchgl %ebx, %eax
441 movw $(PCI_ADDRESS_PORT), %dx
442 outl %eax, %dx
443 xchgl %ebx, %eax
444
445 /* Read the PCI DWORD Data from the data port */
446 movw $(PCI_DATA_PORT), %dx
447 inl %dx, %eax
448
449 RET32
450
451/*----------------------------------------------------------------------------*/
452
453esram_init_done:
454
Lee Leahya7ba56e2016-02-07 10:42:14 -0800455#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1)
456
457 /* Copy FSP image to eSRAM and call it. */
458 /* TODO: FSP location/size could be got in a routine. */
459 cld
460 movl $(0x00040000), %ecx /* 256K DWORDs = 64K */
461 shrl $2, %ecx
462 movl $CONFIG_FSP_LOC, %esi /* The source address. */
463 movl $CONFIG_FSP_ESRAM_LOC, %edi /* FSP destination in ESRAM */
464 rep movsl
465#endif /* CONFIG_PLATFORM_USES_FSP1_1 */
466
467#if IS_ENABLED(CONFIG_ENABLE_DEBUG_LED)
468sd_led:
469
Lee Leahy9fd08952016-02-02 07:17:06 -0800470.equ SD_PFA, (0x14 << 11) /* B0:D20:F0 - SDIO controller */
471.equ SD_CFG_BASE, (PCI_CFG | SD_PFA) /* SD cntrl base in PCI config space */
472.equ SD_CFG_CMD, (SD_CFG_BASE+0x04) /* Command reg in PCI config space */
473.equ SD_CFG_ADDR, (SD_CFG_BASE+0x10) /* Base address in PCI config space */
474.equ SD_BASE_ADDR, (0xA0018000) /* SD controller's base address */
475.equ SD_HOST_CTRL, (SD_BASE_ADDR+0x28) /* HOST_CTRL register */
476
477 /* Set the SDIO controller's base address */
478 movl $(SD_BASE_ADDR), %eax
479 movl $(SD_CFG_ADDR), %ebx
480 leal L40, %esp
481 jmp stackless_PCIConfig_Write
482
483L40:
484 movl $(SD_CFG_ADDR), %ebx
485 leal L41, %esp
486 jmp stackless_PCIConfig_Read
487
488L41:
489 /* Enable the SDIO controller */
490 movl $(SD_CFG_CMD), %ebx
491 leal L42, %esp
492 jmp stackless_PCIConfig_Read
493
494L42:
495 orl $2, %eax
496 movl $(SD_CFG_CMD), %ebx
497 leal L43, %esp
498 jmp stackless_PCIConfig_Write
499
500L43:
501 movl $(SD_CFG_CMD), %ebx
502 leal L44, %esp
503 jmp stackless_PCIConfig_Read
504
505L44:
Lee Leahya7ba56e2016-02-07 10:42:14 -0800506#if IS_ENABLED(CONFIG_ENABLE_DEBUG_LED_ESRAM)
Lee Leahy9fd08952016-02-02 07:17:06 -0800507 /* Turn on SD LED to indicate ESRAM successfully initialized */
508 movl $SD_HOST_CTRL, %ebx
509 movb 0(%ebx), %al
510 orb $1, %al
511 movb %al, 0(%ebx)
512
513 /* Loop forever */
514 jmp .
Lee Leahya7ba56e2016-02-07 10:42:14 -0800515#endif /* CONFIG_ENABLE_DEBUG_LED_ESRAM */
516#endif /* CONFIG_ENABLE_DEBUG_LED */