1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Thunderbolt/USB4 retimer support.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2020, Intel Corporation
6*4882a593Smuzhiyun * Authors: Kranthi Kuntala <kranthi.kuntala@intel.com>
7*4882a593Smuzhiyun * Mika Westerberg <mika.westerberg@linux.intel.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/pm_runtime.h>
12*4882a593Smuzhiyun #include <linux/sched/signal.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include "sb_regs.h"
15*4882a593Smuzhiyun #include "tb.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define TB_MAX_RETIMER_INDEX 6
18*4882a593Smuzhiyun
tb_retimer_nvm_read(void * priv,unsigned int offset,void * val,size_t bytes)19*4882a593Smuzhiyun static int tb_retimer_nvm_read(void *priv, unsigned int offset, void *val,
20*4882a593Smuzhiyun size_t bytes)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun struct tb_nvm *nvm = priv;
23*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(nvm->dev);
24*4882a593Smuzhiyun int ret;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun pm_runtime_get_sync(&rt->dev);
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun if (!mutex_trylock(&rt->tb->lock)) {
29*4882a593Smuzhiyun ret = restart_syscall();
30*4882a593Smuzhiyun goto out;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun ret = usb4_port_retimer_nvm_read(rt->port, rt->index, offset, val, bytes);
34*4882a593Smuzhiyun mutex_unlock(&rt->tb->lock);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun out:
37*4882a593Smuzhiyun pm_runtime_mark_last_busy(&rt->dev);
38*4882a593Smuzhiyun pm_runtime_put_autosuspend(&rt->dev);
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun return ret;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
tb_retimer_nvm_write(void * priv,unsigned int offset,void * val,size_t bytes)43*4882a593Smuzhiyun static int tb_retimer_nvm_write(void *priv, unsigned int offset, void *val,
44*4882a593Smuzhiyun size_t bytes)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun struct tb_nvm *nvm = priv;
47*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(nvm->dev);
48*4882a593Smuzhiyun int ret = 0;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (!mutex_trylock(&rt->tb->lock))
51*4882a593Smuzhiyun return restart_syscall();
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun ret = tb_nvm_write_buf(nvm, offset, val, bytes);
54*4882a593Smuzhiyun mutex_unlock(&rt->tb->lock);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun return ret;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
tb_retimer_nvm_add(struct tb_retimer * rt)59*4882a593Smuzhiyun static int tb_retimer_nvm_add(struct tb_retimer *rt)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun struct tb_nvm *nvm;
62*4882a593Smuzhiyun u32 val, nvm_size;
63*4882a593Smuzhiyun int ret;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun nvm = tb_nvm_alloc(&rt->dev);
66*4882a593Smuzhiyun if (IS_ERR(nvm))
67*4882a593Smuzhiyun return PTR_ERR(nvm);
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun ret = usb4_port_retimer_nvm_read(rt->port, rt->index, NVM_VERSION, &val,
70*4882a593Smuzhiyun sizeof(val));
71*4882a593Smuzhiyun if (ret)
72*4882a593Smuzhiyun goto err_nvm;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun nvm->major = val >> 16;
75*4882a593Smuzhiyun nvm->minor = val >> 8;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun ret = usb4_port_retimer_nvm_read(rt->port, rt->index, NVM_FLASH_SIZE,
78*4882a593Smuzhiyun &val, sizeof(val));
79*4882a593Smuzhiyun if (ret)
80*4882a593Smuzhiyun goto err_nvm;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun nvm_size = (SZ_1M << (val & 7)) / 8;
83*4882a593Smuzhiyun nvm_size = (nvm_size - SZ_16K) / 2;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun ret = tb_nvm_add_active(nvm, nvm_size, tb_retimer_nvm_read);
86*4882a593Smuzhiyun if (ret)
87*4882a593Smuzhiyun goto err_nvm;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun ret = tb_nvm_add_non_active(nvm, NVM_MAX_SIZE, tb_retimer_nvm_write);
90*4882a593Smuzhiyun if (ret)
91*4882a593Smuzhiyun goto err_nvm;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun rt->nvm = nvm;
94*4882a593Smuzhiyun return 0;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun err_nvm:
97*4882a593Smuzhiyun tb_nvm_free(nvm);
98*4882a593Smuzhiyun return ret;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
tb_retimer_nvm_validate_and_write(struct tb_retimer * rt)101*4882a593Smuzhiyun static int tb_retimer_nvm_validate_and_write(struct tb_retimer *rt)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun unsigned int image_size, hdr_size;
104*4882a593Smuzhiyun const u8 *buf = rt->nvm->buf;
105*4882a593Smuzhiyun u16 ds_size, device;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun image_size = rt->nvm->buf_data_size;
108*4882a593Smuzhiyun if (image_size < NVM_MIN_SIZE || image_size > NVM_MAX_SIZE)
109*4882a593Smuzhiyun return -EINVAL;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /*
112*4882a593Smuzhiyun * FARB pointer must point inside the image and must at least
113*4882a593Smuzhiyun * contain parts of the digital section we will be reading here.
114*4882a593Smuzhiyun */
115*4882a593Smuzhiyun hdr_size = (*(u32 *)buf) & 0xffffff;
116*4882a593Smuzhiyun if (hdr_size + NVM_DEVID + 2 >= image_size)
117*4882a593Smuzhiyun return -EINVAL;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* Digital section start should be aligned to 4k page */
120*4882a593Smuzhiyun if (!IS_ALIGNED(hdr_size, SZ_4K))
121*4882a593Smuzhiyun return -EINVAL;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun * Read digital section size and check that it also fits inside
125*4882a593Smuzhiyun * the image.
126*4882a593Smuzhiyun */
127*4882a593Smuzhiyun ds_size = *(u16 *)(buf + hdr_size);
128*4882a593Smuzhiyun if (ds_size >= image_size)
129*4882a593Smuzhiyun return -EINVAL;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /*
132*4882a593Smuzhiyun * Make sure the device ID in the image matches the retimer
133*4882a593Smuzhiyun * hardware.
134*4882a593Smuzhiyun */
135*4882a593Smuzhiyun device = *(u16 *)(buf + hdr_size + NVM_DEVID);
136*4882a593Smuzhiyun if (device != rt->device)
137*4882a593Smuzhiyun return -EINVAL;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Skip headers in the image */
140*4882a593Smuzhiyun buf += hdr_size;
141*4882a593Smuzhiyun image_size -= hdr_size;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun return usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf,
144*4882a593Smuzhiyun image_size);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
device_show(struct device * dev,struct device_attribute * attr,char * buf)147*4882a593Smuzhiyun static ssize_t device_show(struct device *dev, struct device_attribute *attr,
148*4882a593Smuzhiyun char *buf)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun return sprintf(buf, "%#x\n", rt->device);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun static DEVICE_ATTR_RO(device);
155*4882a593Smuzhiyun
nvm_authenticate_show(struct device * dev,struct device_attribute * attr,char * buf)156*4882a593Smuzhiyun static ssize_t nvm_authenticate_show(struct device *dev,
157*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
160*4882a593Smuzhiyun int ret;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if (!mutex_trylock(&rt->tb->lock))
163*4882a593Smuzhiyun return restart_syscall();
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun if (!rt->nvm)
166*4882a593Smuzhiyun ret = -EAGAIN;
167*4882a593Smuzhiyun else
168*4882a593Smuzhiyun ret = sprintf(buf, "%#x\n", rt->auth_status);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun mutex_unlock(&rt->tb->lock);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun return ret;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
nvm_authenticate_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)175*4882a593Smuzhiyun static ssize_t nvm_authenticate_store(struct device *dev,
176*4882a593Smuzhiyun struct device_attribute *attr, const char *buf, size_t count)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
179*4882a593Smuzhiyun bool val;
180*4882a593Smuzhiyun int ret;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun pm_runtime_get_sync(&rt->dev);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun if (!mutex_trylock(&rt->tb->lock)) {
185*4882a593Smuzhiyun ret = restart_syscall();
186*4882a593Smuzhiyun goto exit_rpm;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (!rt->nvm) {
190*4882a593Smuzhiyun ret = -EAGAIN;
191*4882a593Smuzhiyun goto exit_unlock;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun ret = kstrtobool(buf, &val);
195*4882a593Smuzhiyun if (ret)
196*4882a593Smuzhiyun goto exit_unlock;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun /* Always clear status */
199*4882a593Smuzhiyun rt->auth_status = 0;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (val) {
202*4882a593Smuzhiyun if (!rt->nvm->buf) {
203*4882a593Smuzhiyun ret = -EINVAL;
204*4882a593Smuzhiyun goto exit_unlock;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun ret = tb_retimer_nvm_validate_and_write(rt);
208*4882a593Smuzhiyun if (ret)
209*4882a593Smuzhiyun goto exit_unlock;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun ret = usb4_port_retimer_nvm_authenticate(rt->port, rt->index);
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun exit_unlock:
215*4882a593Smuzhiyun mutex_unlock(&rt->tb->lock);
216*4882a593Smuzhiyun exit_rpm:
217*4882a593Smuzhiyun pm_runtime_mark_last_busy(&rt->dev);
218*4882a593Smuzhiyun pm_runtime_put_autosuspend(&rt->dev);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (ret)
221*4882a593Smuzhiyun return ret;
222*4882a593Smuzhiyun return count;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun static DEVICE_ATTR_RW(nvm_authenticate);
225*4882a593Smuzhiyun
nvm_version_show(struct device * dev,struct device_attribute * attr,char * buf)226*4882a593Smuzhiyun static ssize_t nvm_version_show(struct device *dev,
227*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
230*4882a593Smuzhiyun int ret;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun if (!mutex_trylock(&rt->tb->lock))
233*4882a593Smuzhiyun return restart_syscall();
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (!rt->nvm)
236*4882a593Smuzhiyun ret = -EAGAIN;
237*4882a593Smuzhiyun else
238*4882a593Smuzhiyun ret = sprintf(buf, "%x.%x\n", rt->nvm->major, rt->nvm->minor);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun mutex_unlock(&rt->tb->lock);
241*4882a593Smuzhiyun return ret;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun static DEVICE_ATTR_RO(nvm_version);
244*4882a593Smuzhiyun
vendor_show(struct device * dev,struct device_attribute * attr,char * buf)245*4882a593Smuzhiyun static ssize_t vendor_show(struct device *dev, struct device_attribute *attr,
246*4882a593Smuzhiyun char *buf)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun return sprintf(buf, "%#x\n", rt->vendor);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun static DEVICE_ATTR_RO(vendor);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun static struct attribute *retimer_attrs[] = {
255*4882a593Smuzhiyun &dev_attr_device.attr,
256*4882a593Smuzhiyun &dev_attr_nvm_authenticate.attr,
257*4882a593Smuzhiyun &dev_attr_nvm_version.attr,
258*4882a593Smuzhiyun &dev_attr_vendor.attr,
259*4882a593Smuzhiyun NULL
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun static const struct attribute_group retimer_group = {
263*4882a593Smuzhiyun .attrs = retimer_attrs,
264*4882a593Smuzhiyun };
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun static const struct attribute_group *retimer_groups[] = {
267*4882a593Smuzhiyun &retimer_group,
268*4882a593Smuzhiyun NULL
269*4882a593Smuzhiyun };
270*4882a593Smuzhiyun
tb_retimer_release(struct device * dev)271*4882a593Smuzhiyun static void tb_retimer_release(struct device *dev)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun kfree(rt);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun struct device_type tb_retimer_type = {
279*4882a593Smuzhiyun .name = "thunderbolt_retimer",
280*4882a593Smuzhiyun .groups = retimer_groups,
281*4882a593Smuzhiyun .release = tb_retimer_release,
282*4882a593Smuzhiyun };
283*4882a593Smuzhiyun
tb_retimer_add(struct tb_port * port,u8 index,u32 auth_status)284*4882a593Smuzhiyun static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun struct tb_retimer *rt;
287*4882a593Smuzhiyun u32 vendor, device;
288*4882a593Smuzhiyun int ret;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun if (!port->cap_usb4)
291*4882a593Smuzhiyun return -EINVAL;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun ret = usb4_port_retimer_read(port, index, USB4_SB_VENDOR_ID, &vendor,
294*4882a593Smuzhiyun sizeof(vendor));
295*4882a593Smuzhiyun if (ret) {
296*4882a593Smuzhiyun if (ret != -ENODEV)
297*4882a593Smuzhiyun tb_port_warn(port, "failed read retimer VendorId: %d\n", ret);
298*4882a593Smuzhiyun return ret;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun ret = usb4_port_retimer_read(port, index, USB4_SB_PRODUCT_ID, &device,
302*4882a593Smuzhiyun sizeof(device));
303*4882a593Smuzhiyun if (ret) {
304*4882a593Smuzhiyun if (ret != -ENODEV)
305*4882a593Smuzhiyun tb_port_warn(port, "failed read retimer ProductId: %d\n", ret);
306*4882a593Smuzhiyun return ret;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (vendor != PCI_VENDOR_ID_INTEL && vendor != 0x8087) {
310*4882a593Smuzhiyun tb_port_info(port, "retimer NVM format of vendor %#x is not supported\n",
311*4882a593Smuzhiyun vendor);
312*4882a593Smuzhiyun return -EOPNOTSUPP;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /*
316*4882a593Smuzhiyun * Check that it supports NVM operations. If not then don't add
317*4882a593Smuzhiyun * the device at all.
318*4882a593Smuzhiyun */
319*4882a593Smuzhiyun ret = usb4_port_retimer_nvm_sector_size(port, index);
320*4882a593Smuzhiyun if (ret < 0)
321*4882a593Smuzhiyun return ret;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun rt = kzalloc(sizeof(*rt), GFP_KERNEL);
324*4882a593Smuzhiyun if (!rt)
325*4882a593Smuzhiyun return -ENOMEM;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun rt->index = index;
328*4882a593Smuzhiyun rt->vendor = vendor;
329*4882a593Smuzhiyun rt->device = device;
330*4882a593Smuzhiyun rt->auth_status = auth_status;
331*4882a593Smuzhiyun rt->port = port;
332*4882a593Smuzhiyun rt->tb = port->sw->tb;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun rt->dev.parent = &port->sw->dev;
335*4882a593Smuzhiyun rt->dev.bus = &tb_bus_type;
336*4882a593Smuzhiyun rt->dev.type = &tb_retimer_type;
337*4882a593Smuzhiyun dev_set_name(&rt->dev, "%s:%u.%u", dev_name(&port->sw->dev),
338*4882a593Smuzhiyun port->port, index);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun ret = device_register(&rt->dev);
341*4882a593Smuzhiyun if (ret) {
342*4882a593Smuzhiyun dev_err(&rt->dev, "failed to register retimer: %d\n", ret);
343*4882a593Smuzhiyun put_device(&rt->dev);
344*4882a593Smuzhiyun return ret;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun ret = tb_retimer_nvm_add(rt);
348*4882a593Smuzhiyun if (ret) {
349*4882a593Smuzhiyun dev_err(&rt->dev, "failed to add NVM devices: %d\n", ret);
350*4882a593Smuzhiyun device_unregister(&rt->dev);
351*4882a593Smuzhiyun return ret;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun dev_info(&rt->dev, "new retimer found, vendor=%#x device=%#x\n",
355*4882a593Smuzhiyun rt->vendor, rt->device);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun pm_runtime_no_callbacks(&rt->dev);
358*4882a593Smuzhiyun pm_runtime_set_active(&rt->dev);
359*4882a593Smuzhiyun pm_runtime_enable(&rt->dev);
360*4882a593Smuzhiyun pm_runtime_set_autosuspend_delay(&rt->dev, TB_AUTOSUSPEND_DELAY);
361*4882a593Smuzhiyun pm_runtime_mark_last_busy(&rt->dev);
362*4882a593Smuzhiyun pm_runtime_use_autosuspend(&rt->dev);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
tb_retimer_remove(struct tb_retimer * rt)367*4882a593Smuzhiyun static void tb_retimer_remove(struct tb_retimer *rt)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun dev_info(&rt->dev, "retimer disconnected\n");
370*4882a593Smuzhiyun tb_nvm_free(rt->nvm);
371*4882a593Smuzhiyun device_unregister(&rt->dev);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun struct tb_retimer_lookup {
375*4882a593Smuzhiyun const struct tb_port *port;
376*4882a593Smuzhiyun u8 index;
377*4882a593Smuzhiyun };
378*4882a593Smuzhiyun
retimer_match(struct device * dev,void * data)379*4882a593Smuzhiyun static int retimer_match(struct device *dev, void *data)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun const struct tb_retimer_lookup *lookup = data;
382*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun return rt && rt->port == lookup->port && rt->index == lookup->index;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
tb_port_find_retimer(struct tb_port * port,u8 index)387*4882a593Smuzhiyun static struct tb_retimer *tb_port_find_retimer(struct tb_port *port, u8 index)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun struct tb_retimer_lookup lookup = { .port = port, .index = index };
390*4882a593Smuzhiyun struct device *dev;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun dev = device_find_child(&port->sw->dev, &lookup, retimer_match);
393*4882a593Smuzhiyun if (dev)
394*4882a593Smuzhiyun return tb_to_retimer(dev);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun return NULL;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /**
400*4882a593Smuzhiyun * tb_retimer_scan() - Scan for on-board retimers under port
401*4882a593Smuzhiyun * @port: USB4 port to scan
402*4882a593Smuzhiyun *
403*4882a593Smuzhiyun * Tries to enumerate on-board retimers connected to @port. Found
404*4882a593Smuzhiyun * retimers are registered as children of @port. Does not scan for cable
405*4882a593Smuzhiyun * retimers for now.
406*4882a593Smuzhiyun */
tb_retimer_scan(struct tb_port * port)407*4882a593Smuzhiyun int tb_retimer_scan(struct tb_port *port)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
410*4882a593Smuzhiyun int ret, i, last_idx = 0;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun if (!port->cap_usb4)
413*4882a593Smuzhiyun return 0;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun /*
416*4882a593Smuzhiyun * Send broadcast RT to make sure retimer indices facing this
417*4882a593Smuzhiyun * port are set.
418*4882a593Smuzhiyun */
419*4882a593Smuzhiyun ret = usb4_port_enumerate_retimers(port);
420*4882a593Smuzhiyun if (ret)
421*4882a593Smuzhiyun return ret;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /*
424*4882a593Smuzhiyun * Before doing anything else, read the authentication status.
425*4882a593Smuzhiyun * If the retimer has it set, store it for the new retimer
426*4882a593Smuzhiyun * device instance.
427*4882a593Smuzhiyun */
428*4882a593Smuzhiyun for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
429*4882a593Smuzhiyun usb4_port_retimer_nvm_authenticate_status(port, i, &status[i]);
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) {
432*4882a593Smuzhiyun /*
433*4882a593Smuzhiyun * Last retimer is true only for the last on-board
434*4882a593Smuzhiyun * retimer (the one connected directly to the Type-C
435*4882a593Smuzhiyun * port).
436*4882a593Smuzhiyun */
437*4882a593Smuzhiyun ret = usb4_port_retimer_is_last(port, i);
438*4882a593Smuzhiyun if (ret > 0)
439*4882a593Smuzhiyun last_idx = i;
440*4882a593Smuzhiyun else if (ret < 0)
441*4882a593Smuzhiyun break;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (!last_idx)
445*4882a593Smuzhiyun return 0;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun /* Add on-board retimers if they do not exist already */
448*4882a593Smuzhiyun for (i = 1; i <= last_idx; i++) {
449*4882a593Smuzhiyun struct tb_retimer *rt;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun rt = tb_port_find_retimer(port, i);
452*4882a593Smuzhiyun if (rt) {
453*4882a593Smuzhiyun put_device(&rt->dev);
454*4882a593Smuzhiyun } else {
455*4882a593Smuzhiyun ret = tb_retimer_add(port, i, status[i]);
456*4882a593Smuzhiyun if (ret && ret != -EOPNOTSUPP)
457*4882a593Smuzhiyun return ret;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun return 0;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun
remove_retimer(struct device * dev,void * data)464*4882a593Smuzhiyun static int remove_retimer(struct device *dev, void *data)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun struct tb_retimer *rt = tb_to_retimer(dev);
467*4882a593Smuzhiyun struct tb_port *port = data;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun if (rt && rt->port == port)
470*4882a593Smuzhiyun tb_retimer_remove(rt);
471*4882a593Smuzhiyun return 0;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun /**
475*4882a593Smuzhiyun * tb_retimer_remove_all() - Remove all retimers under port
476*4882a593Smuzhiyun * @port: USB4 port whose retimers to remove
477*4882a593Smuzhiyun *
478*4882a593Smuzhiyun * This removes all previously added retimers under @port.
479*4882a593Smuzhiyun */
tb_retimer_remove_all(struct tb_port * port)480*4882a593Smuzhiyun void tb_retimer_remove_all(struct tb_port *port)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun if (port->cap_usb4)
483*4882a593Smuzhiyun device_for_each_child_reverse(&port->sw->dev, port,
484*4882a593Smuzhiyun remove_retimer);
485*4882a593Smuzhiyun }
486