summaryrefslogtreecommitdiff
path: root/sys/dev/ofw
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r--sys/dev/ofw/ofw_misc.c168
-rw-r--r--sys/dev/ofw/ofw_misc.h58
2 files changed, 178 insertions, 48 deletions
diff --git a/sys/dev/ofw/ofw_misc.c b/sys/dev/ofw/ofw_misc.c
index 880457d93d1..53f3aa89685 100644
--- a/sys/dev/ofw/ofw_misc.c
+++ b/sys/dev/ofw/ofw_misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofw_misc.c,v 1.14 2020/03/01 18:00:12 kettenis Exp $ */
+/* $OpenBSD: ofw_misc.c,v 1.15 2020/03/16 21:51:26 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
@@ -440,57 +440,159 @@ nvmem_read_cell(int node, const char *name, void *data, bus_size_t size)
return nd->nd_read(nd->nd_cookie, nc->nc_addr, data, size);
}
-/* Video interface support */
+/* Port/endpoint interface support */
-LIST_HEAD(, video_device) video_devices =
- LIST_HEAD_INITIALIZER(video_devices);
+LIST_HEAD(, endpoint) endpoints =
+ LIST_HEAD_INITIALIZER(endpoints);
void
-video_register(struct video_device *vd)
+endpoint_register(int node, struct device_port *dp, enum endpoint_type type)
{
- vd->vd_phandle = OF_getpropint(vd->vd_node, "phandle", 0);
- if (vd->vd_phandle == 0)
+ struct endpoint *ep;
+
+ ep = malloc(sizeof(*ep), M_DEVBUF, M_WAITOK);
+ ep->ep_node = node;
+ ep->ep_phandle = OF_getpropint(node, "phandle", 0);
+ ep->ep_reg = OF_getpropint(node, "reg", -1);
+ ep->ep_port = dp;
+ ep->ep_type = type;
+
+ LIST_INSERT_HEAD(&endpoints, ep, ep_list);
+ LIST_INSERT_HEAD(&dp->dp_endpoints, ep, ep_plist);
+}
+
+void
+device_port_register(int node, struct device_ports *ports,
+ enum endpoint_type type)
+{
+ struct device_port *dp;
+
+ dp = malloc(sizeof(*dp), M_DEVBUF, M_WAITOK);
+ dp->dp_node = node;
+ dp->dp_phandle = OF_getpropint(node, "phandle", 0);
+ dp->dp_reg = OF_getpropint(node, "reg", -1);
+ dp->dp_ports = ports;
+ LIST_INIT(&dp->dp_endpoints);
+ for (node = OF_child(node); node; node = OF_peer(node))
+ endpoint_register(node, dp, type);
+
+ LIST_INSERT_HEAD(&ports->dp_ports, dp, dp_list);
+}
+
+void
+device_ports_register(struct device_ports *ports,
+ enum endpoint_type type)
+{
+ int node;
+
+ LIST_INIT(&ports->dp_ports);
+
+ node = OF_getnodebyname(ports->dp_node, "ports");
+ if (node == 0) {
+ node = OF_getnodebyname(ports->dp_node, "port");
+ if (node == 0)
+ return;
+
+ device_port_register(node, ports, type);
return;
- LIST_INSERT_HEAD(&video_devices, vd, vd_list);
+ }
+
+ for (node = OF_child(node); node; node = OF_peer(node))
+ device_port_register(node, ports, type);
}
-int
-video_port_activate(uint32_t phandle, struct drm_device *ddev)
+struct endpoint *
+endpoint_byphandle(uint32_t phandle)
{
- uint32_t ep, rep;
- int node, error;
+ struct endpoint *ep;
- node = OF_getnodebyphandle(phandle);
- if (node == 0)
- return ENXIO;
+ LIST_FOREACH(ep, &endpoints, ep_list) {
+ if (ep->ep_phandle == phandle)
+ return ep;
+ }
- for (node = OF_child(node); node; node = OF_peer(node)) {
- ep = OF_getpropint(node, "phandle", 0);
- rep = OF_getpropint(node, "remote-endpoint", 0);
- if (ep == 0 || rep == 0)
- continue;
- error = video_endpoint_activate(ep, ddev);
- if (error)
- continue;
- error = video_endpoint_activate(rep, ddev);
- if (error)
+ return NULL;
+}
+
+struct endpoint *
+endpoint_byreg(struct device_ports *ports, uint32_t dp_reg, uint32_t ep_reg)
+{
+ struct device_port *dp;
+ struct endpoint *ep;
+
+ LIST_FOREACH(dp, &ports->dp_ports, dp_list) {
+ if (dp->dp_reg != dp_reg)
continue;
+ LIST_FOREACH(ep, &dp->dp_endpoints, ep_list) {
+ if (ep->ep_reg != ep_reg)
+ continue;
+ return ep;
+ }
+ }
+
+ return NULL;
+}
+
+struct endpoint *
+endpoint_remote(struct endpoint *ep)
+{
+ struct endpoint *rep;
+ int phandle;
+
+ phandle = OF_getpropint(ep->ep_node, "remote-endpoint", 0);
+ if (phandle == 0)
+ return NULL;
+
+ LIST_FOREACH(rep, &endpoints, ep_list) {
+ if (rep->ep_phandle == phandle)
+ return rep;
}
- return 0;
+ return NULL;
}
int
-video_endpoint_activate(uint32_t phandle, struct drm_device *ddev)
+endpoint_activate(struct endpoint *ep, void *arg)
+{
+ struct device_ports *ports = ep->ep_port->dp_ports;
+ return ports->dp_ep_activate(ports->dp_cookie, ep, arg);
+}
+
+void *
+endpoint_get_cookie(struct endpoint *ep)
{
- struct video_device *vd;
+ struct device_ports *ports = ep->ep_port->dp_ports;
+ return ports->dp_ep_get_cookie(ports->dp_cookie, ep);
+}
- LIST_FOREACH(vd, &video_devices, vd_list) {
- if (vd->vd_phandle == phandle)
+void
+device_port_activate(uint32_t phandle, void *arg)
+{
+ struct device_ports *ports;
+ struct device_port *dp;
+ struct endpoint *ep, *rep;
+ int error;
+
+ LIST_FOREACH(ep, &endpoints, ep_list) {
+ if (ep->ep_port->dp_phandle == phandle) {
+ dp = ep->ep_port;
break;
+ }
}
- if (vd == NULL)
- return ENXIO;
+ if (dp == NULL)
+ return;
- return vd->vd_ep_activate(vd->vd_cookie, ddev);
+ ports = dp->dp_ports;
+ LIST_FOREACH(ep, &dp->dp_endpoints, ep_plist) {
+ rep = endpoint_remote(ep);
+ if (rep == NULL)
+ continue;
+
+ error = endpoint_activate(ep, arg);
+ if (error)
+ continue;
+ error = endpoint_activate(rep, arg);
+ if (error)
+ continue;
+ }
}
diff --git a/sys/dev/ofw/ofw_misc.h b/sys/dev/ofw/ofw_misc.h
index 35a9b15c1a0..8dc20e9c33b 100644
--- a/sys/dev/ofw/ofw_misc.h
+++ b/sys/dev/ofw/ofw_misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofw_misc.h,v 1.10 2020/02/21 15:46:16 patrick Exp $ */
+/* $OpenBSD: ofw_misc.h,v 1.11 2020/03/16 21:51:26 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
@@ -129,24 +129,52 @@ void nvmem_register(struct nvmem_device *);
int nvmem_read(uint32_t, bus_addr_t, void *, bus_size_t);
int nvmem_read_cell(int, const char *name, void *, bus_size_t);
-/* Video interface support */
+/* Port/endpoint interface support */
-struct drm_device;
-struct video_device {
- int vd_node;
- void *vd_cookie;
- int (*vd_read)(void *, bus_addr_t, void *, bus_size_t);
+struct endpoint;
- int (*vd_ep_activate)(void *, struct drm_device *);
- void * (*vd_ep_get_data)(void *);
+struct device_ports {
+ int dp_node;
+ void *dp_cookie;
- LIST_ENTRY(video_device) vd_list;
- uint32_t vd_phandle;
+ int (*dp_ep_activate)(void *, struct endpoint *, void *);
+ void *(*dp_ep_get_cookie)(void *, struct endpoint *);
+
+ LIST_HEAD(, device_port) dp_ports;
+};
+
+struct device_port {
+ int dp_node;
+ uint32_t dp_phandle;
+ uint32_t dp_reg;
+ struct device_ports *dp_ports;
+ LIST_ENTRY(device_port) dp_list;
+ LIST_HEAD(, endpoint) dp_endpoints;
+};
+
+enum endpoint_type {
+ EP_DRM_BRIDGE = 1, /* struct drm_bridge */
+ EP_DRM_CONNECTOR, /* struct drm_connector */
+ EP_DRM_CRTC, /* struct drm_crtc */
+ EP_DRM_ENCODER, /* struct drm_encoder */
+ EP_DRM_PANEL, /* struct drm_panel */
+};
+
+struct endpoint {
+ int ep_node;
+ uint32_t ep_phandle;
+ uint32_t ep_reg;
+ enum endpoint_type ep_type;
+ struct device_port *ep_port;
+ LIST_ENTRY(endpoint) ep_list;
+ LIST_ENTRY(endpoint) ep_plist;
};
-void video_register(struct video_device *);
-int video_port_activate(uint32_t, struct drm_device *);
-int video_endpoint_activate(uint32_t, struct drm_device *);
-void * video_endpoint_get_data(uint32_t);
+void device_ports_register(struct device_ports *, enum endpoint_type);
+void device_port_activate(uint32_t, void *);
+struct endpoint *endpoint_byreg(struct device_ports *, uint32_t, uint32_t);
+struct endpoint *endpoint_remote(struct endpoint *);
+int endpoint_activate(struct endpoint *, void *);
+void *endpoint_get_cookie(struct endpoint *);
#endif /* _DEV_OFW_MISC_H_ */