• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <amdblocks/espi.h>
4 #include <amdblocks/reset.h>
5 #include <bootblock_common.h>
6 #include <baseboard/variants.h>
7 #include <console/console.h>
8 #include <ec/google/chromeec/ec.h>
9 #include <pc80/mc146818rtc.h>
10 #include <soc/espi.h>
11 #include <string.h>
12 
13 #define CMOS_EXTENDED_ADDR(x)          (128 + (x))
14 #define CMOS_MEM_RESTORE_OFFSET        0x0D
15 #define CMOS_BITMAP_SKIP_RESET_TOGGLE  0x10
16 #define HYNIX_PART_NAME                "H9JCNNNCP3MLYR-N6E"
17 #define HYNIX_PART_LEN                 18
18 
19 /* Ensure SKIP_RESET_TOGGLE CMOS bit set for specific Hynix part on Frostflow, cleared otherwise */
hynix_dram_cmos_check(void)20 static void hynix_dram_cmos_check(void)
21 {
22 	char cbi_part_number[DIMM_INFO_PART_NUMBER_SIZE];
23 	bool skip_reset_toggle, cmos_bit_set;
24 	unsigned char byte_value;
25 
26 	byte_value = cmos_read(CMOS_EXTENDED_ADDR(CMOS_MEM_RESTORE_OFFSET));
27 	cmos_bit_set = (byte_value & CMOS_BITMAP_SKIP_RESET_TOGGLE) != 0;
28 
29 	if (CONFIG(BOARD_GOOGLE_FROSTFLOW)) {
30 		printk(BIOS_SPEW, "Checking DRAM part #\n");
31 		if (google_chromeec_cbi_get_dram_part_num(
32 				cbi_part_number, sizeof(cbi_part_number)) == 0) {
33 			skip_reset_toggle = strncmp(cbi_part_number, HYNIX_PART_NAME, HYNIX_PART_LEN) == 0;
34 			if (skip_reset_toggle) {
35 				printk(BIOS_SPEW, "SKIP_RESET_TOGGLE needed, checking CMOS bit is set\n");
36 				if (!cmos_bit_set) {
37 					printk(BIOS_SPEW, "Bit is unset; setting and rebooting\n");
38 					cmos_write((byte_value | CMOS_BITMAP_SKIP_RESET_TOGGLE),
39 							CMOS_EXTENDED_ADDR(CMOS_MEM_RESTORE_OFFSET));
40 					warm_reset();
41 				}
42 				printk(BIOS_SPEW, "Bit already set; nothing to do.\n");
43 				return;
44 			}
45 		} else {
46 			printk(BIOS_ERR, "Unable to read DRAM part # from CBI; CMOS bit will be cleared if set\n");
47 		}
48 	}
49 	/* Ensure SKIP_RESET_TOGGLE bit cleared if not FF, not bad DRAM part, or error reading part # */
50 	if (cmos_bit_set) {
51 		printk(BIOS_SPEW, "CMOS SKIP_RESET_TOGGLE bit is set; clearing and rebooting\n");
52 		cmos_write((byte_value & ~CMOS_BITMAP_SKIP_RESET_TOGGLE),
53 					CMOS_EXTENDED_ADDR(CMOS_MEM_RESTORE_OFFSET));
54 		warm_reset();
55 	} else {
56 		printk(BIOS_SPEW, "No change to CMOS SKIP_RESET_TOGGLE bit is needed\n");
57 	}
58 }
59 
mb_set_up_early_espi(void)60 void mb_set_up_early_espi(void)
61 {
62 	size_t num_gpios;
63 	const struct soc_amd_gpio *gpios;
64 
65 	variant_espi_gpio_table(&gpios, &num_gpios);
66 	gpio_configure_pads(gpios, num_gpios);
67 
68 	espi_switch_to_spi1_pads();
69 }
70 
bootblock_mainboard_early_init(void)71 void bootblock_mainboard_early_init(void)
72 {
73 	size_t num_gpios, override_num_gpios;
74 	const struct soc_amd_gpio *gpios, *override_gpios;
75 
76 	variant_tpm_gpio_table(&gpios, &num_gpios);
77 	gpio_configure_pads(gpios, num_gpios);
78 
79 	variant_early_gpio_table(&gpios, &num_gpios);
80 	variant_early_override_gpio_table(&override_gpios, &override_num_gpios);
81 	gpio_configure_pads_with_override(gpios, num_gpios, override_gpios, override_num_gpios);
82 }
83 
bootblock_mainboard_init(void)84 void bootblock_mainboard_init(void)
85 {
86 	size_t num_gpios;
87 	const struct soc_amd_gpio *gpios;
88 
89 	hynix_dram_cmos_check();
90 
91 	variant_bootblock_gpio_table(&gpios, &num_gpios);
92 	gpio_configure_pads(gpios, num_gpios);
93 }
94