File Index
Files and directories
Sign in
FILE

lenovo-thinkpad-t14s.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/arm64/lenovo-thinkpad-t14s.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2025, Sebastian Reichel
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/bits.h>
  8#include <linux/cleanup.h>
  9#include <linux/container_of.h>
 10#include <linux/device.h>
 11#include <linux/delay.h>
 12#include <linux/dev_printk.h>
 13#include <linux/err.h>
 14#include <linux/i2c.h>
 15#include <linux/input.h>
 16#include <linux/input/sparse-keymap.h>
 17#include <linux/interrupt.h>
 18#include <linux/leds.h>
 19#include <linux/lockdep.h>
 20#include <linux/module.h>
 21#include <linux/regmap.h>
 22#include <linux/slab.h>
 23#include <linux/pm.h>
 24
 25#define T14S_EC_CMD_ECRD	0x02
 26#define T14S_EC_CMD_ECWR	0x03
 27#define T14S_EC_CMD_EVT		0xf0
 28
 29#define T14S_EC_REG_LED				0x0c
 30#define T14S_EC_REG_KBD_BL1			0x0d
 31#define T14S_EC_REG_MODERN_STANDBY		0xe0
 32#define T14S_EC_MODERN_STANDBY_ENTRY		BIT(1)
 33#define T14S_EC_MODERN_STANDBY_EXIT		BIT(0)
 34#define T14S_EC_REG_KBD_BL2			0xe1
 35#define T14S_EC_KBD_BL1_MASK			GENMASK_U8(7, 6)
 36#define T14S_EC_KBD_BL2_MASK			GENMASK_U8(3, 2)
 37#define T14S_EC_REG_AUD				0x30
 38#define T14S_EC_MIC_MUTE_LED			BIT(5)
 39#define T14S_EC_SPK_MUTE_LED			BIT(6)
 40
 41#define T14S_EC_EVT_NONE			0x00
 42#define T14S_EC_EVT_KEY_FN_4			0x13
 43#define T14S_EC_EVT_KEY_FN_F7			0x16
 44#define T14S_EC_EVT_KEY_FN_SPACE		0x1f
 45#define T14S_EC_EVT_KEY_TP_DOUBLE_TAP		0x20
 46#define T14S_EC_EVT_AC_CONNECTED		0x26
 47#define T14S_EC_EVT_AC_DISCONNECTED		0x27
 48#define T14S_EC_EVT_KEY_POWER			0x28
 49#define T14S_EC_EVT_LID_OPEN			0x2a
 50#define T14S_EC_EVT_LID_CLOSED			0x2b
 51#define T14S_EC_EVT_THERMAL_TZ40		0x5c
 52#define T14S_EC_EVT_THERMAL_TZ42		0x5d
 53#define T14S_EC_EVT_THERMAL_TZ39		0x5e
 54#define T14S_EC_EVT_KEY_FN_F12			0x62
 55#define T14S_EC_EVT_KEY_FN_TAB			0x63
 56#define T14S_EC_EVT_KEY_FN_F8			0x64
 57#define T14S_EC_EVT_KEY_FN_F10			0x65
 58#define T14S_EC_EVT_KEY_FN_F4			0x6a
 59#define T14S_EC_EVT_KEY_FN_D			0x6b
 60#define T14S_EC_EVT_KEY_FN_T			0x6c
 61#define T14S_EC_EVT_KEY_FN_H			0x6d
 62#define T14S_EC_EVT_KEY_FN_M			0x6e
 63#define T14S_EC_EVT_KEY_FN_L			0x6f
 64#define T14S_EC_EVT_KEY_FN_RIGHT_SHIFT		0x71
 65#define T14S_EC_EVT_KEY_FN_ESC			0x74
 66#define T14S_EC_EVT_KEY_FN_N			0x79
 67#define T14S_EC_EVT_KEY_FN_F11			0x7a
 68#define T14S_EC_EVT_KEY_FN_G			0x7e
 69
 70/* Hardware LED blink rate is 1 Hz (500ms off, 500ms on) */
 71#define T14S_EC_BLINK_RATE_ON_OFF_MS		500
 72
 73/*
 74 * Add a virtual offset on all key event codes for sparse keymap handling,
 75 * since the sparse keymap infrastructure does not map some raw key event
 76 * codes used by the EC. For example 0x16 (T14S_EC_EVT_KEY_FN_F7) is mapped
 77 * to KEY_MUTE if no offset is applied.
 78 */
 79#define T14S_EC_KEY_EVT_OFFSET			0x1000
 80#define T14S_EC_KEY_ENTRY(key, value) \
 81	{ KE_KEY, T14S_EC_KEY_EVT_OFFSET + T14S_EC_EVT_KEY_##key, { value } }
 82
 83enum t14s_ec_led_status_t {
 84	T14S_EC_LED_OFF =	0x00,
 85	T14S_EC_LED_ON =	0x80,
 86	T14S_EC_LED_BLINK =	0xc0,
 87};
 88
 89struct t14s_ec_led_classdev {
 90	struct led_classdev led_classdev;
 91	int led;
 92	enum t14s_ec_led_status_t cache;
 93	struct t14s_ec *ec;
 94};
 95
 96struct t14s_ec {
 97	struct regmap *regmap;
 98	struct device *dev;
 99	struct t14s_ec_led_classdev led_pwr_btn;
100	struct t14s_ec_led_classdev led_chrg_orange;
101	struct t14s_ec_led_classdev led_chrg_white;
102	struct t14s_ec_led_classdev led_lid_logo_dot;
103	struct led_classdev kbd_backlight;
104	struct led_classdev led_mic_mute;
105	struct led_classdev led_spk_mute;
106	struct input_dev *inputdev;
107};
108
109static const struct regmap_config t14s_ec_regmap_config = {
110	.reg_bits = 8,
111	.val_bits = 8,
112	.max_register = 0xff,
113};
114
115static int t14s_ec_write(void *context, unsigned int reg,
116				  unsigned int val)
117{
118	struct t14s_ec *ec = context;
119	struct i2c_client *client = to_i2c_client(ec->dev);
120	u8 buf[5] = {T14S_EC_CMD_ECWR, reg, 0x00, 0x01, val};
121	int ret;
122
123	ret = i2c_master_send(client, buf, sizeof(buf));
124	if (ret < 0)
125		return ret;
126
127	fsleep(10000);
128	return 0;
129}
130
131static int t14s_ec_read(void *context, unsigned int reg,
132				 unsigned int *val)
133{
134	struct t14s_ec *ec = context;
135	struct i2c_client *client = to_i2c_client(ec->dev);
136	u8 buf[4] = {T14S_EC_CMD_ECRD, reg, 0x00, 0x01};
137	struct i2c_msg request, response;
138	u8 result;
139	int ret;
140
141	request.addr = client->addr;
142	request.flags = I2C_M_STOP;
143	request.len = sizeof(buf);
144	request.buf = buf;
145	response.addr = client->addr;
146	response.flags = I2C_M_RD;
147	response.len = 1;
148	response.buf = &result;
149
150	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
151
152	ret = __i2c_transfer(client->adapter, &request, 1);
153	if (ret < 0)
154		goto out;
155
156	ret = __i2c_transfer(client->adapter, &response, 1);
157	if (ret < 0)
158		goto out;
159
160	*val = result;
161	ret = 0;
162
163out:
164	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
165	fsleep(10000);
166	return ret;
167}
168
169static const struct regmap_bus t14s_ec_regmap_bus = {
170	.reg_write = t14s_ec_write,
171	.reg_read = t14s_ec_read,
172};
173
174static int t14s_ec_read_evt(struct t14s_ec *ec, u8 *val)
175{
176	struct i2c_client *client = to_i2c_client(ec->dev);
177	u8 buf[4] = {T14S_EC_CMD_EVT, 0x00, 0x00, 0x01};
178	struct i2c_msg request, response;
179	int ret;
180
181	request.addr = client->addr;
182	request.flags = I2C_M_STOP;
183	request.len = sizeof(buf);
184	request.buf = buf;
185	response.addr = client->addr;
186	response.flags = I2C_M_RD;
187	response.len = 1;
188	response.buf = val;
189
190	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
191
192	ret = __i2c_transfer(client->adapter, &request, 1);
193	if (ret < 0)
194		goto out;
195
196	ret = __i2c_transfer(client->adapter, &response, 1);
197	if (ret < 0)
198		goto out;
199
200	fsleep(10000);
201
202	ret = 0;
203
204out:
205	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
206	return ret;
207}
208
209static void t14s_ec_write_sequence(struct t14s_ec *ec, u8 reg, u8 val, u8 cnt)
210{
211	int i;
212
213	for (i = 0; i < cnt; i++)
214		regmap_write(ec->regmap, reg, val);
215}
216
217static int t14s_led_set_status(struct t14s_ec *ec,
218			       struct t14s_ec_led_classdev *led,
219			       const enum t14s_ec_led_status_t ledstatus)
220{
221	int ret;
222
223	ret = regmap_write(ec->regmap, T14S_EC_REG_LED,
224			   led->led | ledstatus);
225	if (ret < 0)
226		return ret;
227
228	led->cache = ledstatus;
229	return 0;
230}
231
232static int t14s_led_brightness_set(struct led_classdev *led_cdev,
233				   enum led_brightness brightness)
234{
235	struct t14s_ec_led_classdev *led = container_of(led_cdev,
236				struct t14s_ec_led_classdev, led_classdev);
237	enum t14s_ec_led_status_t new_state;
238
239	if (brightness == LED_OFF)
240		new_state = T14S_EC_LED_OFF;
241	else if (led->cache == T14S_EC_LED_BLINK)
242		new_state = T14S_EC_LED_BLINK;
243	else
244		new_state = T14S_EC_LED_ON;
245
246	return t14s_led_set_status(led->ec, led, new_state);
247}
248
249static int t14s_led_blink_set(struct led_classdev *led_cdev,
250			      unsigned long *delay_on,
251			      unsigned long *delay_off)
252{
253	struct t14s_ec_led_classdev *led = container_of(led_cdev,
254				struct t14s_ec_led_classdev, led_classdev);
255
256	if (*delay_on == 0 && *delay_off == 0) {
257		/* Userspace does not provide a blink rate; we can choose it */
258		*delay_on = T14S_EC_BLINK_RATE_ON_OFF_MS;
259		*delay_off = T14S_EC_BLINK_RATE_ON_OFF_MS;
260	} else if ((*delay_on != T14S_EC_BLINK_RATE_ON_OFF_MS) ||
261		   (*delay_off != T14S_EC_BLINK_RATE_ON_OFF_MS))
262		return -EINVAL;
263
264	return t14s_led_set_status(led->ec, led, T14S_EC_LED_BLINK);
265}
266
267static int t14s_init_led(struct t14s_ec *ec, struct t14s_ec_led_classdev *led,
268			 u8 id, const char *name)
269{
270	led->led_classdev.name = name;
271	led->led_classdev.flags = LED_RETAIN_AT_SHUTDOWN;
272	led->led_classdev.max_brightness = 1;
273	led->led_classdev.brightness_set_blocking = t14s_led_brightness_set;
274	led->led_classdev.blink_set = t14s_led_blink_set;
275	led->ec = ec;
276	led->led = id;
277
278	return devm_led_classdev_register(ec->dev, &led->led_classdev);
279}
280
281static int t14s_leds_probe(struct t14s_ec *ec)
282{
283	int ret;
284
285	ret = t14s_init_led(ec, &ec->led_pwr_btn, 0, "platform::power");
286	if (ret)
287		return ret;
288
289	ret = t14s_init_led(ec, &ec->led_chrg_orange, 1,
290			    "platform:amber:battery-charging");
291	if (ret)
292		return ret;
293
294	ret = t14s_init_led(ec, &ec->led_chrg_white, 2,
295			    "platform:white:battery-full");
296	if (ret)
297		return ret;
298
299	ret = t14s_init_led(ec, &ec->led_lid_logo_dot, 10,
300			    "platform::lid_logo_dot");
301	if (ret)
302		return ret;
303
304	return 0;
305}
306
307static int t14s_kbd_bl_set(struct led_classdev *led_cdev,
308			   enum led_brightness brightness)
309{
310	struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec,
311					  kbd_backlight);
312	int ret;
313	u8 val;
314
315	val = FIELD_PREP(T14S_EC_KBD_BL1_MASK, brightness);
316	ret = regmap_update_bits(ec->regmap, T14S_EC_REG_KBD_BL1,
317				 T14S_EC_KBD_BL1_MASK, val);
318	if (ret < 0)
319		return ret;
320
321	val = FIELD_PREP(T14S_EC_KBD_BL2_MASK, brightness);
322	ret = regmap_update_bits(ec->regmap, T14S_EC_REG_KBD_BL2,
323				 T14S_EC_KBD_BL2_MASK, val);
324	if (ret < 0)
325		return ret;
326
327	return 0;
328}
329
330static enum led_brightness t14s_kbd_bl_get(struct led_classdev *led_cdev)
331{
332	struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec,
333					  kbd_backlight);
334	unsigned int val;
335	int ret;
336
337	ret = regmap_read(ec->regmap, T14S_EC_REG_KBD_BL1, &val);
338	if (ret < 0)
339		return ret;
340
341	return FIELD_GET(T14S_EC_KBD_BL1_MASK, val);
342}
343
344static void t14s_kbd_bl_update(struct t14s_ec *ec)
345{
346	enum led_brightness brightness = t14s_kbd_bl_get(&ec->kbd_backlight);
347
348	led_classdev_notify_brightness_hw_changed(&ec->kbd_backlight, brightness);
349}
350
351static int t14s_kbd_backlight_probe(struct t14s_ec *ec)
352{
353	ec->kbd_backlight.name = "platform::kbd_backlight";
354	ec->kbd_backlight.flags = LED_BRIGHT_HW_CHANGED;
355	ec->kbd_backlight.max_brightness = 2;
356	ec->kbd_backlight.brightness_set_blocking = t14s_kbd_bl_set;
357	ec->kbd_backlight.brightness_get = t14s_kbd_bl_get;
358
359	return devm_led_classdev_register(ec->dev, &ec->kbd_backlight);
360}
361
362static enum led_brightness t14s_audio_led_get(struct t14s_ec *ec, u8 led_bit)
363{
364	unsigned int val;
365	int ret;
366
367	ret = regmap_read(ec->regmap, T14S_EC_REG_AUD, &val);
368	if (ret < 0)
369		return ret;
370
371	return !!(val & led_bit) ? LED_ON : LED_OFF;
372}
373
374static enum led_brightness t14s_audio_led_set(struct t14s_ec *ec,
375						       u8 led_mask,
376						       enum led_brightness brightness)
377{
378	return regmap_assign_bits(ec->regmap, T14S_EC_REG_AUD, led_mask, brightness > 0);
379}
380
381static enum led_brightness t14s_mic_mute_led_get(struct led_classdev *led_cdev)
382{
383	struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec,
384					  led_mic_mute);
385
386	return t14s_audio_led_get(ec, T14S_EC_MIC_MUTE_LED);
387}
388
389static int t14s_mic_mute_led_set(struct led_classdev *led_cdev,
390					  enum led_brightness brightness)
391{
392	struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec,
393					  led_mic_mute);
394
395	return t14s_audio_led_set(ec, T14S_EC_MIC_MUTE_LED, brightness);
396}
397
398static enum led_brightness t14s_spk_mute_led_get(struct led_classdev *led_cdev)
399{
400	struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec,
401					  led_spk_mute);
402
403	return t14s_audio_led_get(ec, T14S_EC_SPK_MUTE_LED);
404}
405
406static int t14s_spk_mute_led_set(struct led_classdev *led_cdev,
407					  enum led_brightness brightness)
408{
409	struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec,
410					  led_spk_mute);
411
412	return t14s_audio_led_set(ec, T14S_EC_SPK_MUTE_LED, brightness);
413}
414
415static int t14s_kbd_audio_led_probe(struct t14s_ec *ec)
416{
417	int ret;
418
419	ec->led_mic_mute.name = "platform::micmute";
420	ec->led_mic_mute.max_brightness = 1;
421	ec->led_mic_mute.default_trigger = "audio-micmute";
422	ec->led_mic_mute.brightness_set_blocking = t14s_mic_mute_led_set;
423	ec->led_mic_mute.brightness_get = t14s_mic_mute_led_get;
424
425	ec->led_spk_mute.name = "platform::mute";
426	ec->led_spk_mute.max_brightness = 1;
427	ec->led_spk_mute.default_trigger = "audio-mute";
428	ec->led_spk_mute.brightness_set_blocking = t14s_spk_mute_led_set;
429	ec->led_spk_mute.brightness_get = t14s_spk_mute_led_get;
430
431	ret = devm_led_classdev_register(ec->dev, &ec->led_mic_mute);
432	if (ret)
433		return ret;
434
435	return devm_led_classdev_register(ec->dev, &ec->led_spk_mute);
436}
437
438static const struct key_entry t14s_keymap[] = {
439	T14S_EC_KEY_ENTRY(FN_4, KEY_SLEEP),
440	T14S_EC_KEY_ENTRY(FN_N, KEY_VENDOR),
441	T14S_EC_KEY_ENTRY(FN_F4, KEY_MICMUTE),
442	T14S_EC_KEY_ENTRY(FN_F7, KEY_SWITCHVIDEOMODE),
443	T14S_EC_KEY_ENTRY(FN_F8, KEY_PERFORMANCE),
444	T14S_EC_KEY_ENTRY(FN_F10, KEY_SELECTIVE_SCREENSHOT),
445	T14S_EC_KEY_ENTRY(FN_F11, KEY_LINK_PHONE),
446	T14S_EC_KEY_ENTRY(FN_F12, KEY_BOOKMARKS),
447	T14S_EC_KEY_ENTRY(FN_SPACE, KEY_KBDILLUMTOGGLE),
448	T14S_EC_KEY_ENTRY(FN_ESC, KEY_FN_ESC),
449	T14S_EC_KEY_ENTRY(FN_TAB, KEY_ZOOM),
450	T14S_EC_KEY_ENTRY(FN_RIGHT_SHIFT, KEY_FN_RIGHT_SHIFT),
451	T14S_EC_KEY_ENTRY(TP_DOUBLE_TAP, KEY_PROG4),
452	{ KE_END }
453};
454
455static int t14s_input_probe(struct t14s_ec *ec)
456{
457	int ret;
458
459	ec->inputdev = devm_input_allocate_device(ec->dev);
460	if (!ec->inputdev)
461		return -ENOMEM;
462
463	ec->inputdev->name = "ThinkPad Extra Buttons";
464	ec->inputdev->phys = "thinkpad/input0";
465	ec->inputdev->id.bustype = BUS_HOST;
466	ec->inputdev->dev.parent = ec->dev;
467
468	ret = sparse_keymap_setup(ec->inputdev, t14s_keymap, NULL);
469	if (ret)
470		return ret;
471
472	return input_register_device(ec->inputdev);
473}
474
475static irqreturn_t t14s_ec_irq_handler(int irq, void *data)
476{
477	struct t14s_ec *ec = data;
478	int ret;
479	u8 val;
480
481	ret = t14s_ec_read_evt(ec, &val);
482	if (ret < 0) {
483		dev_err(ec->dev, "Failed to read event\n");
484		return IRQ_HANDLED;
485	}
486
487	switch (val) {
488	case T14S_EC_EVT_NONE:
489		break;
490	case T14S_EC_EVT_KEY_FN_SPACE:
491		t14s_kbd_bl_update(ec);
492		fallthrough;
493	case T14S_EC_EVT_KEY_FN_F4:
494	case T14S_EC_EVT_KEY_FN_F7:
495	case T14S_EC_EVT_KEY_FN_4:
496	case T14S_EC_EVT_KEY_FN_F8:
497	case T14S_EC_EVT_KEY_FN_F12:
498	case T14S_EC_EVT_KEY_FN_TAB:
499	case T14S_EC_EVT_KEY_FN_F10:
500	case T14S_EC_EVT_KEY_FN_N:
501	case T14S_EC_EVT_KEY_FN_F11:
502	case T14S_EC_EVT_KEY_FN_ESC:
503	case T14S_EC_EVT_KEY_FN_RIGHT_SHIFT:
504	case T14S_EC_EVT_KEY_TP_DOUBLE_TAP:
505		sparse_keymap_report_event(ec->inputdev,
506				T14S_EC_KEY_EVT_OFFSET + val, 1, true);
507		break;
508	case T14S_EC_EVT_AC_CONNECTED:
509		dev_dbg(ec->dev, "AC connected\n");
510		break;
511	case T14S_EC_EVT_AC_DISCONNECTED:
512		dev_dbg(ec->dev, "AC disconnected\n");
513		break;
514	case T14S_EC_EVT_KEY_POWER:
515		dev_dbg(ec->dev, "power button\n");
516		break;
517	case T14S_EC_EVT_LID_OPEN:
518		dev_dbg(ec->dev, "LID open\n");
519		break;
520	case T14S_EC_EVT_LID_CLOSED:
521		dev_dbg(ec->dev, "LID closed\n");
522		break;
523	case T14S_EC_EVT_THERMAL_TZ40:
524		dev_dbg(ec->dev, "Thermal Zone 40 Status Change Event (CPU/GPU)\n");
525		break;
526	case T14S_EC_EVT_THERMAL_TZ42:
527		dev_dbg(ec->dev, "Thermal Zone 42 Status Change Event (Battery)\n");
528		break;
529	case T14S_EC_EVT_THERMAL_TZ39:
530		dev_dbg(ec->dev, "Thermal Zone 39 Status Change Event (CPU/GPU)\n");
531		break;
532	case T14S_EC_EVT_KEY_FN_G:
533		dev_dbg(ec->dev, "FN + G - toggle double-tapping\n");
534		break;
535	case T14S_EC_EVT_KEY_FN_L:
536		dev_dbg(ec->dev, "FN + L - low performance mode\n");
537		break;
538	case T14S_EC_EVT_KEY_FN_M:
539		dev_dbg(ec->dev, "FN + M - medium performance mode\n");
540		break;
541	case T14S_EC_EVT_KEY_FN_H:
542		dev_dbg(ec->dev, "FN + H - high performance mode\n");
543		break;
544	case T14S_EC_EVT_KEY_FN_T:
545		dev_dbg(ec->dev, "FN + T - toggle intelligent cooling mode\n");
546		break;
547	case T14S_EC_EVT_KEY_FN_D:
548		dev_dbg(ec->dev, "FN + D - toggle privacy guard mode\n");
549		break;
550	default:
551		dev_info(ec->dev, "Unknown EC event: 0x%02x\n", val);
552		break;
553	}
554
555	return IRQ_HANDLED;
556}
557
558static int t14s_ec_probe(struct i2c_client *client)
559{
560	struct device *dev = &client->dev;
561	struct t14s_ec *ec;
562	int ret;
563
564	ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
565	if (!ec)
566		return -ENOMEM;
567
568	ec->dev = dev;
569	i2c_set_clientdata(client, ec);
570
571	ec->regmap = devm_regmap_init(dev, &t14s_ec_regmap_bus,
572				      ec, &t14s_ec_regmap_config);
573	if (IS_ERR(ec->regmap))
574		return dev_err_probe(dev, PTR_ERR(ec->regmap),
575				     "Failed to init regmap\n");
576
577	ret = t14s_leds_probe(ec);
578	if (ret < 0)
579		return ret;
580
581	ret = t14s_kbd_backlight_probe(ec);
582	if (ret < 0)
583		return ret;
584
585	ret = t14s_kbd_audio_led_probe(ec);
586	if (ret < 0)
587		return ret;
588
589	ret = t14s_input_probe(ec);
590	if (ret < 0)
591		return ret;
592
593	ret = devm_request_threaded_irq(dev, client->irq, NULL,
594					t14s_ec_irq_handler,
595					IRQF_ONESHOT, dev_name(dev), ec);
596	if (ret < 0)
597		return dev_err_probe(dev, ret, "Failed to get IRQ\n");
598
599	/*
600	 * Disable wakeup support by default, because the driver currently does
601	 * not support masking any events and the laptop should not wake up when
602	 * the LID is closed.
603	 */
604	device_wakeup_disable(dev);
605
606	return 0;
607}
608
609static int t14s_ec_suspend(struct device *dev)
610{
611	struct t14s_ec *ec = dev_get_drvdata(dev);
612
613	led_classdev_suspend(&ec->kbd_backlight);
614
615	t14s_ec_write_sequence(ec, T14S_EC_REG_MODERN_STANDBY,
616			       T14S_EC_MODERN_STANDBY_ENTRY, 3);
617
618	return 0;
619}
620
621static int t14s_ec_resume(struct device *dev)
622{
623	struct t14s_ec *ec = dev_get_drvdata(dev);
624
625	t14s_ec_write_sequence(ec, T14S_EC_REG_MODERN_STANDBY,
626			       T14S_EC_MODERN_STANDBY_EXIT, 3);
627
628	led_classdev_resume(&ec->kbd_backlight);
629
630	return 0;
631}
632
633static const struct of_device_id t14s_ec_of_match[] = {
634	{ .compatible = "lenovo,thinkpad-t14s-ec" },
635	{}
636};
637MODULE_DEVICE_TABLE(of, t14s_ec_of_match);
638
639static const struct i2c_device_id t14s_ec_i2c_id_table[] = {
640	{ "thinkpad-t14s-ec", },
641	{}
642};
643MODULE_DEVICE_TABLE(i2c, t14s_ec_i2c_id_table);
644
645static const struct dev_pm_ops t14s_ec_pm_ops = {
646	SYSTEM_SLEEP_PM_OPS(t14s_ec_suspend, t14s_ec_resume)
647};
648
649static struct i2c_driver t14s_ec_i2c_driver = {
650	.driver = {
651		.name = "thinkpad-t14s-ec",
652		.of_match_table = t14s_ec_of_match,
653		.pm = &t14s_ec_pm_ops,
654	},
655	.probe = t14s_ec_probe,
656	.id_table = t14s_ec_i2c_id_table,
657};
658module_i2c_driver(t14s_ec_i2c_driver);
659
660MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
661MODULE_DESCRIPTION("Lenovo Thinkpad T14s Embedded Controller");
662MODULE_LICENSE("GPL");
~/ Read-only file preview.