1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <console/console.h>
6 #include <device/device.h>
7 #include <pc80/mc146818rtc.h>
8 #include <smp/spinlock.h>
10 #if CONFIG(USE_OPTION_TABLE)
11 # include "option_table.h"
12 # define CMOS_POST_OFFSET (CMOS_VSTART_cmos_post_offset >> 3)
14 # if (CONFIG_CMOS_POST_OFFSET != 0)
15 # define CMOS_POST_OFFSET CONFIG_CMOS_POST_OFFSET
17 # error "Must configure CONFIG_CMOS_POST_OFFSET"
22 * 0 = Bank Select Magic
25 * 3-6 = BANK 0 Extra log
26 * 7-10 = BANK 1 Extra log
28 #define CMOS_POST_BANK_OFFSET (CMOS_POST_OFFSET)
29 #define CMOS_POST_BANK_0_MAGIC 0x80
30 #define CMOS_POST_BANK_0_OFFSET (CMOS_POST_OFFSET + 1)
31 #define CMOS_POST_BANK_0_EXTRA (CMOS_POST_OFFSET + 3)
32 #define CMOS_POST_BANK_1_MAGIC 0x81
33 #define CMOS_POST_BANK_1_OFFSET (CMOS_POST_OFFSET + 2)
34 #define CMOS_POST_BANK_1_EXTRA (CMOS_POST_OFFSET + 7)
36 #define CMOS_POST_EXTRA_DEV_PATH 0x01
38 DECLARE_SPIN_LOCK(cmos_post_lock
)
40 int cmos_post_previous_boot(u8
*code
, u32
*extra
)
45 spin_lock(&cmos_post_lock
);
47 /* Get post code from other bank */
48 switch (cmos_read(CMOS_POST_BANK_OFFSET
)) {
49 case CMOS_POST_BANK_0_MAGIC
:
50 *code
= cmos_read(CMOS_POST_BANK_1_OFFSET
);
51 *extra
= cmos_read32(CMOS_POST_BANK_1_EXTRA
);
53 case CMOS_POST_BANK_1_MAGIC
:
54 *code
= cmos_read(CMOS_POST_BANK_0_OFFSET
);
55 *extra
= cmos_read32(CMOS_POST_BANK_0_EXTRA
);
59 spin_unlock(&cmos_post_lock
);
61 /* Check last post code in previous boot against normal list */
65 case POST_ENTER_ELF_BOOT
:
75 void cmos_post_init(void)
77 u8 magic
= CMOS_POST_BANK_0_MAGIC
;
79 /* Switch to the other bank */
80 switch (cmos_read(CMOS_POST_BANK_OFFSET
)) {
81 case CMOS_POST_BANK_1_MAGIC
:
83 case CMOS_POST_BANK_0_MAGIC
:
84 magic
= CMOS_POST_BANK_1_MAGIC
;
87 /* Initialize to zero */
88 cmos_write(0, CMOS_POST_BANK_0_OFFSET
);
89 cmos_write(0, CMOS_POST_BANK_1_OFFSET
);
90 cmos_write32(0, CMOS_POST_BANK_0_EXTRA
);
91 cmos_write32(0, CMOS_POST_BANK_1_EXTRA
);
94 cmos_write(magic
, CMOS_POST_BANK_OFFSET
);
97 void cmos_post_code(u8 value
)
99 spin_lock(&cmos_post_lock
);
101 switch (cmos_read(CMOS_POST_BANK_OFFSET
)) {
102 case CMOS_POST_BANK_0_MAGIC
:
103 cmos_write(value
, CMOS_POST_BANK_0_OFFSET
);
105 case CMOS_POST_BANK_1_MAGIC
:
106 cmos_write(value
, CMOS_POST_BANK_1_OFFSET
);
110 spin_unlock(&cmos_post_lock
);
113 void cmos_post_extra(u32 value
)
115 spin_lock(&cmos_post_lock
);
117 switch (cmos_read(CMOS_POST_BANK_OFFSET
)) {
118 case CMOS_POST_BANK_0_MAGIC
:
119 cmos_write32(value
, CMOS_POST_BANK_0_EXTRA
);
121 case CMOS_POST_BANK_1_MAGIC
:
122 cmos_write32(value
, CMOS_POST_BANK_1_EXTRA
);
126 spin_unlock(&cmos_post_lock
);
129 void cmos_post_path(const struct device
*dev
)
131 /* Encode path into lower 3 bytes */
132 u32 path
= dev_path_encode(dev
);
133 /* Upper byte contains the log type */
134 path
|= CMOS_POST_EXTRA_DEV_PATH
<< 24;
135 cmos_post_extra(path
);