xref: /linux/drivers/platform/arm64/qcom-hamoa-ec.c (revision 5b05bb3f6c5716fab6911e12d60dd1f43ad9806a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2024 Maya Matuszczyk <maccraft123mc@gmail.com>
4  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5  */
6 
7 #include <linux/bitfield.h>
8 #include <linux/bits.h>
9 #include <linux/device.h>
10 #include <linux/dev_printk.h>
11 #include <linux/err.h>
12 #include <linux/i2c.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/pm.h>
17 #include <linux/slab.h>
18 #include <linux/thermal.h>
19 
20 #define EC_SCI_EVT_READ_CMD	0x05
21 #define EC_FW_VERSION_CMD	0x0e
22 #define EC_MODERN_STANDBY_CMD	0x23
23 #define EC_FAN_DBG_CONTROL_CMD	0x30
24 #define EC_SCI_EVT_CONTROL_CMD	0x35
25 #define EC_THERMAL_CAP_CMD	0x42
26 
27 #define EC_FW_VERSION_RESP_LEN	4
28 #define EC_THERMAL_CAP_RESP_LEN	3
29 #define EC_FAN_DEBUG_CMD_LEN	6
30 #define EC_FAN_SPEED_DATA_SIZE	4
31 
32 #define EC_MODERN_STANDBY_ENTER	0x01
33 #define EC_MODERN_STANDBY_EXIT	0x00
34 
35 #define EC_FAN_DEBUG_MODE_OFF   0
36 #define EC_FAN_DEBUG_MODE_ON    BIT(0)
37 #define EC_FAN_ON               BIT(1)
38 #define EC_FAN_DEBUG_TYPE_PWM   BIT(2)
39 #define EC_MAX_FAN_CNT		2
40 #define EC_FAN_NAME_SIZE	20
41 #define EC_FAN_MAX_PWM		255
42 
43 enum qcom_ec_sci_events {
44 	EC_FAN1_STATUS_CHANGE_EVT = 0x30,
45 	EC_FAN2_STATUS_CHANGE_EVT,
46 	EC_FAN1_SPEED_CHANGE_EVT,
47 	EC_FAN2_SPEED_CHANGE_EVT,
48 	EC_NEW_LUT_SET_EVT,
49 	EC_FAN_PROFILE_SWITCH_EVT,
50 	EC_THERMISTOR_1_THRESHOLD_CROSS_EVT,
51 	EC_THERMISTOR_2_THRESHOLD_CROSS_EVT,
52 	EC_THERMISTOR_3_THRESHOLD_CROSS_EVT,
53 	/* Reserved: 0x39 - 0x3c/0x3f */
54 	EC_RECOVERED_FROM_RESET_EVT = 0x3d,
55 };
56 
57 struct qcom_ec_version {
58 	u8 main_version;
59 	u8 sub_version;
60 	u8 test_version;
61 };
62 
63 struct qcom_ec_thermal_cap {
64 #define EC_THERMAL_FAN_CNT(x)		(FIELD_GET(GENMASK(1, 0), (x)))
65 #define EC_THERMAL_FAN_TYPE(x)		(FIELD_GET(GENMASK(4, 2), (x)))
66 #define EC_THERMAL_THERMISTOR_MASK(x)	(FIELD_GET(GENMASK(7, 0), (x)))
67 	u8 fan_cnt;
68 	u8 fan_type;
69 	u8 thermistor_mask;
70 };
71 
72 struct qcom_ec_cooling_dev {
73 	struct thermal_cooling_device *cdev;
74 	struct device *parent_dev;
75 	u8 fan_id;
76 	u8 state;
77 };
78 
79 struct qcom_ec {
80 	struct qcom_ec_cooling_dev *ec_cdev;
81 	struct qcom_ec_thermal_cap thermal_cap;
82 	struct qcom_ec_version version;
83 	struct i2c_client *client;
84 };
85 
qcom_ec_read(struct qcom_ec * ec,u8 cmd,u8 resp_len,u8 * resp)86 static int qcom_ec_read(struct qcom_ec *ec, u8 cmd, u8 resp_len, u8 *resp)
87 {
88 	int ret;
89 
90 	ret = i2c_smbus_read_i2c_block_data(ec->client, cmd, resp_len, resp);
91 	if (ret < 0)
92 		return ret;
93 	else if (ret == 0 || ret == 0xff)
94 		return -EOPNOTSUPP;
95 	else if (ret != resp_len)
96 		return -EIO;
97 
98 	if (resp[0] != resp_len - 1)
99 		return -EINVAL;
100 
101 	return 0;
102 }
103 
104 /*
105  * EC Device Firmware Version:
106  *
107  * Read Response:
108  * ----------------------------------------------------------------------
109  * | Offset	| Name		| Description				|
110  * ----------------------------------------------------------------------
111  * | 0x00	| Byte count	| Number of bytes in response		|
112  * |		|		| (excluding byte count)		|
113  * ----------------------------------------------------------------------
114  * | 0x01	| Test-version	| Test-version of EC firmware		|
115  * ----------------------------------------------------------------------
116  * | 0x02	| Sub-version	| Sub-version of EC firmware		|
117  * ----------------------------------------------------------------------
118  * | 0x03	| Main-version	| Main-version of EC firmware		|
119  * ----------------------------------------------------------------------
120  *
121  */
qcom_ec_read_fw_version(struct device * dev)122 static int qcom_ec_read_fw_version(struct device *dev)
123 {
124 	struct i2c_client *client = to_i2c_client(dev);
125 	struct qcom_ec *ec = i2c_get_clientdata(client);
126 	struct qcom_ec_version *version = &ec->version;
127 	u8 resp[EC_FW_VERSION_RESP_LEN];
128 	int ret;
129 
130 	ret = qcom_ec_read(ec, EC_FW_VERSION_CMD, EC_FW_VERSION_RESP_LEN, resp);
131 	if (ret < 0)
132 		return ret;
133 
134 	version->main_version = resp[3];
135 	version->sub_version = resp[2];
136 	version->test_version = resp[1];
137 
138 	dev_dbg(dev, "EC Version %d.%d.%d\n",
139 		version->main_version, version->sub_version, version->test_version);
140 
141 	return 0;
142 }
143 
144 /*
145  * EC Device Thermal Capabilities:
146  *
147  * Read Response:
148  * ------------------------------------------------------------------------------
149  * | Offset		| Name		| Description				|
150  * ------------------------------------------------------------------------------
151  * | 0x00		| Byte count	| Number of bytes in response		|
152  * |			|		| (excluding byte count)		|
153  * ------------------------------------------------------------------------------
154  * | 0x02 (LSB)		| EC Thermal	| Bit 0-1: Number of fans		|
155  * | 0x03		| Capabilities	| Bit 2-4: Type of fan			|
156  * |			|		| Bit 5-6: Reserved			|
157  * |			|		| Bit 7: Data Valid/Invalid		|
158  * |			|		|	 (Valid - 1, Invalid - 0)	|
159  * |			|		| Bit 8-15: Thermistor 0 - 7 presence	|
160  * |			|		|	    (1 present, 0 absent)	|
161  * ------------------------------------------------------------------------------
162  *
163  */
qcom_ec_thermal_capabilities(struct device * dev)164 static int qcom_ec_thermal_capabilities(struct device *dev)
165 {
166 	struct i2c_client *client = to_i2c_client(dev);
167 	struct qcom_ec *ec = i2c_get_clientdata(client);
168 	struct qcom_ec_thermal_cap *cap = &ec->thermal_cap;
169 	u8 resp[EC_THERMAL_CAP_RESP_LEN];
170 	int ret;
171 
172 	ret = qcom_ec_read(ec, EC_THERMAL_CAP_CMD, EC_THERMAL_CAP_RESP_LEN, resp);
173 	if (ret < 0)
174 		return ret;
175 
176 	cap->fan_cnt = min(EC_MAX_FAN_CNT, EC_THERMAL_FAN_CNT(resp[1]));
177 	cap->fan_type = EC_THERMAL_FAN_TYPE(resp[1]);
178 	cap->thermistor_mask = EC_THERMAL_THERMISTOR_MASK(resp[2]);
179 
180 	dev_dbg(dev, "Fan count: %d Fan Type: %d Thermistor Mask: %x\n",
181 		cap->fan_cnt, cap->fan_type, cap->thermistor_mask);
182 
183 	return 0;
184 }
185 
qcom_ec_irq(int irq,void * data)186 static irqreturn_t qcom_ec_irq(int irq, void *data)
187 {
188 	struct qcom_ec *ec = data;
189 	struct device *dev = &ec->client->dev;
190 	int val;
191 
192 	val = i2c_smbus_read_byte_data(ec->client, EC_SCI_EVT_READ_CMD);
193 	if (val < 0) {
194 		dev_err_ratelimited(dev, "Failed to read EC SCI Event: %d\n", val);
195 		return IRQ_HANDLED;
196 	}
197 
198 	switch (val) {
199 	case EC_FAN1_STATUS_CHANGE_EVT:
200 		dev_dbg_ratelimited(dev, "Fan1 status changed\n");
201 		break;
202 	case EC_FAN2_STATUS_CHANGE_EVT:
203 		dev_dbg_ratelimited(dev, "Fan2 status changed\n");
204 		break;
205 	case EC_FAN1_SPEED_CHANGE_EVT:
206 		dev_dbg_ratelimited(dev, "Fan1 speed crossed low/high trip point\n");
207 		break;
208 	case EC_FAN2_SPEED_CHANGE_EVT:
209 		dev_dbg_ratelimited(dev, "Fan2 speed crossed low/high trip point\n");
210 		break;
211 	case EC_NEW_LUT_SET_EVT:
212 		dev_dbg_ratelimited(dev, "New LUT set\n");
213 		break;
214 	case EC_FAN_PROFILE_SWITCH_EVT:
215 		dev_dbg_ratelimited(dev, "FAN Profile switched\n");
216 		break;
217 	case EC_THERMISTOR_1_THRESHOLD_CROSS_EVT:
218 		dev_dbg_ratelimited(dev, "Thermistor 1 threshold crossed\n");
219 		break;
220 	case EC_THERMISTOR_2_THRESHOLD_CROSS_EVT:
221 		dev_dbg_ratelimited(dev, "Thermistor 2 threshold crossed\n");
222 		break;
223 	case EC_THERMISTOR_3_THRESHOLD_CROSS_EVT:
224 		dev_dbg_ratelimited(dev, "Thermistor 3 threshold crossed\n");
225 		break;
226 	case EC_RECOVERED_FROM_RESET_EVT:
227 		dev_dbg_ratelimited(dev, "EC recovered from reset\n");
228 		break;
229 	default:
230 		dev_notice_ratelimited(dev, "Unknown EC event: %d\n", val);
231 		break;
232 	}
233 
234 	return IRQ_HANDLED;
235 }
236 
qcom_ec_sci_evt_control(struct device * dev,bool enable)237 static int qcom_ec_sci_evt_control(struct device *dev, bool enable)
238 {
239 	struct i2c_client *client = to_i2c_client(dev);
240 
241 	return i2c_smbus_write_byte_data(client, EC_SCI_EVT_CONTROL_CMD, enable ? 1 : 0);
242 }
243 
qcom_ec_fan_get_max_state(struct thermal_cooling_device * cdev,unsigned long * state)244 static int qcom_ec_fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state)
245 {
246 	*state = EC_FAN_MAX_PWM;
247 
248 	return 0;
249 }
250 
qcom_ec_fan_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * state)251 static int qcom_ec_fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state)
252 {
253 	struct qcom_ec_cooling_dev *ec_cdev = cdev->devdata;
254 
255 	*state = ec_cdev->state;
256 
257 	return 0;
258 }
259 
260 /*
261  * Fan Debug control command:
262  *
263  * Command Payload:
264  * --------------------------------------------------------------------------------------
265  * | Offset		| Name		| Description					|
266  * --------------------------------------------------------------------------------------
267  * | 0x00		| Command	| Fan control command				|
268  * --------------------------------------------------------------------------------------
269  * | 0x01		| Fan ID	| 0x1 : Fan 1					|
270  * |			|		| 0x2 : Fan 2					|
271  * --------------------------------------------------------------------------------------
272  * | 0x02		| Byte count = 4| Size of data to set fan speed			|
273  * --------------------------------------------------------------------------------------
274  * | 0x03		| Mode		| Bit 0: Debug Mode On/Off (0 - OFF, 1 - ON )	|
275  * |			|		| Bit 1: Fan On/Off (0 - Off, 1 - ON)		|
276  * |			|		| Bit 2: Debug Type (0 - RPM, 1 - PWM)		|
277  * --------------------------------------------------------------------------------------
278  * | 0x04 (LSB)		| Speed in RPM	| RPM value, if mode selected is RPM		|
279  * | 0x05		|		|						|
280  * --------------------------------------------------------------------------------------
281  * | 0x06		| Speed in PWM	| PWM value, if mode selected is PWM (0 - 255)	|
282  * ______________________________________________________________________________________
283  *
284  */
qcom_ec_fan_debug_mode_off(struct qcom_ec_cooling_dev * ec_cdev)285 static int qcom_ec_fan_debug_mode_off(struct qcom_ec_cooling_dev *ec_cdev)
286 {
287 	struct device *dev = ec_cdev->parent_dev;
288 	struct i2c_client *client = to_i2c_client(dev);
289 	u8 request[6] = { ec_cdev->fan_id, EC_FAN_SPEED_DATA_SIZE,
290 			  EC_FAN_DEBUG_MODE_OFF, 0, 0, 0 };
291 	int ret;
292 
293 	ret = i2c_smbus_write_i2c_block_data(client, EC_FAN_DBG_CONTROL_CMD,
294 					     sizeof(request), request);
295 	if (ret) {
296 		dev_err(dev, "Failed to turn off fan%d debug mode: %d\n",
297 			ec_cdev->fan_id, ret);
298 	}
299 
300 	return ret;
301 }
302 
qcom_ec_fan_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)303 static int qcom_ec_fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
304 {
305 	struct qcom_ec_cooling_dev *ec_cdev = cdev->devdata;
306 	struct device *dev = ec_cdev->parent_dev;
307 	struct i2c_client *client = to_i2c_client(dev);
308 	u8 request[6] = { ec_cdev->fan_id, EC_FAN_SPEED_DATA_SIZE,
309 			  EC_FAN_DEBUG_MODE_ON | EC_FAN_ON | EC_FAN_DEBUG_TYPE_PWM,
310 			  0, 0, state };
311 	int ret;
312 
313 	ret = i2c_smbus_write_i2c_block_data(client, EC_FAN_DBG_CONTROL_CMD,
314 					     sizeof(request), request);
315 	if (ret) {
316 		dev_err(dev, "Failed to set fan pwm: %d\n", ret);
317 		return ret;
318 	}
319 
320 	ec_cdev->state = state;
321 
322 	return 0;
323 }
324 
325 static const struct thermal_cooling_device_ops qcom_ec_thermal_ops = {
326 	.get_max_state = qcom_ec_fan_get_max_state,
327 	.get_cur_state = qcom_ec_fan_get_cur_state,
328 	.set_cur_state = qcom_ec_fan_set_cur_state,
329 };
330 
qcom_ec_resume(struct device * dev)331 static int qcom_ec_resume(struct device *dev)
332 {
333 	struct i2c_client *client = to_i2c_client(dev);
334 
335 	return i2c_smbus_write_byte_data(client, EC_MODERN_STANDBY_CMD,
336 					 EC_MODERN_STANDBY_EXIT);
337 }
338 
qcom_ec_suspend(struct device * dev)339 static int qcom_ec_suspend(struct device *dev)
340 {
341 	struct i2c_client *client = to_i2c_client(dev);
342 
343 	return i2c_smbus_write_byte_data(client, EC_MODERN_STANDBY_CMD,
344 					 EC_MODERN_STANDBY_ENTER);
345 }
346 
qcom_ec_probe(struct i2c_client * client)347 static int qcom_ec_probe(struct i2c_client *client)
348 {
349 	struct device *dev = &client->dev;
350 	struct qcom_ec *ec;
351 	unsigned int i;
352 	int ret;
353 
354 	ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
355 	if (!ec)
356 		return -ENOMEM;
357 
358 	ec->client = client;
359 
360 	ret = devm_request_threaded_irq(dev, client->irq, NULL, qcom_ec_irq,
361 					IRQF_ONESHOT, "qcom_ec", ec);
362 	if (ret < 0)
363 		return ret;
364 
365 	i2c_set_clientdata(client, ec);
366 
367 	ret = qcom_ec_read_fw_version(dev);
368 	if (ret < 0)
369 		return dev_err_probe(dev, ret, "Failed to read EC firmware version\n");
370 
371 	ret = qcom_ec_sci_evt_control(dev, true);
372 	if (ret < 0)
373 		return dev_err_probe(dev, ret, "Failed to enable SCI events\n");
374 
375 	ret = qcom_ec_thermal_capabilities(dev);
376 	if (ret < 0)
377 		return dev_err_probe(dev, ret, "Failed to read thermal capabilities\n");
378 
379 	if (ec->thermal_cap.fan_cnt == 0) {
380 		dev_warn(dev, FW_BUG "Failed to get fan count, firmware update required\n");
381 		return 0;
382 	}
383 
384 	ec->ec_cdev = devm_kcalloc(dev, ec->thermal_cap.fan_cnt, sizeof(*ec->ec_cdev), GFP_KERNEL);
385 	if (!ec->ec_cdev)
386 		return -ENOMEM;
387 
388 	for (i = 0; i < ec->thermal_cap.fan_cnt; i++) {
389 		struct qcom_ec_cooling_dev *ec_cdev = &ec->ec_cdev[i];
390 		char name[EC_FAN_NAME_SIZE];
391 
392 		scnprintf(name, sizeof(name), "qcom_ec_fan_%u", i);
393 		ec_cdev->fan_id = i + 1;
394 		ec_cdev->parent_dev = dev;
395 
396 		ec_cdev->cdev = devm_thermal_of_child_cooling_device_register(dev, NULL, name, ec_cdev,
397 									&qcom_ec_thermal_ops);
398 		if (IS_ERR(ec_cdev->cdev)) {
399 			return dev_err_probe(dev, PTR_ERR(ec_cdev->cdev),
400 					     "Failed to register fan%d cooling device\n", i);
401 		}
402 	}
403 
404 	return 0;
405 }
406 
qcom_ec_remove(struct i2c_client * client)407 static void qcom_ec_remove(struct i2c_client *client)
408 {
409 	struct qcom_ec *ec = i2c_get_clientdata(client);
410 	struct device *dev = &client->dev;
411 	int ret;
412 
413 	ret = qcom_ec_sci_evt_control(dev, false);
414 	if (ret < 0)
415 		dev_err(dev, "Failed to disable SCI events: %d\n", ret);
416 
417 	for (int i = 0; i < ec->thermal_cap.fan_cnt; i++) {
418 		struct qcom_ec_cooling_dev *ec_cdev = &ec->ec_cdev[i];
419 
420 		qcom_ec_fan_debug_mode_off(ec_cdev);
421 	}
422 }
423 
424 static const struct of_device_id qcom_ec_of_match[] = {
425 	{ .compatible = "qcom,hamoa-crd-ec" },
426 	{}
427 };
428 MODULE_DEVICE_TABLE(of, qcom_ec_of_match);
429 
430 static const struct i2c_device_id qcom_ec_i2c_id_table[] = {
431 	{ "qcom-hamoa-ec", },
432 	{}
433 };
434 MODULE_DEVICE_TABLE(i2c, qcom_ec_i2c_id_table);
435 
436 static DEFINE_SIMPLE_DEV_PM_OPS(qcom_ec_pm_ops,
437 		qcom_ec_suspend,
438 		qcom_ec_resume);
439 
440 static struct i2c_driver qcom_ec_i2c_driver = {
441 	.driver = {
442 		.name = "qcom-hamoa-ec",
443 		.of_match_table = qcom_ec_of_match,
444 		.pm = &qcom_ec_pm_ops,
445 	},
446 	.probe = qcom_ec_probe,
447 	.remove = qcom_ec_remove,
448 	.id_table = qcom_ec_i2c_id_table,
449 };
450 module_i2c_driver(qcom_ec_i2c_driver);
451 
452 MODULE_DESCRIPTION("QCOM Hamoa Embedded Controller");
453 MODULE_LICENSE("GPL");
454