17a8d25c0SNathan Whitehorn /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 371e3c308SPedro F. Giffuni * 47a8d25c0SNathan Whitehorn * Copyright (c) 2011 Nathan Whitehorn 57a8d25c0SNathan Whitehorn * All rights reserved. 67a8d25c0SNathan Whitehorn * 77a8d25c0SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 87a8d25c0SNathan Whitehorn * modification, are permitted provided that the following conditions 97a8d25c0SNathan Whitehorn * are met: 107a8d25c0SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 117a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 127a8d25c0SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 137a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 147a8d25c0SNathan Whitehorn * documentation and/or other materials provided with the distribution. 157a8d25c0SNathan Whitehorn * 167a8d25c0SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 177a8d25c0SNathan Whitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 187a8d25c0SNathan Whitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 197a8d25c0SNathan Whitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 207a8d25c0SNathan Whitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 217a8d25c0SNathan Whitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 227a8d25c0SNathan Whitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 237a8d25c0SNathan Whitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 247a8d25c0SNathan Whitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 257a8d25c0SNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267a8d25c0SNathan Whitehorn * SUCH DAMAGE. 277a8d25c0SNathan Whitehorn */ 287a8d25c0SNathan Whitehorn 297a8d25c0SNathan Whitehorn #include <sys/param.h> 307a8d25c0SNathan Whitehorn #include <sys/systm.h> 317a8d25c0SNathan Whitehorn #include <sys/kernel.h> 327a8d25c0SNathan Whitehorn #include <sys/module.h> 337a8d25c0SNathan Whitehorn #include <sys/malloc.h> 347a8d25c0SNathan Whitehorn #include <sys/bus.h> 357a8d25c0SNathan Whitehorn #include <sys/cpu.h> 367a8d25c0SNathan Whitehorn #include <machine/bus.h> 377a8d25c0SNathan Whitehorn #include <machine/intr_machdep.h> 387a8d25c0SNathan Whitehorn 397a8d25c0SNathan Whitehorn #include <dev/ofw/openfirm.h> 407a8d25c0SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 417a8d25c0SNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 427a8d25c0SNathan Whitehorn 43391dff86SNathan Whitehorn #include <powerpc/pseries/plpar_iommu.h> 44391dff86SNathan Whitehorn 45391dff86SNathan Whitehorn #include "iommu_if.h" 46391dff86SNathan Whitehorn 477a8d25c0SNathan Whitehorn static int vdevice_probe(device_t); 487a8d25c0SNathan Whitehorn static int vdevice_attach(device_t); 497a8d25c0SNathan Whitehorn static const struct ofw_bus_devinfo *vdevice_get_devinfo(device_t dev, 507a8d25c0SNathan Whitehorn device_t child); 517a8d25c0SNathan Whitehorn static int vdevice_print_child(device_t dev, device_t child); 527a8d25c0SNathan Whitehorn static struct resource_list *vdevice_get_resource_list(device_t, device_t); 53391dff86SNathan Whitehorn static bus_dma_tag_t vdevice_get_dma_tag(device_t dev, device_t child); 547a8d25c0SNathan Whitehorn 557a8d25c0SNathan Whitehorn /* 567a8d25c0SNathan Whitehorn * VDevice devinfo 577a8d25c0SNathan Whitehorn */ 587a8d25c0SNathan Whitehorn struct vdevice_devinfo { 597a8d25c0SNathan Whitehorn struct ofw_bus_devinfo mdi_obdinfo; 607a8d25c0SNathan Whitehorn struct resource_list mdi_resources; 61391dff86SNathan Whitehorn bus_dma_tag_t mdi_dma_tag; 627a8d25c0SNathan Whitehorn }; 637a8d25c0SNathan Whitehorn 647a8d25c0SNathan Whitehorn static device_method_t vdevice_methods[] = { 657a8d25c0SNathan Whitehorn /* Device interface */ 667a8d25c0SNathan Whitehorn DEVMETHOD(device_probe, vdevice_probe), 677a8d25c0SNathan Whitehorn DEVMETHOD(device_attach, vdevice_attach), 687a8d25c0SNathan Whitehorn 697a8d25c0SNathan Whitehorn /* Bus interface */ 707a8d25c0SNathan Whitehorn DEVMETHOD(bus_add_child, bus_generic_add_child), 71ddfc9c4cSWarner Losh DEVMETHOD(bus_child_pnpinfo, ofw_bus_gen_child_pnpinfo), 727a8d25c0SNathan Whitehorn DEVMETHOD(bus_print_child, vdevice_print_child), 737a8d25c0SNathan Whitehorn DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 747a8d25c0SNathan Whitehorn DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 757a8d25c0SNathan Whitehorn DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), 767a8d25c0SNathan Whitehorn DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 777a8d25c0SNathan Whitehorn DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 787a8d25c0SNathan Whitehorn DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 797a8d25c0SNathan Whitehorn DEVMETHOD(bus_get_resource_list, vdevice_get_resource_list), 807a8d25c0SNathan Whitehorn 817a8d25c0SNathan Whitehorn /* ofw_bus interface */ 827a8d25c0SNathan Whitehorn DEVMETHOD(ofw_bus_get_devinfo, vdevice_get_devinfo), 837a8d25c0SNathan Whitehorn DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 847a8d25c0SNathan Whitehorn DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 857a8d25c0SNathan Whitehorn DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 867a8d25c0SNathan Whitehorn DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 877a8d25c0SNathan Whitehorn DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 887a8d25c0SNathan Whitehorn 89391dff86SNathan Whitehorn /* IOMMU interface */ 90391dff86SNathan Whitehorn DEVMETHOD(bus_get_dma_tag, vdevice_get_dma_tag), 91391dff86SNathan Whitehorn DEVMETHOD(iommu_map, phyp_iommu_map), 92391dff86SNathan Whitehorn DEVMETHOD(iommu_unmap, phyp_iommu_unmap), 93391dff86SNathan Whitehorn 947a8d25c0SNathan Whitehorn DEVMETHOD_END 957a8d25c0SNathan Whitehorn }; 967a8d25c0SNathan Whitehorn 977a8d25c0SNathan Whitehorn static driver_t vdevice_driver = { 987a8d25c0SNathan Whitehorn "vdevice", 997a8d25c0SNathan Whitehorn vdevice_methods, 1007a8d25c0SNathan Whitehorn 0 1017a8d25c0SNathan Whitehorn }; 1027a8d25c0SNathan Whitehorn 1039b9a5327SJohn Baldwin DRIVER_MODULE(vdevice, ofwbus, vdevice_driver, 0, 0); 1047a8d25c0SNathan Whitehorn 1057a8d25c0SNathan Whitehorn static int 1067a8d25c0SNathan Whitehorn vdevice_probe(device_t dev) 1077a8d25c0SNathan Whitehorn { 1087a8d25c0SNathan Whitehorn const char *name; 1097a8d25c0SNathan Whitehorn 1107a8d25c0SNathan Whitehorn name = ofw_bus_get_name(dev); 1117a8d25c0SNathan Whitehorn 1127a8d25c0SNathan Whitehorn if (name == NULL || strcmp(name, "vdevice") != 0) 1137a8d25c0SNathan Whitehorn return (ENXIO); 1147a8d25c0SNathan Whitehorn 1157a8d25c0SNathan Whitehorn if (!ofw_bus_is_compatible(dev, "IBM,vdevice")) 1167a8d25c0SNathan Whitehorn return (ENXIO); 1177a8d25c0SNathan Whitehorn 1187a8d25c0SNathan Whitehorn device_set_desc(dev, "POWER Hypervisor Virtual Device Root"); 1197a8d25c0SNathan Whitehorn 1207a8d25c0SNathan Whitehorn return (0); 1217a8d25c0SNathan Whitehorn } 1227a8d25c0SNathan Whitehorn 1237a8d25c0SNathan Whitehorn static int 1247a8d25c0SNathan Whitehorn vdevice_attach(device_t dev) 1257a8d25c0SNathan Whitehorn { 1267a8d25c0SNathan Whitehorn phandle_t root, child; 1277a8d25c0SNathan Whitehorn device_t cdev; 1287a8d25c0SNathan Whitehorn struct vdevice_devinfo *dinfo; 1297a8d25c0SNathan Whitehorn 1307a8d25c0SNathan Whitehorn root = ofw_bus_get_node(dev); 1317a8d25c0SNathan Whitehorn 13208b96b9fSNathan Whitehorn /* The XICP (root PIC) will handle all our interrupts */ 13308b96b9fSNathan Whitehorn powerpc_register_pic(root_pic, OF_xref_from_node(root), 13408b96b9fSNathan Whitehorn 1 << 24 /* 24-bit XIRR field */, 1 /* Number of IPIs */, FALSE); 13508b96b9fSNathan Whitehorn 1367a8d25c0SNathan Whitehorn for (child = OF_child(root); child != 0; child = OF_peer(child)) { 1377a8d25c0SNathan Whitehorn dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); 1387a8d25c0SNathan Whitehorn 1397a8d25c0SNathan Whitehorn if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, 1407a8d25c0SNathan Whitehorn child) != 0) { 1417a8d25c0SNathan Whitehorn free(dinfo, M_DEVBUF); 1427a8d25c0SNathan Whitehorn continue; 1437a8d25c0SNathan Whitehorn } 1447a8d25c0SNathan Whitehorn resource_list_init(&dinfo->mdi_resources); 1457a8d25c0SNathan Whitehorn 146a8c5ea04SRuslan Bukin ofw_bus_intr_to_rl(dev, child, &dinfo->mdi_resources, NULL); 1477a8d25c0SNathan Whitehorn 1485b56413dSWarner Losh cdev = device_add_child(dev, NULL, DEVICE_UNIT_ANY); 1497a8d25c0SNathan Whitehorn if (cdev == NULL) { 1507a8d25c0SNathan Whitehorn device_printf(dev, "<%s>: device_add_child failed\n", 1517a8d25c0SNathan Whitehorn dinfo->mdi_obdinfo.obd_name); 1527a8d25c0SNathan Whitehorn ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo); 1537a8d25c0SNathan Whitehorn free(dinfo, M_DEVBUF); 1547a8d25c0SNathan Whitehorn continue; 1557a8d25c0SNathan Whitehorn } 1567a8d25c0SNathan Whitehorn device_set_ivars(cdev, dinfo); 1577a8d25c0SNathan Whitehorn } 1587a8d25c0SNathan Whitehorn 159*18250ec6SJohn Baldwin bus_attach_children(dev); 160*18250ec6SJohn Baldwin return (0); 1617a8d25c0SNathan Whitehorn } 1627a8d25c0SNathan Whitehorn 1637a8d25c0SNathan Whitehorn static const struct ofw_bus_devinfo * 1647a8d25c0SNathan Whitehorn vdevice_get_devinfo(device_t dev, device_t child) 1657a8d25c0SNathan Whitehorn { 1667a8d25c0SNathan Whitehorn return (device_get_ivars(child)); 1677a8d25c0SNathan Whitehorn } 1687a8d25c0SNathan Whitehorn 1697a8d25c0SNathan Whitehorn static int 1707a8d25c0SNathan Whitehorn vdevice_print_child(device_t dev, device_t child) 1717a8d25c0SNathan Whitehorn { 1727a8d25c0SNathan Whitehorn struct vdevice_devinfo *dinfo; 1737a8d25c0SNathan Whitehorn struct resource_list *rl; 1747a8d25c0SNathan Whitehorn int retval = 0; 1757a8d25c0SNathan Whitehorn 1767a8d25c0SNathan Whitehorn dinfo = device_get_ivars(child); 1777a8d25c0SNathan Whitehorn rl = &dinfo->mdi_resources; 1787a8d25c0SNathan Whitehorn 1797a8d25c0SNathan Whitehorn retval += bus_print_child_header(dev, child); 1807a8d25c0SNathan Whitehorn 181f8fd3fb5SJustin Hibbits retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 1827a8d25c0SNathan Whitehorn 1837a8d25c0SNathan Whitehorn retval += bus_print_child_footer(dev, child); 1847a8d25c0SNathan Whitehorn 1857a8d25c0SNathan Whitehorn return (retval); 1867a8d25c0SNathan Whitehorn } 1877a8d25c0SNathan Whitehorn 1887a8d25c0SNathan Whitehorn static struct resource_list * 1897a8d25c0SNathan Whitehorn vdevice_get_resource_list (device_t dev, device_t child) 1907a8d25c0SNathan Whitehorn { 1917a8d25c0SNathan Whitehorn struct vdevice_devinfo *dinfo; 1927a8d25c0SNathan Whitehorn 1937a8d25c0SNathan Whitehorn dinfo = device_get_ivars(child); 1947a8d25c0SNathan Whitehorn return (&dinfo->mdi_resources); 1957a8d25c0SNathan Whitehorn } 1967a8d25c0SNathan Whitehorn 197391dff86SNathan Whitehorn static bus_dma_tag_t 198391dff86SNathan Whitehorn vdevice_get_dma_tag(device_t dev, device_t child) 199391dff86SNathan Whitehorn { 200391dff86SNathan Whitehorn struct vdevice_devinfo *dinfo; 201391dff86SNathan Whitehorn while (child != NULL && device_get_parent(child) != dev) 202391dff86SNathan Whitehorn child = device_get_parent(child); 203391dff86SNathan Whitehorn dinfo = device_get_ivars(child); 204391dff86SNathan Whitehorn 205391dff86SNathan Whitehorn if (dinfo->mdi_dma_tag == NULL) { 206391dff86SNathan Whitehorn bus_dma_tag_create(bus_get_dma_tag(dev), 207391dff86SNathan Whitehorn 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 208391dff86SNathan Whitehorn NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, 209391dff86SNathan Whitehorn BUS_SPACE_MAXSIZE, 0, NULL, NULL, &dinfo->mdi_dma_tag); 210391dff86SNathan Whitehorn phyp_iommu_set_dma_tag(dev, child, dinfo->mdi_dma_tag); 211391dff86SNathan Whitehorn } 212391dff86SNathan Whitehorn 213391dff86SNathan Whitehorn return (dinfo->mdi_dma_tag); 214391dff86SNathan Whitehorn } 215