acpipci.c revision 1.3
133965Sjdp/*	$OpenBSD: acpipci.c,v 1.3 2018/07/28 13:59:08 kettenis Exp $	*/
278828Sobrien/*
3218822Sdim * Copyright (c) 2018 Mark Kettenis
433965Sjdp *
533965Sjdp * Permission to use, copy, modify, and distribute this software for any
633965Sjdp * purpose with or without fee is hereby granted, provided that the above
733965Sjdp * copyright notice and this permission notice appear in all copies.
833965Sjdp *
933965Sjdp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1033965Sjdp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1133965Sjdp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1233965Sjdp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1333965Sjdp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1433965Sjdp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1533965Sjdp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1633965Sjdp */
1733965Sjdp
1833965Sjdp#include <sys/param.h>
19218822Sdim#include <sys/device.h>
20218822Sdim#include <sys/extent.h>
2133965Sjdp#include <sys/malloc.h>
2233965Sjdp#include <sys/systm.h>
2333965Sjdp
2433965Sjdp#include <machine/bus.h>
2533965Sjdp
2633965Sjdp#include <dev/acpi/acpireg.h>
2733965Sjdp#include <dev/acpi/acpivar.h>
2877298Sobrien#include <dev/acpi/acpidev.h>
2933965Sjdp#include <dev/acpi/amltypes.h>
3033965Sjdp#include <dev/acpi/dsdt.h>
3133965Sjdp
3277298Sobrien#include <dev/pci/pcidevs.h>
3377298Sobrien#include <dev/pci/pcireg.h>
3477298Sobrien#include <dev/pci/pcivar.h>
3577298Sobrien#include <dev/pci/ppbreg.h>
3677298Sobrien
37130561Sobrienbus_addr_t pci_mcfg_addr;
38130561Sobrienint pci_mcfg_min_bus, pci_mcfg_max_bus;
3933965Sjdpbus_space_tag_t pci_mcfgt;
4033965Sjdpbus_space_handle_t pci_mcfgh;
4133965Sjdp
4233965Sjdpstruct acpipci_trans {
4333965Sjdp	struct acpipci_trans *at_next;
4433965Sjdp	bus_space_tag_t	at_iot;
4533965Sjdp	bus_addr_t	at_base;
4633965Sjdp	bus_size_t	at_size;
4733965Sjdp	bus_size_t	at_offset;
4833965Sjdp};
4960484Sobrien
5060484Sobrienstruct acpipci_softc {
5160484Sobrien	struct device	sc_dev;
5260484Sobrien	struct acpi_softc *sc_acpi;
5360484Sobrien	struct aml_node *sc_node;
5460484Sobrien
5560484Sobrien	bus_space_tag_t	sc_iot;
5660484Sobrien	bus_space_handle_t sc_ioh;
5760484Sobrien
5833965Sjdp	struct bus_space sc_bus_iot;
5933965Sjdp	struct bus_space sc_bus_memt;
6033965Sjdp	struct acpipci_trans *sc_io_trans;
6133965Sjdp	struct acpipci_trans *sc_mem_trans;
6233965Sjdp
6333965Sjdp	struct arm64_pci_chipset sc_pc;
6433965Sjdp	struct extent	*sc_busex;
6533965Sjdp	struct extent	*sc_memex;
6633965Sjdp	struct extent	*sc_ioex;
6733965Sjdp	char		sc_busex_name[32];
6833965Sjdp	char		sc_ioex_name[32];
6933965Sjdp	char		sc_memex_name[32];
7033965Sjdp	int		sc_bus;
7133965Sjdp};
7233965Sjdp
7333965Sjdpint	acpipci_match(struct device *, void *, void *);
7433965Sjdpvoid	acpipci_attach(struct device *, struct device *, void *);
7533965Sjdp
7633965Sjdpstruct cfattach acpipci_ca = {
7733965Sjdp	sizeof(struct acpipci_softc), acpipci_match, acpipci_attach
7833965Sjdp};
7933965Sjdp
8033965Sjdpstruct cfdriver acpipci_cd = {
8133965Sjdp	NULL, "acpipci", DV_DULL
8233965Sjdp};
83130561Sobrien
8433965Sjdpconst char *acpipci_hids[] = {
8533965Sjdp	"PNP0A08",
8633965Sjdp	NULL
8738889Sjdp};
8838889Sjdp
8938889Sjdpint	acpipci_parse_resources(int, union acpi_resource *, void *);
9038889Sjdpint	acpipci_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
9133965Sjdp	    bus_space_handle_t *);
9233965Sjdp
9333965Sjdpvoid	acpipci_attach_hook(struct device *, struct device *,
9433965Sjdp	    struct pcibus_attach_args *);
9533965Sjdpint	acpipci_bus_maxdevs(void *, int);
9633965Sjdppcitag_t acpipci_make_tag(void *, int, int, int);
9738889Sjdpvoid	acpipci_decompose_tag(void *, pcitag_t, int *, int *, int *);
9838889Sjdpint	acpipci_conf_size(void *, pcitag_t);
9933965Sjdppcireg_t acpipci_conf_read(void *, pcitag_t, int);
10038889Sjdpvoid	acpipci_conf_write(void *, pcitag_t, int, pcireg_t);
10138889Sjdp
10233965Sjdpint	acpipci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
10338889Sjdpint	acpipci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *);
10438889Sjdpint	acpipci_intr_map_msix(struct pci_attach_args *, int,
10538889Sjdp	    pci_intr_handle_t *);
10638889Sjdpconst char *acpipci_intr_string(void *, pci_intr_handle_t);
10738889Sjdpvoid	*acpipci_intr_establish(void *, pci_intr_handle_t, int,
10838889Sjdp	    int (*)(void *), void *, char *);
10938889Sjdpvoid	acpipci_intr_disestablish(void *, void *);
11038889Sjdp
11138889Sjdpint
11238889Sjdpacpipci_match(struct device *parent, void *match, void *aux)
11338889Sjdp{
11433965Sjdp	struct acpi_attach_args *aaa = aux;
11538889Sjdp	struct cfdata *cf = match;
11677298Sobrien
11733965Sjdp	return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name);
11833965Sjdp}
11933965Sjdp
12033965Sjdpvoid
12133965Sjdpacpipci_attach(struct device *parent, struct device *self, void *aux)
12238889Sjdp{
12338889Sjdp	struct acpi_attach_args *aaa = aux;
12433965Sjdp	struct acpipci_softc *sc = (struct acpipci_softc *)self;
12538889Sjdp	struct pcibus_attach_args pba;
12638889Sjdp	struct aml_value res;
12733965Sjdp	uint64_t bbn = 0;
12833965Sjdp
12933965Sjdp	/* Bail out early if we don't have a valid MCFG table. */
13033965Sjdp	if (pci_mcfg_addr == 0 || pci_mcfg_max_bus <= pci_mcfg_min_bus) {
13133965Sjdp		printf(": no registers\n");
13233965Sjdp		return;
13333965Sjdp	}
13433965Sjdp
13577298Sobrien	sc->sc_acpi = (struct acpi_softc *)parent;
13677298Sobrien	sc->sc_node = aaa->aaa_node;
13733965Sjdp	printf(" %s", sc->sc_node->name);
13833965Sjdp
13933965Sjdp	if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) {
14033965Sjdp		printf(": can't find resources\n");
14133965Sjdp		return;
14233965Sjdp	}
14333965Sjdp
14433965Sjdp	aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn);
14533965Sjdp	sc->sc_bus = bbn;
14633965Sjdp
14733965Sjdp	sc->sc_iot = pci_mcfgt;
14833965Sjdp	sc->sc_ioh = pci_mcfgh;
14933965Sjdp
15033965Sjdp	printf("\n");
151218822Sdim
15233965Sjdp	/* Create extents for our address spaces. */
15333965Sjdp	snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name),
15433965Sjdp	    "%s pcibus", sc->sc_dev.dv_xname);
15533965Sjdp	snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name),
15633965Sjdp	    "%s pciio", sc->sc_dev.dv_xname);
15733965Sjdp	snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name),
15833965Sjdp	    "%s pcimem", sc->sc_dev.dv_xname);
15933965Sjdp	sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255,
16033965Sjdp	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
16160484Sobrien	sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff,
16233965Sjdp	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
16333965Sjdp	sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1,
16433965Sjdp	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
16533965Sjdp
16633965Sjdp	aml_parse_resource(&res, acpipci_parse_resources, sc);
16733965Sjdp
16833965Sjdp	memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot));
16933965Sjdp	sc->sc_bus_iot.bus_private = sc->sc_io_trans;
17033965Sjdp	sc->sc_bus_iot._space_map = acpipci_bs_map;
17133965Sjdp	memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt));
17233965Sjdp	sc->sc_bus_memt.bus_private = sc->sc_mem_trans;
17333965Sjdp	sc->sc_bus_memt._space_map = acpipci_bs_map;
17477298Sobrien
17533965Sjdp	sc->sc_pc.pc_conf_v = sc;
17677298Sobrien	sc->sc_pc.pc_attach_hook = acpipci_attach_hook;
177130561Sobrien	sc->sc_pc.pc_bus_maxdevs = acpipci_bus_maxdevs;
17833965Sjdp	sc->sc_pc.pc_make_tag = acpipci_make_tag;
17933965Sjdp	sc->sc_pc.pc_decompose_tag = acpipci_decompose_tag;
18078828Sobrien	sc->sc_pc.pc_conf_size = acpipci_conf_size;
18133965Sjdp	sc->sc_pc.pc_conf_read = acpipci_conf_read;
18233965Sjdp	sc->sc_pc.pc_conf_write = acpipci_conf_write;
18333965Sjdp
18433965Sjdp	sc->sc_pc.pc_intr_v = sc;
18533965Sjdp	sc->sc_pc.pc_intr_map = acpipci_intr_map;
18633965Sjdp	sc->sc_pc.pc_intr_map_msi = acpipci_intr_map_msi;
18733965Sjdp	sc->sc_pc.pc_intr_map_msix = acpipci_intr_map_msix;
18833965Sjdp	sc->sc_pc.pc_intr_string = acpipci_intr_string;
18933965Sjdp	sc->sc_pc.pc_intr_establish = acpipci_intr_establish;
19033965Sjdp	sc->sc_pc.pc_intr_disestablish = acpipci_intr_disestablish;
19133965Sjdp
19233965Sjdp	memset(&pba, 0, sizeof(pba));
19333965Sjdp	pba.pba_busname = "pci";
19478828Sobrien	pba.pba_iot = &sc->sc_bus_iot;
19578828Sobrien	pba.pba_memt = &sc->sc_bus_memt;
19678828Sobrien	pba.pba_dmat = aaa->aaa_dmat;
19778828Sobrien	pba.pba_pc = &sc->sc_pc;
19833965Sjdp	pba.pba_busex = sc->sc_busex;
19933965Sjdp	pba.pba_ioex = sc->sc_ioex;
20033965Sjdp	pba.pba_memex = sc->sc_memex;
20133965Sjdp	pba.pba_domain = pci_ndomains++;
20233965Sjdp	pba.pba_bus = sc->sc_bus;
20378828Sobrien	pba.pba_flags |= PCI_FLAGS_MSI_ENABLED;
20478828Sobrien
20578828Sobrien	config_found(self, &pba, NULL);
20678828Sobrien}
20733965Sjdp
20833965Sjdpint
20933965Sjdpacpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
21033965Sjdp{
21133965Sjdp	struct acpipci_softc *sc = arg;
21289857Sobrien	struct acpipci_trans *at;
21333965Sjdp	int type = AML_CRSTYPE(crs);
21433965Sjdp	int restype, tflags;
21533965Sjdp	u_long min, len = 0, tra;
21633965Sjdp
21733965Sjdp	switch (type) {
21833965Sjdp	case LR_WORD:
21933965Sjdp		restype = crs->lr_word.type;
22089857Sobrien		tflags = crs->lr_word.tflags;
22133965Sjdp		min = crs->lr_word._min;
22233965Sjdp		len = crs->lr_word._len;
22333965Sjdp		tra = crs->lr_word._tra;
22433965Sjdp		break;
22533965Sjdp	case LR_DWORD:
22633965Sjdp		restype = crs->lr_dword.type;
22733965Sjdp		tflags = crs->lr_dword.tflags;
22889857Sobrien		min = crs->lr_dword._min;
22933965Sjdp		len = crs->lr_dword._len;
23033965Sjdp		tra = crs->lr_dword._tra;
23133965Sjdp		break;
23233965Sjdp	case LR_QWORD:
23333965Sjdp		restype = crs->lr_qword.type;
23433965Sjdp		tflags = crs->lr_qword.tflags;
23599461Sobrien		min = crs->lr_qword._min;
23699461Sobrien		len = crs->lr_qword._len;
23799461Sobrien		tra = crs->lr_qword._tra;
23899461Sobrien		break;
23999461Sobrien	}
24099461Sobrien
24199461Sobrien	if (len == 0)
242104834Sobrien		return 0;
24333965Sjdp
24433965Sjdp	switch (restype) {
24533965Sjdp	case LR_TYPE_MEMORY:
24633965Sjdp		if (tflags & LR_MEMORY_TTP)
24789857Sobrien			return 0;
24833965Sjdp		extent_free(sc->sc_memex, min, len, EX_WAITOK);
24933965Sjdp		at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK);
25033965Sjdp		at->at_iot = sc->sc_iot;
25133965Sjdp		at->at_base = min;
25233965Sjdp		at->at_size = len;
25333965Sjdp		at->at_offset = tra;
25433965Sjdp		at->at_next = sc->sc_mem_trans;
25533965Sjdp		sc->sc_mem_trans = at;
25633965Sjdp		break;
25733965Sjdp	case LR_TYPE_IO:
25833965Sjdp		if ((tflags & LR_IO_TTP) == 0)
25933965Sjdp			return 0;
26033965Sjdp		extent_free(sc->sc_ioex, min, len, EX_WAITOK);
26133965Sjdp		at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK);
26233965Sjdp		at->at_iot = sc->sc_iot;
26333965Sjdp		at->at_base = min;
26433965Sjdp		at->at_size = len;
26533965Sjdp		at->at_offset = tra;
26633965Sjdp		at->at_next = sc->sc_io_trans;
26733965Sjdp		sc->sc_io_trans = at;
26833965Sjdp		break;
26933965Sjdp	case LR_TYPE_BUS:
27033965Sjdp		extent_free(sc->sc_busex, min, len, EX_WAITOK);
27133965Sjdp		break;
27233965Sjdp	}
27333965Sjdp
27433965Sjdp	return 0;
27533965Sjdp}
27633965Sjdp
27733965Sjdpvoid
27833965Sjdpacpipci_attach_hook(struct device *parent, struct device *self,
27933965Sjdp    struct pcibus_attach_args *pba)
28033965Sjdp{
28133965Sjdp}
28233965Sjdp
28333965Sjdpint
28433965Sjdpacpipci_bus_maxdevs(void *v, int bus)
28533965Sjdp{
28633965Sjdp	return 32;
28733965Sjdp}
28833965Sjdp
28933965Sjdppcitag_t
29033965Sjdpacpipci_make_tag(void *v, int bus, int device, int function)
29133965Sjdp{
29233965Sjdp	return ((bus << 20) | (device << 15) | (function << 12));
29333965Sjdp}
29433965Sjdp
29533965Sjdpvoid
29633965Sjdpacpipci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
29733965Sjdp{
29833965Sjdp	if (bp != NULL)
29933965Sjdp		*bp = (tag >> 20) & 0xff;
30033965Sjdp	if (dp != NULL)
30133965Sjdp		*dp = (tag >> 15) & 0x1f;
30233965Sjdp	if (fp != NULL)
30333965Sjdp		*fp = (tag >> 12) & 0x7;
30433965Sjdp}
30533965Sjdp
30633965Sjdpint
30733965Sjdpacpipci_conf_size(void *v, pcitag_t tag)
30833965Sjdp{
30933965Sjdp	return PCIE_CONFIG_SPACE_SIZE;
31033965Sjdp}
31133965Sjdp
31260484Sobrienpcireg_t
31360484Sobrienacpipci_conf_read(void *v, pcitag_t tag, int reg)
31460484Sobrien{
31560484Sobrien	struct acpipci_softc *sc = v;
31633965Sjdp
31733965Sjdp	return bus_space_read_4(sc->sc_iot, sc->sc_ioh, tag | reg);
31833965Sjdp}
31933965Sjdp
32033965Sjdpvoid
32133965Sjdpacpipci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
32233965Sjdp{
32333965Sjdp	struct acpipci_softc *sc = v;
32433965Sjdp
32533965Sjdp	bus_space_write_4(sc->sc_iot, sc->sc_ioh, tag | reg, data);
32633965Sjdp}
32733965Sjdp
32833965Sjdpstruct acpipci_intr_handle {
32933965Sjdp	pci_chipset_tag_t	ih_pc;
33033965Sjdp	pcitag_t		ih_tag;
33133965Sjdp	int			ih_intrpin;
33233965Sjdp	int			ih_msi;
33333965Sjdp};
33433965Sjdp
33533965Sjdpint
33633965Sjdpacpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
33733965Sjdp{
33833965Sjdp	struct acpipci_softc *sc = pa->pa_pc->pc_intr_v;
33933965Sjdp	struct aml_node *node;
34033965Sjdp	struct aml_value res;
34133965Sjdp	uint64_t addr, pin, source, index;
34233965Sjdp	struct acpipci_intr_handle *ih;
34378828Sobrien	int i;
344104834Sobrien
34578828Sobrien	if (pa->pa_bridgetag == NULL)
34633965Sjdp		return -1;
34733965Sjdp
34833965Sjdp	node = acpi_find_pci(pa->pa_pc, *pa->pa_bridgetag);
34933965Sjdp	if (node == NULL)
35033965Sjdp		return -1;
35133965Sjdp
35233965Sjdp	if (aml_evalname(sc->sc_acpi, node, "_PRT", 0, NULL, &res))
35333965Sjdp		return -1;
35433965Sjdp
35533965Sjdp	if (res.type != AML_OBJTYPE_PACKAGE)
35633965Sjdp		return -1;
35733965Sjdp
35833965Sjdp	for (i = 0; i < res.length; i++) {
35933965Sjdp		struct aml_value *val = res.v_package[i];
36033965Sjdp
36133965Sjdp		if (val->type != AML_OBJTYPE_PACKAGE)
36233965Sjdp			continue;
36333965Sjdp		if (val->length != 4)
36433965Sjdp			continue;
36533965Sjdp		if (val->v_package[0]->type != AML_OBJTYPE_INTEGER ||
36633965Sjdp		    val->v_package[1]->type != AML_OBJTYPE_INTEGER ||
36733965Sjdp		    val->v_package[2]->type != AML_OBJTYPE_INTEGER ||
368130561Sobrien		    val->v_package[3]->type != AML_OBJTYPE_INTEGER)
36933965Sjdp			continue;
37033965Sjdp
37133965Sjdp		addr = val->v_package[0]->v_integer;
37233965Sjdp		pin = val->v_package[1]->v_integer;
37333965Sjdp		source = val->v_package[2]->v_integer;
37433965Sjdp		index = val->v_package[3]->v_integer;
37533965Sjdp		if (ACPI_ADR_PCIDEV(addr) != pa->pa_device ||
37633965Sjdp		    ACPI_ADR_PCIFUN(addr) != 0xffff ||
37733965Sjdp		    pin != pa->pa_intrpin - 1 || source != 0)
37833965Sjdp			continue;
37933965Sjdp
38033965Sjdp		ih = malloc(sizeof(struct acpipci_intr_handle),
38133965Sjdp		    M_DEVBUF, M_WAITOK);
38233965Sjdp		ih->ih_pc = pa->pa_pc;
38333965Sjdp		ih->ih_tag = pa->pa_tag;
38433965Sjdp		ih->ih_intrpin = index;
38533965Sjdp		ih->ih_msi = 0;
38633965Sjdp		*ihp = (pci_intr_handle_t)ih;
38733965Sjdp
38833965Sjdp		return 0;
38933965Sjdp	}
39033965Sjdp
39133965Sjdp	return -1;
39233965Sjdp}
39333965Sjdp
39433965Sjdpint
39577298Sobrienacpipci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
39633965Sjdp{
39733965Sjdp	pci_chipset_tag_t pc = pa->pa_pc;
398130561Sobrien	pcitag_t tag = pa->pa_tag;
39933965Sjdp	struct acpipci_intr_handle *ih;
40033965Sjdp
40133965Sjdp	if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 ||
40233965Sjdp	    pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0)
40377298Sobrien		return -1;
40433965Sjdp
40533965Sjdp	ih = malloc(sizeof(struct acpipci_intr_handle), M_DEVBUF, M_WAITOK);
406130561Sobrien	ih->ih_pc = pa->pa_pc;
40733965Sjdp	ih->ih_tag = pa->pa_tag;
40833965Sjdp	ih->ih_intrpin = pa->pa_intrpin;
40933965Sjdp	ih->ih_msi = 1;
41033965Sjdp	*ihp = (pci_intr_handle_t)ih;
41133965Sjdp
41233965Sjdp	return 0;
41333965Sjdp}
41433965Sjdp
41533965Sjdpint
41633965Sjdpacpipci_intr_map_msix(struct pci_attach_args *pa, int vec,
41733965Sjdp    pci_intr_handle_t *ihp)
41833965Sjdp{
41933965Sjdp	return -1;
42033965Sjdp}
42160484Sobrien
42233965Sjdpconst char *
42333965Sjdpacpipci_intr_string(void *v, pci_intr_handle_t ihp)
42433965Sjdp{
42533965Sjdp	struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp;
42633965Sjdp	static char irqstr[32];
42733965Sjdp
42833965Sjdp	if (ih->ih_msi)
42933965Sjdp		return "msi";
43033965Sjdp
43133965Sjdp	snprintf(irqstr, sizeof(irqstr), "irq %d", ih->ih_intrpin);
43233965Sjdp	return irqstr;
43333965Sjdp}
43433965Sjdp
43533965Sjdpvoid *
43633965Sjdpacpipci_intr_establish(void *v, pci_intr_handle_t ihp, int level,
43733965Sjdp    int (*func)(void *), void *arg, char *name)
43833965Sjdp{
43933965Sjdp	struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp;
44033965Sjdp	struct interrupt_controller *ic;
44133965Sjdp	void *cookie;
44233965Sjdp
44333965Sjdp	extern LIST_HEAD(, interrupt_controller) interrupt_controllers;
44433965Sjdp	LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
44533965Sjdp		if (ic->ic_establish_msi)
44633965Sjdp			break;
44733965Sjdp	}
44877298Sobrien	if (ic == NULL)
44933965Sjdp		return NULL;
45077298Sobrien
45133965Sjdp	if (ih->ih_msi) {
45233965Sjdp		uint64_t addr, data;
45333965Sjdp		pcireg_t reg;
45433965Sjdp		int off;
45533965Sjdp
45633965Sjdp		cookie = ic->ic_establish_msi(ic->ic_cookie, &addr,
45733965Sjdp		    &data, level, func, arg, name);
45833965Sjdp		if (cookie == NULL)
45933965Sjdp			return NULL;
46033965Sjdp
46133965Sjdp		/* TODO: translate address to the PCI device's view */
46233965Sjdp
46333965Sjdp		if (pci_get_capability(ih->ih_pc, ih->ih_tag, PCI_CAP_MSI,
46433965Sjdp		    &off, &reg) == 0)
46533965Sjdp			panic("%s: no msi capability", __func__);
46689857Sobrien
46733965Sjdp		if (reg & PCI_MSI_MC_C64) {
46833965Sjdp			pci_conf_write(ih->ih_pc, ih->ih_tag,
46933965Sjdp			    off + PCI_MSI_MA, addr);
47033965Sjdp			pci_conf_write(ih->ih_pc, ih->ih_tag,
47133965Sjdp			    off + PCI_MSI_MAU32, addr >> 32);
47233965Sjdp			pci_conf_write(ih->ih_pc, ih->ih_tag,
47333965Sjdp			    off + PCI_MSI_MD64, data);
47433965Sjdp		} else {
47533965Sjdp			pci_conf_write(ih->ih_pc, ih->ih_tag,
47633965Sjdp			    off + PCI_MSI_MA, addr);
47733965Sjdp			pci_conf_write(ih->ih_pc, ih->ih_tag,
47833965Sjdp			    off + PCI_MSI_MD32, data);
47933965Sjdp		}
48033965Sjdp		pci_conf_write(ih->ih_pc, ih->ih_tag,
48133965Sjdp		    off, reg | PCI_MSI_MC_MSIE);
48233965Sjdp	} else {
48338889Sjdp		cookie = acpi_intr_establish(ih->ih_intrpin, 0, level,
48460484Sobrien		    func, arg, name);
48538889Sjdp	}
48638889Sjdp
487130561Sobrien	free(ih, M_DEVBUF, sizeof(struct acpipci_intr_handle));
48838889Sjdp	return cookie;
48960484Sobrien}
49060484Sobrien
49160484Sobrienvoid
49260484Sobrienacpipci_intr_disestablish(void *v, void *cookie)
493130561Sobrien{
494130561Sobrien	panic("%s", __func__);
495130561Sobrien}
496130561Sobrien
497130561Sobrien/*
498130561Sobrien * Translate memory address if needed.
499130561Sobrien */
500130561Sobrienint
501130561Sobrienacpipci_bs_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
50260484Sobrien    int flags, bus_space_handle_t *bshp)
50360484Sobrien{
50460484Sobrien	struct acpipci_trans *at;
50560484Sobrien
50660484Sobrien	for (at = t->bus_private; at; at = at->at_next) {
50760484Sobrien		if (addr >= at->at_base && addr < at->at_base + at->at_size) {
50860484Sobrien			return bus_space_map(at->at_iot,
509130561Sobrien			    addr + at->at_offset, size, flags, bshp);
51060484Sobrien		}
51138889Sjdp	}
51260484Sobrien
51338889Sjdp	return ENXIO;
51438889Sjdp}
51577298Sobrien
51677298Sobrienstruct arm64_pci_chipset pci_mcfg_chipset;
51777298Sobrien
518130561Sobrienpcireg_t
51938889Sjdppci_mcfg_conf_read(void *v, pcitag_t tag, int reg)
52077298Sobrien{
52177298Sobrien	return bus_space_read_4(pci_mcfgt, pci_mcfgh, tag | reg);
52277298Sobrien}
52377298Sobrien
52438889Sjdpvoid
52538889Sjdppci_mcfg_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
52638889Sjdp{
52738889Sjdp	bus_space_write_4(pci_mcfgt, pci_mcfgh, tag | reg, data);
52838889Sjdp}
52938889Sjdp
53077298Sobrienpci_chipset_tag_t
53177298Sobrienpci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int min_bus, int max_bus)
53277298Sobrien{
53377298Sobrien	pci_chipset_tag_t pc = &pci_mcfg_chipset;
53477298Sobrien
53577298Sobrien	pci_mcfgt = iot;
53677298Sobrien	pci_mcfg_addr = addr;
53777298Sobrien	pci_mcfg_min_bus = min_bus;
53877298Sobrien	pci_mcfg_max_bus = max_bus;
53977298Sobrien
54077298Sobrien	if (bus_space_map(iot, addr, (pci_mcfg_max_bus + 1) << 20, 0,
54138889Sjdp	    &pci_mcfgh))
54277298Sobrien		panic("%s: can't map config space", __func__);
54389857Sobrien
54438889Sjdp	memset(pc, 0, sizeof(*pc));
54577298Sobrien	pc->pc_bus_maxdevs = acpipci_bus_maxdevs;
54677298Sobrien	pc->pc_make_tag = acpipci_make_tag;
54777298Sobrien	pc->pc_decompose_tag = acpipci_decompose_tag;
54877298Sobrien	pc->pc_conf_size = acpipci_conf_size;
54960484Sobrien	pc->pc_conf_read = pci_mcfg_conf_read;
55077298Sobrien	pc->pc_conf_write = pci_mcfg_conf_write;
55177298Sobrien
55238889Sjdp	return pc;
55377298Sobrien}
55477298Sobrien