File Index
Files and directories
Sign in
FILE

ucsi_glink.c

File preview with syntax highlighting.

linux-6.19.14/drivers/usb/typec/ucsi/ucsi_glink.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
  4 * Copyright (c) 2023, Linaro Ltd
  5 */
  6#include <linux/auxiliary_bus.h>
  7#include <linux/module.h>
  8#include <linux/mutex.h>
  9#include <linux/of_device.h>
 10#include <linux/property.h>
 11#include <linux/soc/qcom/pdr.h>
 12#include <linux/usb/typec_mux.h>
 13#include <linux/gpio/consumer.h>
 14#include <linux/soc/qcom/pmic_glink.h>
 15#include "ucsi.h"
 16
 17#define PMIC_GLINK_MAX_PORTS		3
 18
 19#define UCSI_BUF_V1_SIZE		(UCSI_MESSAGE_OUT + (UCSI_MESSAGE_OUT - UCSI_MESSAGE_IN))
 20#define UCSI_BUF_V2_SIZE		(UCSIv2_MESSAGE_OUT + (UCSIv2_MESSAGE_OUT - UCSI_MESSAGE_IN))
 21
 22#define MSG_TYPE_REQ_RESP               1
 23
 24#define UC_NOTIFY_RECEIVER_UCSI         0x0
 25#define UC_UCSI_READ_BUF_REQ            0x11
 26#define UC_UCSI_WRITE_BUF_REQ           0x12
 27#define UC_UCSI_USBC_NOTIFY_IND         0x13
 28
 29struct ucsi_read_buf_req_msg {
 30	struct pmic_glink_hdr   hdr;
 31};
 32
 33struct __packed ucsi_read_buf_resp_msg {
 34	struct pmic_glink_hdr   hdr;
 35	union {
 36		u8 v2_buf[UCSI_BUF_V2_SIZE];
 37		u8 v1_buf[UCSI_BUF_V1_SIZE];
 38	} buf;
 39	u32                     ret_code;
 40};
 41
 42struct __packed ucsi_write_buf_req_msg {
 43	struct pmic_glink_hdr   hdr;
 44	union {
 45		u8 v2_buf[UCSI_BUF_V2_SIZE];
 46		u8 v1_buf[UCSI_BUF_V1_SIZE];
 47	} buf;
 48	u32                     reserved;
 49};
 50
 51struct __packed ucsi_write_buf_resp_msg {
 52	struct pmic_glink_hdr   hdr;
 53	u32                     ret_code;
 54};
 55
 56struct __packed ucsi_notify_ind_msg {
 57	struct pmic_glink_hdr   hdr;
 58	u32                     notification;
 59	u32                     receiver;
 60	u32                     reserved;
 61};
 62
 63struct pmic_glink_ucsi {
 64	struct device *dev;
 65
 66	struct gpio_desc *port_orientation[PMIC_GLINK_MAX_PORTS];
 67
 68	struct pmic_glink_client *client;
 69
 70	struct ucsi *ucsi;
 71	struct completion read_ack;
 72	struct completion write_ack;
 73	struct mutex lock;	/* protects concurrent access to PMIC Glink interface */
 74
 75	struct work_struct notify_work;
 76	struct work_struct register_work;
 77	spinlock_t state_lock;
 78	bool ucsi_registered;
 79	bool pd_running;
 80
 81	u8 read_buf[UCSI_BUF_V2_SIZE];
 82};
 83
 84static int pmic_glink_ucsi_read(struct ucsi *__ucsi, unsigned int offset,
 85				void *val, size_t val_len)
 86{
 87	struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi);
 88	struct ucsi_read_buf_req_msg req = {};
 89	unsigned long left;
 90	int ret;
 91
 92	req.hdr.owner = PMIC_GLINK_OWNER_USBC;
 93	req.hdr.type = MSG_TYPE_REQ_RESP;
 94	req.hdr.opcode = UC_UCSI_READ_BUF_REQ;
 95
 96	mutex_lock(&ucsi->lock);
 97	memset(ucsi->read_buf, 0, sizeof(ucsi->read_buf));
 98	reinit_completion(&ucsi->read_ack);
 99
100	ret = pmic_glink_send(ucsi->client, &req, sizeof(req));
101	if (ret < 0) {
102		dev_err(ucsi->dev, "failed to send UCSI read request: %d\n", ret);
103		goto out_unlock;
104	}
105
106	left = wait_for_completion_timeout(&ucsi->read_ack, 5 * HZ);
107	if (!left) {
108		dev_err(ucsi->dev, "timeout waiting for UCSI read response\n");
109		ret = -ETIMEDOUT;
110		goto out_unlock;
111	}
112
113	memcpy(val, &ucsi->read_buf[offset], val_len);
114	ret = 0;
115
116out_unlock:
117	mutex_unlock(&ucsi->lock);
118
119	return ret;
120}
121
122static int pmic_glink_ucsi_read_version(struct ucsi *ucsi, u16 *version)
123{
124	return pmic_glink_ucsi_read(ucsi, UCSI_VERSION, version, sizeof(*version));
125}
126
127static int pmic_glink_ucsi_read_cci(struct ucsi *ucsi, u32 *cci)
128{
129	return pmic_glink_ucsi_read(ucsi, UCSI_CCI, cci, sizeof(*cci));
130}
131
132static int pmic_glink_ucsi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
133{
134	return pmic_glink_ucsi_read(ucsi, UCSI_MESSAGE_IN, val, val_len);
135}
136
137static int pmic_glink_ucsi_locked_write(struct pmic_glink_ucsi *ucsi, unsigned int offset,
138					const void *val, size_t val_len)
139{
140	struct ucsi_write_buf_req_msg req = {};
141	size_t req_len, buf_len;
142	unsigned long left;
143	int ret;
144	u8 *buf;
145
146	req.hdr.owner = PMIC_GLINK_OWNER_USBC;
147	req.hdr.type = MSG_TYPE_REQ_RESP;
148	req.hdr.opcode = UC_UCSI_WRITE_BUF_REQ;
149
150	if (ucsi->ucsi->version >= UCSI_VERSION_2_0) {
151		buf_len = UCSI_BUF_V2_SIZE;
152		buf = req.buf.v2_buf;
153	} else if (ucsi->ucsi->version) {
154		buf_len = UCSI_BUF_V1_SIZE;
155		buf = req.buf.v1_buf;
156	} else {
157		dev_err(ucsi->dev, "UCSI version unknown\n");
158		return -EINVAL;
159	}
160	req_len = sizeof(struct pmic_glink_hdr) + buf_len + sizeof(u32);
161
162	if (offset + val_len > buf_len)
163		return -EINVAL;
164
165	memcpy(&buf[offset], val, val_len);
166
167	reinit_completion(&ucsi->write_ack);
168
169	ret = pmic_glink_send(ucsi->client, &req, req_len);
170	if (ret < 0) {
171		dev_err(ucsi->dev, "failed to send UCSI write request: %d\n", ret);
172		return ret;
173	}
174
175	left = wait_for_completion_timeout(&ucsi->write_ack, 5 * HZ);
176	if (!left) {
177		dev_err(ucsi->dev, "timeout waiting for UCSI write response\n");
178		return -ETIMEDOUT;
179	}
180
181	return 0;
182}
183
184static int pmic_glink_ucsi_async_control(struct ucsi *__ucsi, u64 command)
185{
186	struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi);
187	int ret;
188
189	mutex_lock(&ucsi->lock);
190	ret = pmic_glink_ucsi_locked_write(ucsi, UCSI_CONTROL, &command, sizeof(command));
191	mutex_unlock(&ucsi->lock);
192
193	return ret;
194}
195
196static void pmic_glink_ucsi_update_connector(struct ucsi_connector *con)
197{
198	struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
199
200	if (con->num > PMIC_GLINK_MAX_PORTS ||
201	    !ucsi->port_orientation[con->num - 1])
202		return;
203
204	con->typec_cap.orientation_aware = true;
205}
206
207static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
208{
209	struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
210	int orientation;
211
212	if (!UCSI_CONSTAT(con, CONNECTED)) {
213		typec_set_orientation(con->port, TYPEC_ORIENTATION_NONE);
214		return;
215	}
216
217	if (con->num > PMIC_GLINK_MAX_PORTS ||
218	    !ucsi->port_orientation[con->num - 1])
219		return;
220
221	orientation = gpiod_get_value(ucsi->port_orientation[con->num - 1]);
222	if (orientation >= 0) {
223		typec_set_orientation(con->port,
224				      orientation ?
225				      TYPEC_ORIENTATION_REVERSE :
226				      TYPEC_ORIENTATION_NORMAL);
227	}
228}
229
230static const struct ucsi_operations pmic_glink_ucsi_ops = {
231	.read_version = pmic_glink_ucsi_read_version,
232	.read_cci = pmic_glink_ucsi_read_cci,
233	.poll_cci = pmic_glink_ucsi_read_cci,
234	.read_message_in = pmic_glink_ucsi_read_message_in,
235	.sync_control = ucsi_sync_control_common,
236	.async_control = pmic_glink_ucsi_async_control,
237	.update_connector = pmic_glink_ucsi_update_connector,
238	.connector_status = pmic_glink_ucsi_connector_status,
239};
240
241static void pmic_glink_ucsi_read_ack(struct pmic_glink_ucsi *ucsi, const void *data, int len)
242{
243	u32 ret_code, resp_len, buf_len = 0;
244	u8 *buf;
245
246	if (ucsi->ucsi->version) {
247		if (ucsi->ucsi->version >= UCSI_VERSION_2_0) {
248			buf = ((struct ucsi_read_buf_resp_msg *)data)->buf.v2_buf;
249			buf_len = UCSI_BUF_V2_SIZE;
250		} else {
251			buf = ((struct ucsi_read_buf_resp_msg *)data)->buf.v1_buf;
252			buf_len = UCSI_BUF_V1_SIZE;
253		}
254	} else if (!ucsi->ucsi_registered) {
255		/*
256		 * If UCSI version is not known yet because device is not registered, choose buffer
257		 * size which best fits incoming data
258		 */
259		if (len > sizeof(struct pmic_glink_hdr) + UCSI_BUF_V2_SIZE) {
260			buf = ((struct ucsi_read_buf_resp_msg *)data)->buf.v2_buf;
261			buf_len = UCSI_BUF_V2_SIZE;
262		} else {
263			buf = ((struct ucsi_read_buf_resp_msg *)data)->buf.v1_buf;
264			buf_len = UCSI_BUF_V1_SIZE;
265		}
266	} else {
267		dev_err(ucsi->dev, "Device has been registered but UCSI version is still unknown\n");
268		return;
269	}
270
271	resp_len = sizeof(struct pmic_glink_hdr) + buf_len + sizeof(u32);
272
273	if (len > resp_len)
274		return;
275
276	/* Ensure that buffer_len leaves space for ret_code to be read back from memory */
277	if (buf_len > len - sizeof(struct pmic_glink_hdr) - sizeof(u32))
278		buf_len = len - sizeof(struct pmic_glink_hdr) - sizeof(u32);
279
280	memcpy(&ret_code, buf + buf_len, sizeof(u32));
281	if (ret_code)
282		return;
283
284	memcpy(ucsi->read_buf, buf, buf_len);
285	complete(&ucsi->read_ack);
286}
287
288static void pmic_glink_ucsi_write_ack(struct pmic_glink_ucsi *ucsi, const void *data, int len)
289{
290	const struct ucsi_write_buf_resp_msg *resp = data;
291
292	if (resp->ret_code)
293		return;
294
295	complete(&ucsi->write_ack);
296}
297
298static void pmic_glink_ucsi_notify(struct work_struct *work)
299{
300	struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, notify_work);
301	u32 cci;
302	int ret;
303
304	ret = pmic_glink_ucsi_read(ucsi->ucsi, UCSI_CCI, &cci, sizeof(cci));
305	if (ret) {
306		dev_err(ucsi->dev, "failed to read CCI on notification\n");
307		return;
308	}
309
310	ucsi_notify_common(ucsi->ucsi, cci);
311}
312
313static void pmic_glink_ucsi_register(struct work_struct *work)
314{
315	struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work);
316	unsigned long flags;
317	bool pd_running;
318
319	spin_lock_irqsave(&ucsi->state_lock, flags);
320	pd_running = ucsi->pd_running;
321	spin_unlock_irqrestore(&ucsi->state_lock, flags);
322
323	if (!ucsi->ucsi_registered && pd_running) {
324		ucsi_register(ucsi->ucsi);
325		ucsi->ucsi_registered = true;
326	} else if (ucsi->ucsi_registered && !pd_running) {
327		ucsi_unregister(ucsi->ucsi);
328		ucsi->ucsi_registered = false;
329	}
330}
331
332static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv)
333{
334	struct pmic_glink_ucsi *ucsi = priv;
335	const struct pmic_glink_hdr *hdr = data;
336
337	switch (le32_to_cpu(hdr->opcode)) {
338	case UC_UCSI_READ_BUF_REQ:
339		pmic_glink_ucsi_read_ack(ucsi, data, len);
340		break;
341	case UC_UCSI_WRITE_BUF_REQ:
342		pmic_glink_ucsi_write_ack(ucsi, data, len);
343		break;
344	case UC_UCSI_USBC_NOTIFY_IND:
345		schedule_work(&ucsi->notify_work);
346		break;
347	}
348}
349
350static void pmic_glink_ucsi_pdr_notify(void *priv, int state)
351{
352	struct pmic_glink_ucsi *ucsi = priv;
353	unsigned long flags;
354
355	spin_lock_irqsave(&ucsi->state_lock, flags);
356	ucsi->pd_running = (state == SERVREG_SERVICE_STATE_UP);
357	spin_unlock_irqrestore(&ucsi->state_lock, flags);
358	schedule_work(&ucsi->register_work);
359}
360
361static void pmic_glink_ucsi_destroy(void *data)
362{
363	struct pmic_glink_ucsi *ucsi = data;
364
365	/* Protect to make sure we're not in a middle of a transaction from a glink callback */
366	mutex_lock(&ucsi->lock);
367	ucsi_destroy(ucsi->ucsi);
368	mutex_unlock(&ucsi->lock);
369}
370
371static unsigned long quirk_sc8180x = UCSI_NO_PARTNER_PDOS;
372static unsigned long quirk_sc8280xp = UCSI_NO_PARTNER_PDOS | UCSI_DELAY_DEVICE_PDOS;
373static unsigned long quirk_sm8450 = UCSI_DELAY_DEVICE_PDOS;
374
375static const struct of_device_id pmic_glink_ucsi_of_quirks[] = {
376	{ .compatible = "qcom,qcm6490-pmic-glink", .data = &quirk_sc8280xp, },
377	{ .compatible = "qcom,sc8180x-pmic-glink", .data = &quirk_sc8180x, },
378	{ .compatible = "qcom,sc8280xp-pmic-glink", .data = &quirk_sc8280xp, },
379	{ .compatible = "qcom,sm8350-pmic-glink", .data = &quirk_sc8180x, },
380	{ .compatible = "qcom,sm8450-pmic-glink", .data = &quirk_sm8450, },
381	{ .compatible = "qcom,sm8550-pmic-glink", .data = &quirk_sm8450, },
382	{}
383};
384
385static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
386				 const struct auxiliary_device_id *id)
387{
388	struct pmic_glink_ucsi *ucsi;
389	struct device *dev = &adev->dev;
390	const struct of_device_id *match;
391	int ret;
392
393	ucsi = devm_kzalloc(dev, sizeof(*ucsi), GFP_KERNEL);
394	if (!ucsi)
395		return -ENOMEM;
396
397	ucsi->dev = dev;
398	dev_set_drvdata(dev, ucsi);
399
400	INIT_WORK(&ucsi->notify_work, pmic_glink_ucsi_notify);
401	INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register);
402	init_completion(&ucsi->read_ack);
403	init_completion(&ucsi->write_ack);
404	spin_lock_init(&ucsi->state_lock);
405	mutex_init(&ucsi->lock);
406
407	ucsi->ucsi = ucsi_create(dev, &pmic_glink_ucsi_ops);
408	if (IS_ERR(ucsi->ucsi))
409		return PTR_ERR(ucsi->ucsi);
410
411	/* Make sure we destroy *after* pmic_glink unregister */
412	ret = devm_add_action_or_reset(dev, pmic_glink_ucsi_destroy, ucsi);
413	if (ret)
414		return ret;
415
416	match = of_match_device(pmic_glink_ucsi_of_quirks, dev->parent);
417	if (match)
418		ucsi->ucsi->quirks = *(unsigned long *)match->data;
419
420	ucsi_set_drvdata(ucsi->ucsi, ucsi);
421
422	device_for_each_child_node_scoped(dev, fwnode) {
423		struct gpio_desc *desc;
424		u32 port;
425
426		ret = fwnode_property_read_u32(fwnode, "reg", &port);
427		if (ret < 0) {
428			dev_err(dev, "missing reg property of %pOFn\n", fwnode);
429			return ret;
430		}
431
432		if (port >= PMIC_GLINK_MAX_PORTS) {
433			dev_warn(dev, "invalid connector number, ignoring\n");
434			continue;
435		}
436
437		desc = devm_gpiod_get_index_optional(&adev->dev, "orientation", port, GPIOD_IN);
438
439		/* If GPIO isn't found, continue */
440		if (!desc)
441			continue;
442
443		if (IS_ERR(desc))
444			return dev_err_probe(dev, PTR_ERR(desc),
445					     "unable to acquire orientation gpio\n");
446
447		ucsi->port_orientation[port] = desc;
448	}
449
450	ucsi->client = devm_pmic_glink_client_alloc(dev, PMIC_GLINK_OWNER_USBC,
451						    pmic_glink_ucsi_callback,
452						    pmic_glink_ucsi_pdr_notify,
453						    ucsi);
454	if (IS_ERR(ucsi->client))
455		return PTR_ERR(ucsi->client);
456
457	pmic_glink_client_register(ucsi->client);
458
459	return 0;
460}
461
462static void pmic_glink_ucsi_remove(struct auxiliary_device *adev)
463{
464	struct pmic_glink_ucsi *ucsi = dev_get_drvdata(&adev->dev);
465
466	/* Unregister first to stop having read & writes */
467	ucsi_unregister(ucsi->ucsi);
468}
469
470static const struct auxiliary_device_id pmic_glink_ucsi_id_table[] = {
471	{ .name = "pmic_glink.ucsi", },
472	{},
473};
474MODULE_DEVICE_TABLE(auxiliary, pmic_glink_ucsi_id_table);
475
476static struct auxiliary_driver pmic_glink_ucsi_driver = {
477	.name = "pmic_glink_ucsi",
478	.probe = pmic_glink_ucsi_probe,
479	.remove = pmic_glink_ucsi_remove,
480	.id_table = pmic_glink_ucsi_id_table,
481};
482
483module_auxiliary_driver(pmic_glink_ucsi_driver);
484
485MODULE_DESCRIPTION("Qualcomm PMIC GLINK UCSI driver");
486MODULE_LICENSE("GPL");
~/ Read-only file preview.