1*08596ce2Smacallan /* $NetBSD: fdt_port.c,v 1.7 2022/01/21 21:00:26 macallan Exp $ */
24b1d4a54Sbouyer
34b1d4a54Sbouyer /*-
44b1d4a54Sbouyer * Copyright (c) 2018 The NetBSD Foundation, Inc.
54b1d4a54Sbouyer * All rights reserved.
64b1d4a54Sbouyer *
74b1d4a54Sbouyer * This code is derived from software contributed to The NetBSD Foundation
84b1d4a54Sbouyer * by Manuel Bouyer.
94b1d4a54Sbouyer *
104b1d4a54Sbouyer * Redistribution and use in source and binary forms, with or without
114b1d4a54Sbouyer * modification, are permitted provided that the following conditions
124b1d4a54Sbouyer * are met:
134b1d4a54Sbouyer * 1. Redistributions of source code must retain the above copyright
144b1d4a54Sbouyer * notice, this list of conditions and the following disclaimer.
154b1d4a54Sbouyer * 2. Redistributions in binary form must reproduce the above copyright
164b1d4a54Sbouyer * notice, this list of conditions and the following disclaimer in the
174b1d4a54Sbouyer * documentation and/or other materials provided with the distribution.
184b1d4a54Sbouyer *
194b1d4a54Sbouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
204b1d4a54Sbouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
214b1d4a54Sbouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
224b1d4a54Sbouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
234b1d4a54Sbouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
244b1d4a54Sbouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
254b1d4a54Sbouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
264b1d4a54Sbouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
274b1d4a54Sbouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
284b1d4a54Sbouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
294b1d4a54Sbouyer * POSSIBILITY OF SUCH DAMAGE.
304b1d4a54Sbouyer */
314b1d4a54Sbouyer
324b1d4a54Sbouyer /*
334b1d4a54Sbouyer * ports and endpoints management. from
344b1d4a54Sbouyer * linux/Documentation/devicetree/bindings/graph.txt
354b1d4a54Sbouyer * Given a device and its node, it enumerates all ports and endpoints for this
364b1d4a54Sbouyer * device, and register connections with the remote endpoints.
374b1d4a54Sbouyer */
384b1d4a54Sbouyer
394b1d4a54Sbouyer #include <sys/cdefs.h>
404b1d4a54Sbouyer
41*08596ce2Smacallan __KERNEL_RCSID(1, "$NetBSD: fdt_port.c,v 1.7 2022/01/21 21:00:26 macallan Exp $");
424b1d4a54Sbouyer
434b1d4a54Sbouyer #include <sys/param.h>
444b1d4a54Sbouyer #include <sys/systm.h>
454b1d4a54Sbouyer #include <sys/device.h>
464b1d4a54Sbouyer #include <sys/bus.h>
474b1d4a54Sbouyer #include <sys/kmem.h>
484b1d4a54Sbouyer
494b1d4a54Sbouyer #include <dev/fdt/fdtvar.h>
504b1d4a54Sbouyer #include <dev/fdt/fdt_port.h>
514b1d4a54Sbouyer
524b1d4a54Sbouyer struct fdt_endpoint;
534b1d4a54Sbouyer
544b1d4a54Sbouyer struct fdt_port {
554b1d4a54Sbouyer int port_id;
564b1d4a54Sbouyer int port_phandle; /* port's node */
574b1d4a54Sbouyer struct fdt_endpoint *port_ep; /* this port's endpoints */
584b1d4a54Sbouyer int port_nep; /* number of endpoints for this port */
594b1d4a54Sbouyer struct fdt_device_ports *port_dp; /* this port's device */
604b1d4a54Sbouyer };
614b1d4a54Sbouyer
624b1d4a54Sbouyer struct fdt_endpoint {
634b1d4a54Sbouyer int ep_id;
644b1d4a54Sbouyer enum endpoint_type ep_type;
654b1d4a54Sbouyer int ep_phandle;
664b1d4a54Sbouyer struct fdt_port *ep_port; /* parent of this endpoint */
674b1d4a54Sbouyer int ep_rphandle; /* report endpoint */
684b1d4a54Sbouyer struct fdt_endpoint *ep_rep;
694b1d4a54Sbouyer bool ep_active;
704b1d4a54Sbouyer bool ep_enabled;
714b1d4a54Sbouyer };
724b1d4a54Sbouyer
734b1d4a54Sbouyer SLIST_HEAD(, fdt_device_ports) fdt_port_devices =
744b1d4a54Sbouyer SLIST_HEAD_INITIALIZER(&fdt_port_devices);
754b1d4a54Sbouyer
764b1d4a54Sbouyer static void fdt_endpoints_register(int, struct fdt_port *, enum endpoint_type);
774b1d4a54Sbouyer static const char *ep_name(struct fdt_endpoint *, char *, int);
784b1d4a54Sbouyer
794b1d4a54Sbouyer struct fdt_endpoint *
fdt_endpoint_get_from_phandle(int rphandle)804b1d4a54Sbouyer fdt_endpoint_get_from_phandle(int rphandle)
814b1d4a54Sbouyer {
824b1d4a54Sbouyer struct fdt_device_ports *ports;
834b1d4a54Sbouyer int p, e;
844b1d4a54Sbouyer
854b1d4a54Sbouyer if (rphandle < 0)
864b1d4a54Sbouyer return NULL;
874b1d4a54Sbouyer
884b1d4a54Sbouyer SLIST_FOREACH(ports, &fdt_port_devices, dp_list) {
894b1d4a54Sbouyer for (p = 0; p < ports->dp_nports; p++) {
904b1d4a54Sbouyer struct fdt_port *port = &ports->dp_port[p];
914b1d4a54Sbouyer for (e = 0; e < port->port_nep; e++) {
924b1d4a54Sbouyer struct fdt_endpoint *ep = &port->port_ep[e];
934b1d4a54Sbouyer if (ep->ep_phandle == rphandle)
944b1d4a54Sbouyer return ep;
954b1d4a54Sbouyer }
964b1d4a54Sbouyer }
974b1d4a54Sbouyer }
984b1d4a54Sbouyer return NULL;
994b1d4a54Sbouyer
1004b1d4a54Sbouyer }
1014b1d4a54Sbouyer
1024b1d4a54Sbouyer struct fdt_endpoint *
fdt_endpoint_get_from_index(struct fdt_device_ports * device_ports,int port_index,int ep_index)1034b1d4a54Sbouyer fdt_endpoint_get_from_index(struct fdt_device_ports *device_ports,
1044b1d4a54Sbouyer int port_index, int ep_index)
1054b1d4a54Sbouyer {
1064b1d4a54Sbouyer int p, e;
1074b1d4a54Sbouyer for (p = 0; p < device_ports->dp_nports; p++) {
1084b1d4a54Sbouyer struct fdt_port *port = &device_ports->dp_port[p];
1094b1d4a54Sbouyer if (port->port_id != port_index)
1104b1d4a54Sbouyer continue;
1114b1d4a54Sbouyer for (e = 0; e < port->port_nep; e++) {
1124b1d4a54Sbouyer struct fdt_endpoint *ep = &port->port_ep[e];
1134b1d4a54Sbouyer if (ep->ep_id == ep_index) {
1144b1d4a54Sbouyer return ep;
1154b1d4a54Sbouyer }
1164b1d4a54Sbouyer }
1174b1d4a54Sbouyer }
1184b1d4a54Sbouyer return NULL;
1194b1d4a54Sbouyer }
1204b1d4a54Sbouyer
1214b1d4a54Sbouyer struct fdt_endpoint *
fdt_endpoint_remote_from_index(struct fdt_device_ports * device_ports,int port_index,int ep_index)122a9d03646Sjmcneill fdt_endpoint_remote_from_index(struct fdt_device_ports *device_ports,
123a9d03646Sjmcneill int port_index, int ep_index)
124a9d03646Sjmcneill {
125a9d03646Sjmcneill struct fdt_endpoint *ep;
126a9d03646Sjmcneill
127a9d03646Sjmcneill ep = fdt_endpoint_get_from_index(device_ports, port_index,
128a9d03646Sjmcneill ep_index);
129a9d03646Sjmcneill if (ep == NULL)
130a9d03646Sjmcneill return NULL;
131a9d03646Sjmcneill
132a9d03646Sjmcneill return fdt_endpoint_remote(ep);
133a9d03646Sjmcneill }
134a9d03646Sjmcneill
135a9d03646Sjmcneill struct fdt_endpoint *
fdt_endpoint_remote(struct fdt_endpoint * ep)1364b1d4a54Sbouyer fdt_endpoint_remote(struct fdt_endpoint *ep)
1374b1d4a54Sbouyer {
1384b1d4a54Sbouyer return ep->ep_rep;
1394b1d4a54Sbouyer }
1404b1d4a54Sbouyer
1414b1d4a54Sbouyer int
fdt_endpoint_port_index(struct fdt_endpoint * ep)1424b1d4a54Sbouyer fdt_endpoint_port_index(struct fdt_endpoint *ep)
1434b1d4a54Sbouyer {
1444b1d4a54Sbouyer return ep->ep_port->port_id;
1454b1d4a54Sbouyer }
1464b1d4a54Sbouyer
1474b1d4a54Sbouyer int
fdt_endpoint_index(struct fdt_endpoint * ep)1484b1d4a54Sbouyer fdt_endpoint_index(struct fdt_endpoint *ep)
1494b1d4a54Sbouyer {
1504b1d4a54Sbouyer return ep->ep_id;
1514b1d4a54Sbouyer }
1524b1d4a54Sbouyer
1534b1d4a54Sbouyer device_t
fdt_endpoint_device(struct fdt_endpoint * ep)1544b1d4a54Sbouyer fdt_endpoint_device(struct fdt_endpoint *ep)
1554b1d4a54Sbouyer {
1564b1d4a54Sbouyer return ep->ep_port->port_dp->dp_dev;
1574b1d4a54Sbouyer }
1584b1d4a54Sbouyer
1594b1d4a54Sbouyer bool
fdt_endpoint_is_active(struct fdt_endpoint * ep)1604b1d4a54Sbouyer fdt_endpoint_is_active(struct fdt_endpoint *ep)
1614b1d4a54Sbouyer {
1624b1d4a54Sbouyer return ep->ep_active;
1634b1d4a54Sbouyer }
1644b1d4a54Sbouyer
1654b1d4a54Sbouyer bool
fdt_endpoint_is_enabled(struct fdt_endpoint * ep)1664b1d4a54Sbouyer fdt_endpoint_is_enabled(struct fdt_endpoint *ep)
1674b1d4a54Sbouyer {
1684b1d4a54Sbouyer return ep->ep_enabled;
1694b1d4a54Sbouyer }
1704b1d4a54Sbouyer
171a9d03646Sjmcneill enum endpoint_type
fdt_endpoint_type(struct fdt_endpoint * ep)172a9d03646Sjmcneill fdt_endpoint_type(struct fdt_endpoint *ep)
173a9d03646Sjmcneill {
174a9d03646Sjmcneill return ep->ep_type;
175a9d03646Sjmcneill }
176a9d03646Sjmcneill
1774b1d4a54Sbouyer int
fdt_endpoint_activate(struct fdt_endpoint * ep,bool activate)1784b1d4a54Sbouyer fdt_endpoint_activate(struct fdt_endpoint *ep, bool activate)
1794b1d4a54Sbouyer {
1804b1d4a54Sbouyer struct fdt_endpoint *rep = fdt_endpoint_remote(ep);
1814b1d4a54Sbouyer struct fdt_device_ports *rdp;
1824b1d4a54Sbouyer int error = 0;
1834b1d4a54Sbouyer
1844b1d4a54Sbouyer if (rep == NULL)
1854b1d4a54Sbouyer return ENODEV;
1864b1d4a54Sbouyer
1874b1d4a54Sbouyer KASSERT(ep->ep_active == rep->ep_active);
1884b1d4a54Sbouyer KASSERT(ep->ep_enabled == rep->ep_enabled);
1894b1d4a54Sbouyer if (!activate && ep->ep_enabled)
1904b1d4a54Sbouyer return EBUSY;
1914b1d4a54Sbouyer
1924b1d4a54Sbouyer rdp = rep->ep_port->port_dp;
1933f26cba0Sjmcneill aprint_debug_dev(rdp->dp_dev, "activating port %d endpoint %d\n",
194a9d03646Sjmcneill fdt_endpoint_port_index(rep), fdt_endpoint_index(rep));
1954b1d4a54Sbouyer if (rdp->dp_ep_activate)
1964b1d4a54Sbouyer error = rdp->dp_ep_activate(rdp->dp_dev, rep, activate);
1974b1d4a54Sbouyer
1984b1d4a54Sbouyer if (error == 0)
1994b1d4a54Sbouyer rep->ep_active = ep->ep_active = activate;
2004b1d4a54Sbouyer return error;
2014b1d4a54Sbouyer }
2024b1d4a54Sbouyer
2034b1d4a54Sbouyer int
fdt_endpoint_activate_direct(struct fdt_endpoint * ep,bool activate)204a9d03646Sjmcneill fdt_endpoint_activate_direct(struct fdt_endpoint *ep, bool activate)
205a9d03646Sjmcneill {
206a9d03646Sjmcneill struct fdt_device_ports *dp;
207a9d03646Sjmcneill int error = 0;
208a9d03646Sjmcneill
209a9d03646Sjmcneill dp = ep->ep_port->port_dp;
2103f26cba0Sjmcneill aprint_debug_dev(dp->dp_dev, "activating port %d endpoint %d (direct)\n",
211a9d03646Sjmcneill fdt_endpoint_port_index(ep), fdt_endpoint_index(ep));
212a9d03646Sjmcneill if (dp->dp_ep_activate)
213a9d03646Sjmcneill error = dp->dp_ep_activate(dp->dp_dev, ep, activate);
214a9d03646Sjmcneill
215a9d03646Sjmcneill return error;
216a9d03646Sjmcneill }
217a9d03646Sjmcneill
218a9d03646Sjmcneill int
fdt_endpoint_enable(struct fdt_endpoint * ep,bool enable)2194b1d4a54Sbouyer fdt_endpoint_enable(struct fdt_endpoint *ep, bool enable)
2204b1d4a54Sbouyer {
2214b1d4a54Sbouyer struct fdt_endpoint *rep = fdt_endpoint_remote(ep);
2224b1d4a54Sbouyer struct fdt_device_ports *rdp;
2234b1d4a54Sbouyer int error = 0;
2244b1d4a54Sbouyer
2254b1d4a54Sbouyer if (rep == NULL)
2264b1d4a54Sbouyer return EINVAL;
2274b1d4a54Sbouyer
2284b1d4a54Sbouyer KASSERT(ep->ep_active == rep->ep_active);
2294b1d4a54Sbouyer KASSERT(ep->ep_enabled == rep->ep_enabled);
2304b1d4a54Sbouyer if (ep->ep_active == false)
2314b1d4a54Sbouyer return EINVAL;
2324b1d4a54Sbouyer
2334b1d4a54Sbouyer rdp = rep->ep_port->port_dp;
2344b1d4a54Sbouyer if (rdp->dp_ep_enable)
2354b1d4a54Sbouyer error = rdp->dp_ep_enable(rdp->dp_dev, rep, enable);
2364b1d4a54Sbouyer
2374b1d4a54Sbouyer if (error == 0)
2384b1d4a54Sbouyer rep->ep_enabled = ep->ep_enabled = enable;
2394b1d4a54Sbouyer return error;
2404b1d4a54Sbouyer }
2414b1d4a54Sbouyer
2424b1d4a54Sbouyer void *
fdt_endpoint_get_data(struct fdt_endpoint * ep)2434b1d4a54Sbouyer fdt_endpoint_get_data(struct fdt_endpoint *ep)
2444b1d4a54Sbouyer {
2454b1d4a54Sbouyer struct fdt_device_ports *dp = ep->ep_port->port_dp;
2464b1d4a54Sbouyer
2474b1d4a54Sbouyer if (dp->dp_ep_get_data)
2484b1d4a54Sbouyer return dp->dp_ep_get_data(dp->dp_dev, ep);
2494b1d4a54Sbouyer
2504b1d4a54Sbouyer return NULL;
2514b1d4a54Sbouyer }
2524b1d4a54Sbouyer
2534b1d4a54Sbouyer int
fdt_ports_register(struct fdt_device_ports * ports,device_t self,int phandle,enum endpoint_type type)2544b1d4a54Sbouyer fdt_ports_register(struct fdt_device_ports *ports, device_t self,
2554b1d4a54Sbouyer int phandle, enum endpoint_type type)
2564b1d4a54Sbouyer {
2574b1d4a54Sbouyer int port_phandle, child;
2584b1d4a54Sbouyer int i;
2594b1d4a54Sbouyer char buf[20];
2601658f66eSskrll bus_addr_t id;
2614b1d4a54Sbouyer
2624b1d4a54Sbouyer ports->dp_dev = self;
2634b1d4a54Sbouyer SLIST_INSERT_HEAD(&fdt_port_devices, ports, dp_list);
2644b1d4a54Sbouyer
2654b1d4a54Sbouyer /*
2664b1d4a54Sbouyer * walk the childs looking for ports. ports may be grouped under
2674b1d4a54Sbouyer * an optional ports node
2684b1d4a54Sbouyer */
2694b1d4a54Sbouyer port_phandle = phandle;
2704b1d4a54Sbouyer again:
2714b1d4a54Sbouyer ports->dp_nports = 0;
2724b1d4a54Sbouyer for (child = OF_child(port_phandle); child; child = OF_peer(child)) {
2734b1d4a54Sbouyer if (OF_getprop(child, "name", buf, sizeof(buf)) <= 0)
2744b1d4a54Sbouyer continue;
2754b1d4a54Sbouyer if (strcmp(buf, "ports") == 0) {
2764b1d4a54Sbouyer port_phandle = child;
2774b1d4a54Sbouyer goto again;
2784b1d4a54Sbouyer }
2794b1d4a54Sbouyer if (strcmp(buf, "port") != 0)
2804b1d4a54Sbouyer continue;
2814b1d4a54Sbouyer ports->dp_nports++;
2824b1d4a54Sbouyer }
2834b1d4a54Sbouyer if (ports->dp_nports == 0)
2844b1d4a54Sbouyer return 0;
2854b1d4a54Sbouyer
2864b1d4a54Sbouyer ports->dp_port =
2874b1d4a54Sbouyer kmem_zalloc(sizeof(struct fdt_port) * ports->dp_nports, KM_SLEEP);
2884b1d4a54Sbouyer KASSERT(ports->dp_port != NULL);
2894b1d4a54Sbouyer /* now scan again ports, looking for endpoints */
2904b1d4a54Sbouyer for (child = OF_child(port_phandle), i = 0; child;
2914b1d4a54Sbouyer child = OF_peer(child)) {
2924b1d4a54Sbouyer if (OF_getprop(child, "name", buf, sizeof(buf)) <= 0)
2934b1d4a54Sbouyer continue;
2944b1d4a54Sbouyer if (strcmp(buf, "ports") == 0) {
2954b1d4a54Sbouyer panic("fdt_ports_register: undetected ports");
2964b1d4a54Sbouyer }
2974b1d4a54Sbouyer if (strcmp(buf, "port") != 0)
2984b1d4a54Sbouyer continue;
299f8205820Sjmcneill if (fdtbus_get_reg(child, 0, &id, NULL) != 0) {
3004b1d4a54Sbouyer if (ports->dp_nports > 1)
301*08596ce2Smacallan aprint_debug_dev(self,
3024b1d4a54Sbouyer "%s: missing reg property",
3034b1d4a54Sbouyer fdtbus_get_string(child, "name"));
304*08596ce2Smacallan id = 0;
3054b1d4a54Sbouyer }
3064b1d4a54Sbouyer ports->dp_port[i].port_id = id;
3074b1d4a54Sbouyer ports->dp_port[i].port_phandle = child;
3084b1d4a54Sbouyer ports->dp_port[i].port_dp = ports;
3094b1d4a54Sbouyer fdt_endpoints_register(child, &ports->dp_port[i], type);
3104b1d4a54Sbouyer i++;
3114b1d4a54Sbouyer }
3124b1d4a54Sbouyer KASSERT(i == ports->dp_nports);
3134b1d4a54Sbouyer return 0;
3144b1d4a54Sbouyer }
3154b1d4a54Sbouyer
3164b1d4a54Sbouyer
3174b1d4a54Sbouyer static void
fdt_endpoints_register(int phandle,struct fdt_port * port,enum endpoint_type type)3184b1d4a54Sbouyer fdt_endpoints_register(int phandle, struct fdt_port *port,
3194b1d4a54Sbouyer enum endpoint_type type)
3204b1d4a54Sbouyer {
3214b1d4a54Sbouyer int child;
3224b1d4a54Sbouyer int i;
3234b1d4a54Sbouyer char buf[128];
3244b1d4a54Sbouyer uint64_t id;
3254b1d4a54Sbouyer struct fdt_endpoint *ep, *rep;
3264b1d4a54Sbouyer struct fdt_device_ports *dp;
3274b1d4a54Sbouyer
3284b1d4a54Sbouyer port->port_nep = 0;
3294b1d4a54Sbouyer for (child = OF_child(phandle); child; child = OF_peer(child)) {
3304b1d4a54Sbouyer if (OF_getprop(child, "name", buf, sizeof(buf)) <= 0)
3314b1d4a54Sbouyer continue;
3324b1d4a54Sbouyer if (strcmp(buf, "endpoint") != 0)
3334b1d4a54Sbouyer continue;
3344b1d4a54Sbouyer port->port_nep++;
3354b1d4a54Sbouyer }
3364b1d4a54Sbouyer if (port->port_nep == 0) {
3374b1d4a54Sbouyer port->port_ep = NULL;
3384b1d4a54Sbouyer return;
3394b1d4a54Sbouyer }
3404b1d4a54Sbouyer
3414b1d4a54Sbouyer port->port_ep =
3424b1d4a54Sbouyer kmem_zalloc(sizeof(struct fdt_endpoint) * port->port_nep, KM_SLEEP);
3434b1d4a54Sbouyer KASSERT(port->port_ep != NULL);
3444b1d4a54Sbouyer /* now scan again ports, looking for endpoints */
3454b1d4a54Sbouyer for (child = OF_child(phandle), i = 0; child; child = OF_peer(child)) {
3464b1d4a54Sbouyer if (OF_getprop(child, "name", buf, sizeof(buf)) <= 0)
3474b1d4a54Sbouyer continue;
3484b1d4a54Sbouyer if (strcmp(buf, "endpoint") != 0)
3494b1d4a54Sbouyer continue;
3504b1d4a54Sbouyer if (fdtbus_get_reg64(child, 0, &id, NULL) != 0) {
3514b1d4a54Sbouyer if (port->port_nep > 1)
352*08596ce2Smacallan aprint_debug_dev(port->port_dp->dp_dev,
3534b1d4a54Sbouyer "%s: missing reg property",
3544b1d4a54Sbouyer fdtbus_get_string(child, "name"));
355*08596ce2Smacallan id = 0;
3564b1d4a54Sbouyer }
3574b1d4a54Sbouyer ep = &port->port_ep[i];
3584b1d4a54Sbouyer ep->ep_id = id;
3594b1d4a54Sbouyer ep->ep_type = type;
3604b1d4a54Sbouyer ep->ep_phandle = child;
3614b1d4a54Sbouyer ep->ep_port = port;
3624b1d4a54Sbouyer ep->ep_rphandle = fdtbus_get_phandle(child, "remote-endpoint");
3634b1d4a54Sbouyer ep->ep_rep = fdt_endpoint_get_from_phandle(
3644b1d4a54Sbouyer port->port_ep[i].ep_rphandle);
3654b1d4a54Sbouyer rep = ep->ep_rep;
3664b1d4a54Sbouyer if (rep != NULL && rep->ep_rep != NULL) {
3674b1d4a54Sbouyer aprint_error("%s: ", ep_name(ep, buf, sizeof(buf)));
3684b1d4a54Sbouyer aprint_error("remote endpoint %s ",
3694b1d4a54Sbouyer ep_name(rep, buf, sizeof(buf)));
3704b1d4a54Sbouyer aprint_error("already connected to %s\n",
3714b1d4a54Sbouyer ep_name(rep->ep_rep, buf, sizeof(buf)));
3724b1d4a54Sbouyer } else if (rep != NULL) {
3734b1d4a54Sbouyer rep->ep_rep = ep;
3744b1d4a54Sbouyer rep->ep_rphandle = child;
3753f26cba0Sjmcneill aprint_debug("%s ", ep_name(ep, buf, sizeof(buf)));
3763f26cba0Sjmcneill aprint_debug("connected to %s\n",
3774b1d4a54Sbouyer ep_name(rep, buf, sizeof(buf)));
3784b1d4a54Sbouyer if (rep->ep_type == EP_OTHER)
3794b1d4a54Sbouyer rep->ep_type = ep->ep_type;
3804b1d4a54Sbouyer else if (ep->ep_type == EP_OTHER)
3814b1d4a54Sbouyer ep->ep_type = rep->ep_type;
3824b1d4a54Sbouyer dp = port->port_dp;
3834b1d4a54Sbouyer if (dp->dp_ep_connect)
3844b1d4a54Sbouyer dp->dp_ep_connect(dp->dp_dev, ep, true);
3854b1d4a54Sbouyer dp = rep->ep_port->port_dp;
3864b1d4a54Sbouyer if (dp->dp_ep_connect)
3874b1d4a54Sbouyer dp->dp_ep_connect(dp->dp_dev, rep, true);
3884b1d4a54Sbouyer }
3894b1d4a54Sbouyer i++;
3904b1d4a54Sbouyer }
3914b1d4a54Sbouyer KASSERT(i == port->port_nep);
3924b1d4a54Sbouyer }
3934b1d4a54Sbouyer
3944b1d4a54Sbouyer static const char *
ep_name(struct fdt_endpoint * ep,char * buf,int size)3954b1d4a54Sbouyer ep_name(struct fdt_endpoint *ep, char *buf, int size)
3964b1d4a54Sbouyer {
3974b1d4a54Sbouyer int a;
3984b1d4a54Sbouyer
3994b1d4a54Sbouyer a = snprintf(&buf[0], size, "%s",
4004b1d4a54Sbouyer device_xname(ep->ep_port->port_dp->dp_dev));
4014b1d4a54Sbouyer if (ep->ep_port->port_id >= 0 && a < size)
4024b1d4a54Sbouyer a += snprintf(&buf[a], size - a, " port %d",
4034b1d4a54Sbouyer ep->ep_port->port_id);
4044b1d4a54Sbouyer if (ep->ep_id >= 0 && a < size)
4054b1d4a54Sbouyer snprintf(&buf[a], size - a, " endpoint %d", ep->ep_id);
4064b1d4a54Sbouyer return buf;
4074b1d4a54Sbouyer }
408