xref: /freebsd/sys/dev/ntb/ntb_hw/ntb_hw_amd.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
16683132dSAlexander Motin /*-
26683132dSAlexander Motin  * This file is provided under a dual BSD/GPLv2 license.  When using or
36683132dSAlexander Motin  * redistributing this file, you may do so under either license.
46683132dSAlexander Motin  *
56683132dSAlexander Motin  * GPL LICENSE SUMMARY
66683132dSAlexander Motin  *
76683132dSAlexander Motin  * Copyright (C) 2019 Advanced Micro Devices, Inc.
86683132dSAlexander Motin  *
96683132dSAlexander Motin  * This program is free software; you can redistribute it and/or modify
106683132dSAlexander Motin  * it under the terms of version 2 of the GNU General Public License as
116683132dSAlexander Motin  * published by the Free Software Foundation.
126683132dSAlexander Motin  *
136683132dSAlexander Motin  * BSD LICENSE
146683132dSAlexander Motin  *
156683132dSAlexander Motin  * Copyright (c) 2019 Advanced Micro Devices, Inc.
166683132dSAlexander Motin  *
176683132dSAlexander Motin  * Redistribution and use in source and binary forms, with or without
186683132dSAlexander Motin  * modification, are permitted provided that the following conditions
196683132dSAlexander Motin  * are met:
206683132dSAlexander Motin  * 1. Redistributions of source code must retain the above copyright
216683132dSAlexander Motin  *    notice, this list of conditions and the following disclaimer.
226683132dSAlexander Motin  * 2. Redistributions in binary form must reproduce the above copyright
236683132dSAlexander Motin  *    notice, this list of conditions and the following disclaimer in the
246683132dSAlexander Motin  *    documentation and/or other materials provided with the distribution.
256683132dSAlexander Motin  * 3. Neither the name of AMD corporation nor the names of its
266683132dSAlexander Motin  *    contributors may be used to endorse or promote products derived
276683132dSAlexander Motin  *    from this software without specific prior written permission.
286683132dSAlexander Motin  *
296683132dSAlexander Motin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
306683132dSAlexander Motin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
316683132dSAlexander Motin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
326683132dSAlexander Motin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
336683132dSAlexander Motin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
346683132dSAlexander Motin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
356683132dSAlexander Motin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
366683132dSAlexander Motin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
376683132dSAlexander Motin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
386683132dSAlexander Motin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
396683132dSAlexander Motin  * SUCH DAMAGE.
406683132dSAlexander Motin  *
416683132dSAlexander Motin  * Contact Information :
426683132dSAlexander Motin  * Rajesh Kumar <rajesh1.kumar@amd.com>
436683132dSAlexander Motin  */
446683132dSAlexander Motin 
456683132dSAlexander Motin /*
466683132dSAlexander Motin  * The Non-Transparent Bridge (NTB) is a device that allows you to connect
476683132dSAlexander Motin  * two or more systems using a PCI-e links, providing remote memory access.
486683132dSAlexander Motin  *
496683132dSAlexander Motin  * This module contains a driver for NTB hardware in AMD CPUs
506683132dSAlexander Motin  *
516683132dSAlexander Motin  * Much of the code in this module is shared with Linux. Any patches may
526683132dSAlexander Motin  * be picked up and redistributed in Linux with a dual GPL/BSD license.
536683132dSAlexander Motin  */
546683132dSAlexander Motin 
556683132dSAlexander Motin #include <sys/param.h>
566683132dSAlexander Motin #include <sys/kernel.h>
576683132dSAlexander Motin #include <sys/systm.h>
586683132dSAlexander Motin #include <sys/bus.h>
593a76d901SAlexander Motin #include <sys/lock.h>
606683132dSAlexander Motin #include <sys/malloc.h>
616683132dSAlexander Motin #include <sys/module.h>
626683132dSAlexander Motin #include <sys/mutex.h>
636683132dSAlexander Motin #include <sys/rman.h>
646683132dSAlexander Motin #include <sys/sbuf.h>
656683132dSAlexander Motin #include <sys/sysctl.h>
666683132dSAlexander Motin 
676683132dSAlexander Motin #include <vm/vm.h>
686683132dSAlexander Motin #include <vm/pmap.h>
696683132dSAlexander Motin 
706683132dSAlexander Motin #include <machine/bus.h>
716683132dSAlexander Motin 
726683132dSAlexander Motin #include <dev/pci/pcireg.h>
736683132dSAlexander Motin #include <dev/pci/pcivar.h>
746683132dSAlexander Motin 
756683132dSAlexander Motin #include "ntb_hw_amd.h"
766683132dSAlexander Motin #include "dev/ntb/ntb.h"
776683132dSAlexander Motin 
786683132dSAlexander Motin MALLOC_DEFINE(M_AMD_NTB, "amd_ntb_hw", "amd_ntb_hw driver memory allocations");
796683132dSAlexander Motin 
80e67b1223SAlexander Motin static const struct amd_ntb_hw_info amd_ntb_hw_info_list[] = {
81e67b1223SAlexander Motin 	{ .vendor_id = NTB_HW_AMD_VENDOR_ID,
82e67b1223SAlexander Motin 	  .device_id = NTB_HW_AMD_DEVICE_ID1,
83e67b1223SAlexander Motin 	  .mw_count = 3,
84e67b1223SAlexander Motin 	  .bar_start_idx = 1,
85e67b1223SAlexander Motin 	  .spad_count = 16,
86e67b1223SAlexander Motin 	  .db_count = 16,
87e67b1223SAlexander Motin 	  .msix_vector_count = 24,
88e67b1223SAlexander Motin 	  .quirks = QUIRK_MW0_32BIT,
89e67b1223SAlexander Motin 	  .desc = "AMD Non-Transparent Bridge"},
90e67b1223SAlexander Motin 
91e67b1223SAlexander Motin 	{ .vendor_id = NTB_HW_AMD_VENDOR_ID,
92e67b1223SAlexander Motin 	  .device_id = NTB_HW_AMD_DEVICE_ID2,
93e67b1223SAlexander Motin 	  .mw_count = 2,
94e67b1223SAlexander Motin 	  .bar_start_idx = 2,
95e67b1223SAlexander Motin 	  .spad_count = 16,
96e67b1223SAlexander Motin 	  .db_count = 16,
97e67b1223SAlexander Motin 	  .msix_vector_count = 24,
98e67b1223SAlexander Motin 	  .quirks = 0,
99e67b1223SAlexander Motin 	  .desc = "AMD Non-Transparent Bridge"},
1000d9cef0aSAlexander Motin 
1010d9cef0aSAlexander Motin 	{ .vendor_id = NTB_HW_HYGON_VENDOR_ID,
1020d9cef0aSAlexander Motin 	  .device_id = NTB_HW_HYGON_DEVICE_ID1,
1030d9cef0aSAlexander Motin 	  .mw_count = 3,
1040d9cef0aSAlexander Motin 	  .bar_start_idx = 1,
1050d9cef0aSAlexander Motin 	  .spad_count = 16,
1060d9cef0aSAlexander Motin 	  .db_count = 16,
1070d9cef0aSAlexander Motin 	  .msix_vector_count = 24,
1080d9cef0aSAlexander Motin 	  .quirks = QUIRK_MW0_32BIT,
1090d9cef0aSAlexander Motin 	  .desc = "Hygon Non-Transparent Bridge"},
110e67b1223SAlexander Motin };
111e67b1223SAlexander Motin 
112e67b1223SAlexander Motin static const struct pci_device_table amd_ntb_devs[] = {
113e67b1223SAlexander Motin 	{ PCI_DEV(NTB_HW_AMD_VENDOR_ID, NTB_HW_AMD_DEVICE_ID1),
114e67b1223SAlexander Motin 	  .driver_data = (uintptr_t)&amd_ntb_hw_info_list[0],
115e67b1223SAlexander Motin 	  PCI_DESCR("AMD Non-Transparent Bridge") },
116e67b1223SAlexander Motin 	{ PCI_DEV(NTB_HW_AMD_VENDOR_ID, NTB_HW_AMD_DEVICE_ID2),
117e67b1223SAlexander Motin 	  .driver_data = (uintptr_t)&amd_ntb_hw_info_list[1],
1180d9cef0aSAlexander Motin 	  PCI_DESCR("AMD Non-Transparent Bridge") },
1190d9cef0aSAlexander Motin 	{ PCI_DEV(NTB_HW_HYGON_VENDOR_ID, NTB_HW_HYGON_DEVICE_ID1),
1200d9cef0aSAlexander Motin 	  .driver_data = (uintptr_t)&amd_ntb_hw_info_list[0],
1210d9cef0aSAlexander Motin 	  PCI_DESCR("Hygon Non-Transparent Bridge") }
1226683132dSAlexander Motin };
1236683132dSAlexander Motin 
1246683132dSAlexander Motin static unsigned g_amd_ntb_hw_debug_level;
1256683132dSAlexander Motin SYSCTL_UINT(_hw_ntb, OID_AUTO, debug_level, CTLFLAG_RWTUN,
1266683132dSAlexander Motin     &g_amd_ntb_hw_debug_level, 0, "amd_ntb_hw log level -- higher is verbose");
1276683132dSAlexander Motin 
1286683132dSAlexander Motin #define amd_ntb_printf(lvl, ...) do {				\
1296683132dSAlexander Motin         if (lvl <= g_amd_ntb_hw_debug_level)			\
1306683132dSAlexander Motin                 device_printf(ntb->device, __VA_ARGS__);	\
1316683132dSAlexander Motin } while (0)
1326683132dSAlexander Motin 
1337b96ad44SAlexander Motin #ifdef __i386__
1347b96ad44SAlexander Motin static __inline uint64_t
bus_space_read_8(bus_space_tag_t tag,bus_space_handle_t handle,bus_size_t offset)1357b96ad44SAlexander Motin bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t handle,
1367b96ad44SAlexander Motin     bus_size_t offset)
1377b96ad44SAlexander Motin {
1387b96ad44SAlexander Motin 
1397b96ad44SAlexander Motin 	return (bus_space_read_4(tag, handle, offset) |
1407b96ad44SAlexander Motin 	    ((uint64_t)bus_space_read_4(tag, handle, offset + 4)) << 32);
1417b96ad44SAlexander Motin }
1427b96ad44SAlexander Motin 
1437b96ad44SAlexander Motin static __inline void
bus_space_write_8(bus_space_tag_t tag,bus_space_handle_t handle,bus_size_t offset,uint64_t val)1447b96ad44SAlexander Motin bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t handle,
1457b96ad44SAlexander Motin     bus_size_t offset, uint64_t val)
1467b96ad44SAlexander Motin {
1477b96ad44SAlexander Motin 
1487b96ad44SAlexander Motin 	bus_space_write_4(tag, handle, offset, val);
1497b96ad44SAlexander Motin 	bus_space_write_4(tag, handle, offset + 4, val >> 32);
1507b96ad44SAlexander Motin }
1517b96ad44SAlexander Motin #endif
1527b96ad44SAlexander Motin 
1536683132dSAlexander Motin /*
1546683132dSAlexander Motin  * AMD NTB INTERFACE ROUTINES
1556683132dSAlexander Motin  */
1566683132dSAlexander Motin static int
amd_ntb_port_number(device_t dev)1576683132dSAlexander Motin amd_ntb_port_number(device_t dev)
1586683132dSAlexander Motin {
1596683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
1606683132dSAlexander Motin 
1616683132dSAlexander Motin 	amd_ntb_printf(1, "%s: conn_type %d\n", __func__, ntb->conn_type);
1626683132dSAlexander Motin 
1636683132dSAlexander Motin 	switch (ntb->conn_type) {
1646683132dSAlexander Motin 	case NTB_CONN_PRI:
1656683132dSAlexander Motin 		return (NTB_PORT_PRI_USD);
1666683132dSAlexander Motin 	case NTB_CONN_SEC:
1676683132dSAlexander Motin 		return (NTB_PORT_SEC_DSD);
1686683132dSAlexander Motin 	default:
1696683132dSAlexander Motin 		break;
1706683132dSAlexander Motin 	}
1716683132dSAlexander Motin 
1726683132dSAlexander Motin 	return (-EINVAL);
1736683132dSAlexander Motin }
1746683132dSAlexander Motin 
1756683132dSAlexander Motin static int
amd_ntb_peer_port_count(device_t dev)1766683132dSAlexander Motin amd_ntb_peer_port_count(device_t dev)
1776683132dSAlexander Motin {
1786683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
1796683132dSAlexander Motin 
1806683132dSAlexander Motin 	amd_ntb_printf(1, "%s: peer cnt %d\n", __func__, NTB_DEF_PEER_CNT);
1816683132dSAlexander Motin 	return (NTB_DEF_PEER_CNT);
1826683132dSAlexander Motin }
1836683132dSAlexander Motin 
1846683132dSAlexander Motin static int
amd_ntb_peer_port_number(device_t dev,int pidx)1856683132dSAlexander Motin amd_ntb_peer_port_number(device_t dev, int pidx)
1866683132dSAlexander Motin {
1876683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
1886683132dSAlexander Motin 
1896683132dSAlexander Motin 	amd_ntb_printf(1, "%s: pidx %d conn type %d\n",
1906683132dSAlexander Motin 	    __func__, pidx, ntb->conn_type);
1916683132dSAlexander Motin 
1926683132dSAlexander Motin 	if (pidx != NTB_DEF_PEER_IDX)
1936683132dSAlexander Motin 		return (-EINVAL);
1946683132dSAlexander Motin 
1956683132dSAlexander Motin 	switch (ntb->conn_type) {
1966683132dSAlexander Motin 	case NTB_CONN_PRI:
1976683132dSAlexander Motin 		return (NTB_PORT_SEC_DSD);
1986683132dSAlexander Motin 	case NTB_CONN_SEC:
1996683132dSAlexander Motin 		return (NTB_PORT_PRI_USD);
2006683132dSAlexander Motin 	default:
2016683132dSAlexander Motin 		break;
2026683132dSAlexander Motin 	}
2036683132dSAlexander Motin 
2046683132dSAlexander Motin 	return (-EINVAL);
2056683132dSAlexander Motin }
2066683132dSAlexander Motin 
2076683132dSAlexander Motin static int
amd_ntb_peer_port_idx(device_t dev,int port)2086683132dSAlexander Motin amd_ntb_peer_port_idx(device_t dev, int port)
2096683132dSAlexander Motin {
2106683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
2116683132dSAlexander Motin 	int peer_port;
2126683132dSAlexander Motin 
2136683132dSAlexander Motin 	peer_port = amd_ntb_peer_port_number(dev, NTB_DEF_PEER_IDX);
2146683132dSAlexander Motin 
2156683132dSAlexander Motin 	amd_ntb_printf(1, "%s: port %d peer_port %d\n",
2166683132dSAlexander Motin 	    __func__, port, peer_port);
2176683132dSAlexander Motin 
2186683132dSAlexander Motin 	if (peer_port == -EINVAL || port != peer_port)
2196683132dSAlexander Motin 		return (-EINVAL);
2206683132dSAlexander Motin 
2216683132dSAlexander Motin 	return (0);
2226683132dSAlexander Motin }
2236683132dSAlexander Motin 
2246683132dSAlexander Motin /*
2256683132dSAlexander Motin  * AMD NTB INTERFACE - LINK ROUTINES
2266683132dSAlexander Motin  */
2276683132dSAlexander Motin static inline int
amd_link_is_up(struct amd_ntb_softc * ntb)2286683132dSAlexander Motin amd_link_is_up(struct amd_ntb_softc *ntb)
2296683132dSAlexander Motin {
2306683132dSAlexander Motin 
2316683132dSAlexander Motin 	amd_ntb_printf(2, "%s: peer_sta 0x%x cntl_sta 0x%x\n",
2326683132dSAlexander Motin 	    __func__, ntb->peer_sta, ntb->cntl_sta);
2336683132dSAlexander Motin 
2346683132dSAlexander Motin 	if (!ntb->peer_sta)
2356683132dSAlexander Motin 		return (NTB_LNK_STA_ACTIVE(ntb->cntl_sta));
2366683132dSAlexander Motin 
2376683132dSAlexander Motin 	return (0);
2386683132dSAlexander Motin }
2396683132dSAlexander Motin 
2406683132dSAlexander Motin static inline enum ntb_speed
amd_ntb_link_sta_speed(struct amd_ntb_softc * ntb)2416683132dSAlexander Motin amd_ntb_link_sta_speed(struct amd_ntb_softc *ntb)
2426683132dSAlexander Motin {
2436683132dSAlexander Motin 
2446683132dSAlexander Motin 	if (!amd_link_is_up(ntb))
2456683132dSAlexander Motin 		return (NTB_SPEED_NONE);
2466683132dSAlexander Motin 
2476683132dSAlexander Motin 	return (NTB_LNK_STA_SPEED(ntb->lnk_sta));
2486683132dSAlexander Motin }
2496683132dSAlexander Motin 
2506683132dSAlexander Motin static inline enum ntb_width
amd_ntb_link_sta_width(struct amd_ntb_softc * ntb)2516683132dSAlexander Motin amd_ntb_link_sta_width(struct amd_ntb_softc *ntb)
2526683132dSAlexander Motin {
2536683132dSAlexander Motin 
2546683132dSAlexander Motin 	if (!amd_link_is_up(ntb))
2556683132dSAlexander Motin 		return (NTB_WIDTH_NONE);
2566683132dSAlexander Motin 
2576683132dSAlexander Motin 	return (NTB_LNK_STA_WIDTH(ntb->lnk_sta));
2586683132dSAlexander Motin }
2596683132dSAlexander Motin 
2606683132dSAlexander Motin static bool
amd_ntb_link_is_up(device_t dev,enum ntb_speed * speed,enum ntb_width * width)2616683132dSAlexander Motin amd_ntb_link_is_up(device_t dev, enum ntb_speed *speed, enum ntb_width *width)
2626683132dSAlexander Motin {
2636683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
2646683132dSAlexander Motin 
2656683132dSAlexander Motin 	if (speed != NULL)
2666683132dSAlexander Motin 		*speed = amd_ntb_link_sta_speed(ntb);
2676683132dSAlexander Motin 	if (width != NULL)
2686683132dSAlexander Motin 		*width = amd_ntb_link_sta_width(ntb);
2696683132dSAlexander Motin 
2706683132dSAlexander Motin 	return (amd_link_is_up(ntb));
2716683132dSAlexander Motin }
2726683132dSAlexander Motin 
2736683132dSAlexander Motin static int
amd_ntb_link_enable(device_t dev,enum ntb_speed max_speed,enum ntb_width max_width)2746683132dSAlexander Motin amd_ntb_link_enable(device_t dev, enum ntb_speed max_speed,
2756683132dSAlexander Motin     enum ntb_width max_width)
2766683132dSAlexander Motin {
2776683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
2786683132dSAlexander Motin 	uint32_t ntb_ctl;
2796683132dSAlexander Motin 
2806683132dSAlexander Motin 	amd_ntb_printf(1, "%s: int_mask 0x%x conn_type %d\n",
2816683132dSAlexander Motin 	    __func__, ntb->int_mask, ntb->conn_type);
2826683132dSAlexander Motin 
2836683132dSAlexander Motin 	amd_init_side_info(ntb);
2846683132dSAlexander Motin 
2856683132dSAlexander Motin 	/* Enable event interrupt */
2866683132dSAlexander Motin 	ntb->int_mask &= ~AMD_EVENT_INTMASK;
2876683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_INTMASK_OFFSET, ntb->int_mask);
2886683132dSAlexander Motin 
2896683132dSAlexander Motin 	if (ntb->conn_type == NTB_CONN_SEC)
2906683132dSAlexander Motin 		return (EINVAL);
2916683132dSAlexander Motin 
2926683132dSAlexander Motin 	amd_ntb_printf(0, "%s: Enabling Link.\n", __func__);
2936683132dSAlexander Motin 
2946683132dSAlexander Motin 	ntb_ctl = amd_ntb_reg_read(4, AMD_CNTL_OFFSET);
2956683132dSAlexander Motin 	ntb_ctl |= (PMM_REG_CTL | SMM_REG_CTL);
2966683132dSAlexander Motin 	amd_ntb_printf(1, "%s: ntb_ctl 0x%x\n", __func__, ntb_ctl);
2976683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_CNTL_OFFSET, ntb_ctl);
2986683132dSAlexander Motin 
2996683132dSAlexander Motin 	return (0);
3006683132dSAlexander Motin }
3016683132dSAlexander Motin 
3026683132dSAlexander Motin static int
amd_ntb_link_disable(device_t dev)3036683132dSAlexander Motin amd_ntb_link_disable(device_t dev)
3046683132dSAlexander Motin {
3056683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
3066683132dSAlexander Motin 	uint32_t ntb_ctl;
3076683132dSAlexander Motin 
3086683132dSAlexander Motin 	amd_ntb_printf(1, "%s: int_mask 0x%x conn_type %d\n",
3096683132dSAlexander Motin 	    __func__, ntb->int_mask, ntb->conn_type);
3106683132dSAlexander Motin 
3116683132dSAlexander Motin 	amd_deinit_side_info(ntb);
3126683132dSAlexander Motin 
3136683132dSAlexander Motin 	/* Disable event interrupt */
3146683132dSAlexander Motin 	ntb->int_mask |= AMD_EVENT_INTMASK;
3156683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_INTMASK_OFFSET, ntb->int_mask);
3166683132dSAlexander Motin 
3176683132dSAlexander Motin 	if (ntb->conn_type == NTB_CONN_SEC)
3186683132dSAlexander Motin 		return (EINVAL);
3196683132dSAlexander Motin 
3206683132dSAlexander Motin 	amd_ntb_printf(0, "%s: Disabling Link.\n", __func__);
3216683132dSAlexander Motin 
3226683132dSAlexander Motin 	ntb_ctl = amd_ntb_reg_read(4, AMD_CNTL_OFFSET);
3236683132dSAlexander Motin 	ntb_ctl &= ~(PMM_REG_CTL | SMM_REG_CTL);
3246683132dSAlexander Motin 	amd_ntb_printf(1, "%s: ntb_ctl 0x%x\n", __func__, ntb_ctl);
3256683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_CNTL_OFFSET, ntb_ctl);
3266683132dSAlexander Motin 
3276683132dSAlexander Motin 	return (0);
3286683132dSAlexander Motin }
3296683132dSAlexander Motin 
3306683132dSAlexander Motin /*
3316683132dSAlexander Motin  * AMD NTB memory window routines
3326683132dSAlexander Motin  */
3336683132dSAlexander Motin static uint8_t
amd_ntb_mw_count(device_t dev)3346683132dSAlexander Motin amd_ntb_mw_count(device_t dev)
3356683132dSAlexander Motin {
3366683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
3376683132dSAlexander Motin 
338e67b1223SAlexander Motin 	return (ntb->hw_info->mw_count);
3396683132dSAlexander Motin }
3406683132dSAlexander Motin 
3416683132dSAlexander Motin static int
amd_ntb_mw_get_range(device_t dev,unsigned mw_idx,vm_paddr_t * base,caddr_t * vbase,size_t * size,size_t * align,size_t * align_size,bus_addr_t * plimit)3426683132dSAlexander Motin amd_ntb_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base,
3436683132dSAlexander Motin     caddr_t *vbase, size_t *size, size_t *align, size_t *align_size,
3446683132dSAlexander Motin     bus_addr_t *plimit)
3456683132dSAlexander Motin {
3466683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
3476683132dSAlexander Motin 	struct amd_ntb_pci_bar_info *bar_info;
3486683132dSAlexander Motin 
349e67b1223SAlexander Motin 	if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count)
3506683132dSAlexander Motin 		return (EINVAL);
3516683132dSAlexander Motin 
352e67b1223SAlexander Motin 	bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx];
3536683132dSAlexander Motin 
3546683132dSAlexander Motin 	if (base != NULL)
3556683132dSAlexander Motin 		*base = bar_info->pbase;
3566683132dSAlexander Motin 
3576683132dSAlexander Motin 	if (vbase != NULL)
3586683132dSAlexander Motin 		*vbase = bar_info->vbase;
3596683132dSAlexander Motin 
3606683132dSAlexander Motin 	if (align != NULL)
3616683132dSAlexander Motin 		*align = bar_info->size;
3626683132dSAlexander Motin 
3636683132dSAlexander Motin 	if (size != NULL)
3646683132dSAlexander Motin 		*size = bar_info->size;
3656683132dSAlexander Motin 
3666683132dSAlexander Motin 	if (align_size != NULL)
3676683132dSAlexander Motin 		*align_size = 1;
3686683132dSAlexander Motin 
3696683132dSAlexander Motin 	if (plimit != NULL) {
370e67b1223SAlexander Motin 		/*
371e67b1223SAlexander Motin 		 * For Device ID 0x145B (which has 3 memory windows),
372e67b1223SAlexander Motin 		 * memory window 0 use a 32-bit bar. The remaining
373e67b1223SAlexander Motin 		 * cases all use 64-bit bar.
374e67b1223SAlexander Motin 		 */
375e67b1223SAlexander Motin 		if ((mw_idx == 0) && (ntb->hw_info->quirks & QUIRK_MW0_32BIT))
3766683132dSAlexander Motin 			*plimit = BUS_SPACE_MAXADDR_32BIT;
377e67b1223SAlexander Motin 		else
378e67b1223SAlexander Motin 			*plimit = BUS_SPACE_MAXADDR;
3796683132dSAlexander Motin 	}
3806683132dSAlexander Motin 
3816683132dSAlexander Motin 	return (0);
3826683132dSAlexander Motin }
3836683132dSAlexander Motin 
3846683132dSAlexander Motin static int
amd_ntb_mw_set_trans(device_t dev,unsigned mw_idx,bus_addr_t addr,size_t size)3856683132dSAlexander Motin amd_ntb_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size)
3866683132dSAlexander Motin {
3876683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
3886683132dSAlexander Motin 	struct amd_ntb_pci_bar_info *bar_info;
3896683132dSAlexander Motin 
390e67b1223SAlexander Motin 	if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count)
3916683132dSAlexander Motin 		return (EINVAL);
3926683132dSAlexander Motin 
393e67b1223SAlexander Motin 	bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx];
3946683132dSAlexander Motin 
395e67b1223SAlexander Motin 	/* Make sure the range fits in the usable mw size. */
3966683132dSAlexander Motin 	if (size > bar_info->size) {
397d8335b53SAlexander Motin 		amd_ntb_printf(0, "%s: size 0x%jx greater than mw_size 0x%jx\n",
398d8335b53SAlexander Motin 		    __func__, (uintmax_t)size, (uintmax_t)bar_info->size);
3996683132dSAlexander Motin 		return (EINVAL);
4006683132dSAlexander Motin 	}
4016683132dSAlexander Motin 
402d8335b53SAlexander Motin 	amd_ntb_printf(1, "%s: mw %d mw_size 0x%jx size 0x%jx base %p\n",
403d8335b53SAlexander Motin 	    __func__, mw_idx, (uintmax_t)bar_info->size,
404d8335b53SAlexander Motin 	    (uintmax_t)size, (void *)bar_info->pci_bus_handle);
4056683132dSAlexander Motin 
4066683132dSAlexander Motin 	/*
4076683132dSAlexander Motin 	 * AMD NTB XLAT and Limit registers needs to be written only after
408e67b1223SAlexander Motin 	 * link enable.
4096683132dSAlexander Motin 	 *
410e67b1223SAlexander Motin 	 * Set and verify setting the translation address register.
4116683132dSAlexander Motin 	 */
4126683132dSAlexander Motin 	amd_ntb_peer_reg_write(8, bar_info->xlat_off, (uint64_t)addr);
4137b96ad44SAlexander Motin 	amd_ntb_printf(0, "%s: mw %d xlat_off 0x%x cur_val 0x%jx addr %p\n",
4146683132dSAlexander Motin 	    __func__, mw_idx, bar_info->xlat_off,
4156683132dSAlexander Motin 	    amd_ntb_peer_reg_read(8, bar_info->xlat_off), (void *)addr);
4166683132dSAlexander Motin 
417e67b1223SAlexander Motin 	/*
418e67b1223SAlexander Motin 	 * Set and verify setting the limit register.
419e67b1223SAlexander Motin 	 *
420e67b1223SAlexander Motin 	 * For Device ID 0x145B (which has 3 memory windows),
421e67b1223SAlexander Motin 	 * memory window 0 use a 32-bit bar. The remaining
422e67b1223SAlexander Motin 	 * cases all use 64-bit bar.
423e67b1223SAlexander Motin 	 */
424e67b1223SAlexander Motin 	if ((mw_idx == 0) && (ntb->hw_info->quirks & QUIRK_MW0_32BIT)) {
425d8335b53SAlexander Motin 		amd_ntb_reg_write(4, bar_info->limit_off, (uint32_t)size);
4266683132dSAlexander Motin 		amd_ntb_printf(1, "%s: limit_off 0x%x cur_val 0x%x limit 0x%x\n",
4276683132dSAlexander Motin 		    __func__, bar_info->limit_off,
428e67b1223SAlexander Motin 		    amd_ntb_peer_reg_read(4, bar_info->limit_off),
429e67b1223SAlexander Motin 		    (uint32_t)size);
430e67b1223SAlexander Motin 	} else {
431e67b1223SAlexander Motin 		amd_ntb_reg_write(8, bar_info->limit_off, (uint64_t)size);
432d8335b53SAlexander Motin 		amd_ntb_printf(1, "%s: limit_off 0x%x cur_val 0x%jx limit 0x%jx\n",
433e67b1223SAlexander Motin 		    __func__, bar_info->limit_off,
434e67b1223SAlexander Motin 		    amd_ntb_peer_reg_read(8, bar_info->limit_off),
435d8335b53SAlexander Motin 		    (uintmax_t)size);
4366683132dSAlexander Motin 	}
4376683132dSAlexander Motin 
4386683132dSAlexander Motin 	return (0);
4396683132dSAlexander Motin }
4406683132dSAlexander Motin 
4416683132dSAlexander Motin static int
amd_ntb_mw_clear_trans(device_t dev,unsigned mw_idx)4426683132dSAlexander Motin amd_ntb_mw_clear_trans(device_t dev, unsigned mw_idx)
4436683132dSAlexander Motin {
4446683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
4456683132dSAlexander Motin 
4466683132dSAlexander Motin 	amd_ntb_printf(1, "%s: mw_idx %d\n", __func__, mw_idx);
4476683132dSAlexander Motin 
448e67b1223SAlexander Motin 	if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count)
4496683132dSAlexander Motin 		return (EINVAL);
4506683132dSAlexander Motin 
4516683132dSAlexander Motin 	return (amd_ntb_mw_set_trans(dev, mw_idx, 0, 0));
4526683132dSAlexander Motin }
4536683132dSAlexander Motin 
4546683132dSAlexander Motin static int
amd_ntb_mw_set_wc(device_t dev,unsigned int mw_idx,vm_memattr_t mode)4556683132dSAlexander Motin amd_ntb_mw_set_wc(device_t dev, unsigned int mw_idx, vm_memattr_t mode)
4566683132dSAlexander Motin {
4576683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
4586683132dSAlexander Motin 	struct amd_ntb_pci_bar_info *bar_info;
4596683132dSAlexander Motin 	int rc;
4606683132dSAlexander Motin 
461e67b1223SAlexander Motin 	if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count)
4626683132dSAlexander Motin 		return (EINVAL);
4636683132dSAlexander Motin 
464e67b1223SAlexander Motin 	bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx];
4656683132dSAlexander Motin 	if (mode == bar_info->map_mode)
4666683132dSAlexander Motin 		return (0);
4676683132dSAlexander Motin 
4686683132dSAlexander Motin 	rc = pmap_change_attr((vm_offset_t)bar_info->vbase, bar_info->size, mode);
4696683132dSAlexander Motin 	if (rc == 0)
4706683132dSAlexander Motin 		bar_info->map_mode = mode;
4716683132dSAlexander Motin 
4726683132dSAlexander Motin 	return (rc);
4736683132dSAlexander Motin }
4746683132dSAlexander Motin 
4756683132dSAlexander Motin static int
amd_ntb_mw_get_wc(device_t dev,unsigned mw_idx,vm_memattr_t * mode)4766683132dSAlexander Motin amd_ntb_mw_get_wc(device_t dev, unsigned mw_idx, vm_memattr_t *mode)
4776683132dSAlexander Motin {
4786683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
4796683132dSAlexander Motin 	struct amd_ntb_pci_bar_info *bar_info;
4806683132dSAlexander Motin 
4816683132dSAlexander Motin 	amd_ntb_printf(1, "%s: mw_idx %d\n", __func__, mw_idx);
4826683132dSAlexander Motin 
483e67b1223SAlexander Motin 	if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count)
4846683132dSAlexander Motin 		return (EINVAL);
4856683132dSAlexander Motin 
486e67b1223SAlexander Motin 	bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx];
4876683132dSAlexander Motin 	*mode = bar_info->map_mode;
4886683132dSAlexander Motin 
4896683132dSAlexander Motin 	return (0);
4906683132dSAlexander Motin }
4916683132dSAlexander Motin 
4926683132dSAlexander Motin /*
4936683132dSAlexander Motin  * AMD NTB doorbell routines
4946683132dSAlexander Motin  */
4956683132dSAlexander Motin static int
amd_ntb_db_vector_count(device_t dev)4966683132dSAlexander Motin amd_ntb_db_vector_count(device_t dev)
4976683132dSAlexander Motin {
4986683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
4996683132dSAlexander Motin 
500e67b1223SAlexander Motin 	amd_ntb_printf(1, "%s: db_count 0x%x\n", __func__,
501e67b1223SAlexander Motin 	    ntb->hw_info->db_count);
5026683132dSAlexander Motin 
503e67b1223SAlexander Motin 	return (ntb->hw_info->db_count);
5046683132dSAlexander Motin }
5056683132dSAlexander Motin 
5066683132dSAlexander Motin static uint64_t
amd_ntb_db_valid_mask(device_t dev)5076683132dSAlexander Motin amd_ntb_db_valid_mask(device_t dev)
5086683132dSAlexander Motin {
5096683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5106683132dSAlexander Motin 
5116683132dSAlexander Motin 	amd_ntb_printf(1, "%s: db_valid_mask 0x%x\n",
5126683132dSAlexander Motin 	    __func__, ntb->db_valid_mask);
5136683132dSAlexander Motin 
5146683132dSAlexander Motin 	return (ntb->db_valid_mask);
5156683132dSAlexander Motin }
5166683132dSAlexander Motin 
5176683132dSAlexander Motin static uint64_t
amd_ntb_db_vector_mask(device_t dev,uint32_t vector)5186683132dSAlexander Motin amd_ntb_db_vector_mask(device_t dev, uint32_t vector)
5196683132dSAlexander Motin {
5206683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5216683132dSAlexander Motin 
5226683132dSAlexander Motin 	amd_ntb_printf(1, "%s: vector %d db_count 0x%x db_valid_mask 0x%x\n",
523e67b1223SAlexander Motin 	    __func__, vector, ntb->hw_info->db_count, ntb->db_valid_mask);
5246683132dSAlexander Motin 
525e67b1223SAlexander Motin 	if (vector < 0 || vector >= ntb->hw_info->db_count)
5266683132dSAlexander Motin 		return (0);
5276683132dSAlexander Motin 
5286683132dSAlexander Motin 	return (ntb->db_valid_mask & (1 << vector));
5296683132dSAlexander Motin }
5306683132dSAlexander Motin 
5316683132dSAlexander Motin static uint64_t
amd_ntb_db_read(device_t dev)5326683132dSAlexander Motin amd_ntb_db_read(device_t dev)
5336683132dSAlexander Motin {
5346683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5356683132dSAlexander Motin 	uint64_t dbstat_off;
5366683132dSAlexander Motin 
5376683132dSAlexander Motin 	dbstat_off = (uint64_t)amd_ntb_reg_read(2, AMD_DBSTAT_OFFSET);
5386683132dSAlexander Motin 
5397b96ad44SAlexander Motin 	amd_ntb_printf(1, "%s: dbstat_off 0x%jx\n", __func__, dbstat_off);
5406683132dSAlexander Motin 
5416683132dSAlexander Motin 	return (dbstat_off);
5426683132dSAlexander Motin }
5436683132dSAlexander Motin 
5446683132dSAlexander Motin static void
amd_ntb_db_clear(device_t dev,uint64_t db_bits)5456683132dSAlexander Motin amd_ntb_db_clear(device_t dev, uint64_t db_bits)
5466683132dSAlexander Motin {
5476683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5486683132dSAlexander Motin 
5497b96ad44SAlexander Motin 	amd_ntb_printf(1, "%s: db_bits 0x%jx\n", __func__, db_bits);
5506683132dSAlexander Motin 	amd_ntb_reg_write(2, AMD_DBSTAT_OFFSET, (uint16_t)db_bits);
5516683132dSAlexander Motin }
5526683132dSAlexander Motin 
5536683132dSAlexander Motin static void
amd_ntb_db_set_mask(device_t dev,uint64_t db_bits)5546683132dSAlexander Motin amd_ntb_db_set_mask(device_t dev, uint64_t db_bits)
5556683132dSAlexander Motin {
5566683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5576683132dSAlexander Motin 
5586683132dSAlexander Motin 	DB_MASK_LOCK(ntb);
5597b96ad44SAlexander Motin 	amd_ntb_printf(1, "%s: db_mask 0x%x db_bits 0x%jx\n",
5606683132dSAlexander Motin 	    __func__, ntb->db_mask, db_bits);
5616683132dSAlexander Motin 
5626683132dSAlexander Motin 	ntb->db_mask |= db_bits;
5636683132dSAlexander Motin 	amd_ntb_reg_write(2, AMD_DBMASK_OFFSET, ntb->db_mask);
5646683132dSAlexander Motin 	DB_MASK_UNLOCK(ntb);
5656683132dSAlexander Motin }
5666683132dSAlexander Motin 
5676683132dSAlexander Motin static void
amd_ntb_db_clear_mask(device_t dev,uint64_t db_bits)5686683132dSAlexander Motin amd_ntb_db_clear_mask(device_t dev, uint64_t db_bits)
5696683132dSAlexander Motin {
5706683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5716683132dSAlexander Motin 
5726683132dSAlexander Motin 	DB_MASK_LOCK(ntb);
5737b96ad44SAlexander Motin 	amd_ntb_printf(1, "%s: db_mask 0x%x db_bits 0x%jx\n",
5746683132dSAlexander Motin 	    __func__, ntb->db_mask, db_bits);
5756683132dSAlexander Motin 
5766683132dSAlexander Motin 	ntb->db_mask &= ~db_bits;
5776683132dSAlexander Motin 	amd_ntb_reg_write(2, AMD_DBMASK_OFFSET, ntb->db_mask);
5786683132dSAlexander Motin 	DB_MASK_UNLOCK(ntb);
5796683132dSAlexander Motin }
5806683132dSAlexander Motin 
5816683132dSAlexander Motin static void
amd_ntb_peer_db_set(device_t dev,uint64_t db_bits)5826683132dSAlexander Motin amd_ntb_peer_db_set(device_t dev, uint64_t db_bits)
5836683132dSAlexander Motin {
5846683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5856683132dSAlexander Motin 
5867b96ad44SAlexander Motin 	amd_ntb_printf(1, "%s: db_bits 0x%jx\n", __func__, db_bits);
5876683132dSAlexander Motin 	amd_ntb_reg_write(2, AMD_DBREQ_OFFSET, (uint16_t)db_bits);
5886683132dSAlexander Motin }
5896683132dSAlexander Motin 
5906683132dSAlexander Motin /*
5916683132dSAlexander Motin  * AMD NTB scratchpad routines
5926683132dSAlexander Motin  */
5936683132dSAlexander Motin static uint8_t
amd_ntb_spad_count(device_t dev)5946683132dSAlexander Motin amd_ntb_spad_count(device_t dev)
5956683132dSAlexander Motin {
5966683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
5976683132dSAlexander Motin 
598e67b1223SAlexander Motin 	amd_ntb_printf(1, "%s: spad_count 0x%x\n", __func__,
599e67b1223SAlexander Motin 	    ntb->spad_count);
6006683132dSAlexander Motin 
6016683132dSAlexander Motin 	return (ntb->spad_count);
6026683132dSAlexander Motin }
6036683132dSAlexander Motin 
6046683132dSAlexander Motin static int
amd_ntb_spad_read(device_t dev,unsigned int idx,uint32_t * val)6056683132dSAlexander Motin amd_ntb_spad_read(device_t dev, unsigned int idx, uint32_t *val)
6066683132dSAlexander Motin {
6076683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
6086683132dSAlexander Motin 	uint32_t offset;
6096683132dSAlexander Motin 
6106683132dSAlexander Motin 	amd_ntb_printf(2, "%s: idx %d\n", __func__, idx);
6116683132dSAlexander Motin 
6126683132dSAlexander Motin 	if (idx < 0 || idx >= ntb->spad_count)
6136683132dSAlexander Motin 		return (EINVAL);
6146683132dSAlexander Motin 
6156683132dSAlexander Motin 	offset = ntb->self_spad + (idx << 2);
6166683132dSAlexander Motin 	*val = amd_ntb_reg_read(4, AMD_SPAD_OFFSET + offset);
6176683132dSAlexander Motin 	amd_ntb_printf(2, "%s: offset 0x%x val 0x%x\n", __func__, offset, *val);
6186683132dSAlexander Motin 
6196683132dSAlexander Motin 	return (0);
6206683132dSAlexander Motin }
6216683132dSAlexander Motin 
6226683132dSAlexander Motin static int
amd_ntb_spad_write(device_t dev,unsigned int idx,uint32_t val)6236683132dSAlexander Motin amd_ntb_spad_write(device_t dev, unsigned int idx, uint32_t val)
6246683132dSAlexander Motin {
6256683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
6266683132dSAlexander Motin 	uint32_t offset;
6276683132dSAlexander Motin 
6286683132dSAlexander Motin 	amd_ntb_printf(2, "%s: idx %d\n", __func__, idx);
6296683132dSAlexander Motin 
6306683132dSAlexander Motin 	if (idx < 0 || idx >= ntb->spad_count)
6316683132dSAlexander Motin 		return (EINVAL);
6326683132dSAlexander Motin 
6336683132dSAlexander Motin 	offset = ntb->self_spad + (idx << 2);
6346683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_SPAD_OFFSET + offset, val);
6356683132dSAlexander Motin 	amd_ntb_printf(2, "%s: offset 0x%x val 0x%x\n", __func__, offset, val);
6366683132dSAlexander Motin 
6376683132dSAlexander Motin 	return (0);
6386683132dSAlexander Motin }
6396683132dSAlexander Motin 
6406683132dSAlexander Motin static void
amd_ntb_spad_clear(struct amd_ntb_softc * ntb)6416683132dSAlexander Motin amd_ntb_spad_clear(struct amd_ntb_softc *ntb)
6426683132dSAlexander Motin {
6436683132dSAlexander Motin 	uint8_t i;
6446683132dSAlexander Motin 
6456683132dSAlexander Motin 	for (i = 0; i < ntb->spad_count; i++)
6466683132dSAlexander Motin 		amd_ntb_spad_write(ntb->device, i, 0);
6476683132dSAlexander Motin }
6486683132dSAlexander Motin 
6496683132dSAlexander Motin static int
amd_ntb_peer_spad_read(device_t dev,unsigned int idx,uint32_t * val)6506683132dSAlexander Motin amd_ntb_peer_spad_read(device_t dev, unsigned int idx, uint32_t *val)
6516683132dSAlexander Motin {
6526683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
6536683132dSAlexander Motin 	uint32_t offset;
6546683132dSAlexander Motin 
6556683132dSAlexander Motin 	amd_ntb_printf(2, "%s: idx %d\n", __func__, idx);
6566683132dSAlexander Motin 
6576683132dSAlexander Motin 	if (idx < 0 || idx >= ntb->spad_count)
6586683132dSAlexander Motin 		return (EINVAL);
6596683132dSAlexander Motin 
6606683132dSAlexander Motin 	offset = ntb->peer_spad + (idx << 2);
6616683132dSAlexander Motin 	*val = amd_ntb_reg_read(4, AMD_SPAD_OFFSET + offset);
6626683132dSAlexander Motin 	amd_ntb_printf(2, "%s: offset 0x%x val 0x%x\n", __func__, offset, *val);
6636683132dSAlexander Motin 
6646683132dSAlexander Motin 	return (0);
6656683132dSAlexander Motin }
6666683132dSAlexander Motin 
6676683132dSAlexander Motin static int
amd_ntb_peer_spad_write(device_t dev,unsigned int idx,uint32_t val)6686683132dSAlexander Motin amd_ntb_peer_spad_write(device_t dev, unsigned int idx, uint32_t val)
6696683132dSAlexander Motin {
6706683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(dev);
6716683132dSAlexander Motin 	uint32_t offset;
6726683132dSAlexander Motin 
6736683132dSAlexander Motin 	amd_ntb_printf(2, "%s: idx %d\n", __func__, idx);
6746683132dSAlexander Motin 
6756683132dSAlexander Motin 	if (idx < 0 || idx >= ntb->spad_count)
6766683132dSAlexander Motin 		return (EINVAL);
6776683132dSAlexander Motin 
6786683132dSAlexander Motin 	offset = ntb->peer_spad + (idx << 2);
6796683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_SPAD_OFFSET + offset, val);
6806683132dSAlexander Motin 	amd_ntb_printf(2, "%s: offset 0x%x val 0x%x\n", __func__, offset, val);
6816683132dSAlexander Motin 
6826683132dSAlexander Motin 	return (0);
6836683132dSAlexander Motin }
6846683132dSAlexander Motin 
6856683132dSAlexander Motin /*
6866683132dSAlexander Motin  * AMD NTB INIT
6876683132dSAlexander Motin  */
6886683132dSAlexander Motin static int
amd_ntb_hw_info_handler(SYSCTL_HANDLER_ARGS)6896683132dSAlexander Motin amd_ntb_hw_info_handler(SYSCTL_HANDLER_ARGS)
6906683132dSAlexander Motin {
6916683132dSAlexander Motin 	struct amd_ntb_softc* ntb = arg1;
6926683132dSAlexander Motin 	struct sbuf *sb;
6936683132dSAlexander Motin 	int rc = 0;
6946683132dSAlexander Motin 
6956683132dSAlexander Motin 	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
6966683132dSAlexander Motin 	if (sb == NULL)
6976683132dSAlexander Motin 		return (sb->s_error);
6986683132dSAlexander Motin 
6996683132dSAlexander Motin 	sbuf_printf(sb, "NTB AMD Hardware info:\n\n");
7006683132dSAlexander Motin 	sbuf_printf(sb, "AMD NTB side: %s\n",
7016683132dSAlexander Motin 	    (ntb->conn_type == NTB_CONN_PRI)? "PRIMARY" : "SECONDARY");
7026683132dSAlexander Motin 	sbuf_printf(sb, "AMD LNK STA: 0x%#06x\n", ntb->lnk_sta);
7036683132dSAlexander Motin 
7046683132dSAlexander Motin 	if (!amd_link_is_up(ntb))
7056683132dSAlexander Motin 		sbuf_printf(sb, "AMD Link Status: Down\n");
7066683132dSAlexander Motin 	else {
7076683132dSAlexander Motin 		sbuf_printf(sb, "AMD Link Status: Up\n");
7086683132dSAlexander Motin 		sbuf_printf(sb, "AMD Link Speed: PCI-E Gen %u\n",
7096683132dSAlexander Motin 		    NTB_LNK_STA_SPEED(ntb->lnk_sta));
7106683132dSAlexander Motin 		sbuf_printf(sb, "AMD Link Width: PCI-E Width %u\n",
7116683132dSAlexander Motin 		    NTB_LNK_STA_WIDTH(ntb->lnk_sta));
7126683132dSAlexander Motin 	}
7136683132dSAlexander Motin 
7146683132dSAlexander Motin 	sbuf_printf(sb, "AMD Memory window count: %d\n",
715e67b1223SAlexander Motin 	    ntb->hw_info->mw_count);
7166683132dSAlexander Motin 	sbuf_printf(sb, "AMD Spad count: %d\n",
7176683132dSAlexander Motin 	    ntb->spad_count);
7186683132dSAlexander Motin 	sbuf_printf(sb, "AMD Doorbell count: %d\n",
719e67b1223SAlexander Motin 	    ntb->hw_info->db_count);
7206683132dSAlexander Motin 	sbuf_printf(sb, "AMD MSI-X vec count: %d\n\n",
7216683132dSAlexander Motin 	    ntb->msix_vec_count);
7226683132dSAlexander Motin 	sbuf_printf(sb, "AMD Doorbell valid mask: 0x%x\n",
7236683132dSAlexander Motin 	    ntb->db_valid_mask);
7246683132dSAlexander Motin 	sbuf_printf(sb, "AMD Doorbell Mask: 0x%x\n",
7256683132dSAlexander Motin 	    amd_ntb_reg_read(4, AMD_DBMASK_OFFSET));
7266683132dSAlexander Motin 	sbuf_printf(sb, "AMD Doorbell: 0x%x\n",
7276683132dSAlexander Motin 	    amd_ntb_reg_read(4, AMD_DBSTAT_OFFSET));
7286683132dSAlexander Motin 	sbuf_printf(sb, "AMD NTB Incoming XLAT: \n");
7297b96ad44SAlexander Motin 	sbuf_printf(sb, "AMD XLAT1: 0x%jx\n",
7306683132dSAlexander Motin 	    amd_ntb_peer_reg_read(8, AMD_BAR1XLAT_OFFSET));
7317b96ad44SAlexander Motin 	sbuf_printf(sb, "AMD XLAT23: 0x%jx\n",
7326683132dSAlexander Motin 	    amd_ntb_peer_reg_read(8, AMD_BAR23XLAT_OFFSET));
7337b96ad44SAlexander Motin 	sbuf_printf(sb, "AMD XLAT45: 0x%jx\n",
7346683132dSAlexander Motin 	    amd_ntb_peer_reg_read(8, AMD_BAR45XLAT_OFFSET));
7356683132dSAlexander Motin 	sbuf_printf(sb, "AMD LMT1: 0x%x\n",
7366683132dSAlexander Motin 	    amd_ntb_reg_read(4, AMD_BAR1LMT_OFFSET));
7377b96ad44SAlexander Motin 	sbuf_printf(sb, "AMD LMT23: 0x%jx\n",
7386683132dSAlexander Motin 	    amd_ntb_reg_read(8, AMD_BAR23LMT_OFFSET));
7397b96ad44SAlexander Motin 	sbuf_printf(sb, "AMD LMT45: 0x%jx\n",
7406683132dSAlexander Motin 	    amd_ntb_reg_read(8, AMD_BAR45LMT_OFFSET));
7416683132dSAlexander Motin 
7426683132dSAlexander Motin 	rc = sbuf_finish(sb);
7436683132dSAlexander Motin 	sbuf_delete(sb);
7446683132dSAlexander Motin 	return (rc);
7456683132dSAlexander Motin }
7466683132dSAlexander Motin 
7476683132dSAlexander Motin static void
amd_ntb_sysctl_init(struct amd_ntb_softc * ntb)7486683132dSAlexander Motin amd_ntb_sysctl_init(struct amd_ntb_softc *ntb)
7496683132dSAlexander Motin {
7506683132dSAlexander Motin 	struct sysctl_oid_list *globals;
7516683132dSAlexander Motin 	struct sysctl_ctx_list *ctx;
7526683132dSAlexander Motin 
7536683132dSAlexander Motin 	ctx = device_get_sysctl_ctx(ntb->device);
7546683132dSAlexander Motin 	globals = SYSCTL_CHILDREN(device_get_sysctl_tree(ntb->device));
7556683132dSAlexander Motin 
7566683132dSAlexander Motin 	SYSCTL_ADD_PROC(ctx, globals, OID_AUTO, "info",
7576683132dSAlexander Motin 	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, ntb, 0,
7586683132dSAlexander Motin 	    amd_ntb_hw_info_handler, "A", "AMD NTB HW Information");
7596683132dSAlexander Motin }
7606683132dSAlexander Motin 
7616683132dSAlexander Motin /*
7626683132dSAlexander Motin  * Polls the HW link status register(s); returns true if something has changed.
7636683132dSAlexander Motin  */
7646683132dSAlexander Motin static bool
amd_ntb_poll_link(struct amd_ntb_softc * ntb)7656683132dSAlexander Motin amd_ntb_poll_link(struct amd_ntb_softc *ntb)
7666683132dSAlexander Motin {
7676683132dSAlexander Motin 	uint32_t fullreg, reg, stat;
7686683132dSAlexander Motin 
7696683132dSAlexander Motin 	fullreg = amd_ntb_peer_reg_read(4, AMD_SIDEINFO_OFFSET);
7706683132dSAlexander Motin 	reg = fullreg & NTB_LIN_STA_ACTIVE_BIT;
7716683132dSAlexander Motin 
7726683132dSAlexander Motin 	if (reg == ntb->cntl_sta)
7736683132dSAlexander Motin 		return (false);
7746683132dSAlexander Motin 
7756683132dSAlexander Motin 	amd_ntb_printf(0, "%s: SIDEINFO reg_val = 0x%x cntl_sta 0x%x\n",
7766683132dSAlexander Motin 	    __func__, fullreg, ntb->cntl_sta);
7776683132dSAlexander Motin 
7786683132dSAlexander Motin 	ntb->cntl_sta = reg;
7796683132dSAlexander Motin 
7806683132dSAlexander Motin 	stat = pci_read_config(ntb->device, AMD_LINK_STATUS_OFFSET, 4);
7816683132dSAlexander Motin 
7826683132dSAlexander Motin 	amd_ntb_printf(0, "%s: LINK_STATUS stat = 0x%x lnk_sta 0x%x.\n",
7836683132dSAlexander Motin 	    __func__, stat, ntb->lnk_sta);
7846683132dSAlexander Motin 
7856683132dSAlexander Motin 	ntb->lnk_sta = stat;
7866683132dSAlexander Motin 
7876683132dSAlexander Motin 	return (true);
7886683132dSAlexander Motin }
7896683132dSAlexander Motin 
7906683132dSAlexander Motin static void
amd_link_hb(void * arg)7916683132dSAlexander Motin amd_link_hb(void *arg)
7926683132dSAlexander Motin {
7936683132dSAlexander Motin 	struct amd_ntb_softc *ntb = arg;
7946683132dSAlexander Motin 
7956683132dSAlexander Motin 	if (amd_ntb_poll_link(ntb))
7966683132dSAlexander Motin 		ntb_link_event(ntb->device);
7976683132dSAlexander Motin 
7986683132dSAlexander Motin 	if (!amd_link_is_up(ntb)) {
7996683132dSAlexander Motin 		callout_reset(&ntb->hb_timer, AMD_LINK_HB_TIMEOUT,
8006683132dSAlexander Motin 		    amd_link_hb, ntb);
8016683132dSAlexander Motin 	} else {
8026683132dSAlexander Motin 		callout_reset(&ntb->hb_timer, (AMD_LINK_HB_TIMEOUT * 10),
8036683132dSAlexander Motin 		    amd_link_hb, ntb);
8046683132dSAlexander Motin 	}
8056683132dSAlexander Motin }
8066683132dSAlexander Motin 
8076683132dSAlexander Motin static void
amd_ntb_interrupt(struct amd_ntb_softc * ntb,uint16_t vec)8086683132dSAlexander Motin amd_ntb_interrupt(struct amd_ntb_softc *ntb, uint16_t vec)
8096683132dSAlexander Motin {
810e67b1223SAlexander Motin 	if (vec < ntb->hw_info->db_count)
8116683132dSAlexander Motin 		ntb_db_event(ntb->device, vec);
8126683132dSAlexander Motin 	else
8136683132dSAlexander Motin 		amd_ntb_printf(0, "Invalid vector %d\n", vec);
8146683132dSAlexander Motin }
8156683132dSAlexander Motin 
8166683132dSAlexander Motin static void
amd_ntb_vec_isr(void * arg)8176683132dSAlexander Motin amd_ntb_vec_isr(void *arg)
8186683132dSAlexander Motin {
8196683132dSAlexander Motin 	struct amd_ntb_vec *nvec = arg;
8206683132dSAlexander Motin 
8216683132dSAlexander Motin 	amd_ntb_interrupt(nvec->ntb, nvec->num);
8226683132dSAlexander Motin }
8236683132dSAlexander Motin 
8246683132dSAlexander Motin static void
amd_ntb_irq_isr(void * arg)8256683132dSAlexander Motin amd_ntb_irq_isr(void *arg)
8266683132dSAlexander Motin {
8276683132dSAlexander Motin 	/* If we couldn't set up MSI-X, we only have the one vector. */
8286683132dSAlexander Motin 	amd_ntb_interrupt(arg, 0);
8296683132dSAlexander Motin }
8306683132dSAlexander Motin 
8316683132dSAlexander Motin static void
amd_init_side_info(struct amd_ntb_softc * ntb)8326683132dSAlexander Motin amd_init_side_info(struct amd_ntb_softc *ntb)
8336683132dSAlexander Motin {
8346683132dSAlexander Motin 	unsigned int reg;
8356683132dSAlexander Motin 
8366683132dSAlexander Motin 	reg = amd_ntb_reg_read(4, AMD_SIDEINFO_OFFSET);
8376683132dSAlexander Motin 	if (!(reg & AMD_SIDE_READY)) {
8386683132dSAlexander Motin 		reg |= AMD_SIDE_READY;
8396683132dSAlexander Motin 		amd_ntb_reg_write(4, AMD_SIDEINFO_OFFSET, reg);
8406683132dSAlexander Motin 	}
8416683132dSAlexander Motin 	reg = amd_ntb_reg_read(4, AMD_SIDEINFO_OFFSET);
8426683132dSAlexander Motin }
8436683132dSAlexander Motin 
8446683132dSAlexander Motin static void
amd_deinit_side_info(struct amd_ntb_softc * ntb)8456683132dSAlexander Motin amd_deinit_side_info(struct amd_ntb_softc *ntb)
8466683132dSAlexander Motin {
8476683132dSAlexander Motin 	unsigned int reg;
8486683132dSAlexander Motin 
8496683132dSAlexander Motin 	reg = amd_ntb_reg_read(4, AMD_SIDEINFO_OFFSET);
8506683132dSAlexander Motin 	if (reg & AMD_SIDE_READY) {
8516683132dSAlexander Motin 		reg &= ~AMD_SIDE_READY;
8526683132dSAlexander Motin 		amd_ntb_reg_write(4, AMD_SIDEINFO_OFFSET, reg);
8536683132dSAlexander Motin 		amd_ntb_reg_read(4, AMD_SIDEINFO_OFFSET);
8546683132dSAlexander Motin 	}
8556683132dSAlexander Motin }
8566683132dSAlexander Motin 
8576683132dSAlexander Motin static int
amd_ntb_setup_isr(struct amd_ntb_softc * ntb,uint16_t num_vectors,bool msi,bool intx)8586683132dSAlexander Motin amd_ntb_setup_isr(struct amd_ntb_softc *ntb, uint16_t num_vectors, bool msi,
8596683132dSAlexander Motin     bool intx)
8606683132dSAlexander Motin {
8616683132dSAlexander Motin 	uint16_t i;
8626683132dSAlexander Motin 	int flags = 0, rc = 0;
8636683132dSAlexander Motin 
8646683132dSAlexander Motin 	flags |= RF_ACTIVE;
8656683132dSAlexander Motin 	if (intx)
8666683132dSAlexander Motin 		flags |= RF_SHAREABLE;
8676683132dSAlexander Motin 
8686683132dSAlexander Motin 	for (i = 0; i < num_vectors; i++) {
8696683132dSAlexander Motin 		/* RID should be 0 for intx */
8706683132dSAlexander Motin 		if (intx)
8716683132dSAlexander Motin 			ntb->int_info[i].rid = i;
8726683132dSAlexander Motin 		else
8736683132dSAlexander Motin 			ntb->int_info[i].rid = i + 1;
8746683132dSAlexander Motin 
8756683132dSAlexander Motin 		ntb->int_info[i].res = bus_alloc_resource_any(ntb->device,
8766683132dSAlexander Motin 		    SYS_RES_IRQ, &ntb->int_info[i].rid, flags);
8776683132dSAlexander Motin 		if (ntb->int_info[i].res == NULL) {
8786683132dSAlexander Motin 			amd_ntb_printf(0, "bus_alloc_resource IRQ failed\n");
8796683132dSAlexander Motin 			return (ENOMEM);
8806683132dSAlexander Motin 		}
8816683132dSAlexander Motin 
8826683132dSAlexander Motin 		ntb->int_info[i].tag = NULL;
8836683132dSAlexander Motin 		ntb->allocated_interrupts++;
8846683132dSAlexander Motin 
8856683132dSAlexander Motin 		if (msi || intx) {
8866683132dSAlexander Motin 			rc = bus_setup_intr(ntb->device, ntb->int_info[i].res,
8876683132dSAlexander Motin 			    INTR_MPSAFE | INTR_TYPE_MISC, NULL, amd_ntb_irq_isr,
8886683132dSAlexander Motin 			    ntb, &ntb->int_info[i].tag);
8896683132dSAlexander Motin 		} else {
8906683132dSAlexander Motin 			rc = bus_setup_intr(ntb->device, ntb->int_info[i].res,
8916683132dSAlexander Motin 			    INTR_MPSAFE | INTR_TYPE_MISC, NULL, amd_ntb_vec_isr,
8926683132dSAlexander Motin 			    &ntb->msix_vec[i], &ntb->int_info[i].tag);
8936683132dSAlexander Motin 		}
8946683132dSAlexander Motin 
8956683132dSAlexander Motin 		if (rc != 0) {
8966683132dSAlexander Motin 			amd_ntb_printf(0, "bus_setup_intr %d failed\n", i);
8976683132dSAlexander Motin 			return (ENXIO);
8986683132dSAlexander Motin 		}
8996683132dSAlexander Motin 	}
9006683132dSAlexander Motin 
9016683132dSAlexander Motin 	return (0);
9026683132dSAlexander Motin }
9036683132dSAlexander Motin 
9046683132dSAlexander Motin static int
amd_ntb_create_msix_vec(struct amd_ntb_softc * ntb,uint32_t max_vectors)9056683132dSAlexander Motin amd_ntb_create_msix_vec(struct amd_ntb_softc *ntb, uint32_t max_vectors)
9066683132dSAlexander Motin {
9076683132dSAlexander Motin 	uint8_t i;
9086683132dSAlexander Motin 
9096683132dSAlexander Motin 	ntb->msix_vec = malloc(max_vectors * sizeof(*ntb->msix_vec), M_AMD_NTB,
9106683132dSAlexander Motin 	    M_ZERO | M_WAITOK);
9116683132dSAlexander Motin 
9126683132dSAlexander Motin 	for (i = 0; i < max_vectors; i++) {
9136683132dSAlexander Motin 		ntb->msix_vec[i].num = i;
9146683132dSAlexander Motin 		ntb->msix_vec[i].ntb = ntb;
9156683132dSAlexander Motin 	}
9166683132dSAlexander Motin 
9176683132dSAlexander Motin 	return (0);
9186683132dSAlexander Motin }
9196683132dSAlexander Motin 
9206683132dSAlexander Motin static void
amd_ntb_free_msix_vec(struct amd_ntb_softc * ntb)9216683132dSAlexander Motin amd_ntb_free_msix_vec(struct amd_ntb_softc *ntb)
9226683132dSAlexander Motin {
9236683132dSAlexander Motin 	if (ntb->msix_vec_count) {
9246683132dSAlexander Motin 		pci_release_msi(ntb->device);
9256683132dSAlexander Motin 		ntb->msix_vec_count = 0;
9266683132dSAlexander Motin 	}
9276683132dSAlexander Motin 
9286683132dSAlexander Motin 	if (ntb->msix_vec != NULL) {
9296683132dSAlexander Motin 		free(ntb->msix_vec, M_AMD_NTB);
9306683132dSAlexander Motin 		ntb->msix_vec = NULL;
9316683132dSAlexander Motin 	}
9326683132dSAlexander Motin }
9336683132dSAlexander Motin 
9346683132dSAlexander Motin static int
amd_ntb_init_isr(struct amd_ntb_softc * ntb)9356683132dSAlexander Motin amd_ntb_init_isr(struct amd_ntb_softc *ntb)
9366683132dSAlexander Motin {
9376683132dSAlexander Motin 	uint32_t supported_vectors, num_vectors;
9386683132dSAlexander Motin 	bool msi = false, intx = false;
9396683132dSAlexander Motin 	int rc = 0;
9406683132dSAlexander Motin 
9416683132dSAlexander Motin 	ntb->db_mask = ntb->db_valid_mask;
9426683132dSAlexander Motin 
943e67b1223SAlexander Motin 	rc = amd_ntb_create_msix_vec(ntb, ntb->hw_info->msix_vector_count);
9446683132dSAlexander Motin 	if (rc != 0) {
9456683132dSAlexander Motin 		amd_ntb_printf(0, "Error creating msix vectors: %d\n", rc);
9466683132dSAlexander Motin 		return (ENOMEM);
9476683132dSAlexander Motin 	}
9486683132dSAlexander Motin 
9496683132dSAlexander Motin 	/*
9506683132dSAlexander Motin 	 * Check the number of MSI-X message supported by the device.
951e67b1223SAlexander Motin 	 * Minimum necessary MSI-X message count should be equal to db_count.
9526683132dSAlexander Motin 	 */
9536683132dSAlexander Motin 	supported_vectors = pci_msix_count(ntb->device);
954e67b1223SAlexander Motin 	num_vectors = MIN(supported_vectors, ntb->hw_info->db_count);
955e67b1223SAlexander Motin 	if (num_vectors < ntb->hw_info->db_count) {
9566683132dSAlexander Motin 		amd_ntb_printf(0, "No minimum msix: supported %d db %d\n",
957e67b1223SAlexander Motin 		    supported_vectors, ntb->hw_info->db_count);
9586683132dSAlexander Motin 		msi = true;
9596683132dSAlexander Motin 		goto err_msix_enable;
9606683132dSAlexander Motin 	}
9616683132dSAlexander Motin 
9626683132dSAlexander Motin 	/* Allocate the necessary number of MSI-x messages */
9636683132dSAlexander Motin 	rc = pci_alloc_msix(ntb->device, &num_vectors);
9646683132dSAlexander Motin 	if (rc != 0) {
9656683132dSAlexander Motin 		amd_ntb_printf(0, "Error allocating msix vectors: %d\n", rc);
9666683132dSAlexander Motin 		msi = true;
9676683132dSAlexander Motin 		goto err_msix_enable;
9686683132dSAlexander Motin 	}
9696683132dSAlexander Motin 
970e67b1223SAlexander Motin 	if (num_vectors < ntb->hw_info->db_count) {
9716683132dSAlexander Motin 		amd_ntb_printf(0, "Allocated only %d MSI-X\n", num_vectors);
9726683132dSAlexander Motin 		msi = true;
9736683132dSAlexander Motin 		/*
974e67b1223SAlexander Motin 		 * Else set ntb->hw_info->db_count = ntb->msix_vec_count =
975e67b1223SAlexander Motin 		 * num_vectors, msi=false and dont release msi.
9766683132dSAlexander Motin 		 */
9776683132dSAlexander Motin 	}
9786683132dSAlexander Motin 
9796683132dSAlexander Motin err_msix_enable:
9806683132dSAlexander Motin 
9816683132dSAlexander Motin 	if (msi) {
9826683132dSAlexander Motin 		free(ntb->msix_vec, M_AMD_NTB);
9836683132dSAlexander Motin 		ntb->msix_vec = NULL;
9846683132dSAlexander Motin 		pci_release_msi(ntb->device);
9856683132dSAlexander Motin 		num_vectors = 1;
9866683132dSAlexander Motin 		rc = pci_alloc_msi(ntb->device, &num_vectors);
9876683132dSAlexander Motin 		if (rc != 0) {
9886683132dSAlexander Motin 			amd_ntb_printf(0, "Error allocating msix vectors: %d\n", rc);
9896683132dSAlexander Motin 			msi = false;
9906683132dSAlexander Motin 			intx = true;
9916683132dSAlexander Motin 		}
9926683132dSAlexander Motin 	}
9936683132dSAlexander Motin 
994e67b1223SAlexander Motin 	ntb->hw_info->db_count = ntb->msix_vec_count = num_vectors;
9956683132dSAlexander Motin 
9966683132dSAlexander Motin 	if (intx) {
9976683132dSAlexander Motin 		num_vectors = 1;
998e67b1223SAlexander Motin 		ntb->hw_info->db_count = 1;
9996683132dSAlexander Motin 		ntb->msix_vec_count = 0;
10006683132dSAlexander Motin 	}
10016683132dSAlexander Motin 
10026683132dSAlexander Motin 	amd_ntb_printf(0, "%s: db %d msix %d msi %d intx %d\n",
1003e67b1223SAlexander Motin 	    __func__, ntb->hw_info->db_count, ntb->msix_vec_count, (int)msi, (int)intx);
10046683132dSAlexander Motin 
10056683132dSAlexander Motin 	rc = amd_ntb_setup_isr(ntb, num_vectors, msi, intx);
10066683132dSAlexander Motin 	if (rc != 0) {
10076683132dSAlexander Motin 		amd_ntb_printf(0, "Error setting up isr: %d\n", rc);
10086683132dSAlexander Motin 		amd_ntb_free_msix_vec(ntb);
10096683132dSAlexander Motin 	}
10106683132dSAlexander Motin 
10116683132dSAlexander Motin 	return (rc);
10126683132dSAlexander Motin }
10136683132dSAlexander Motin 
10146683132dSAlexander Motin static void
amd_ntb_deinit_isr(struct amd_ntb_softc * ntb)10156683132dSAlexander Motin amd_ntb_deinit_isr(struct amd_ntb_softc *ntb)
10166683132dSAlexander Motin {
10176683132dSAlexander Motin 	struct amd_ntb_int_info *current_int;
10186683132dSAlexander Motin 	int i;
10196683132dSAlexander Motin 
10206683132dSAlexander Motin 	/* Mask all doorbell interrupts */
10216683132dSAlexander Motin 	ntb->db_mask = ntb->db_valid_mask;
10226683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_DBMASK_OFFSET, ntb->db_mask);
10236683132dSAlexander Motin 
10246683132dSAlexander Motin 	for (i = 0; i < ntb->allocated_interrupts; i++) {
10256683132dSAlexander Motin 		current_int = &ntb->int_info[i];
10266683132dSAlexander Motin 		if (current_int->tag != NULL)
10276683132dSAlexander Motin 			bus_teardown_intr(ntb->device, current_int->res,
10286683132dSAlexander Motin 			    current_int->tag);
10296683132dSAlexander Motin 
10306683132dSAlexander Motin 		if (current_int->res != NULL)
10316683132dSAlexander Motin 			bus_release_resource(ntb->device, SYS_RES_IRQ,
10326683132dSAlexander Motin 			    rman_get_rid(current_int->res), current_int->res);
10336683132dSAlexander Motin 	}
10346683132dSAlexander Motin 
10356683132dSAlexander Motin 	amd_ntb_free_msix_vec(ntb);
10366683132dSAlexander Motin }
10376683132dSAlexander Motin 
10386683132dSAlexander Motin static enum amd_ntb_conn_type
amd_ntb_get_topo(struct amd_ntb_softc * ntb)10396683132dSAlexander Motin amd_ntb_get_topo(struct amd_ntb_softc *ntb)
10406683132dSAlexander Motin {
10416683132dSAlexander Motin 	uint32_t info;
10426683132dSAlexander Motin 
10436683132dSAlexander Motin 	info = amd_ntb_reg_read(4, AMD_SIDEINFO_OFFSET);
10446683132dSAlexander Motin 
10456683132dSAlexander Motin 	if (info & AMD_SIDE_MASK)
10466683132dSAlexander Motin 		return (NTB_CONN_SEC);
10476683132dSAlexander Motin 
10486683132dSAlexander Motin 	return (NTB_CONN_PRI);
10496683132dSAlexander Motin }
10506683132dSAlexander Motin 
10516683132dSAlexander Motin static int
amd_ntb_init_dev(struct amd_ntb_softc * ntb)10526683132dSAlexander Motin amd_ntb_init_dev(struct amd_ntb_softc *ntb)
10536683132dSAlexander Motin {
1054e67b1223SAlexander Motin 	ntb->db_valid_mask	 = (1ull << ntb->hw_info->db_count) - 1;
10556683132dSAlexander Motin 	mtx_init(&ntb->db_mask_lock, "amd ntb db bits", NULL, MTX_SPIN);
10566683132dSAlexander Motin 
10576683132dSAlexander Motin 	switch (ntb->conn_type) {
10586683132dSAlexander Motin 	case NTB_CONN_PRI:
10596683132dSAlexander Motin 	case NTB_CONN_SEC:
10606683132dSAlexander Motin 		ntb->spad_count >>= 1;
10616683132dSAlexander Motin 
10626683132dSAlexander Motin 		if (ntb->conn_type == NTB_CONN_PRI) {
10636683132dSAlexander Motin 			ntb->self_spad = 0;
10646683132dSAlexander Motin 			ntb->peer_spad = 0x20;
10656683132dSAlexander Motin 		} else {
10666683132dSAlexander Motin 			ntb->self_spad = 0x20;
10676683132dSAlexander Motin 			ntb->peer_spad = 0;
10686683132dSAlexander Motin 		}
10696683132dSAlexander Motin 
10706683132dSAlexander Motin 		callout_init(&ntb->hb_timer, 1);
10716683132dSAlexander Motin 		callout_reset(&ntb->hb_timer, AMD_LINK_HB_TIMEOUT,
10726683132dSAlexander Motin 		    amd_link_hb, ntb);
10736683132dSAlexander Motin 
10746683132dSAlexander Motin 		break;
10756683132dSAlexander Motin 
10766683132dSAlexander Motin 	default:
10776683132dSAlexander Motin 		amd_ntb_printf(0, "Unsupported AMD NTB topology %d\n",
10786683132dSAlexander Motin 		    ntb->conn_type);
10796683132dSAlexander Motin 		return (EINVAL);
10806683132dSAlexander Motin 	}
10816683132dSAlexander Motin 
10826683132dSAlexander Motin 	ntb->int_mask = AMD_EVENT_INTMASK;
10836683132dSAlexander Motin 	amd_ntb_reg_write(4, AMD_INTMASK_OFFSET, ntb->int_mask);
10846683132dSAlexander Motin 
10856683132dSAlexander Motin 	return (0);
10866683132dSAlexander Motin }
10876683132dSAlexander Motin 
10886683132dSAlexander Motin static int
amd_ntb_init(struct amd_ntb_softc * ntb)10896683132dSAlexander Motin amd_ntb_init(struct amd_ntb_softc *ntb)
10906683132dSAlexander Motin {
10916683132dSAlexander Motin 	int rc = 0;
10926683132dSAlexander Motin 
10936683132dSAlexander Motin 	ntb->conn_type = amd_ntb_get_topo(ntb);
10946683132dSAlexander Motin 	amd_ntb_printf(0, "AMD NTB Side: %s\n",
10956683132dSAlexander Motin 	    (ntb->conn_type == NTB_CONN_PRI)? "PRIMARY" : "SECONDARY");
10966683132dSAlexander Motin 
10976683132dSAlexander Motin 	rc = amd_ntb_init_dev(ntb);
10986683132dSAlexander Motin 	if (rc != 0)
10996683132dSAlexander Motin 		return (rc);
11006683132dSAlexander Motin 
11016683132dSAlexander Motin 	rc = amd_ntb_init_isr(ntb);
11026683132dSAlexander Motin 	if (rc != 0)
11036683132dSAlexander Motin 		return (rc);
11046683132dSAlexander Motin 
11056683132dSAlexander Motin 	return (0);
11066683132dSAlexander Motin }
11076683132dSAlexander Motin 
11086683132dSAlexander Motin static void
print_map_success(struct amd_ntb_softc * ntb,struct amd_ntb_pci_bar_info * bar,const char * kind)11096683132dSAlexander Motin print_map_success(struct amd_ntb_softc *ntb, struct amd_ntb_pci_bar_info *bar,
11106683132dSAlexander Motin     const char *kind)
11116683132dSAlexander Motin {
1112*124e4673SJohn Baldwin 	amd_ntb_printf(0, "Mapped BAR%d v:[%p-%p] p:[0x%jx-0x%jx] (0x%jx bytes) (%s)\n",
11136683132dSAlexander Motin 	    PCI_RID2BAR(bar->pci_resource_id), bar->vbase,
1114*124e4673SJohn Baldwin 	    (char *)bar->vbase + bar->size - 1, (uintmax_t)bar->pbase,
1115*124e4673SJohn Baldwin 	    (uintmax_t)(bar->pbase + bar->size - 1), (uintmax_t)bar->size, kind);
11166683132dSAlexander Motin }
11176683132dSAlexander Motin 
11186683132dSAlexander Motin static void
save_bar_parameters(struct amd_ntb_pci_bar_info * bar)11196683132dSAlexander Motin save_bar_parameters(struct amd_ntb_pci_bar_info *bar)
11206683132dSAlexander Motin {
11216683132dSAlexander Motin 	bar->pci_bus_tag = rman_get_bustag(bar->pci_resource);
11226683132dSAlexander Motin 	bar->pci_bus_handle = rman_get_bushandle(bar->pci_resource);
11236683132dSAlexander Motin 	bar->pbase = rman_get_start(bar->pci_resource);
11246683132dSAlexander Motin 	bar->size = rman_get_size(bar->pci_resource);
11256683132dSAlexander Motin 	bar->vbase = rman_get_virtual(bar->pci_resource);
11266683132dSAlexander Motin 	bar->map_mode = VM_MEMATTR_UNCACHEABLE;
11276683132dSAlexander Motin }
11286683132dSAlexander Motin 
11296683132dSAlexander Motin static int
map_bar(struct amd_ntb_softc * ntb,struct amd_ntb_pci_bar_info * bar)11306683132dSAlexander Motin map_bar(struct amd_ntb_softc *ntb, struct amd_ntb_pci_bar_info *bar)
11316683132dSAlexander Motin {
11326683132dSAlexander Motin 	bar->pci_resource = bus_alloc_resource_any(ntb->device, SYS_RES_MEMORY,
11336683132dSAlexander Motin 	    &bar->pci_resource_id, RF_ACTIVE);
11346683132dSAlexander Motin 	if (bar->pci_resource == NULL)
11356683132dSAlexander Motin 		return (ENXIO);
11366683132dSAlexander Motin 
11376683132dSAlexander Motin 	save_bar_parameters(bar);
11386683132dSAlexander Motin 	print_map_success(ntb, bar, "mmr");
11396683132dSAlexander Motin 
11406683132dSAlexander Motin 	return (0);
11416683132dSAlexander Motin }
11426683132dSAlexander Motin 
11436683132dSAlexander Motin static int
amd_ntb_map_pci_bars(struct amd_ntb_softc * ntb)11446683132dSAlexander Motin amd_ntb_map_pci_bars(struct amd_ntb_softc *ntb)
11456683132dSAlexander Motin {
11466683132dSAlexander Motin 	int rc = 0;
11476683132dSAlexander Motin 
11486683132dSAlexander Motin 	/* NTB Config/Control registers - BAR 0 */
11496683132dSAlexander Motin 	ntb->bar_info[NTB_CONFIG_BAR].pci_resource_id = PCIR_BAR(0);
11506683132dSAlexander Motin 	rc = map_bar(ntb, &ntb->bar_info[NTB_CONFIG_BAR]);
11516683132dSAlexander Motin 	if (rc != 0)
11526683132dSAlexander Motin 		goto out;
11536683132dSAlexander Motin 
11546683132dSAlexander Motin 	/* Memory Window 0 BAR - BAR 1 */
11556683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_1].pci_resource_id = PCIR_BAR(1);
11566683132dSAlexander Motin 	rc = map_bar(ntb, &ntb->bar_info[NTB_BAR_1]);
11576683132dSAlexander Motin 	if (rc != 0)
11586683132dSAlexander Motin 		goto out;
11596683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_1].xlat_off = AMD_BAR1XLAT_OFFSET;
11606683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_1].limit_off = AMD_BAR1LMT_OFFSET;
11616683132dSAlexander Motin 
11626683132dSAlexander Motin 	/* Memory Window 1 BAR - BAR 2&3 */
11636683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_2].pci_resource_id = PCIR_BAR(2);
11646683132dSAlexander Motin 	rc = map_bar(ntb, &ntb->bar_info[NTB_BAR_2]);
11656683132dSAlexander Motin 	if (rc != 0)
11666683132dSAlexander Motin 		goto out;
11676683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_2].xlat_off = AMD_BAR23XLAT_OFFSET;
11686683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_2].limit_off = AMD_BAR23LMT_OFFSET;
11696683132dSAlexander Motin 
11706683132dSAlexander Motin 	/* Memory Window 2 BAR - BAR 4&5 */
11716683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_3].pci_resource_id = PCIR_BAR(4);
11726683132dSAlexander Motin 	rc = map_bar(ntb, &ntb->bar_info[NTB_BAR_3]);
11736683132dSAlexander Motin 	if (rc != 0)
11746683132dSAlexander Motin 		goto out;
11756683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_3].xlat_off = AMD_BAR45XLAT_OFFSET;
11766683132dSAlexander Motin 	ntb->bar_info[NTB_BAR_3].limit_off = AMD_BAR45LMT_OFFSET;
11776683132dSAlexander Motin 
11786683132dSAlexander Motin out:
11796683132dSAlexander Motin 	if (rc != 0)
11806683132dSAlexander Motin 		amd_ntb_printf(0, "unable to allocate pci resource\n");
11816683132dSAlexander Motin 
11826683132dSAlexander Motin 	return (rc);
11836683132dSAlexander Motin }
11846683132dSAlexander Motin 
11856683132dSAlexander Motin static void
amd_ntb_unmap_pci_bars(struct amd_ntb_softc * ntb)11866683132dSAlexander Motin amd_ntb_unmap_pci_bars(struct amd_ntb_softc *ntb)
11876683132dSAlexander Motin {
11886683132dSAlexander Motin 	struct amd_ntb_pci_bar_info *bar_info;
11896683132dSAlexander Motin 	int i;
11906683132dSAlexander Motin 
11916683132dSAlexander Motin 	for (i = 0; i < NTB_MAX_BARS; i++) {
11926683132dSAlexander Motin 		bar_info = &ntb->bar_info[i];
11936683132dSAlexander Motin 		if (bar_info->pci_resource != NULL)
11946683132dSAlexander Motin 			bus_release_resource(ntb->device, SYS_RES_MEMORY,
11956683132dSAlexander Motin 			    bar_info->pci_resource_id, bar_info->pci_resource);
11966683132dSAlexander Motin 	}
11976683132dSAlexander Motin }
11986683132dSAlexander Motin 
11996683132dSAlexander Motin static int
amd_ntb_probe(device_t device)12006683132dSAlexander Motin amd_ntb_probe(device_t device)
12016683132dSAlexander Motin {
1202e67b1223SAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(device);
12036683132dSAlexander Motin 	const struct pci_device_table *tbl;
12046683132dSAlexander Motin 
12056683132dSAlexander Motin 	tbl = PCI_MATCH(device, amd_ntb_devs);
12066683132dSAlexander Motin 	if (tbl == NULL)
12076683132dSAlexander Motin 		return (ENXIO);
12086683132dSAlexander Motin 
1209e67b1223SAlexander Motin 	ntb->hw_info = (struct amd_ntb_hw_info *)tbl->driver_data;
1210e67b1223SAlexander Motin 	ntb->spad_count = ntb->hw_info->spad_count;
12116683132dSAlexander Motin 	device_set_desc(device, tbl->descr);
12126683132dSAlexander Motin 
12136683132dSAlexander Motin 	return (BUS_PROBE_GENERIC);
12146683132dSAlexander Motin }
12156683132dSAlexander Motin 
12166683132dSAlexander Motin static int
amd_ntb_attach(device_t device)12176683132dSAlexander Motin amd_ntb_attach(device_t device)
12186683132dSAlexander Motin {
12196683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(device);
12206683132dSAlexander Motin 	int error;
12216683132dSAlexander Motin 
12226683132dSAlexander Motin 	ntb->device = device;
12236683132dSAlexander Motin 
12246683132dSAlexander Motin 	/* Enable PCI bus mastering for "device" */
12256683132dSAlexander Motin 	pci_enable_busmaster(ntb->device);
12266683132dSAlexander Motin 
12276683132dSAlexander Motin 	error = amd_ntb_map_pci_bars(ntb);
12286683132dSAlexander Motin 	if (error)
12296683132dSAlexander Motin 		goto out;
12306683132dSAlexander Motin 
12316683132dSAlexander Motin 	error = amd_ntb_init(ntb);
12326683132dSAlexander Motin 	if (error)
12336683132dSAlexander Motin 		goto out;
12346683132dSAlexander Motin 
12356683132dSAlexander Motin 	amd_init_side_info(ntb);
12366683132dSAlexander Motin 
12376683132dSAlexander Motin 	amd_ntb_spad_clear(ntb);
12386683132dSAlexander Motin 
12396683132dSAlexander Motin 	amd_ntb_sysctl_init(ntb);
12406683132dSAlexander Motin 
12416683132dSAlexander Motin 	/* Attach children to this controller */
12426683132dSAlexander Motin 	error = ntb_register_device(device);
12436683132dSAlexander Motin 
12446683132dSAlexander Motin out:
12456683132dSAlexander Motin 	if (error)
12466683132dSAlexander Motin 		amd_ntb_detach(device);
12476683132dSAlexander Motin 
12486683132dSAlexander Motin 	return (error);
12496683132dSAlexander Motin }
12506683132dSAlexander Motin 
12516683132dSAlexander Motin static int
amd_ntb_detach(device_t device)12526683132dSAlexander Motin amd_ntb_detach(device_t device)
12536683132dSAlexander Motin {
12546683132dSAlexander Motin 	struct amd_ntb_softc *ntb = device_get_softc(device);
12556683132dSAlexander Motin 
12566683132dSAlexander Motin 	ntb_unregister_device(device);
12576683132dSAlexander Motin 	amd_deinit_side_info(ntb);
12586683132dSAlexander Motin 	callout_drain(&ntb->hb_timer);
12596683132dSAlexander Motin 	amd_ntb_deinit_isr(ntb);
12606683132dSAlexander Motin 	mtx_destroy(&ntb->db_mask_lock);
12616683132dSAlexander Motin 	pci_disable_busmaster(ntb->device);
12626683132dSAlexander Motin 	amd_ntb_unmap_pci_bars(ntb);
12636683132dSAlexander Motin 
12646683132dSAlexander Motin 	return (0);
12656683132dSAlexander Motin }
12666683132dSAlexander Motin 
12676683132dSAlexander Motin static device_method_t ntb_amd_methods[] = {
12686683132dSAlexander Motin 	/* Device interface */
12696683132dSAlexander Motin 	DEVMETHOD(device_probe,		amd_ntb_probe),
12706683132dSAlexander Motin 	DEVMETHOD(device_attach,	amd_ntb_attach),
12716683132dSAlexander Motin 	DEVMETHOD(device_detach,	amd_ntb_detach),
12726683132dSAlexander Motin 
12736683132dSAlexander Motin 	/* Bus interface */
1274ddfc9c4cSWarner Losh 	DEVMETHOD(bus_child_location,	ntb_child_location),
12756683132dSAlexander Motin 	DEVMETHOD(bus_print_child,	ntb_print_child),
12767f215e07SAlexander Motin 	DEVMETHOD(bus_get_dma_tag,	ntb_get_dma_tag),
12776683132dSAlexander Motin 
12786683132dSAlexander Motin 	/* NTB interface */
12796683132dSAlexander Motin 	DEVMETHOD(ntb_port_number,	amd_ntb_port_number),
12806683132dSAlexander Motin 	DEVMETHOD(ntb_peer_port_count,	amd_ntb_peer_port_count),
12816683132dSAlexander Motin 	DEVMETHOD(ntb_peer_port_number,	amd_ntb_peer_port_number),
12826683132dSAlexander Motin 	DEVMETHOD(ntb_peer_port_idx, 	amd_ntb_peer_port_idx),
12836683132dSAlexander Motin 	DEVMETHOD(ntb_link_is_up,	amd_ntb_link_is_up),
12846683132dSAlexander Motin 	DEVMETHOD(ntb_link_enable,	amd_ntb_link_enable),
12856683132dSAlexander Motin 	DEVMETHOD(ntb_link_disable,	amd_ntb_link_disable),
12866683132dSAlexander Motin 	DEVMETHOD(ntb_mw_count,		amd_ntb_mw_count),
12876683132dSAlexander Motin 	DEVMETHOD(ntb_mw_get_range,	amd_ntb_mw_get_range),
12886683132dSAlexander Motin 	DEVMETHOD(ntb_mw_set_trans,	amd_ntb_mw_set_trans),
12896683132dSAlexander Motin 	DEVMETHOD(ntb_mw_clear_trans,	amd_ntb_mw_clear_trans),
12906683132dSAlexander Motin 	DEVMETHOD(ntb_mw_set_wc,	amd_ntb_mw_set_wc),
12916683132dSAlexander Motin 	DEVMETHOD(ntb_mw_get_wc,	amd_ntb_mw_get_wc),
12926683132dSAlexander Motin 	DEVMETHOD(ntb_db_valid_mask,	amd_ntb_db_valid_mask),
12936683132dSAlexander Motin 	DEVMETHOD(ntb_db_vector_count,	amd_ntb_db_vector_count),
12946683132dSAlexander Motin 	DEVMETHOD(ntb_db_vector_mask,	amd_ntb_db_vector_mask),
12956683132dSAlexander Motin 	DEVMETHOD(ntb_db_read,		amd_ntb_db_read),
12966683132dSAlexander Motin 	DEVMETHOD(ntb_db_clear,		amd_ntb_db_clear),
12976683132dSAlexander Motin 	DEVMETHOD(ntb_db_set_mask,	amd_ntb_db_set_mask),
12986683132dSAlexander Motin 	DEVMETHOD(ntb_db_clear_mask,	amd_ntb_db_clear_mask),
12996683132dSAlexander Motin 	DEVMETHOD(ntb_peer_db_set,	amd_ntb_peer_db_set),
13006683132dSAlexander Motin 	DEVMETHOD(ntb_spad_count,	amd_ntb_spad_count),
13016683132dSAlexander Motin 	DEVMETHOD(ntb_spad_read,	amd_ntb_spad_read),
13026683132dSAlexander Motin 	DEVMETHOD(ntb_spad_write,	amd_ntb_spad_write),
13036683132dSAlexander Motin 	DEVMETHOD(ntb_peer_spad_read,	amd_ntb_peer_spad_read),
13046683132dSAlexander Motin 	DEVMETHOD(ntb_peer_spad_write,	amd_ntb_peer_spad_write),
13056683132dSAlexander Motin 	DEVMETHOD_END
13066683132dSAlexander Motin };
13076683132dSAlexander Motin 
13086683132dSAlexander Motin static DEFINE_CLASS_0(ntb_hw, ntb_amd_driver, ntb_amd_methods,
13096683132dSAlexander Motin     sizeof(struct amd_ntb_softc));
13109940f7a7SJohn Baldwin DRIVER_MODULE(ntb_hw_amd, pci, ntb_amd_driver, NULL, NULL);
13116683132dSAlexander Motin MODULE_DEPEND(ntb_hw_amd, ntb, 1, 1, 1);
13126683132dSAlexander Motin MODULE_VERSION(ntb_hw_amd, 1);
13136683132dSAlexander Motin PCI_PNP_INFO(amd_ntb_devs);
1314