1/*	$OpenBSD: ccp_pci.c,v 1.11 2024/06/13 17:59:08 bluhm Exp $ */
2
3/*
4 * Copyright (c) 2018 David Gwynne <dlg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/systm.h>
21#include <sys/device.h>
22#include <sys/timeout.h>
23
24#include <machine/bus.h>
25
26#include <dev/pci/pcidevs.h>
27#include <dev/pci/pcivar.h>
28
29#include <dev/ic/ccpvar.h>
30
31#define CCP_PCI_BAR	0x18
32
33int	ccp_pci_match(struct device *, void *, void *);
34void	ccp_pci_attach(struct device *, struct device *, void *);
35
36#ifdef __amd64__
37void	psp_pci_attach(struct device *, struct device *, void *);
38int	psp_pci_intr(void *);
39#endif
40
41const struct cfattach ccp_pci_ca = {
42	sizeof(struct ccp_softc),
43	ccp_pci_match,
44	ccp_pci_attach,
45};
46
47static const struct pci_matchid ccp_pci_devices[] = {
48	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_16_CCP },
49	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_17_CCP_1 },
50	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_17_CCP_2 },
51	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_17_1X_CCP },
52	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_17_3X_CCP },
53	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_17_90_CCP },
54	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_19_1X_PSP },
55};
56
57int
58ccp_pci_match(struct device *parent, void *match, void *aux)
59{
60	return (pci_matchbyid(aux, ccp_pci_devices, nitems(ccp_pci_devices)));
61}
62
63void
64ccp_pci_attach(struct device *parent, struct device *self, void *aux)
65{
66	struct ccp_softc *sc = (struct ccp_softc *)self;
67	struct pci_attach_args *pa = aux;
68	pcireg_t memtype;
69
70	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, CCP_PCI_BAR);
71	if (PCI_MAPREG_TYPE(memtype) != PCI_MAPREG_TYPE_MEM) {
72		printf(": wrong memory type\n");
73		return;
74	}
75
76	if (pci_mapreg_map(pa, CCP_PCI_BAR, memtype, 0,
77	    &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0) != 0) {
78		printf(": cannot map registers\n");
79		return;
80	}
81
82#ifdef __amd64__
83	psp_pci_attach(parent, self, aux);
84#endif
85
86	ccp_attach(sc);
87}
88
89#ifdef __amd64__
90void
91psp_pci_attach(struct device *parent, struct device *self, void *aux)
92{
93	struct ccp_softc *sc = (struct ccp_softc *)self;
94	struct pci_attach_args *pa = aux;
95	pci_intr_handle_t ih;
96	const char *intrstr = NULL;
97
98	sc->sc_dmat = pa->pa_dmat;
99
100	sc->sc_capabilities = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
101	    PSP_REG_CAPABILITIES);
102
103	/* clear and disable interrupts */
104	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, 0);
105	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, -1);
106
107	if (pci_intr_map_msix(pa, 0, &ih) != 0 &&
108	    pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
109		printf(": couldn't map interrupt\n");
110		return;
111	}
112
113	intrstr = pci_intr_string(pa->pa_pc, ih);
114	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, psp_pci_intr,
115	    sc, sc->sc_dev.dv_xname);
116	if (sc->sc_ih != NULL)
117		printf(": %s", intrstr);
118
119	if (!psp_attach(sc)) {
120		pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
121		sc->sc_ih = NULL;
122		return;
123	}
124
125	/* enable interrupts */
126	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, -1);
127}
128
129int
130psp_pci_intr(void *arg)
131{
132	struct ccp_softc *sc = arg;
133	uint32_t status;
134
135	status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS);
136	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, status);
137
138	if (sc->sc_sev_intr)
139		return (sc->sc_sev_intr(sc, status));
140
141	return (1);
142}
143#endif	/* __amd64__ */
144