18ce15a8br/*-
28ce15a8br * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
38ce15a8br * All rights reserved.
48ce15a8br *
58ce15a8br * This software was developed by SRI International and the University of
68ce15a8br * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
78ce15a8br * ("CTSRD"), as part of the DARPA CRASH research programme.
88ce15a8br *
98ce15a8br * Redistribution and use in source and binary forms, with or without
108ce15a8br * modification, are permitted provided that the following conditions
118ce15a8br * are met:
128ce15a8br * 1. Redistributions of source code must retain the above copyright
138ce15a8br *    notice, this list of conditions and the following disclaimer.
148ce15a8br * 2. Redistributions in binary form must reproduce the above copyright
158ce15a8br *    notice, this list of conditions and the following disclaimer in the
168ce15a8br *    documentation and/or other materials provided with the distribution.
178ce15a8br *
188ce15a8br * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
198ce15a8br * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
208ce15a8br * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
218ce15a8br * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
228ce15a8br * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
238ce15a8br * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
248ce15a8br * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
258ce15a8br * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
268ce15a8br * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
278ce15a8br * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
288ce15a8br * SUCH DAMAGE.
298ce15a8br */
308ce15a8br
318ce15a8br#include <sys/cdefs.h>
328ce15a8br__FBSDID("$FreeBSD$");
338ce15a8br
348ce15a8br#include <sys/param.h>
358ce15a8br#include <sys/systm.h>
368ce15a8br#include <sys/bus.h>
378ce15a8br#include <sys/rman.h>
388ce15a8br#include <sys/kernel.h>
398ce15a8br#include <sys/lock.h>
408ce15a8br#include <sys/module.h>
418ce15a8br#include <sys/mutex.h>
428ce15a8br#include <machine/bus.h>
438ce15a8br
448ce15a8br#include <dev/ofw/ofw_bus.h>
458ce15a8br#include <dev/ofw/ofw_bus_subr.h>
468ce15a8br
478ce15a8br#include <arm64/coresight/coresight.h>
488ce15a8br
498ce15a8brstatic int
508ce15a8brcoresight_fdt_get_ports(phandle_t dev_node,
518ce15a8br    struct coresight_platform_data *pdata)
528ce15a8br{
538ce15a8br	phandle_t node, child;
548ce15a8br	pcell_t port_reg;
558ce15a8br	phandle_t xref;
568ce15a8br	char *name;
578ce15a8br	int ret;
588ce15a8br	phandle_t endpoint_child;
598ce15a8br	struct endpoint *endp;
608ce15a8br
618ce15a8br	child = ofw_bus_find_child(dev_node, "ports");
628ce15a8br	if (child)
638ce15a8br		node = child;
648ce15a8br	else
658ce15a8br		node = dev_node;
668ce15a8br
678ce15a8br	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
688ce15a8br		ret = OF_getprop_alloc(child, "name", (void **)&name);
698ce15a8br		if (ret == -1)
708ce15a8br			continue;
718ce15a8br
728ce15a8br		if (strcasecmp(name, "port") ||
738ce15a8br		    strncasecmp(name, "port@", 6)) {
748ce15a8br			port_reg = -1;
758ce15a8br			OF_getencprop(child, "reg", (void *)&port_reg,
768ce15a8br			    sizeof(port_reg));
778ce15a8br
788ce15a8br			endpoint_child = ofw_bus_find_child(child, "endpoint");
798ce15a8br			if (endpoint_child) {
808ce15a8br				if (OF_getencprop(endpoint_child,
818ce15a8br				    "remote-endpoint", &xref,
828ce15a8br				    sizeof(xref)) == -1) {
838ce15a8br					printf("failed\n");
848ce15a8br					continue;
858ce15a8br				}
868ce15a8br				endp = malloc(sizeof(struct endpoint),
878ce15a8br				    M_CORESIGHT, M_WAITOK | M_ZERO);
888ce15a8br				endp->my_node = endpoint_child;
898ce15a8br				endp->their_node = OF_node_from_xref(xref);
908ce15a8br				endp->dev_node = dev_node;
918ce15a8br				endp->reg = port_reg;
928ce15a8br				if (OF_getproplen(endpoint_child,
938ce15a8br				    "slave-mode") >= 0) {
948ce15a8br					pdata->in_ports++;
958ce15a8br					endp->input = 1;
968ce15a8br				} else
978ce15a8br					pdata->out_ports++;
988ce15a8br
998ce15a8br				mtx_lock(&pdata->mtx_lock);
1008ce15a8br				TAILQ_INSERT_TAIL(&pdata->endpoints,
1018ce15a8br				    endp, link);
1028ce15a8br				mtx_unlock(&pdata->mtx_lock);
1038ce15a8br			}
1048ce15a8br		}
1058ce15a8br	}
1068ce15a8br
1078ce15a8br	return (0);
1088ce15a8br}
1098ce15a8br
1108ce15a8brstatic int
1118ce15a8brcoresight_fdt_get_cpu(phandle_t node,
1128ce15a8br    struct coresight_platform_data *pdata)
1138ce15a8br{
1148ce15a8br	phandle_t cpu_node;
1158ce15a8br	pcell_t xref;
1168ce15a8br	pcell_t cpu_reg;
1178ce15a8br
1188ce15a8br	if (OF_getencprop(node, "cpu", &xref, sizeof(xref)) != -1) {
1198ce15a8br		cpu_node = OF_node_from_xref(xref);
1208ce15a8br		if (OF_getencprop(cpu_node, "reg", (void *)&cpu_reg,
1218ce15a8br			sizeof(cpu_reg)) > 0) {
1228ce15a8br			pdata->cpu = cpu_reg;
1238ce15a8br			return (0);
1248ce15a8br		}
1258ce15a8br	}
1268ce15a8br
1278ce15a8br	return (-1);
1288ce15a8br}
1298ce15a8br
1308ce15a8brstruct coresight_platform_data *
1318ce15a8brcoresight_fdt_get_platform_data(device_t dev)
1328ce15a8br{
1338ce15a8br	struct coresight_platform_data *pdata;
1348ce15a8br	phandle_t node;
1358ce15a8br
1368ce15a8br	node = ofw_bus_get_node(dev);
1378ce15a8br
1388ce15a8br	pdata = malloc(sizeof(struct coresight_platform_data),
1398ce15a8br	    M_CORESIGHT, M_WAITOK | M_ZERO);
1408ce15a8br	pdata->bus_type = CORESIGHT_BUS_FDT;
1418ce15a8br
1428ce15a8br	mtx_init(&pdata->mtx_lock, "Coresight Platform Data", NULL, MTX_DEF);
1438ce15a8br	TAILQ_INIT(&pdata->endpoints);
1448ce15a8br
1458ce15a8br	coresight_fdt_get_cpu(node, pdata);
1468ce15a8br	coresight_fdt_get_ports(node, pdata);
1478ce15a8br
1488ce15a8br	if (bootverbose)
1498ce15a8br		printf("Total ports: in %d out %d\n",
1508ce15a8br		    pdata->in_ports, pdata->out_ports);
1518ce15a8br
1528ce15a8br	return (pdata);
1538ce15a8br}
154