• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <device/device.h>
5 #include <device/pnp.h>
6 #include <ec/acpi/ec.h>
7 #include <option.h>
8 
9 #include "ec.h"
10 #include "ecdefs.h"
11 
ec_get_version(void)12 uint16_t ec_get_version(void)
13 {
14 	return (ec_read(ECRAM_MAJOR_VERSION) << 8) | ec_read(ECRAM_MINOR_VERSION);
15 }
16 
get_ec_value_from_option(const char * name,unsigned int fallback,const uint8_t * lut,size_t lut_size)17 static uint8_t get_ec_value_from_option(const char *name,
18 					unsigned int fallback,
19 					const uint8_t *lut,
20 					size_t lut_size)
21 {
22 	unsigned int index = get_uint_option(name, fallback);
23 	if (index >= lut_size)
24 		index = fallback;
25 	return lut[index];
26 }
27 
ec_mirror_flag(void)28 void ec_mirror_flag(void)
29 {
30 	/*
31 	 * For the mirror flag to work, the status of the EC pin must be known
32 	 * at all times, which means external power. This can be either a DC
33 	 * charger, or PD with CCG6. PD with an ANX7447 requires configuration
34 	 * from the EC, so the update will interrupt this.
35 	 *
36 	 * This means we can unconditionally apply the mirror flag to devices
37 	 * that have CCG6, present on devices with TBT, but have a manual
38 	 * flag for devices without it.
39 	 */
40 	uint16_t ec_version = ec_get_version();
41 
42 	/* Full mirror support was added in EC 1.18 (0x0112) */
43 	if (ec_version < 0x0112)
44 		return;
45 
46 	if (CONFIG(EC_STARLABS_MIRROR_SUPPORT) &&
47 		(CONFIG(DRIVERS_INTEL_USB4_RETIMER) || get_uint_option("mirror_flag", 0)) &&
48 		(ec_version != CONFIG_EC_STARLABS_MIRROR_VERSION)) {
49 		printk(BIOS_ERR, "ITE: EC version 0x%x doesn't match coreboot version 0x%x.\n",
50 			ec_version, CONFIG_EC_STARLABS_MIRROR_VERSION);
51 
52 		ec_write(ECRAM_MIRROR_FLAG, MIRROR_ENABLED);
53 	}
54 }
55 
ec_get_chip_id(unsigned int port)56 static uint16_t ec_get_chip_id(unsigned int port)
57 {
58 	return (pnp_read_index(port, ITE_CHIPID1) << 8) |
59 		pnp_read_index(port, ITE_CHIPID2);
60 }
61 
merlin_init(struct device * dev)62 static void merlin_init(struct device *dev)
63 {
64 	if (!dev->enabled)
65 		return;
66 
67 	/*
68 	 * The address/data IO port pair for the ite EC are configurable
69 	 * through the EC domain and are fixed by the EC's firmware blob. If
70 	 * the value(s) passed through the "dev" structure don't match the
71 	 * expected values then output severe warnings.
72 	 */
73 	if (dev->path.pnp.port != ITE_FIXED_ADDR) {
74 		printk(BIOS_ERR, "ITE: Incorrect ports defined in devicetree.cb.\n");
75 		printk(BIOS_ERR, "ITE: Serious operational issues will arise.\n");
76 		return;
77 	}
78 
79 	const uint16_t chip_id = ec_get_chip_id(dev->path.pnp.port);
80 
81 	if (chip_id != ITE_CHIPID_VAL) {
82 		printk(BIOS_ERR, "ITE: Expected chip ID 0x%04x, but got 0x%04x instead.\n",
83 			ITE_CHIPID_VAL, chip_id);
84 		return;
85 	}
86 
87 	ec_mirror_flag();
88 
89 	/*
90 	 * Restore settings from CMOS into EC RAM:
91 	 *
92 	 * kbl_timeout
93 	 * fn_ctrl_swap
94 	 * max_charge
95 	 * fan_mode
96 	 * fn_lock_state
97 	 * trackpad_state
98 	 * kbl_brightness
99 	 * kbl_state
100 	 */
101 
102 	/*
103 	 * Keyboard Backlight Timeout
104 	 *
105 	 * Setting:	kbl_timeout
106 	 *
107 	 * Values:	30 Seconds, 1 Minute, 3 Minutes, 5 Minutes, Never
108 	 * Default:	30 Seconds
109 	 *
110 	 */
111 	const uint8_t kbl_timeout[] = {
112 		SEC_30,
113 		MIN_1,
114 		MIN_3,
115 		MIN_5,
116 		NEVER
117 	};
118 
119 	ec_write(ECRAM_KBL_TIMEOUT,
120 		get_ec_value_from_option("kbl_timeout",
121 					 0,
122 					 kbl_timeout,
123 					 ARRAY_SIZE(kbl_timeout)));
124 
125 	/*
126 	 * Fn Ctrl Reverse
127 	 *
128 	 * Setting:	fn_ctrl_swap
129 	 *
130 	 * Values:	Enabled, Disabled
131 	 * Default:	Disabled
132 	 *
133 	 */
134 	const uint8_t fn_ctrl_swap[] = {
135 		FN_CTRL,
136 		CTRL_FN
137 	};
138 
139 	ec_write(ECRAM_FN_CTRL_REVERSE,
140 		get_ec_value_from_option("fn_ctrl_swap",
141 					 0,
142 					 fn_ctrl_swap,
143 					 ARRAY_SIZE(fn_ctrl_swap)));
144 
145 	/*
146 	 * Maximum Charge Level
147 	 *
148 	 * Setting:	max_charge
149 	 *
150 	 * Values:	60%, 80%, 100%
151 	 * Default:	100%
152 	 *
153 	 */
154 	const uint8_t max_charge[] = {
155 		CHARGE_100,
156 		CHARGE_80,
157 		CHARGE_60
158 	};
159 
160 	if (CONFIG(EC_STARLABS_MAX_CHARGE))
161 		ec_write(ECRAM_MAX_CHARGE,
162 			get_ec_value_from_option("max_charge",
163 						 0,
164 						 max_charge,
165 						 ARRAY_SIZE(max_charge)));
166 
167 	/*
168 	 * Fan Mode
169 	 *
170 	 * Setting:	fan_mode
171 	 *
172 	 * Values:	Quiet, Normal, Aggressive
173 	 * Default:	Normal
174 	 *
175 	 */
176 	const uint8_t fan_mode[] = {
177 		FAN_NORMAL,
178 		FAN_AGGRESSIVE,
179 		FAN_QUIET
180 	};
181 
182 	if (CONFIG(EC_STARLABS_FAN))
183 		ec_write(ECRAM_FAN_MODE,
184 			get_ec_value_from_option("fan_mode",
185 						 0,
186 						 fan_mode,
187 						 ARRAY_SIZE(fan_mode)));
188 
189 	/*
190 	 * Function Lock
191 	 *
192 	 * Setting:	fn_lock_state
193 	 *
194 	 * Values:	Locked, Unlocked
195 	 * Default:	Locked
196 	 *
197 	 */
198 	const uint8_t fn_lock_state[] = {
199 		UNLOCKED,
200 		LOCKED
201 	};
202 
203 	ec_write(ECRAM_FN_LOCK_STATE,
204 		get_ec_value_from_option("fn_lock_state",
205 					 1,
206 					 fn_lock_state,
207 					 ARRAY_SIZE(fn_lock_state)));
208 
209 	/*
210 	 * Trackpad State
211 	 *
212 	 * Setting:	trackpad_state
213 	 *
214 	 * Values:	Enabled, Disabled
215 	 * Default:	Enabled
216 	 *
217 	 */
218 	const uint8_t trackpad_state[] = {
219 		TRACKPAD_ENABLED,
220 		TRACKPAD_DISABLED
221 	};
222 
223 	ec_write(ECRAM_TRACKPAD_STATE,
224 		get_ec_value_from_option("trackpad_state",
225 					 0,
226 					 trackpad_state,
227 					 ARRAY_SIZE(trackpad_state)));
228 
229 	/*
230 	 * Keyboard Backlight Brightness
231 	 *
232 	 * Setting:	kbl_brightness
233 	 *
234 	 * Values:	Off, Low, High / Off, On
235 	 * Default:	Low
236 	 *
237 	 */
238 	const uint8_t kbl_brightness[] = {
239 		KBL_ON,
240 		KBL_OFF,
241 		KBL_LOW,
242 		KBL_HIGH
243 	};
244 
245 	if (CONFIG(EC_STARLABS_KBL_LEVELS))
246 		ec_write(ECRAM_KBL_BRIGHTNESS,
247 			get_ec_value_from_option("kbl_brightness",
248 						 2,
249 						 kbl_brightness,
250 						 ARRAY_SIZE(kbl_brightness)));
251 	else
252 		ec_write(ECRAM_KBL_BRIGHTNESS,
253 			get_ec_value_from_option("kbl_brightness",
254 						 0,
255 						 kbl_brightness,
256 						 ARRAY_SIZE(kbl_brightness)));
257 
258 	/*
259 	 * Keyboard Backlight State
260 	 *
261 	 * Setting:	kbl_state
262 	 *
263 	 * Values:	Off, On
264 	 * Default:	On
265 	 *
266 	 * Note:	Always enable, as the brightness level of `off` disables it.
267 	 *
268 	 */
269 
270 	ec_write(ECRAM_KBL_STATE, KBL_ENABLED);
271 }
272 
273 static struct device_operations ops = {
274 	.init		= merlin_init,
275 	.read_resources	= noop_read_resources,
276 	.set_resources	= noop_set_resources,
277 };
278 
279 static struct pnp_info pnp_dev_info[] = {
280 	/* Serial Port 1 (UART1) */
281 	{ NULL,	ITE_SP1,	PNP_IO0 | PNP_IRQ0,		0x0ff8,		},
282 	/* Serial Port 2 (UART2) */
283 	{ NULL, ITE_SP2,	PNP_IO0 | PNP_IRQ0,		0x0ff8,		},
284 	/* System Wake-Up Control (SWUC) */
285 	{ NULL,	ITE_SWUC,	PNP_IO0 | PNP_IRQ0,		0xfff0,		},
286 	/* KBC / Mouse Interface */
287 	{ NULL, ITE_SWUC,	PNP_IRQ0,					},
288 	/* KBC / Keyboard Interface */
289 	{ NULL, ITE_KBCK,	PNP_IO0 | PNP_IO1 | PNP_IRQ0,	0x07ff,	0x07ff,	},
290 	/* Consumer IR (CIR) */
291 	{ NULL, ITE_IR,		PNP_IO0 | PNP_IRQ0,		0xfff8,		},
292 	/* Shared Memory / Flash Interface (SMFI) */
293 	{ NULL, ITE_SMFI,	PNP_IO0 | PNP_IRQ0,		0xfff0,		},
294 	/* RTC-like Timer (RCTC) */
295 	{ NULL, ITE_RTCT,	PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IO3 | PNP_IRQ0,
296 				0xfffe, 0xfffe, 0xfffe, 0xfffe,			},
297 	/* Power Management I/F Channel 1 (PMC1) */
298 	{ NULL, ITE_PMC1,	PNP_IO0 | PNP_IO1 | PNP_IRQ0,	0x07ff,	0x07ff,	},
299 	/* Power Management I/F Channel 2 (PMC2) */
300 	{ NULL, ITE_PMC2,	PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IRQ0,	0x07fc,
301 				0x07fc, 0xfff0,					},
302 	/* Serial Peripheral Interface (SSPI) */
303 	{ NULL,	ITE_SSPI,	PNP_IO0 | PNP_IRQ0,		0xfff8,		},
304 	/* Platform Environment Control Interface (PECI) */
305 	{ NULL, ITE_PECI,	PNP_IRQ0,			0xfff8,		},
306 	/* Power Management I/F Channel 3 (PMC3) */
307 	{ NULL, ITE_PMC3,	PNP_IO0 | PNP_IO1 | PNP_IRQ0,	0x07ff,	0x07ff,	},
308 	/* Power Management I/F Channel 4 (PMC4) */
309 	{ NULL, ITE_PMC4,	PNP_IO0 | PNP_IO1 | PNP_IRQ0,	0x07ff,	0x07ff,	},
310 	/* Power Management I/F Channel 5 (PMC5) */
311 	{ NULL, ITE_PMC5,	PNP_IO0 | PNP_IO1 | PNP_IRQ0,	0x07ff,	0x07ff,	},
312 };
313 
enable_dev(struct device * dev)314 static void enable_dev(struct device *dev)
315 {
316 	pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
317 }
318 
319 struct chip_operations ec_starlabs_merlin_ops = {
320 	.name = "ITE EC",
321 	.enable_dev = enable_dev
322 };
323