Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
Note: File does not exist in v6.8.
  1/*
  2 * USB Type-C Connector System Software Interface driver
  3 *
  4 * Copyright (C) 2016, Intel Corporation
  5 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License version 2 as
  9 * published by the Free Software Foundation.
 10 */
 11
 12#include <linux/platform_device.h>
 13#include <linux/module.h>
 14#include <linux/delay.h>
 15#include <linux/acpi.h>
 16
 17#include "ucsi.h"
 18
 19/* Double the time defined by MIN_TIME_TO_RESPOND_WITH_BUSY */
 20#define UCSI_TIMEOUT_MS 20
 21
 22enum ucsi_status {
 23	UCSI_IDLE = 0,
 24	UCSI_BUSY,
 25	UCSI_ERROR,
 26};
 27
 28struct ucsi_connector {
 29	int num;
 30	struct ucsi *ucsi;
 31	struct work_struct work;
 32	struct ucsi_connector_capability cap;
 33};
 34
 35struct ucsi {
 36	struct device *dev;
 37	struct ucsi_data __iomem *data;
 38
 39	enum ucsi_status status;
 40	struct completion complete;
 41	struct ucsi_capability cap;
 42	struct ucsi_connector *connector;
 43
 44	/* device lock */
 45	spinlock_t dev_lock;
 46
 47	/* PPM Communication lock */
 48	struct mutex ppm_lock;
 49
 50	/* PPM communication flags */
 51	unsigned long flags;
 52#define EVENT_PENDING	0
 53#define COMMAND_PENDING	1
 54};
 55
 56static int ucsi_acpi_cmd(struct ucsi *ucsi, struct ucsi_control *ctrl)
 57{
 58	uuid_le uuid = UUID_LE(0x6f8398c2, 0x7ca4, 0x11e4,
 59			       0xad, 0x36, 0x63, 0x10, 0x42, 0xb5, 0x00, 0x8f);
 60	union acpi_object *obj;
 61
 62	ucsi->data->ctrl.raw_cmd = ctrl->raw_cmd;
 63
 64	obj = acpi_evaluate_dsm(ACPI_HANDLE(ucsi->dev), uuid.b, 1, 1, NULL);
 65	if (!obj) {
 66		dev_err(ucsi->dev, "%s: failed to evaluate _DSM\n", __func__);
 67		return -EIO;
 68	}
 69
 70	ACPI_FREE(obj);
 71	return 0;
 72}
 73
 74static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
 75{
 76	struct ucsi *ucsi = data;
 77	struct ucsi_cci *cci;
 78
 79	spin_lock(&ucsi->dev_lock);
 80
 81	ucsi->status = UCSI_IDLE;
 82	cci = &ucsi->data->cci;
 83
 84	/*
 85	 * REVISIT: This is not documented behavior, but all known PPMs ACK
 86	 * asynchronous events by sending notification with cleared CCI.
 87	 */
 88	if (!ucsi->data->raw_cci) {
 89		if (test_bit(EVENT_PENDING, &ucsi->flags))
 90			complete(&ucsi->complete);
 91		else
 92			dev_WARN(ucsi->dev, "spurious notification\n");
 93		goto out_unlock;
 94	}
 95
 96	if (test_bit(COMMAND_PENDING, &ucsi->flags)) {
 97		if (cci->busy) {
 98			ucsi->status = UCSI_BUSY;
 99			complete(&ucsi->complete);
100
101			goto out_unlock;
102		} else if (cci->ack_complete || cci->cmd_complete) {
103			/* Error Indication is only valid with commands */
104			if (cci->error && cci->cmd_complete)
105				ucsi->status = UCSI_ERROR;
106
107			ucsi->data->ctrl.raw_cmd = 0;
108			complete(&ucsi->complete);
109		}
110	}
111
112	if (cci->connector_change) {
113		struct ucsi_connector *con;
114
115		/*
116		 * This is workaround for buggy PPMs that create asynchronous
117		 * event notifications before OPM has enabled them.
118		 */
119		if (!ucsi->connector)
120			goto out_unlock;
121
122		con = ucsi->connector + (cci->connector_change - 1);
123
124		/*
125		 * PPM will not clear the connector specific bit in Connector
126		 * Change Indication field of CCI until the driver has ACK it,
127		 * and the driver can not ACK it before it has been processed.
128		 * The PPM will not generate new events before the first has
129		 * been acknowledged, even if they are for an other connector.
130		 * So only one event at a time.
131		 */
132		if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags))
133			schedule_work(&con->work);
134	}
135out_unlock:
136	spin_unlock(&ucsi->dev_lock);
137}
138
139static int ucsi_ack(struct ucsi *ucsi, u8 cmd)
140{
141	struct ucsi_control ctrl;
142	int ret;
143
144	ctrl.cmd.cmd = UCSI_ACK_CC_CI;
145	ctrl.cmd.length = 0;
146	ctrl.cmd.data = cmd;
147	ret = ucsi_acpi_cmd(ucsi, &ctrl);
148	if (ret)
149		return ret;
150
151	/* Waiting for ACK also with ACK CMD for now */
152	ret = wait_for_completion_timeout(&ucsi->complete,
153					  msecs_to_jiffies(UCSI_TIMEOUT_MS));
154	if (!ret)
155		return -ETIMEDOUT;
156	return 0;
157}
158
159static int ucsi_run_cmd(struct ucsi *ucsi, struct ucsi_control *ctrl,
160			void *data, size_t size)
161{
162	u16 err_value = 0;
163	int ret;
164
165	set_bit(COMMAND_PENDING, &ucsi->flags);
166
167	ret = ucsi_acpi_cmd(ucsi, ctrl);
168	if (ret)
169		goto err_clear_flag;
170
171	ret = wait_for_completion_timeout(&ucsi->complete,
172					  msecs_to_jiffies(UCSI_TIMEOUT_MS));
173	if (!ret) {
174		ret = -ETIMEDOUT;
175		goto err_clear_flag;
176	}
177
178	switch (ucsi->status) {
179	case UCSI_IDLE:
180		if (data)
181			memcpy(data, ucsi->data->message_in, size);
182
183		ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
184		break;
185	case UCSI_BUSY:
186		/* The caller decides whether to cancel or not */
187		ret = -EBUSY;
188		goto err_clear_flag;
189	case UCSI_ERROR:
190		ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
191		if (ret)
192			goto err_clear_flag;
193
194		ctrl->cmd.cmd = UCSI_GET_ERROR_STATUS;
195		ctrl->cmd.length = 0;
196		ctrl->cmd.data = 0;
197		ret = ucsi_acpi_cmd(ucsi, ctrl);
198		if (ret)
199			goto err_clear_flag;
200
201		ret = wait_for_completion_timeout(&ucsi->complete,
202					msecs_to_jiffies(UCSI_TIMEOUT_MS));
203		if (!ret) {
204			ret = -ETIMEDOUT;
205			goto err_clear_flag;
206		}
207
208		memcpy(&err_value, ucsi->data->message_in, sizeof(err_value));
209
210		/* Something has really gone wrong */
211		if (WARN_ON(ucsi->status == UCSI_ERROR)) {
212			ret = -ENODEV;
213			goto err_clear_flag;
214		}
215
216		ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
217		if (ret)
218			goto err_clear_flag;
219
220		switch (err_value) {
221		case UCSI_ERROR_INCOMPATIBLE_PARTNER:
222			ret = -EOPNOTSUPP;
223			break;
224		case UCSI_ERROR_CC_COMMUNICATION_ERR:
225			ret = -ECOMM;
226			break;
227		case UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL:
228			ret = -EIO;
229			break;
230		case UCSI_ERROR_DEAD_BATTERY:
231			dev_warn(ucsi->dev, "Dead battery condition!\n");
232			ret = -EPERM;
233			break;
234		/* The following mean a bug in this driver */
235		case UCSI_ERROR_INVALID_CON_NUM:
236		case UCSI_ERROR_UNREGONIZED_CMD:
237		case UCSI_ERROR_INVALID_CMD_ARGUMENT:
238		default:
239			dev_warn(ucsi->dev,
240				 "%s: possible UCSI driver bug - error %hu\n",
241				 __func__, err_value);
242			ret = -EINVAL;
243			break;
244		}
245		break;
246	}
247	ctrl->raw_cmd = 0;
248err_clear_flag:
249	clear_bit(COMMAND_PENDING, &ucsi->flags);
250	return ret;
251}
252
253static void ucsi_connector_change(struct work_struct *work)
254{
255	struct ucsi_connector *con = container_of(work, struct ucsi_connector,
256						  work);
257	struct ucsi_connector_status constat;
258	struct ucsi *ucsi = con->ucsi;
259	struct ucsi_control ctrl;
260	int ret;
261
262	mutex_lock(&ucsi->ppm_lock);
263
264	ctrl.cmd.cmd = UCSI_GET_CONNECTOR_STATUS;
265	ctrl.cmd.length = 0;
266	ctrl.cmd.data = con->num;
267	ret = ucsi_run_cmd(con->ucsi, &ctrl, &constat, sizeof(constat));
268	if (ret) {
269		dev_err(ucsi->dev, "%s: failed to read connector status (%d)\n",
270			__func__, ret);
271		goto out_ack_event;
272	}
273
274	/* Ignoring disconnections and Alternate Modes */
275	if (!constat.connected || !(constat.change &
276	    (UCSI_CONSTAT_PARTNER_CHANGE | UCSI_CONSTAT_CONNECT_CHANGE)) ||
277	    constat.partner_flags & UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE)
278		goto out_ack_event;
279
280	/* If the partner got USB Host role, attempting swap */
281	if (constat.partner_type & UCSI_CONSTAT_PARTNER_TYPE_DFP) {
282		ctrl.uor.cmd = UCSI_SET_UOR;
283		ctrl.uor.con_num = con->num;
284		ctrl.uor.role = UCSI_UOR_ROLE_DFP;
285
286		ret = ucsi_run_cmd(con->ucsi, &ctrl, NULL, 0);
287		if (ret)
288			dev_err(ucsi->dev, "%s: failed to swap role (%d)\n",
289				__func__, ret);
290	}
291out_ack_event:
292	ucsi_ack(ucsi, UCSI_ACK_EVENT);
293	clear_bit(EVENT_PENDING, &ucsi->flags);
294	mutex_unlock(&ucsi->ppm_lock);
295}
296
297static int ucsi_reset_ppm(struct ucsi *ucsi)
298{
299	int timeout = UCSI_TIMEOUT_MS;
300	struct ucsi_control ctrl;
301	int ret;
302
303	memset(&ctrl, 0, sizeof(ctrl));
304	ctrl.cmd.cmd = UCSI_PPM_RESET;
305	ret = ucsi_acpi_cmd(ucsi, &ctrl);
306	if (ret)
307		return ret;
308
309	/* There is no quarantee the PPM will ever set the RESET_COMPLETE bit */
310	while (!ucsi->data->cci.reset_complete && timeout--)
311		usleep_range(1000, 2000);
312	return 0;
313}
314
315static int ucsi_init(struct ucsi *ucsi)
316{
317	struct ucsi_connector *con;
318	struct ucsi_control ctrl;
319	int ret;
320	int i;
321
322	init_completion(&ucsi->complete);
323	spin_lock_init(&ucsi->dev_lock);
324	mutex_init(&ucsi->ppm_lock);
325
326	/* Reset the PPM */
327	ret = ucsi_reset_ppm(ucsi);
328	if (ret)
329		return ret;
330
331	/*
332	 * REVISIT: Executing second reset to WA an issue seen on some of the
333	 * Broxton based platforms, where the first reset puts the PPM into a
334	 * state where it's unable to recognise some of the commands.
335	 */
336	ret = ucsi_reset_ppm(ucsi);
337	if (ret)
338		return ret;
339
340	mutex_lock(&ucsi->ppm_lock);
341
342	/* Enable basic notifications */
343	ctrl.cmd.cmd = UCSI_SET_NOTIFICATION_ENABLE;
344	ctrl.cmd.length = 0;
345	ctrl.cmd.data = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
346	ret = ucsi_run_cmd(ucsi, &ctrl, NULL, 0);
347	if (ret)
348		goto err_reset;
349
350	/* Get PPM capabilities */
351	ctrl.cmd.cmd = UCSI_GET_CAPABILITY;
352	ret = ucsi_run_cmd(ucsi, &ctrl, &ucsi->cap, sizeof(ucsi->cap));
353	if (ret)
354		goto err_reset;
355
356	if (!ucsi->cap.num_connectors) {
357		ret = -ENODEV;
358		goto err_reset;
359	}
360
361	ucsi->connector = devm_kcalloc(ucsi->dev, ucsi->cap.num_connectors,
362				       sizeof(*ucsi->connector), GFP_KERNEL);
363	if (!ucsi->connector) {
364		ret = -ENOMEM;
365		goto err_reset;
366	}
367
368	for (i = 1, con = ucsi->connector; i < ucsi->cap.num_connectors + 1;
369	     i++, con++) {
370		/* Get connector capability */
371		ctrl.cmd.cmd = UCSI_GET_CONNECTOR_CAPABILITY;
372		ctrl.cmd.data = i;
373		ret = ucsi_run_cmd(ucsi, &ctrl, &con->cap, sizeof(con->cap));
374		if (ret)
375			goto err_reset;
376
377		con->num = i;
378		con->ucsi = ucsi;
379		INIT_WORK(&con->work, ucsi_connector_change);
380	}
381
382	/* Enable all notifications */
383	ctrl.cmd.cmd = UCSI_SET_NOTIFICATION_ENABLE;
384	ctrl.cmd.data = UCSI_ENABLE_NTFY_ALL;
385	ret = ucsi_run_cmd(ucsi, &ctrl, NULL, 0);
386	if (ret < 0)
387		goto err_reset;
388
389	mutex_unlock(&ucsi->ppm_lock);
390	return 0;
391err_reset:
392	ucsi_reset_ppm(ucsi);
393	mutex_unlock(&ucsi->ppm_lock);
394	return ret;
395}
396
397static int ucsi_acpi_probe(struct platform_device *pdev)
398{
399	struct resource *res;
400	acpi_status status;
401	struct ucsi *ucsi;
402	int ret;
403
404	ucsi = devm_kzalloc(&pdev->dev, sizeof(*ucsi), GFP_KERNEL);
405	if (!ucsi)
406		return -ENOMEM;
407
408	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
409	if (!res) {
410		dev_err(&pdev->dev, "missing memory resource\n");
411		return -ENODEV;
412	}
413
414	/*
415	 * NOTE: ACPI has claimed the memory region as it's also an Operation
416	 * Region. It's not possible to request it in the driver.
417	 */
418	ucsi->data = devm_ioremap(&pdev->dev, res->start, resource_size(res));
419	if (!ucsi->data)
420		return -ENOMEM;
421
422	ucsi->dev = &pdev->dev;
423
424	status = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
425					     ACPI_ALL_NOTIFY,
426					     ucsi_acpi_notify, ucsi);
427	if (ACPI_FAILURE(status))
428		return -ENODEV;
429
430	ret = ucsi_init(ucsi);
431	if (ret) {
432		acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
433					   ACPI_ALL_NOTIFY,
434					   ucsi_acpi_notify);
435		return ret;
436	}
437
438	platform_set_drvdata(pdev, ucsi);
439	return 0;
440}
441
442static int ucsi_acpi_remove(struct platform_device *pdev)
443{
444	struct ucsi *ucsi = platform_get_drvdata(pdev);
445
446	acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
447				   ACPI_ALL_NOTIFY, ucsi_acpi_notify);
448
449	/* Make sure there are no events in the middle of being processed */
450	if (wait_on_bit_timeout(&ucsi->flags, EVENT_PENDING,
451				TASK_UNINTERRUPTIBLE,
452				msecs_to_jiffies(UCSI_TIMEOUT_MS)))
453		dev_WARN(ucsi->dev, "%s: Events still pending\n", __func__);
454
455	ucsi_reset_ppm(ucsi);
456	return 0;
457}
458
459static const struct acpi_device_id ucsi_acpi_match[] = {
460	{ "PNP0CA0", 0 },
461	{ },
462};
463MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match);
464
465static struct platform_driver ucsi_acpi_platform_driver = {
466	.driver = {
467		.name = "ucsi_acpi",
468		.acpi_match_table = ACPI_PTR(ucsi_acpi_match),
469	},
470	.probe = ucsi_acpi_probe,
471	.remove = ucsi_acpi_remove,
472};
473
474module_platform_driver(ucsi_acpi_platform_driver);
475
476MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
477MODULE_LICENSE("GPL v2");
478MODULE_DESCRIPTION("USB Type-C System Software Interface (UCSI) driver");