1// SPDX-License-Identifier: GPL-2.0
2/*
3 * USB4 port device
4 *
5 * Copyright (C) 2021, Intel Corporation
6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
7 */
8
9#include <linux/pm_runtime.h>
10#include <linux/component.h>
11#include <linux/property.h>
12
13#include "tb.h"
14
15static int connector_bind(struct device *dev, struct device *connector, void *data)
16{
17	int ret;
18
19	ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector");
20	if (ret)
21		return ret;
22
23	ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev));
24	if (ret)
25		sysfs_remove_link(&dev->kobj, "connector");
26
27	return ret;
28}
29
30static void connector_unbind(struct device *dev, struct device *connector, void *data)
31{
32	sysfs_remove_link(&connector->kobj, dev_name(dev));
33	sysfs_remove_link(&dev->kobj, "connector");
34}
35
36static const struct component_ops connector_ops = {
37	.bind = connector_bind,
38	.unbind = connector_unbind,
39};
40
41static ssize_t link_show(struct device *dev, struct device_attribute *attr,
42			 char *buf)
43{
44	struct usb4_port *usb4 = tb_to_usb4_port_device(dev);
45	struct tb_port *port = usb4->port;
46	struct tb *tb = port->sw->tb;
47	const char *link;
48
49	if (mutex_lock_interruptible(&tb->lock))
50		return -ERESTARTSYS;
51
52	if (tb_is_upstream_port(port))
53		link = port->sw->link_usb4 ? "usb4" : "tbt";
54	else if (tb_port_has_remote(port))
55		link = port->remote->sw->link_usb4 ? "usb4" : "tbt";
56	else if (port->xdomain)
57		link = port->xdomain->link_usb4 ? "usb4" : "tbt";
58	else
59		link = "none";
60
61	mutex_unlock(&tb->lock);
62
63	return sysfs_emit(buf, "%s\n", link);
64}
65static DEVICE_ATTR_RO(link);
66
67static struct attribute *common_attrs[] = {
68	&dev_attr_link.attr,
69	NULL
70};
71
72static const struct attribute_group common_group = {
73	.attrs = common_attrs,
74};
75
76static int usb4_port_offline(struct usb4_port *usb4)
77{
78	struct tb_port *port = usb4->port;
79	int ret;
80
81	ret = tb_acpi_power_on_retimers(port);
82	if (ret)
83		return ret;
84
85	ret = usb4_port_router_offline(port);
86	if (ret) {
87		tb_acpi_power_off_retimers(port);
88		return ret;
89	}
90
91	ret = tb_retimer_scan(port, false);
92	if (ret) {
93		usb4_port_router_online(port);
94		tb_acpi_power_off_retimers(port);
95	}
96
97	return ret;
98}
99
100static void usb4_port_online(struct usb4_port *usb4)
101{
102	struct tb_port *port = usb4->port;
103
104	usb4_port_router_online(port);
105	tb_acpi_power_off_retimers(port);
106}
107
108static ssize_t offline_show(struct device *dev,
109	struct device_attribute *attr, char *buf)
110{
111	struct usb4_port *usb4 = tb_to_usb4_port_device(dev);
112
113	return sysfs_emit(buf, "%d\n", usb4->offline);
114}
115
116static ssize_t offline_store(struct device *dev,
117	struct device_attribute *attr, const char *buf, size_t count)
118{
119	struct usb4_port *usb4 = tb_to_usb4_port_device(dev);
120	struct tb_port *port = usb4->port;
121	struct tb *tb = port->sw->tb;
122	bool val;
123	int ret;
124
125	ret = kstrtobool(buf, &val);
126	if (ret)
127		return ret;
128
129	pm_runtime_get_sync(&usb4->dev);
130
131	if (mutex_lock_interruptible(&tb->lock)) {
132		ret = -ERESTARTSYS;
133		goto out_rpm;
134	}
135
136	if (val == usb4->offline)
137		goto out_unlock;
138
139	/* Offline mode works only for ports that are not connected */
140	if (tb_port_has_remote(port)) {
141		ret = -EBUSY;
142		goto out_unlock;
143	}
144
145	if (val) {
146		ret = usb4_port_offline(usb4);
147		if (ret)
148			goto out_unlock;
149	} else {
150		usb4_port_online(usb4);
151		tb_retimer_remove_all(port);
152	}
153
154	usb4->offline = val;
155	tb_port_dbg(port, "%s offline mode\n", val ? "enter" : "exit");
156
157out_unlock:
158	mutex_unlock(&tb->lock);
159out_rpm:
160	pm_runtime_mark_last_busy(&usb4->dev);
161	pm_runtime_put_autosuspend(&usb4->dev);
162
163	return ret ? ret : count;
164}
165static DEVICE_ATTR_RW(offline);
166
167static ssize_t rescan_store(struct device *dev,
168	struct device_attribute *attr, const char *buf, size_t count)
169{
170	struct usb4_port *usb4 = tb_to_usb4_port_device(dev);
171	struct tb_port *port = usb4->port;
172	struct tb *tb = port->sw->tb;
173	bool val;
174	int ret;
175
176	ret = kstrtobool(buf, &val);
177	if (ret)
178		return ret;
179
180	if (!val)
181		return count;
182
183	pm_runtime_get_sync(&usb4->dev);
184
185	if (mutex_lock_interruptible(&tb->lock)) {
186		ret = -ERESTARTSYS;
187		goto out_rpm;
188	}
189
190	/* Must be in offline mode already */
191	if (!usb4->offline) {
192		ret = -EINVAL;
193		goto out_unlock;
194	}
195
196	tb_retimer_remove_all(port);
197	ret = tb_retimer_scan(port, true);
198
199out_unlock:
200	mutex_unlock(&tb->lock);
201out_rpm:
202	pm_runtime_mark_last_busy(&usb4->dev);
203	pm_runtime_put_autosuspend(&usb4->dev);
204
205	return ret ? ret : count;
206}
207static DEVICE_ATTR_WO(rescan);
208
209static struct attribute *service_attrs[] = {
210	&dev_attr_offline.attr,
211	&dev_attr_rescan.attr,
212	NULL
213};
214
215static umode_t service_attr_is_visible(struct kobject *kobj,
216				       struct attribute *attr, int n)
217{
218	struct device *dev = kobj_to_dev(kobj);
219	struct usb4_port *usb4 = tb_to_usb4_port_device(dev);
220
221	/*
222	 * Always need some platform help to cycle the modes so that
223	 * retimers can be accessed through the sideband.
224	 */
225	return usb4->can_offline ? attr->mode : 0;
226}
227
228static const struct attribute_group service_group = {
229	.attrs = service_attrs,
230	.is_visible = service_attr_is_visible,
231};
232
233static const struct attribute_group *usb4_port_device_groups[] = {
234	&common_group,
235	&service_group,
236	NULL
237};
238
239static void usb4_port_device_release(struct device *dev)
240{
241	struct usb4_port *usb4 = container_of(dev, struct usb4_port, dev);
242
243	kfree(usb4);
244}
245
246const struct device_type usb4_port_device_type = {
247	.name = "usb4_port",
248	.groups = usb4_port_device_groups,
249	.release = usb4_port_device_release,
250};
251
252/**
253 * usb4_port_device_add() - Add USB4 port device
254 * @port: Lane 0 adapter port to add the USB4 port
255 *
256 * Creates and registers a USB4 port device for @port. Returns the new
257 * USB4 port device pointer or ERR_PTR() in case of error.
258 */
259struct usb4_port *usb4_port_device_add(struct tb_port *port)
260{
261	struct usb4_port *usb4;
262	int ret;
263
264	usb4 = kzalloc(sizeof(*usb4), GFP_KERNEL);
265	if (!usb4)
266		return ERR_PTR(-ENOMEM);
267
268	usb4->port = port;
269	usb4->dev.type = &usb4_port_device_type;
270	usb4->dev.parent = &port->sw->dev;
271	dev_set_name(&usb4->dev, "usb4_port%d", port->port);
272
273	ret = device_register(&usb4->dev);
274	if (ret) {
275		put_device(&usb4->dev);
276		return ERR_PTR(ret);
277	}
278
279	if (dev_fwnode(&usb4->dev)) {
280		ret = component_add(&usb4->dev, &connector_ops);
281		if (ret) {
282			dev_err(&usb4->dev, "failed to add component\n");
283			device_unregister(&usb4->dev);
284		}
285	}
286
287	if (!tb_is_upstream_port(port))
288		device_set_wakeup_capable(&usb4->dev, true);
289
290	pm_runtime_no_callbacks(&usb4->dev);
291	pm_runtime_set_active(&usb4->dev);
292	pm_runtime_enable(&usb4->dev);
293	pm_runtime_set_autosuspend_delay(&usb4->dev, TB_AUTOSUSPEND_DELAY);
294	pm_runtime_mark_last_busy(&usb4->dev);
295	pm_runtime_use_autosuspend(&usb4->dev);
296
297	return usb4;
298}
299
300/**
301 * usb4_port_device_remove() - Removes USB4 port device
302 * @usb4: USB4 port device
303 *
304 * Unregisters the USB4 port device from the system. The device will be
305 * released when the last reference is dropped.
306 */
307void usb4_port_device_remove(struct usb4_port *usb4)
308{
309	if (dev_fwnode(&usb4->dev))
310		component_del(&usb4->dev, &connector_ops);
311	device_unregister(&usb4->dev);
312}
313
314/**
315 * usb4_port_device_resume() - Resumes USB4 port device
316 * @usb4: USB4 port device
317 *
318 * Used to resume USB4 port device after sleep state.
319 */
320int usb4_port_device_resume(struct usb4_port *usb4)
321{
322	return usb4->offline ? usb4_port_offline(usb4) : 0;
323}
324