Angel Pons | 8a7d786 | 2020-04-05 13:21:24 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 2 | |
Furquan Shaikh | 76cedd2 | 2020-05-02 10:24:23 -0700 | [diff] [blame] | 3 | #include <acpi/acpi.h> |
David Wu | 80496f0 | 2018-09-14 21:30:39 +0800 | [diff] [blame] | 4 | #include <baseboard/variants.h> |
Kyösti Mälkki | be7692a | 2021-11-03 17:54:14 +0200 | [diff] [blame^] | 5 | #include <bootmode.h> |
Shelley Chen | 8c81c6a | 2017-06-29 14:58:59 -0700 | [diff] [blame] | 6 | #include <chip.h> |
Elyes HAOUAS | 187655c | 2019-10-30 09:06:43 +0100 | [diff] [blame] | 7 | #include <console/console.h> |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 8 | #include <delay.h> |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 9 | #include <device/device.h> |
| 10 | #include <ec/ec.h> |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 11 | #include <ec/google/chromeec/ec.h> |
| 12 | #include <gpio.h> |
Sumeet R Pawnikar | 97c5464 | 2020-05-10 01:24:11 +0530 | [diff] [blame] | 13 | #include <intelblocks/power_limit.h> |
Shelley Chen | a35ad0e | 2017-11-21 15:47:12 -0800 | [diff] [blame] | 14 | #include <smbios.h> |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 15 | #include <soc/gpio.h> |
Shelley Chen | db287aa | 2017-06-09 12:56:08 -0700 | [diff] [blame] | 16 | #include <soc/pci_devs.h> |
Kevin Cheng | 2a6f4ae | 2017-06-06 10:37:59 +0800 | [diff] [blame] | 17 | #include <soc/nhlt.h> |
Shelley Chen | a35ad0e | 2017-11-21 15:47:12 -0800 | [diff] [blame] | 18 | #include <string.h> |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 19 | #include <timer.h> |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 20 | #include <vendorcode/google/chromeos/chromeos.h> |
| 21 | |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 22 | #include <variant/gpio.h> |
| 23 | |
Shelley Chen | 4fef781 | 2018-01-16 13:20:04 -0800 | [diff] [blame] | 24 | #define FIZZ_SKU_ID_I7_U42 0x4 |
| 25 | #define FIZZ_SKU_ID_I5_U42 0x5 |
| 26 | #define FIZZ_SKU_ID_I3_U42 0x6 |
| 27 | #define FIZZ_SKU_ID_I7_U22 0x3 |
| 28 | #define FIZZ_SKU_ID_I5_U22 0x2 |
| 29 | #define FIZZ_SKU_ID_I3_U22 0x1 |
| 30 | #define FIZZ_SKU_ID_CEL_U22 0x0 |
| 31 | #define FIZZ_PL2_U42 44 |
| 32 | #define FIZZ_PL2_U22 29 |
| 33 | #define FIZZ_PSYSPL2_U22 65 |
| 34 | #define FIZZ_PSYSPL2_U42 90 |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 35 | #define FIZZ_MAX_TIME_WINDOW 6 |
| 36 | #define FIZZ_MIN_DUTYCYCLE 4 |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 37 | /* |
| 38 | * For type-C chargers, set PL2 to 90% of max power to account for |
| 39 | * cable loss and FET Rdson loss in the path from the source. |
| 40 | */ |
Shelley Chen | e87d3cd | 2018-01-26 12:50:54 -0800 | [diff] [blame] | 41 | #define SET_PSYSPL2(w) (9 * (w) / 10) |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 42 | |
Daisuke Nojiri | 0592776 | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 43 | static uint8_t read_sku_id_from_gpio(void) |
Daisuke Nojiri | a0ab764 | 2017-11-28 14:15:51 -0800 | [diff] [blame] | 44 | { |
Daisuke Nojiri | a0ab764 | 2017-11-28 14:15:51 -0800 | [diff] [blame] | 45 | const gpio_t sku_id_gpios[] = { |
| 46 | GPIO_SKU_ID0, |
| 47 | GPIO_SKU_ID1, |
| 48 | GPIO_SKU_ID2, |
| 49 | GPIO_SKU_ID3, |
| 50 | }; |
Daisuke Nojiri | 0592776 | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 51 | return gpio_base2_value(sku_id_gpios, ARRAY_SIZE(sku_id_gpios)); |
| 52 | } |
| 53 | |
| 54 | static uint8_t board_sku_id(void) |
| 55 | { |
| 56 | static int sku_id = -1; |
| 57 | |
| 58 | if (sku_id < 0) { |
| 59 | uint32_t id; |
| 60 | if (google_chromeec_cbi_get_sku_id(&id)) |
| 61 | /* TODO: Once transition completes, raise error instead |
| 62 | of returning gpio value which could be unintended. */ |
| 63 | /* Reading from EC may succeed next time but we do not |
| 64 | want to return different values. So, we cache the |
| 65 | value read from GPIOs. */ |
| 66 | id = read_sku_id_from_gpio(); |
| 67 | sku_id = id; |
| 68 | } |
| 69 | |
| 70 | return sku_id; |
Daisuke Nojiri | a0ab764 | 2017-11-28 14:15:51 -0800 | [diff] [blame] | 71 | } |
| 72 | |
Shelley Chen | 8c81c6a | 2017-06-29 14:58:59 -0700 | [diff] [blame] | 73 | /* |
Shelley Chen | 750ec94 | 2018-01-08 18:24:03 -0800 | [diff] [blame] | 74 | * mainboard_set_power_limits |
Shelley Chen | 8c81c6a | 2017-06-29 14:58:59 -0700 | [diff] [blame] | 75 | * |
Shelley Chen | 750ec94 | 2018-01-08 18:24:03 -0800 | [diff] [blame] | 76 | * Set Pl2 and SysPl2 values based on detected charger. |
Shelley Chen | 4fef781 | 2018-01-16 13:20:04 -0800 | [diff] [blame] | 77 | * If detected barrel jack, use values below based on SKU. |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 78 | * definitions: |
| 79 | * x = no value entered. Use default value in parenthesis. |
| 80 | * will set 0 to anything that shouldn't be set. |
| 81 | * n = max value of power adapter. |
| 82 | * +-------------+-----+---------+-----------+-------+ |
| 83 | * | sku_id | PL2 | PsysPL2 | PsysPL3 | PL4 | |
| 84 | * +-------------+-----+---------+-----------+-------+ |
| 85 | * | i7 U42 | 44 | 81 | x(.85PL4) | x(71) | |
| 86 | * | i5 U42 | 44 | 81 | x(.85PL4) | x(71) | |
| 87 | * | i3 U42 | 44 | 81 | x(.85PL4) | x(71) | |
| 88 | * | i7 U22 | 29 | 58 | x(.85PL4) | x(43) | |
| 89 | * | i5 U22 | 29 | 58 | x(.85PL4) | x(43) | |
| 90 | * | i3 U22 | 29 | 58 | x(.85PL4) | x(43) | |
| 91 | * | celeron U22 | 29 | 58 | x(.85PL4) | x(43) | |
| 92 | * +-------------+-----+---------+-----------+-------+ |
Shelley Chen | e87d3cd | 2018-01-26 12:50:54 -0800 | [diff] [blame] | 93 | * For USB C charger: |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 94 | * +-------------+-----+---------+---------+-------+ |
| 95 | * | Max Power(W)| PL2 | PsysPL2 | PsysPL3 | PL4 | |
| 96 | * +-------------+-----+---------+---------+-------+ |
| 97 | * | 60 (U42) | 44 | 54 | 54 | 54 | |
| 98 | * | 60 (U22) | 29 | 54 | 54 | x(43) | |
| 99 | * | n (U42) | 44 | .9n | .9n | .9n | |
| 100 | * | n (U22) | 29 | .9n | .9n | x(43) | |
| 101 | * +-------------+-----+---------+---------+-------+ |
Shelley Chen | 8c81c6a | 2017-06-29 14:58:59 -0700 | [diff] [blame] | 102 | */ |
Sumeet R Pawnikar | 97c5464 | 2020-05-10 01:24:11 +0530 | [diff] [blame] | 103 | static void mainboard_set_power_limits(struct soc_power_limits_config *conf) |
Shelley Chen | 8c81c6a | 2017-06-29 14:58:59 -0700 | [diff] [blame] | 104 | { |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 105 | enum usb_chg_type type; |
| 106 | u32 watts; |
Gaggery Tsai | 52f18df | 2020-03-25 11:34:25 -0700 | [diff] [blame] | 107 | u16 volts_mv, current_ma; |
Shelley Chen | 750ec94 | 2018-01-08 18:24:03 -0800 | [diff] [blame] | 108 | u32 pl2, psyspl2; |
Gaggery Tsai | 52f18df | 2020-03-25 11:34:25 -0700 | [diff] [blame] | 109 | int rv = google_chromeec_get_usb_pd_power_info(&type, ¤t_ma, &volts_mv); |
Shelley Chen | 4fef781 | 2018-01-16 13:20:04 -0800 | [diff] [blame] | 110 | uint8_t sku = board_sku_id(); |
| 111 | const uint32_t u42_mask = (1 << FIZZ_SKU_ID_I7_U42) | |
| 112 | (1 << FIZZ_SKU_ID_I5_U42) | |
| 113 | (1 << FIZZ_SKU_ID_I3_U42); |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 114 | |
Shelley Chen | e87d3cd | 2018-01-26 12:50:54 -0800 | [diff] [blame] | 115 | /* PL2 value is sku-based, no matter what charger we are using */ |
| 116 | pl2 = FIZZ_PL2_U22; |
| 117 | if ((1 << sku) & u42_mask) |
| 118 | pl2 = FIZZ_PL2_U42; |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 119 | conf->tdp_psyspl3 = conf->tdp_pl4 = 0; |
Shelley Chen | e87d3cd | 2018-01-26 12:50:54 -0800 | [diff] [blame] | 120 | |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 121 | /* If we can't get charger info or not PD charger, assume barrel jack */ |
| 122 | if (rv != 0 || type != USB_CHG_TYPE_PD) { |
Shelley Chen | e87d3cd | 2018-01-26 12:50:54 -0800 | [diff] [blame] | 123 | /* using the barrel jack, get PsysPL2 based on sku id */ |
Shelley Chen | 4fef781 | 2018-01-16 13:20:04 -0800 | [diff] [blame] | 124 | psyspl2 = FIZZ_PSYSPL2_U22; |
| 125 | /* Running a U42 SKU */ |
Shelley Chen | e87d3cd | 2018-01-26 12:50:54 -0800 | [diff] [blame] | 126 | if ((1 << sku) & u42_mask) |
Shelley Chen | 4fef781 | 2018-01-16 13:20:04 -0800 | [diff] [blame] | 127 | psyspl2 = FIZZ_PSYSPL2_U42; |
Shelley Chen | 750ec94 | 2018-01-08 18:24:03 -0800 | [diff] [blame] | 128 | } else { |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 129 | /* Detected TypeC. Base on max value of adapter */ |
Gaggery Tsai | 52f18df | 2020-03-25 11:34:25 -0700 | [diff] [blame] | 130 | watts = ((u32)volts_mv * current_ma) / 1000000; |
Shelley Chen | 750ec94 | 2018-01-08 18:24:03 -0800 | [diff] [blame] | 131 | psyspl2 = watts; |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 132 | conf->tdp_psyspl3 = SET_PSYSPL2(psyspl2); |
| 133 | /* set max possible time window */ |
| 134 | conf->tdp_psyspl3_time = FIZZ_MAX_TIME_WINDOW; |
| 135 | /* set minimum duty cycle */ |
| 136 | conf->tdp_psyspl3_dutycycle = FIZZ_MIN_DUTYCYCLE; |
| 137 | if ((1 << sku) & u42_mask) |
| 138 | conf->tdp_pl4 = SET_PSYSPL2(psyspl2); |
Shelley Chen | 750ec94 | 2018-01-08 18:24:03 -0800 | [diff] [blame] | 139 | } |
Shelley Chen | bdfc5f5 | 2017-09-28 10:26:26 -0700 | [diff] [blame] | 140 | |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 141 | conf->tdp_pl2_override = pl2; |
Shelley Chen | e87d3cd | 2018-01-26 12:50:54 -0800 | [diff] [blame] | 142 | /* set psyspl2 to 90% of max adapter power */ |
Shelley Chen | c12dff9 | 2018-01-31 15:57:43 -0800 | [diff] [blame] | 143 | conf->tdp_psyspl2 = SET_PSYSPL2(psyspl2); |
Shelley Chen | 8c81c6a | 2017-06-29 14:58:59 -0700 | [diff] [blame] | 144 | } |
| 145 | |
Daisuke Nojiri | 0592776 | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 146 | static uint8_t read_oem_id_from_gpio(void) |
Shelley Chen | a35ad0e | 2017-11-21 15:47:12 -0800 | [diff] [blame] | 147 | { |
Shelley Chen | a35ad0e | 2017-11-21 15:47:12 -0800 | [diff] [blame] | 148 | const gpio_t oem_id_gpios[] = { |
| 149 | GPIO_OEM_ID1, |
| 150 | GPIO_OEM_ID2, |
| 151 | GPIO_OEM_ID3, |
| 152 | }; |
Daisuke Nojiri | 0592776 | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 153 | return gpio_base2_value(oem_id_gpios, ARRAY_SIZE(oem_id_gpios)); |
| 154 | } |
| 155 | |
| 156 | static uint8_t board_oem_id(void) |
| 157 | { |
| 158 | static int oem_id = -1; |
| 159 | |
| 160 | if (oem_id < 0) { |
| 161 | uint32_t id; |
| 162 | if (google_chromeec_cbi_get_oem_id(&id)) |
| 163 | /* TODO: Once transition completes, raise error instead |
| 164 | of returning gpio value which could be unintended. */ |
| 165 | /* Reading from EC may succeed next time but we do not |
| 166 | want to return different values. So, we cache the |
| 167 | value read from GPIOs. */ |
| 168 | id = read_oem_id_from_gpio(); |
| 169 | oem_id = id; |
| 170 | } |
| 171 | |
| 172 | return oem_id; |
Shelley Chen | a35ad0e | 2017-11-21 15:47:12 -0800 | [diff] [blame] | 173 | } |
| 174 | |
Nico Huber | ebd8a4f | 2017-11-01 09:49:16 +0100 | [diff] [blame] | 175 | const char *smbios_system_sku(void) |
Shelley Chen | a35ad0e | 2017-11-21 15:47:12 -0800 | [diff] [blame] | 176 | { |
Jeff Chase | 71090c6 | 2020-02-24 18:43:23 -0500 | [diff] [blame] | 177 | static char sku_str[7]; /* sku{0..255} */ |
Shelley Chen | a35ad0e | 2017-11-21 15:47:12 -0800 | [diff] [blame] | 178 | |
| 179 | snprintf(sku_str, sizeof(sku_str), "sku%d", board_oem_id()); |
| 180 | |
| 181 | return sku_str; |
| 182 | } |
| 183 | |
Elyes HAOUAS | d129d43 | 2018-05-04 20:23:33 +0200 | [diff] [blame] | 184 | static void mainboard_init(struct device *dev) |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 185 | { |
| 186 | mainboard_ec_init(); |
| 187 | } |
| 188 | |
Kevin Cheng | 2a6f4ae | 2017-06-06 10:37:59 +0800 | [diff] [blame] | 189 | static unsigned long mainboard_write_acpi_tables( |
Furquan Shaikh | 0f007d8 | 2020-04-24 06:41:18 -0700 | [diff] [blame] | 190 | const struct device *device, unsigned long current, acpi_rsdp_t *rsdp) |
Kevin Cheng | 2a6f4ae | 2017-06-06 10:37:59 +0800 | [diff] [blame] | 191 | { |
David Wu | 80496f0 | 2018-09-14 21:30:39 +0800 | [diff] [blame] | 192 | const char *oem_id = NULL; |
| 193 | const char *oem_table_id = NULL; |
| 194 | uint32_t oem_revision = 0; |
Kevin Cheng | 2a6f4ae | 2017-06-06 10:37:59 +0800 | [diff] [blame] | 195 | uintptr_t start_addr; |
| 196 | uintptr_t end_addr; |
| 197 | struct nhlt *nhlt; |
| 198 | |
| 199 | start_addr = current; |
| 200 | |
| 201 | nhlt = nhlt_init(); |
| 202 | if (!nhlt) |
| 203 | return start_addr; |
| 204 | |
David Wu | 80496f0 | 2018-09-14 21:30:39 +0800 | [diff] [blame] | 205 | variant_nhlt_init(nhlt); |
| 206 | variant_nhlt_oem_overrides(&oem_id, &oem_table_id, &oem_revision); |
Kevin Cheng | 2a6f4ae | 2017-06-06 10:37:59 +0800 | [diff] [blame] | 207 | |
| 208 | end_addr = nhlt_soc_serialize_oem_overrides(nhlt, start_addr, |
David Wu | 80496f0 | 2018-09-14 21:30:39 +0800 | [diff] [blame] | 209 | oem_id, oem_table_id, oem_revision); |
Kevin Cheng | 2a6f4ae | 2017-06-06 10:37:59 +0800 | [diff] [blame] | 210 | |
| 211 | if (end_addr != start_addr) |
| 212 | acpi_add_table(rsdp, (void *)start_addr); |
| 213 | |
| 214 | return end_addr; |
| 215 | } |
| 216 | |
Elyes HAOUAS | d129d43 | 2018-05-04 20:23:33 +0200 | [diff] [blame] | 217 | static void mainboard_enable(struct device *dev) |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 218 | { |
Sumeet R Pawnikar | 97c5464 | 2020-05-10 01:24:11 +0530 | [diff] [blame] | 219 | struct soc_power_limits_config *soc_conf; |
Kyösti Mälkki | d5f645c | 2019-09-28 00:20:27 +0300 | [diff] [blame] | 220 | config_t *conf = config_of_soc(); |
Shelley Chen | 8c81c6a | 2017-06-29 14:58:59 -0700 | [diff] [blame] | 221 | |
Sumeet R Pawnikar | 97c5464 | 2020-05-10 01:24:11 +0530 | [diff] [blame] | 222 | soc_conf = &conf->power_limits_config; |
| 223 | mainboard_set_power_limits(soc_conf); |
Shelley Chen | db287aa | 2017-06-09 12:56:08 -0700 | [diff] [blame] | 224 | |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 225 | dev->ops->init = mainboard_init; |
Nico Huber | 68680dd | 2020-03-31 17:34:52 +0200 | [diff] [blame] | 226 | dev->ops->acpi_inject_dsdt = chromeos_dsdt_generator; |
Kevin Cheng | 2a6f4ae | 2017-06-06 10:37:59 +0800 | [diff] [blame] | 227 | dev->ops->write_acpi_tables = mainboard_write_acpi_tables; |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 228 | } |
| 229 | |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 230 | #define GPIO_HDMI_HPD GPP_E13 |
| 231 | #define GPIO_DP_HPD GPP_E14 |
| 232 | |
| 233 | /* TODO: This can be moved to common directory */ |
| 234 | static void wait_for_hpd(gpio_t gpio, long timeout) |
| 235 | { |
| 236 | struct stopwatch sw; |
| 237 | |
| 238 | printk(BIOS_INFO, "Waiting for HPD\n"); |
| 239 | gpio_input(gpio); |
| 240 | |
| 241 | stopwatch_init_msecs_expire(&sw, timeout); |
| 242 | while (!gpio_get(gpio)) { |
| 243 | if (stopwatch_expired(&sw)) { |
| 244 | printk(BIOS_WARNING, |
| 245 | "HPD not ready after %ldms. Abort.\n", timeout); |
| 246 | return; |
| 247 | } |
| 248 | mdelay(200); |
| 249 | } |
| 250 | printk(BIOS_INFO, "HPD ready after %lu ms\n", |
| 251 | stopwatch_duration_msecs(&sw)); |
| 252 | } |
| 253 | |
Jeff Chase | ad1a835 | 2020-06-04 17:24:59 -0400 | [diff] [blame] | 254 | void __weak variant_chip_display_init(void) |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 255 | { |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 256 | static const long display_timeout_ms = 3000; |
| 257 | |
| 258 | /* This is reconfigured back to whatever FSP-S expects by |
| 259 | gpio_configure_pads. */ |
| 260 | gpio_input(GPIO_HDMI_HPD); |
| 261 | if (display_init_required() && !gpio_get(GPIO_HDMI_HPD)) { |
| 262 | /* This has to be done before FSP-S runs. */ |
| 263 | if (google_chromeec_wait_for_displayport(display_timeout_ms)) |
| 264 | wait_for_hpd(GPIO_DP_HPD, display_timeout_ms); |
| 265 | } |
Jeff Chase | ad1a835 | 2020-06-04 17:24:59 -0400 | [diff] [blame] | 266 | } |
| 267 | |
| 268 | static void mainboard_chip_init(void *chip_info) |
| 269 | { |
| 270 | const struct pad_config *pads; |
| 271 | size_t num; |
| 272 | |
| 273 | variant_chip_display_init(); |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 274 | |
| 275 | pads = variant_gpio_table(&num); |
| 276 | gpio_configure_pads(pads, num); |
| 277 | } |
| 278 | |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 279 | struct chip_operations mainboard_ops = { |
Furquan Shaikh | fb9f320 | 2019-10-23 09:52:32 -0700 | [diff] [blame] | 280 | .init = mainboard_chip_init, |
Shelley Chen | 243dc39 | 2017-03-15 15:25:48 -0700 | [diff] [blame] | 281 | .enable_dev = mainboard_enable, |
| 282 | }; |