coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
mainboard.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <baseboard/variants.h>
5 #include <bootmode.h>
6 #include <chip.h>
7 #include <console/console.h>
8 #include <delay.h>
9 #include <device/device.h>
10 #include <ec/ec.h>
11 #include <ec/google/chromeec/ec.h>
12 #include <gpio.h>
14 #include <smbios.h>
15 #include <soc/gpio.h>
16 #include <soc/pci_devs.h>
17 #include <soc/nhlt.h>
18 #include <string.h>
19 #include <timer.h>
20 
21 #include <variant/gpio.h>
22 
23 #define FIZZ_SKU_ID_I7_U42 0x4
24 #define FIZZ_SKU_ID_I5_U42 0x5
25 #define FIZZ_SKU_ID_I3_U42 0x6
26 #define FIZZ_SKU_ID_I7_U22 0x3
27 #define FIZZ_SKU_ID_I5_U22 0x2
28 #define FIZZ_SKU_ID_I3_U22 0x1
29 #define FIZZ_SKU_ID_CEL_U22 0x0
30 #define FIZZ_PL2_U42 44
31 #define FIZZ_PL2_U22 29
32 #define FIZZ_PSYSPL2_U22 65
33 #define FIZZ_PSYSPL2_U42 90
34 #define FIZZ_MAX_TIME_WINDOW 6
35 #define FIZZ_MIN_DUTYCYCLE 4
36 /*
37  * For type-C chargers, set PL2 to 90% of max power to account for
38  * cable loss and FET Rdson loss in the path from the source.
39  */
40 #define SET_PSYSPL2(w) (9 * (w) / 10)
41 
43 {
44  const gpio_t sku_id_gpios[] = {
49  };
50  return gpio_base2_value(sku_id_gpios, ARRAY_SIZE(sku_id_gpios));
51 }
52 
53 static uint8_t board_sku_id(void)
54 {
55  static int sku_id = -1;
56 
57  if (sku_id < 0) {
58  uint32_t id;
60  /* TODO: Once transition completes, raise error instead
61  of returning gpio value which could be unintended. */
62  /* Reading from EC may succeed next time but we do not
63  want to return different values. So, we cache the
64  value read from GPIOs. */
65  id = read_sku_id_from_gpio();
66  sku_id = id;
67  }
68 
69  return sku_id;
70 }
71 
72 /*
73  * mainboard_set_power_limits
74  *
75  * Set Pl2 and SysPl2 values based on detected charger.
76  * If detected barrel jack, use values below based on SKU.
77  * definitions:
78  * x = no value entered. Use default value in parenthesis.
79  * will set 0 to anything that shouldn't be set.
80  * n = max value of power adapter.
81  * +-------------+-----+---------+-----------+-------+
82  * | sku_id | PL2 | PsysPL2 | PsysPL3 | PL4 |
83  * +-------------+-----+---------+-----------+-------+
84  * | i7 U42 | 44 | 81 | x(.85PL4) | x(71) |
85  * | i5 U42 | 44 | 81 | x(.85PL4) | x(71) |
86  * | i3 U42 | 44 | 81 | x(.85PL4) | x(71) |
87  * | i7 U22 | 29 | 58 | x(.85PL4) | x(43) |
88  * | i5 U22 | 29 | 58 | x(.85PL4) | x(43) |
89  * | i3 U22 | 29 | 58 | x(.85PL4) | x(43) |
90  * | celeron U22 | 29 | 58 | x(.85PL4) | x(43) |
91  * +-------------+-----+---------+-----------+-------+
92  * For USB C charger:
93  * +-------------+-----+---------+---------+-------+
94  * | Max Power(W)| PL2 | PsysPL2 | PsysPL3 | PL4 |
95  * +-------------+-----+---------+---------+-------+
96  * | 60 (U42) | 44 | 54 | 54 | 54 |
97  * | 60 (U22) | 29 | 54 | 54 | x(43) |
98  * | n (U42) | 44 | .9n | .9n | .9n |
99  * | n (U22) | 29 | .9n | .9n | x(43) |
100  * +-------------+-----+---------+---------+-------+
101  */
103 {
104  enum usb_chg_type type;
105  u32 watts;
106  u16 volts_mv, current_ma;
107  u32 pl2, psyspl2;
108  int rv = google_chromeec_get_usb_pd_power_info(&type, &current_ma, &volts_mv);
110  const uint32_t u42_mask = (1 << FIZZ_SKU_ID_I7_U42) |
111  (1 << FIZZ_SKU_ID_I5_U42) |
112  (1 << FIZZ_SKU_ID_I3_U42);
113 
114  /* PL2 value is sku-based, no matter what charger we are using */
115  pl2 = FIZZ_PL2_U22;
116  if ((1 << sku) & u42_mask)
117  pl2 = FIZZ_PL2_U42;
118  conf->tdp_psyspl3 = conf->tdp_pl4 = 0;
119 
120  /* If we can't get charger info or not PD charger, assume barrel jack */
121  if (rv != 0 || type != USB_CHG_TYPE_PD) {
122  /* using the barrel jack, get PsysPL2 based on sku id */
123  psyspl2 = FIZZ_PSYSPL2_U22;
124  /* Running a U42 SKU */
125  if ((1 << sku) & u42_mask)
126  psyspl2 = FIZZ_PSYSPL2_U42;
127  } else {
128  /* Detected TypeC. Base on max value of adapter */
129  watts = ((u32)volts_mv * current_ma) / 1000000;
130  psyspl2 = watts;
131  conf->tdp_psyspl3 = SET_PSYSPL2(psyspl2);
132  /* set max possible time window */
134  /* set minimum duty cycle */
136  if ((1 << sku) & u42_mask)
137  conf->tdp_pl4 = SET_PSYSPL2(psyspl2);
138  }
139 
140  conf->tdp_pl2_override = pl2;
141  /* set psyspl2 to 90% of max adapter power */
142  conf->tdp_psyspl2 = SET_PSYSPL2(psyspl2);
143 }
144 
146 {
147  const gpio_t oem_id_gpios[] = {
148  GPIO_OEM_ID1,
149  GPIO_OEM_ID2,
150  GPIO_OEM_ID3,
151  };
152  return gpio_base2_value(oem_id_gpios, ARRAY_SIZE(oem_id_gpios));
153 }
154 
155 static uint8_t board_oem_id(void)
156 {
157  static int oem_id = -1;
158 
159  if (oem_id < 0) {
160  uint32_t id;
162  /* TODO: Once transition completes, raise error instead
163  of returning gpio value which could be unintended. */
164  /* Reading from EC may succeed next time but we do not
165  want to return different values. So, we cache the
166  value read from GPIOs. */
167  id = read_oem_id_from_gpio();
168  oem_id = id;
169  }
170 
171  return oem_id;
172 }
173 
174 const char *smbios_system_sku(void)
175 {
176  static char sku_str[7]; /* sku{0..255} */
177 
178  snprintf(sku_str, sizeof(sku_str), "sku%d", board_oem_id());
179 
180  return sku_str;
181 }
182 
183 static void mainboard_init(struct device *dev)
184 {
186 }
187 
188 static unsigned long mainboard_write_acpi_tables(
189  const struct device *device, unsigned long current, acpi_rsdp_t *rsdp)
190 {
191  const char *oem_id = NULL;
192  const char *oem_table_id = NULL;
193  uint32_t oem_revision = 0;
194  uintptr_t start_addr;
195  uintptr_t end_addr;
196  struct nhlt *nhlt;
197 
198  start_addr = current;
199 
200  nhlt = nhlt_init();
201  if (!nhlt)
202  return start_addr;
203 
205  variant_nhlt_oem_overrides(&oem_id, &oem_table_id, &oem_revision);
206 
207  end_addr = nhlt_soc_serialize_oem_overrides(nhlt, start_addr,
208  oem_id, oem_table_id, oem_revision);
209 
210  if (end_addr != start_addr)
211  acpi_add_table(rsdp, (void *)start_addr);
212 
213  return end_addr;
214 }
215 
216 static void mainboard_enable(struct device *dev)
217 {
218  struct soc_power_limits_config *soc_conf;
219  config_t *conf = config_of_soc();
220 
221  soc_conf = &conf->power_limits_config;
222  mainboard_set_power_limits(soc_conf);
223 
224  dev->ops->init = mainboard_init;
225  dev->ops->write_acpi_tables = mainboard_write_acpi_tables;
226 }
227 
228 #define GPIO_HDMI_HPD GPP_E13
229 #define GPIO_DP_HPD GPP_E14
230 
231 /* TODO: This can be moved to common directory */
232 static void wait_for_hpd(gpio_t gpio, long timeout)
233 {
234  struct stopwatch sw;
235 
236  printk(BIOS_INFO, "Waiting for HPD\n");
237  gpio_input(gpio);
238 
239  stopwatch_init_msecs_expire(&sw, timeout);
240  while (!gpio_get(gpio)) {
241  if (stopwatch_expired(&sw)) {
243  "HPD not ready after %ldms. Abort.\n", timeout);
244  return;
245  }
246  mdelay(200);
247  }
248  printk(BIOS_INFO, "HPD ready after %lu ms\n",
250 }
251 
253 {
254  static const long display_timeout_ms = 3000;
255 
256  /* This is reconfigured back to whatever FSP-S expects by
257  gpio_configure_pads. */
260  /* This has to be done before FSP-S runs. */
261  if (google_chromeec_wait_for_displayport(display_timeout_ms))
262  wait_for_hpd(GPIO_DP_HPD, display_timeout_ms);
263  }
264 }
265 
266 static void mainboard_chip_init(void *chip_info)
267 {
268  const struct pad_config *pads;
269  size_t num;
270 
272 
273  pads = variant_gpio_table(&num);
274  gpio_configure_pads(pads, num);
275 }
276 
279  .enable_dev = mainboard_enable,
280 };
struct chip_operations mainboard_ops
Definition: mainboard.c:19
void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
Add an ACPI table to the RSDT (and XSDT) structure, recalculate length and checksum.
Definition: acpi.c:49
int display_init_required(void)
Definition: bootmode.c:22
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
void mdelay(unsigned int msecs)
Definition: delay.c:2
void mainboard_ec_init(void)
Definition: ec.c:8
int google_chromeec_wait_for_displayport(long timeout_ms)
Wait for DisplayPort to be ready.
Definition: ec.c:1668
int google_chromeec_cbi_get_oem_id(uint32_t *id)
Get data from Cros Board Info.
Definition: ec.c:865
int google_chromeec_get_usb_pd_power_info(enum usb_chg_type *type, uint16_t *current_max, uint16_t *voltage_max)
Definition: ec.c:1163
int google_chromeec_cbi_get_sku_id(uint32_t *id)
Definition: ec.c:839
usb_chg_type
Definition: ec_commands.h:5618
@ USB_CHG_TYPE_PD
Definition: ec_commands.h:5620
static void mainboard_init(struct device *dev)
Definition: mainboard.c:183
#define FIZZ_PL2_U22
Definition: mainboard.c:31
static unsigned long mainboard_write_acpi_tables(const struct device *device, unsigned long current, acpi_rsdp_t *rsdp)
Definition: mainboard.c:188
const char * smbios_system_sku(void)
Definition: mainboard.c:174
#define FIZZ_MAX_TIME_WINDOW
Definition: mainboard.c:34
void __weak variant_chip_display_init(void)
Definition: mainboard.c:252
static uint8_t read_sku_id_from_gpio(void)
Definition: mainboard.c:42
#define GPIO_DP_HPD
Definition: mainboard.c:229
static uint8_t board_oem_id(void)
Definition: mainboard.c:155
#define GPIO_HDMI_HPD
Definition: mainboard.c:228
#define FIZZ_PSYSPL2_U42
Definition: mainboard.c:33
static uint8_t read_oem_id_from_gpio(void)
Definition: mainboard.c:145
#define FIZZ_SKU_ID_I7_U42
Definition: mainboard.c:23
static uint8_t board_sku_id(void)
Definition: mainboard.c:53
static void mainboard_chip_init(void *chip_info)
Definition: mainboard.c:266
static void mainboard_set_power_limits(struct soc_power_limits_config *conf)
Definition: mainboard.c:102
#define FIZZ_SKU_ID_I3_U42
Definition: mainboard.c:25
static void mainboard_enable(struct device *dev)
Definition: mainboard.c:216
#define FIZZ_PSYSPL2_U22
Definition: mainboard.c:32
#define FIZZ_PL2_U42
Definition: mainboard.c:30
#define SET_PSYSPL2(w)
Definition: mainboard.c:40
static void wait_for_hpd(gpio_t gpio, long timeout)
Definition: mainboard.c:232
#define FIZZ_SKU_ID_I5_U42
Definition: mainboard.c:24
#define FIZZ_MIN_DUTYCYCLE
Definition: mainboard.c:35
void variant_nhlt_init(struct nhlt *nhlt)
Definition: nhlt.c:7
uint32_t sku_id(void)
Definition: mainboard.c:11
enum project_sku sku
Definition: mainboard.c:51
void __weak variant_nhlt_oem_overrides(const char **oem_id, const char **oem_table_id, uint32_t *oem_revision)
Definition: mainboard.c:86
#define config_of_soc()
Definition: device.h:394
int gpio_get(gpio_t gpio)
Definition: gpio.c:166
uint32_t gpio_base2_value(const gpio_t gpio[], int num_gpio)
Definition: gpio.c:30
void gpio_input(gpio_t gpio)
Definition: gpio.c:189
struct nhlt * nhlt_init(void)
Definition: nhlt.c:23
uintptr_t nhlt_soc_serialize_oem_overrides(struct nhlt *nhlt, uintptr_t acpi_addr, const char *oem_id, const char *oem_table_id, uint32_t oem_revision)
Definition: nhlt.c:12
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static long stopwatch_duration_msecs(struct stopwatch *sw)
Definition: timer.h:182
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
unsigned int type
Definition: edid.c:57
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
const struct pad_config *__weak variant_gpio_table(size_t *num)
Definition: gpio.c:406
#define GPIO_SKU_ID2
Definition: gpio.h:24
#define GPIO_SKU_ID0
Definition: gpio.h:22
#define GPIO_OEM_ID3
Definition: gpio.h:30
#define GPIO_SKU_ID3
Definition: gpio.h:25
#define GPIO_SKU_ID1
Definition: gpio.h:23
#define GPIO_OEM_ID1
Definition: gpio.h:28
#define GPIO_OEM_ID2
Definition: gpio.h:29
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
void gpio_configure_pads(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
program a particular set of GPIO
Definition: gpio.c:307
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
uint16_t u16
Definition: stdint.h:48
unsigned char uint8_t
Definition: stdint.h:8
Definition: acpi.h:82
void(* init)(void *chip_info)
Definition: device.h:25
void(* init)(struct device *dev)
Definition: device.h:42
Definition: device.h:107
struct device_operations * ops
Definition: device.h:143
Definition: pinmux.c:36
Definition: nhlt.h:287
uint32_t tdp_psyspl3_dutycycle
Definition: power_limit.h:32
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35