• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <baseboard/cbi_ssfc.h>
5 #include <baseboard/variants.h>
6 #include <boardid.h>
7 #include <bootstate.h>
8 #include <console/console.h>
9 #include <device/device.h>
10 #include <device/pci_def.h>
11 #include <device/pci_ops.h>
12 #include <drivers/i2c/generic/chip.h>
13 #include <ec/google/chromeec/ec.h>
14 #include <ec/ec.h>
15 #include <intelblocks/xhci.h>
16 #include <nhlt.h>
17 #include <smbios.h>
18 #include <soc/cpu.h>
19 #include <soc/gpio.h>
20 #include <soc/nhlt.h>
21 #include <soc/pci_devs.h>
22 #include <stdint.h>
23 #include <variant/ec.h>
24 #include <variant/gpio.h>
25 
26 extern struct chip_operations drivers_i2c_generic_ops;
27 extern struct chip_operations drivers_i2c_cs42l42_ops;
28 extern struct chip_operations drivers_i2c_da7219_ops;
29 
is_cnvi_held_in_reset(void)30 static bool is_cnvi_held_in_reset(void)
31 {
32 	struct device *dev = pcidev_path_on_root(PCH_DEVFN_CNVI);
33 	uint32_t reg = pci_read_config32(dev, PCI_VENDOR_ID);
34 
35 	/*
36 	 * If vendor/device ID for CNVi reads as 0xffffffff, then it is safe to
37 	 * assume that it is being held in reset.
38 	 */
39 	if (reg == 0xffffffff)
40 		return true;
41 
42 	return false;
43 }
44 
disable_wifi_wake(void)45 static void disable_wifi_wake(void)
46 {
47 	static const struct pad_config wifi_wake_gpio[] = {
48 		PAD_NC(GPIO_119, UP_20K),
49 	};
50 
51 	gpio_configure_pads(wifi_wake_gpio, ARRAY_SIZE(wifi_wake_gpio));
52 }
53 
54 /*
55  * GPIO_137 for two audio codecs right now has the different configuration so
56  * if SSFC indicates that codec is different than default one then GPIO_137
57  * needs to be overridden for the corresponding second source.
58  */
gpio_modification_by_ssfc(struct pad_config * table,size_t num)59 static void gpio_modification_by_ssfc(struct pad_config *table, size_t num)
60 {
61 	/* For RT5682, GPIO 137 should be set as EDGE_BOTH. */
62 	const struct pad_config rt5682_gpio_137 = PAD_CFG_GPI_APIC_IOS(GPIO_137,
63 			NONE, DEEP, EDGE_BOTH, INVERT, HIZCRx1, DISPUPD);
64 	enum ssfc_audio_codec codec = ssfc_get_audio_codec();
65 
66 	if (table == NULL || num == 0)
67 		return;
68 
69 	/*
70 	 * Currently we only have the case of RT5682 as the second source. And
71 	 * in case of Ampton which used RT5682 as the default source, it didn't
72 	 * provide override_table right now so it will be returned earlier since
73 	 * table above is NULL.
74 	 */
75 	if ((codec != SSFC_AUDIO_CODEC_RT5682) &&
76 		(codec != SSFC_AUDIO_CODEC_RT5682_VS))
77 		return;
78 
79 	while (num--) {
80 		if (table->pad == GPIO_137) {
81 			*table = rt5682_gpio_137;
82 			printk(BIOS_INFO,
83 				"Configure GPIO 137 based on SSFC.\n");
84 			return;
85 		}
86 
87 		table++;
88 	}
89 }
90 
mainboard_init(void * chip_info)91 static void mainboard_init(void *chip_info)
92 {
93 	int boardid;
94 	const struct pad_config *base_pads;
95 	const struct pad_config *override_pads;
96 	size_t base_num, override_num;
97 
98 	boardid = board_id();
99 	printk(BIOS_INFO, "Board ID: %d\n", boardid);
100 
101 	base_pads = baseboard_gpio_table(&base_num);
102 	override_pads = variant_override_gpio_table(&override_num);
103 	gpio_modification_by_ssfc((struct pad_config *)override_pads,
104 			override_num);
105 
106 	gpio_configure_pads_with_override(base_pads, base_num,
107 			override_pads, override_num);
108 
109 	if (!is_cnvi_held_in_reset())
110 		disable_wifi_wake();
111 
112 	mainboard_ec_init();
113 }
114 
mainboard_write_acpi_tables(const struct device * device,unsigned long current,acpi_rsdp_t * rsdp)115 static unsigned long mainboard_write_acpi_tables(
116 	const struct device *device, unsigned long current, acpi_rsdp_t *rsdp)
117 {
118 	uintptr_t start_addr;
119 	uintptr_t end_addr;
120 	struct nhlt *nhlt;
121 
122 	start_addr = current;
123 
124 	nhlt = nhlt_init();
125 
126 	if (nhlt == NULL)
127 		return start_addr;
128 
129 	variant_nhlt_init(nhlt);
130 
131 	end_addr = nhlt_soc_serialize(nhlt, start_addr);
132 
133 	if (end_addr != start_addr)
134 		acpi_add_table(rsdp, (void *)start_addr);
135 
136 	return end_addr;
137 }
138 
mainboard_enable(struct device * dev)139 static void mainboard_enable(struct device *dev)
140 {
141 	dev->ops->write_acpi_tables = mainboard_write_acpi_tables;
142 }
143 
144 struct chip_operations mainboard_ops = {
145 	.init = mainboard_init,
146 	.enable_dev = mainboard_enable,
147 };
148 
variant_update_devtree(struct device * dev)149 void __weak variant_update_devtree(struct device *dev)
150 {
151 	/* Place holder for common updates. */
152 }
153 
154 /*
155  * Check if CNVi PCI device is released from reset. If yes, then the system is
156  * booting with CNVi module. In this case, the PCIe device for WiFi needs to
157  * be disabled. If CNVi device is held in reset, then disable it.
158  */
wifi_device_update(void)159 static void wifi_device_update(void)
160 {
161 	struct device *dev;
162 	unsigned int devfn;
163 
164 	if (is_cnvi_held_in_reset())
165 		devfn = PCH_DEVFN_CNVI;
166 	else
167 		devfn = PCH_DEVFN_PCIE1;
168 
169 	dev = pcidev_path_on_root(devfn);
170 	if (dev)
171 		dev->enabled = 0;
172 }
173 
174 /*
175  * Base on SSFC value in the CBI from EC to enable one of audio codec sources in
176  * the device tree.
177  */
audio_codec_device_update(void)178 static void audio_codec_device_update(void)
179 {
180 	struct device *audio_dev = NULL;
181 	struct bus *audio_i2c_bus =
182 		pcidev_path_on_root(PCH_DEVFN_I2C5)->downstream;
183 	enum ssfc_audio_codec codec = ssfc_get_audio_codec();
184 
185 	while ((audio_dev = dev_bus_each_child(audio_i2c_bus, audio_dev))) {
186 		if (audio_dev->chip_info == NULL)
187 			continue;
188 
189 		if ((audio_dev->chip_ops == &drivers_i2c_da7219_ops) &&
190 			(codec == SSFC_AUDIO_CODEC_DA7219)) {
191 			printk(BIOS_INFO, "enable DA7219.\n");
192 			continue;
193 		}
194 
195 		if (audio_dev->chip_ops == &drivers_i2c_generic_ops) {
196 			struct drivers_i2c_generic_config *cfg =
197 				audio_dev->chip_info;
198 
199 			if ((cfg != NULL && !strcmp(cfg->hid, "10EC5682")) &&
200 				(codec == SSFC_AUDIO_CODEC_RT5682)) {
201 				printk(BIOS_INFO, "enable RT5682 VD.\n");
202 				continue;
203 			}
204 
205 			if ((cfg != NULL && !strcmp(cfg->hid, "10EC5682")) &&
206 				(codec == SSFC_AUDIO_CODEC_RT5682_VS)) {
207 				cfg->hid = "RTL5682";
208 				printk(BIOS_INFO, "enable RT5682 VS.\n");
209 				continue;
210 			}
211 
212 			if ((cfg != NULL && !strcmp(cfg->hid, "RTL5682")) &&
213 				(codec == SSFC_AUDIO_CODEC_RT5682_VS)) {
214 				printk(BIOS_INFO, "enable RT5682 VS.\n");
215 				continue;
216 			}
217 		}
218 
219 		if ((audio_dev->chip_ops == &drivers_i2c_cs42l42_ops) &&
220 			(codec == SSFC_AUDIO_CODEC_CS42L42)) {
221 			printk(BIOS_INFO, "enable CS42L42.\n");
222 			continue;
223 		}
224 
225 		printk(BIOS_INFO, "%s has been disabled\n", audio_dev->chip_ops->name);
226 		audio_dev->enabled = 0;
227 	}
228 }
229 
mainboard_devtree_update(struct device * dev)230 void mainboard_devtree_update(struct device *dev)
231 {
232 	/* Apply common devtree updates. */
233 	wifi_device_update();
234 	audio_codec_device_update();
235 
236 	/* Defer to variant for board-specific updates. */
237 	variant_update_devtree(dev);
238 }
239 
variant_ext_usb_status(unsigned int port_type,unsigned int port_id)240 bool __weak variant_ext_usb_status(unsigned int port_type, unsigned int port_id)
241 {
242 	/* All externally visible USB ports are present */
243 	return true;
244 }
245 
disable_unused_devices(void * unused)246 static void disable_unused_devices(void *unused)
247 {
248 	usb_xhci_disable_unused(variant_ext_usb_status);
249 }
250 
251 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, disable_unused_devices, NULL);
252