xref: /openbsd-src/sys/dev/pci/ccp_pci.c (revision 820d5ee45796e6ae149ce2b9530670d2f363a3eb)
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 
33 int	ccp_pci_match(struct device *, void *, void *);
34 void	ccp_pci_attach(struct device *, struct device *, void *);
35 
36 #ifdef __amd64__
37 void	psp_pci_attach(struct device *, struct device *, void *);
38 int	psp_pci_intr(void *);
39 #endif
40 
41 const struct cfattach ccp_pci_ca = {
42 	sizeof(struct ccp_softc),
43 	ccp_pci_match,
44 	ccp_pci_attach,
45 };
46 
47 static 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 
57 int
58 ccp_pci_match(struct device *parent, void *match, void *aux)
59 {
60 	return (pci_matchbyid(aux, ccp_pci_devices, nitems(ccp_pci_devices)));
61 }
62 
63 void
64 ccp_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__
90 void
91 psp_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 
129 int
130 psp_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