xref: /openbsd-src/sys/arch/octeon/dev/octpcie.c (revision 5a65bf4ec4c7ec84a668360b775cc941d824c812)
1*5a65bf4eSvisa /*	$OpenBSD: octpcie.c,v 1.2 2019/09/22 04:43:24 visa Exp $	*/
2750f12e5Svisa 
3750f12e5Svisa /*
4750f12e5Svisa  * Copyright (c) 2019 Visa Hankala
5750f12e5Svisa  *
6750f12e5Svisa  * Permission to use, copy, modify, and/or distribute this software for any
7750f12e5Svisa  * purpose with or without fee is hereby granted, provided that the above
8750f12e5Svisa  * copyright notice and this permission notice appear in all copies.
9750f12e5Svisa  *
10750f12e5Svisa  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11750f12e5Svisa  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12750f12e5Svisa  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13750f12e5Svisa  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14750f12e5Svisa  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15750f12e5Svisa  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16750f12e5Svisa  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17750f12e5Svisa  */
18750f12e5Svisa 
19750f12e5Svisa /*
20750f12e5Svisa  * Driver for OCTEON II and OCTEON III PCIe controller.
21750f12e5Svisa  */
22750f12e5Svisa 
23750f12e5Svisa #include <sys/param.h>
24750f12e5Svisa #include <sys/systm.h>
25750f12e5Svisa #include <sys/device.h>
26750f12e5Svisa #include <sys/extent.h>
27750f12e5Svisa 
28750f12e5Svisa #include <machine/autoconf.h>
29750f12e5Svisa #include <machine/octeonreg.h>
30750f12e5Svisa #include <machine/octeonvar.h>
31750f12e5Svisa #include <machine/octeon_model.h>
32750f12e5Svisa 
33750f12e5Svisa #include <dev/pci/pcidevs.h>
34750f12e5Svisa #include <dev/pci/pcireg.h>
35750f12e5Svisa #include <dev/pci/pcivar.h>
36750f12e5Svisa #include <dev/pci/ppbreg.h>
37750f12e5Svisa 
38750f12e5Svisa #include <octeon/dev/iobusvar.h>
39750f12e5Svisa 
40750f12e5Svisa #define PEM_BASE(port)		(0x11800c0000000ULL + (port) * PEM_SIZE)
41750f12e5Svisa #define PEM_SIZE		0x01000000
42750f12e5Svisa 
43750f12e5Svisa #define PEM_BAR0_SIZE		(1ULL << 14)
44750f12e5Svisa #define PEM_BAR2_SIZE		(1ULL << 41)
45750f12e5Svisa 
46750f12e5Svisa #define PEM_CTL_STATUS		0x00000000
47750f12e5Svisa #define   PEM_CTL_STATUS_LNK_ENB	0x0000000000000010ULL
48750f12e5Svisa #define PEM_CFG_WR		0x00000028
49750f12e5Svisa #define PEM_CFG_RD		0x00000030
50750f12e5Svisa #define PEM_P2P_BAR_START(i)	(0x00000040 + (i) * 16)
51750f12e5Svisa #define PEM_P2P_BAR_END(i)	(0x00000048 + (i) * 16)
52750f12e5Svisa #define PEM_P2N_BAR_START(i)	(0x00000080 + (i) * 8)
53750f12e5Svisa #define PEM_BAR_CTL(cfg)	((cfg)->cfg_bar_ctl_reg)
54750f12e5Svisa #define   PEM_BAR_CTL_BAR1_SIZ_M	0x0000000000000070ULL
55750f12e5Svisa #define   PEM_BAR_CTL_BAR1_SIZ_256M	0x0000000000000030ULL
56750f12e5Svisa #define   PEM_BAR_CTL_BAR2_ENB		0x0000000000000008ULL
57750f12e5Svisa #define   PEM_BAR_CTL_BAR2_ESX_M	0x0000000000000006ULL
58750f12e5Svisa #define   PEM_BAR_CTL_BAR2_ESX_S	1
59750f12e5Svisa #define   PEM_BAR_CTL_BAR2_CAX		0x0000000000000001ULL
60750f12e5Svisa #define PEM_BAR1_INDEX(cfg, i)	((cfg)->cfg_bar1_index_reg + (i) * 8)
61750f12e5Svisa #define PEM_STRAP		0x00000408
62750f12e5Svisa #define   PEM_STRAP_PIMODE_M		0x0000000000000003ULL
63750f12e5Svisa #define   PEM_STRAP_PIMODE_RC		0x0000000000000003ULL
64750f12e5Svisa 
65750f12e5Svisa #define PCIERC_CFG001		0x00000004
66750f12e5Svisa #define   PCIERC_CFG001_I_DIS		0x00000400U
67750f12e5Svisa #define   PCIERC_CFG001_SEE		0x00000100U
68750f12e5Svisa #define   PCIERC_CFG001_ME		0x00000004U
69750f12e5Svisa #define   PCIERC_CFG001_MSAE		0x00000002U
70750f12e5Svisa #define PCIERC_CFG006		0x00000018
71750f12e5Svisa #define PCIERC_CFG008		0x00000020
72750f12e5Svisa #define   PCIERC_CFG008_MLADDR_M	0xfff00000U
73750f12e5Svisa #define   PCIERC_CFG008_MLADDR_S	20
74750f12e5Svisa #define   PCIERC_CFG008_MBADDR_M	0x0000fff0U
75750f12e5Svisa #define   PCIERC_CFG008_MBADDR_S	4
76750f12e5Svisa #define PCIERC_CFG009		0x00000024
77750f12e5Svisa #define   PCIERC_CFG009_LMEM_LIMIT_M	0xfff00000U
78750f12e5Svisa #define   PCIERC_CFG009_LMEM_LIMIT_S	20
79750f12e5Svisa #define   PCIERC_CFG009_LMEM_BASE_M	0x0000fff0U
80750f12e5Svisa #define   PCIERC_CFG009_LMEM_BASE_S	4
81750f12e5Svisa #define PCIERC_CFG010		0x00000028
82750f12e5Svisa #define   PCIERC_CFG010_UMEM_BASE_M	0xffffffffU
83750f12e5Svisa #define   PCIERC_CFG010_UMEM_BASE_S	0
84750f12e5Svisa #define PCIERC_CFG011		0x0000002c
85750f12e5Svisa #define   PCIERC_CFG011_UMEM_LIMIT_M	0xffffffffU
86750f12e5Svisa #define   PCIERC_CFG011_UMEM_LIMIT_S	0
87750f12e5Svisa #define PCIERC_CFG030		0x00000078
88750f12e5Svisa #define   PCIERC_CFG030_MRRS_M		0x00007000U
89750f12e5Svisa #define   PCIERC_CFG030_MRRS_S		12
90750f12e5Svisa #define   PCIERC_CFG030_NS_EN		0x00000800U
91750f12e5Svisa #define   PCIERC_CFG030_AP_EN		0x00000400U
92750f12e5Svisa #define   PCIERC_CFG030_PF_EN		0x00000200U
93750f12e5Svisa #define   PCIERC_CFG030_ETF_EN		0x00000100U
94750f12e5Svisa #define   PCIERC_CFG030_MPS_M		0x000000e0U
95750f12e5Svisa #define   PCIERC_CFG030_MPS_S		5
96750f12e5Svisa #define   PCIERC_CFG030_RO_EN		0x00000010U
97750f12e5Svisa #define   PCIERC_CFG030_UR_EN		0x00000008U
98750f12e5Svisa #define   PCIERC_CFG030_FE_EN		0x00000004U
99750f12e5Svisa #define   PCIERC_CFG030_NFE_EN		0x00000002U
100750f12e5Svisa #define   PCIERC_CFG030_CE_EN		0x00000001U
101750f12e5Svisa #define PCIERC_CFG032		0x00000080
102750f12e5Svisa #define   PCIERC_CFG032_DLLA		0x20000000U
103750f12e5Svisa #define   PCIERC_CFG032_LT		0x08000000U
104750f12e5Svisa #define   PCIERC_CFG032_ASLPC_M		0x00000003U
105750f12e5Svisa #define   PCIERC_CFG032_ASLPC_S		0
106750f12e5Svisa #define PCIERC_CFG034		0x00000088
107750f12e5Svisa #define   PCIERC_CFG034_DLLS_EN		0x00001000U
108750f12e5Svisa #define   PCIERC_CFG034_CCINT_EN	0x00000010U
109750f12e5Svisa #define PCIERC_CFG035		0x0000008c
110750f12e5Svisa #define   PCIERC_CFG035_PMEIE		0x00000008U
111750f12e5Svisa #define   PCIERC_CFG035_SEFEE		0x00000004U
112750f12e5Svisa #define   PCIERC_CFG035_SENFEE		0x00000002U
113750f12e5Svisa #define   PCIERC_CFG035_SECEE		0x00000001U
114750f12e5Svisa #define PCIERC_CFG066		0x00000108
115750f12e5Svisa #define PCIERC_CFG069		0x00000114
116750f12e5Svisa #define PCIERC_CFG070		0x00000118
117750f12e5Svisa #define   PCIERC_CFG070_CE		0x00000100U
118750f12e5Svisa #define   PCIERC_CFG070_GE		0x00000040U
119750f12e5Svisa #define PCIERC_CFG075		0x0000012c
120750f12e5Svisa #define   PCIERC_CFG075_FERE		0x00000004U
121750f12e5Svisa #define   PCIERC_CFG075_NFERE		0x00000002U
122750f12e5Svisa #define   PCIERC_CFG075_CERE		0x00000001U
123750f12e5Svisa #define PCIERC_CFG515		0x0000080c
124750f12e5Svisa #define   PCIERC_CFG515_DSC		0x00000200U
125750f12e5Svisa 
126750f12e5Svisa #define DPI_BASE		0x1df0000000040ULL
127750f12e5Svisa #define DPI_SIZE		0x00001000
128750f12e5Svisa #define DPI_SLI_PRT_CFG(port)	(0x00000900 + (port) * 8)
129750f12e5Svisa #define   DPI_SLI_PRT_CFG_MOLR_M	0x0000000000003f00ULL
130750f12e5Svisa #define   DPI_SLI_PRT_CFG_MOLR_S	8
131750f12e5Svisa #define   DPI_SLI_PRT_CFG_MPS_M		0x0000000000000010ULL
132750f12e5Svisa #define   DPI_SLI_PRT_CFG_MPS_S		4
133750f12e5Svisa #define   DPI_SLI_PRT_CFG_MRRS_M	0x0000000000000003ULL
134750f12e5Svisa #define   DPI_SLI_PRT_CFG_MRRS_S	0
135750f12e5Svisa 
136750f12e5Svisa #define SLI_BASE		0x11f0000000000ULL
137750f12e5Svisa #define SLI_SIZE		0x00020000
138750f12e5Svisa #define SLI_S2M_PORT_CTL(port)	(0x00013d80 + (port) * 16)
139750f12e5Svisa #define   SLI_S2M_PORT_CTL_MRRS_M	0x0000000000000007ULL
140750f12e5Svisa #define   SLI_S2M_PORT_CTL_MRRS_S	0
141750f12e5Svisa #define SLI_MEM_ACCESS_CTL		0x000102f0U
142750f12e5Svisa #define   SLI_MEM_ACCESS_CTL_MAXW_M	0x0000000000003c00ULL
143750f12e5Svisa #define   SLI_MEM_ACCESS_CTL_MAXW_S	10
144750f12e5Svisa #define   SLI_MEM_ACCESS_CTL_TIMER_M	0x00000000000003ffULL
145750f12e5Svisa #define   SLI_MEM_ACCESS_CTL_TIMER_S	0
146750f12e5Svisa #define SLI_MEM_ACCESS_SUBID(i)	(0x000000e0 + (i) * 16)
147750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_PORT_M	0x0000038000000000ULL
148750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_PORT_S	39
149750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_NMERGE	0x0000004000000000ULL
150750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_ESR_M	0x0000003000000000ULL
151750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_ESR_S	36
152750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_ESW_M	0x0000000c00000000ULL
153750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_ESW_S	34
154750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_WTYPE_M	0x0000000300000000ULL
155750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_WTYPE_S	32
156750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_RTYPE_M	0x00000000c0000000ULL
157750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_RTYPE_S	30
158750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_BA_M	0x000000003fffffffULL
159750f12e5Svisa #define   SLI_MEM_ACCESS_SUBID_BA_S	0
160750f12e5Svisa 
161750f12e5Svisa #define SLI_PCIECFG_BASE(port)	(0x1190c00000000ULL + (port) * SLI_PCIECFG_SIZE)
162750f12e5Svisa #define SLI_PCIECFG_SIZE	(1ULL << 32)
163750f12e5Svisa #define SLI_PCIEIO_BASE(port)	(0x11a0400000000ULL + (port) * SLI_PCIEIO_SIZE)
164750f12e5Svisa #define SLI_PCIEIO_SIZE		(1ULL << 32)
165750f12e5Svisa #define SLI_PCIEMEM_BASE(port)	(0x11b0000000000ULL + (port) * SLI_PCIEMEM_SIZE)
166750f12e5Svisa #define SLI_PCIEMEM_SIZE	(1ULL << 40)
167750f12e5Svisa 
168750f12e5Svisa #define CIU_SOFT_PRST_ADDR	0x1070000000748ULL
169750f12e5Svisa #define CIU_SOFT_PRST1_ADDR	0x1070000000758ULL
170750f12e5Svisa #define RST_SOFT_PRST_ADDR(port) (0x11800060016c0ULL + (port) * 8)
171750f12e5Svisa #define   PRST_SOFT_PRST		0x0000000000000001ULL
172750f12e5Svisa 
173750f12e5Svisa #define CIU3_PEM_INTSN_INTA(i)	(((0xc0 + i) << 12) + 60)
174750f12e5Svisa 
175750f12e5Svisa struct octpcie_softc;
176750f12e5Svisa 
177750f12e5Svisa struct octpcie_config {
178750f12e5Svisa 	int			 cfg_nports;
179750f12e5Svisa 	uint32_t		 cfg_bar_ctl_reg;
180750f12e5Svisa 	uint32_t		 cfg_bar1_index_reg;
181750f12e5Svisa 	char			 cfg_has_ciu3;
182750f12e5Svisa };
183750f12e5Svisa 
184750f12e5Svisa struct octpcie_port {
185750f12e5Svisa 	struct mips_pci_chipset	 port_pc;
186750f12e5Svisa 	struct octpcie_softc	*port_sc;
187750f12e5Svisa 	bus_space_tag_t		 port_iot;
188750f12e5Svisa 	bus_space_handle_t	 port_pem_ioh;
189750f12e5Svisa 	bus_space_handle_t	 port_pciecfg_ioh;
190750f12e5Svisa 	struct extent		*port_ioex;
191750f12e5Svisa 	struct extent		*port_memex;
192750f12e5Svisa 	char			 port_ioex_name[32];
193750f12e5Svisa 	char			 port_memex_name[32];
194750f12e5Svisa 	int			 port_index;
195750f12e5Svisa 	struct mips_bus_space	 port_bus_iot;
196750f12e5Svisa 	struct mips_bus_space	 port_bus_memt;
197750f12e5Svisa };
198750f12e5Svisa 
199750f12e5Svisa struct octpcie_softc {
200750f12e5Svisa 	struct device		 sc_dev;
201750f12e5Svisa 	bus_space_tag_t		 sc_iot;
202750f12e5Svisa 	bus_space_handle_t	 sc_dpi_ioh;
203750f12e5Svisa 	bus_space_handle_t	 sc_sli_ioh;
204750f12e5Svisa 	struct machine_bus_dma_tag *sc_dmat;
205750f12e5Svisa 	const struct octpcie_config *sc_cfg;
206750f12e5Svisa 	struct octpcie_port	*sc_ports;
207750f12e5Svisa };
208750f12e5Svisa 
209750f12e5Svisa int	 octpcie_match(struct device *, void *, void *);
210750f12e5Svisa void	 octpcie_attach(struct device *, struct device *, void *);
211750f12e5Svisa int	 octpcie_print(void *, const char *);
212750f12e5Svisa 
213750f12e5Svisa void	 octpcie_attach_hook(struct device *, struct device *,
214750f12e5Svisa 	    struct pcibus_attach_args *pba);
215750f12e5Svisa int	 octpcie_bus_maxdevs(void *, int);
216750f12e5Svisa pcitag_t octpcie_make_tag(void *, int, int, int);
217750f12e5Svisa void	 octpcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
218750f12e5Svisa int	 octpcie_conf_size(void *, pcitag_t);
219750f12e5Svisa pcireg_t octpcie_conf_read(void *, pcitag_t, int);
220750f12e5Svisa void	 octpcie_conf_write(void *, pcitag_t, int, pcireg_t);
221750f12e5Svisa int	 octpcie_pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
222750f12e5Svisa const char *
223750f12e5Svisa 	 octpcie_pci_intr_string(void *, pci_intr_handle_t);
224750f12e5Svisa void	*octpcie_pci_intr_establish(void *, pci_intr_handle_t, int,
225750f12e5Svisa 	    int (*)(void *), void *, char *);
226750f12e5Svisa void	 octpcie_pci_intr_disestablish(void *, void *);
227750f12e5Svisa 
228750f12e5Svisa int	 octpcie_io_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
229750f12e5Svisa 	    bus_space_handle_t *);
230750f12e5Svisa int	 octpcie_mem_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
231750f12e5Svisa 	    bus_space_handle_t *);
232750f12e5Svisa 
233750f12e5Svisa void	 octpcie_port_attach(struct octpcie_port *);
234750f12e5Svisa int	 octpcie_port_is_host(struct octpcie_port *);
235750f12e5Svisa int	 octpcie_port_reset(struct octpcie_port *);
236750f12e5Svisa 
237750f12e5Svisa uint32_t octpcie_cfgreg_read(struct octpcie_port *, uint32_t);
238750f12e5Svisa void	 octpcie_cfgreg_write(struct octpcie_port *, uint32_t, uint32_t);
239750f12e5Svisa 
240750f12e5Svisa const struct cfattach octpcie_ca = {
241750f12e5Svisa 	sizeof(struct octpcie_softc), octpcie_match, octpcie_attach
242750f12e5Svisa };
243750f12e5Svisa 
244750f12e5Svisa struct cfdriver octpcie_cd = {
245750f12e5Svisa 	NULL, "octpcie", DV_DULL
246750f12e5Svisa };
247750f12e5Svisa 
248750f12e5Svisa const struct octpcie_config cn61xx_config = {
249750f12e5Svisa 	.cfg_nports		= 2,
250750f12e5Svisa 	.cfg_bar_ctl_reg	= 0x00000128,
251750f12e5Svisa 	.cfg_bar1_index_reg	= 0x000000a8,
252750f12e5Svisa };
253750f12e5Svisa const struct octpcie_config cn71xx_config = {
254750f12e5Svisa 	.cfg_nports		= 3,
255750f12e5Svisa 	.cfg_bar_ctl_reg	= 0x000000a8,
256750f12e5Svisa 	.cfg_bar1_index_reg	= 0x00000100,
257750f12e5Svisa };
258750f12e5Svisa const struct octpcie_config cn78xx_config = {
259750f12e5Svisa 	.cfg_nports		= 4,
260750f12e5Svisa 	.cfg_bar_ctl_reg	= 0x000000a8,
261750f12e5Svisa 	.cfg_bar1_index_reg	= 0x00000100,
262750f12e5Svisa 	.cfg_has_ciu3		= 1,
263750f12e5Svisa };
264750f12e5Svisa 
265750f12e5Svisa int
octpcie_match(struct device * parent,void * match,void * aux)266750f12e5Svisa octpcie_match(struct device *parent, void *match, void *aux)
267750f12e5Svisa {
268750f12e5Svisa 	struct iobus_attach_args *aa = aux;
269750f12e5Svisa 
270750f12e5Svisa 	if (strcmp(aa->aa_name, octpcie_cd.cd_name) != 0)
271750f12e5Svisa 		return 0;
272750f12e5Svisa 
273750f12e5Svisa 	return 1;
274750f12e5Svisa }
275750f12e5Svisa 
276750f12e5Svisa void
octpcie_attach(struct device * parent,struct device * self,void * aux)277750f12e5Svisa octpcie_attach(struct device *parent, struct device *self, void *aux)
278750f12e5Svisa {
279750f12e5Svisa 	struct iobus_attach_args *aa = aux;
280750f12e5Svisa 	const struct octpcie_config *cfg;
281750f12e5Svisa 	struct octpcie_port *port;
282750f12e5Svisa 	struct octpcie_softc *sc = (struct octpcie_softc *)self;
283750f12e5Svisa 	uint64_t val;
284750f12e5Svisa 	uint32_t chipid;
285750f12e5Svisa 	int pi;
286750f12e5Svisa 
287750f12e5Svisa 	sc->sc_iot = aa->aa_bust;
288750f12e5Svisa 	sc->sc_dmat = aa->aa_dmat;
289750f12e5Svisa 
290750f12e5Svisa 	chipid = octeon_get_chipid();
291750f12e5Svisa 	switch (octeon_model_family(chipid)) {
292750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN61XX:
293750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN63XX:
294750f12e5Svisa 		cfg = &cn61xx_config;
295750f12e5Svisa 		break;
296750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN71XX:
297750f12e5Svisa 		cfg = &cn71xx_config;
298750f12e5Svisa 		break;
299750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN73XX:
300750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN78XX:
301750f12e5Svisa 		cfg = &cn78xx_config;
302750f12e5Svisa 		break;
303750f12e5Svisa 	default:
304750f12e5Svisa 		printf(": unhandled chipid 0x%x\n", chipid);
305750f12e5Svisa 		return;
306750f12e5Svisa 	}
307750f12e5Svisa 	sc->sc_cfg = cfg;
308750f12e5Svisa 
309750f12e5Svisa 	if (bus_space_map(sc->sc_iot, DPI_BASE, DPI_SIZE, 0,
310750f12e5Svisa 	    &sc->sc_dpi_ioh) != 0) {
311750f12e5Svisa 		printf(": can't map DPI registers\n");
312750f12e5Svisa 		return;
313750f12e5Svisa 	}
314750f12e5Svisa 
315750f12e5Svisa 	if (bus_space_map(sc->sc_iot, SLI_BASE, SLI_SIZE, 0,
316750f12e5Svisa 	    &sc->sc_sli_ioh) != 0) {
317750f12e5Svisa 		printf(": can't map SLI registers\n");
318750f12e5Svisa 		goto error;
319750f12e5Svisa 	}
320750f12e5Svisa 
321750f12e5Svisa 	val = bus_space_read_8(sc->sc_iot, sc->sc_sli_ioh, SLI_MEM_ACCESS_CTL);
322750f12e5Svisa 	val &= ~SLI_MEM_ACCESS_CTL_MAXW_M;
323750f12e5Svisa 	val &= ~SLI_MEM_ACCESS_CTL_TIMER_M;
324750f12e5Svisa 	val |= 127 << SLI_MEM_ACCESS_CTL_TIMER_S;
325750f12e5Svisa 	bus_space_write_8(sc->sc_iot, sc->sc_sli_ioh, SLI_MEM_ACCESS_CTL, val);
326750f12e5Svisa 
327750f12e5Svisa 	printf(": %d ports\n", cfg->cfg_nports);
328750f12e5Svisa 
329750f12e5Svisa 	sc->sc_ports = mallocarray(cfg->cfg_nports, sizeof(*sc->sc_ports),
330750f12e5Svisa 	    M_DEVBUF, M_WAITOK | M_ZERO);
331750f12e5Svisa 	for (pi = 0; pi < cfg->cfg_nports; pi++) {
332750f12e5Svisa 		port = &sc->sc_ports[pi];
333750f12e5Svisa 		port->port_sc = sc;
334750f12e5Svisa 		port->port_index = pi;
335750f12e5Svisa 		port->port_iot = sc->sc_iot;
336750f12e5Svisa 		octpcie_port_attach(port);
337750f12e5Svisa 	}
338750f12e5Svisa 	return;
339750f12e5Svisa 
340750f12e5Svisa error:
341750f12e5Svisa 	bus_space_unmap(sc->sc_iot, sc->sc_dpi_ioh, DPI_SIZE);
342750f12e5Svisa }
343750f12e5Svisa 
344750f12e5Svisa void
octpcie_port_attach(struct octpcie_port * port)345750f12e5Svisa octpcie_port_attach(struct octpcie_port *port)
346750f12e5Svisa {
347750f12e5Svisa 	struct pcibus_attach_args pba;
348750f12e5Svisa 	struct octpcie_softc *sc = port->port_sc;
349750f12e5Svisa 	pci_chipset_tag_t pc = &port->port_pc;
350750f12e5Svisa 
351750f12e5Svisa 	if (bus_space_map(port->port_iot, PEM_BASE(port->port_index),
352750f12e5Svisa 	    PEM_SIZE, 0, &port->port_pem_ioh) != 0) {
353750f12e5Svisa 		printf("%s port %d: can't map PEM registers\n",
354750f12e5Svisa 		    sc->sc_dev.dv_xname, port->port_index);
355750f12e5Svisa 		return;
356750f12e5Svisa 	}
357750f12e5Svisa 
358750f12e5Svisa 	if (bus_space_map(port->port_iot, SLI_PCIECFG_BASE(port->port_index),
359750f12e5Svisa 	    SLI_PCIECFG_SIZE, 0, &port->port_pciecfg_ioh) != 0) {
360750f12e5Svisa 		printf("%s port %d: can't map PCIECFG registers\n",
361750f12e5Svisa 		    sc->sc_dev.dv_xname, port->port_index);
362750f12e5Svisa 		goto error_pem;
363750f12e5Svisa 	}
364750f12e5Svisa 
365*5a65bf4eSvisa 	if (octpcie_port_is_host(port) == 0)
366750f12e5Svisa 		goto error_pciecfg;
367750f12e5Svisa 
368750f12e5Svisa 	if (octpcie_port_reset(port) != 0) {
369750f12e5Svisa 		/* Error has been printed already. */
370750f12e5Svisa 		goto error_pciecfg;
371750f12e5Svisa 	}
372750f12e5Svisa 
373750f12e5Svisa 	snprintf(port->port_ioex_name, sizeof(port->port_ioex_name),
374750f12e5Svisa 	    "%s port %d pciio", sc->sc_dev.dv_xname, port->port_index);
375750f12e5Svisa 	snprintf(port->port_memex_name, sizeof(port->port_memex_name),
376750f12e5Svisa 	    "%s port %d pcimem", sc->sc_dev.dv_xname, port->port_index);
377750f12e5Svisa 	port->port_ioex = extent_create(port->port_ioex_name, 0, 0xffffffff,
378750f12e5Svisa 	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
379750f12e5Svisa 	port->port_memex = extent_create(port->port_memex_name, 0, (u_long)-1,
380750f12e5Svisa 	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
381750f12e5Svisa 
382750f12e5Svisa 	extent_free(port->port_ioex, 0, 0xffffffff, EX_WAITOK);
383750f12e5Svisa 	extent_free(port->port_memex, PEM_BAR0_SIZE, PEM_BAR2_SIZE - 1,
384750f12e5Svisa 	    EX_WAITOK);
385750f12e5Svisa 
386750f12e5Svisa 	port->port_bus_iot = *port->port_iot;
387750f12e5Svisa 	port->port_bus_iot.bus_private = port;
388750f12e5Svisa 	port->port_bus_iot._space_map = octpcie_io_map;
389750f12e5Svisa 
390750f12e5Svisa 	port->port_bus_memt = *port->port_iot;
391750f12e5Svisa 	port->port_bus_memt.bus_private = port;
392750f12e5Svisa 	port->port_bus_memt._space_map = octpcie_mem_map;
393750f12e5Svisa 
394750f12e5Svisa 	pc->pc_conf_v = port;
395750f12e5Svisa 	pc->pc_attach_hook = octpcie_attach_hook;
396750f12e5Svisa 	pc->pc_bus_maxdevs = octpcie_bus_maxdevs;
397750f12e5Svisa 	pc->pc_make_tag = octpcie_make_tag;
398750f12e5Svisa 	pc->pc_decompose_tag = octpcie_decompose_tag;
399750f12e5Svisa 	pc->pc_conf_size = octpcie_conf_size;
400750f12e5Svisa 	pc->pc_conf_read = octpcie_conf_read;
401750f12e5Svisa 	pc->pc_conf_write = octpcie_conf_write;
402750f12e5Svisa 
403750f12e5Svisa 	pc->pc_intr_v = port;
404750f12e5Svisa 	pc->pc_intr_map = octpcie_pci_intr_map;
405750f12e5Svisa 	pc->pc_intr_string = octpcie_pci_intr_string;
406750f12e5Svisa 	pc->pc_intr_establish = octpcie_pci_intr_establish;
407750f12e5Svisa 	pc->pc_intr_disestablish = octpcie_pci_intr_disestablish;
408750f12e5Svisa 
409750f12e5Svisa 	memset(&pba, 0, sizeof(pba));
410750f12e5Svisa 	pba.pba_busname = "pci";
411750f12e5Svisa 	pba.pba_iot = &port->port_bus_iot;
412750f12e5Svisa 	pba.pba_memt = &port->port_bus_memt;
413750f12e5Svisa 	pba.pba_dmat = sc->sc_dmat;
414750f12e5Svisa 	pba.pba_pc = pc;
415750f12e5Svisa 	pba.pba_domain = pci_ndomains++;
416750f12e5Svisa 	pba.pba_bus = 0;
417750f12e5Svisa 	pba.pba_ioex = port->port_ioex;
418750f12e5Svisa 	pba.pba_memex = port->port_memex;
419750f12e5Svisa 	config_found(&sc->sc_dev, &pba, octpcie_print);
420750f12e5Svisa 	return;
421750f12e5Svisa 
422750f12e5Svisa error_pciecfg:
423750f12e5Svisa 	bus_space_unmap(port->port_iot, port->port_pciecfg_ioh,
424750f12e5Svisa 	    SLI_PCIECFG_SIZE);
425750f12e5Svisa error_pem:
426750f12e5Svisa 	bus_space_unmap(port->port_iot, port->port_pem_ioh, PEM_SIZE);
427750f12e5Svisa }
428750f12e5Svisa 
429750f12e5Svisa int
octpcie_port_reset(struct octpcie_port * port)430750f12e5Svisa octpcie_port_reset(struct octpcie_port *port)
431750f12e5Svisa {
432750f12e5Svisa 	struct octpcie_softc *sc = port->port_sc;
433750f12e5Svisa 	const struct octpcie_config *cfg = sc->sc_cfg;
434750f12e5Svisa 	paddr_t ctl_reg, rst_reg;
435750f12e5Svisa 	uint64_t val;
436750f12e5Svisa 	uint32_t chipid, cr;
437750f12e5Svisa 	int i, timeout;
438750f12e5Svisa 
439750f12e5Svisa 	chipid = octeon_get_chipid();
440750f12e5Svisa 	switch (octeon_model_family(chipid)) {
441750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN61XX:
442750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN63XX:
443750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN66XX:
444750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN68XX:
445750f12e5Svisa 		ctl_reg = MIO_RST_CTL(port->port_index);
446750f12e5Svisa 		if (port->port_index == 0)
447750f12e5Svisa 			rst_reg = CIU_SOFT_PRST_ADDR;
448750f12e5Svisa 		else
449750f12e5Svisa 			rst_reg = CIU_SOFT_PRST1_ADDR;
450750f12e5Svisa 		break;
451750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN71XX:
452750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN73XX:
453750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN78XX:
454750f12e5Svisa 		ctl_reg = RST_CTL(port->port_index);
455750f12e5Svisa 		rst_reg = RST_SOFT_PRST_ADDR(port->port_index);
456750f12e5Svisa 		break;
457750f12e5Svisa 	default:
458750f12e5Svisa 		printf("%s port %d: unhandled chipid 0x%x\n",
459750f12e5Svisa 		    sc->sc_dev.dv_xname, port->port_index, chipid);
460750f12e5Svisa 		return -1;
461750f12e5Svisa 	}
462750f12e5Svisa 
463750f12e5Svisa 	/* Put the hardware in reset. */
464750f12e5Svisa 	val = octeon_xkphys_read_8(rst_reg);
465750f12e5Svisa 	octeon_xkphys_write_8(rst_reg, val);
466750f12e5Svisa 	(void)octeon_xkphys_read_8(rst_reg);
467750f12e5Svisa 	delay(2000);
468750f12e5Svisa 
469750f12e5Svisa 	/* Take the hardware out of reset. */
470750f12e5Svisa 	val &= ~PRST_SOFT_PRST;
471750f12e5Svisa 	octeon_xkphys_write_8(rst_reg, val);
472750f12e5Svisa 	(void)octeon_xkphys_read_8(rst_reg);
473750f12e5Svisa 	delay(1000);
474750f12e5Svisa 
475750f12e5Svisa 	/* Wait until the reset has completed. */
476750f12e5Svisa 	for (timeout = 100000; timeout > 0; timeout--) {
477750f12e5Svisa 		val = octeon_xkphys_read_8(ctl_reg);
478750f12e5Svisa 		if (val & RST_CTL_RST_DONE)
479750f12e5Svisa 			break;
480750f12e5Svisa 	}
481750f12e5Svisa 	if (timeout == 0) {
482750f12e5Svisa 		printf("%s port %d: reset timeout\n",
483750f12e5Svisa 		    sc->sc_dev.dv_xname, port->port_index);
484750f12e5Svisa 		return -1;
485750f12e5Svisa 	}
486750f12e5Svisa 
487750f12e5Svisa 	/*
488750f12e5Svisa 	 * Initialize the configuration registers of the root complex.
489750f12e5Svisa 	 */
490750f12e5Svisa 
491750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG030);
492750f12e5Svisa 	cr &= ~PCIERC_CFG030_MPS_M;
493750f12e5Svisa 	cr &= ~PCIERC_CFG030_MRRS_M;
494750f12e5Svisa 	cr |= 0 << PCIERC_CFG030_MPS_S;
495750f12e5Svisa 	cr |= 3 << PCIERC_CFG030_MRRS_S;
496750f12e5Svisa 	cr |= PCIERC_CFG030_NS_EN;
497750f12e5Svisa 	cr |= PCIERC_CFG030_RO_EN;
498750f12e5Svisa 	cr |= PCIERC_CFG030_UR_EN;
499750f12e5Svisa 	cr |= PCIERC_CFG030_FE_EN;
500750f12e5Svisa 	cr |= PCIERC_CFG030_NFE_EN;
501750f12e5Svisa 	cr |= PCIERC_CFG030_CE_EN;
502750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG030, cr);
503750f12e5Svisa 
504750f12e5Svisa 	val = bus_space_read_8(sc->sc_iot, sc->sc_dpi_ioh,
505750f12e5Svisa 	    DPI_SLI_PRT_CFG(port->port_index));
506750f12e5Svisa 	val &= ~DPI_SLI_PRT_CFG_MPS_M;
507750f12e5Svisa 	val &= ~DPI_SLI_PRT_CFG_MRRS_M;
508750f12e5Svisa 	val |= 0 << DPI_SLI_PRT_CFG_MPS_S;
509750f12e5Svisa 	val |= 3 << DPI_SLI_PRT_CFG_MRRS_S;
510750f12e5Svisa 	val &= ~DPI_SLI_PRT_CFG_MOLR_M;
511750f12e5Svisa 	val |= 32 << DPI_SLI_PRT_CFG_MOLR_S;
512750f12e5Svisa 	bus_space_write_8(sc->sc_iot, sc->sc_dpi_ioh,
513750f12e5Svisa 	    DPI_SLI_PRT_CFG(port->port_index), val);
514750f12e5Svisa 	(void)bus_space_read_8(sc->sc_iot, sc->sc_dpi_ioh,
515750f12e5Svisa 	    DPI_SLI_PRT_CFG(port->port_index));
516750f12e5Svisa 
517750f12e5Svisa 	val = bus_space_read_8(sc->sc_iot, sc->sc_sli_ioh,
518750f12e5Svisa 	    SLI_S2M_PORT_CTL(port->port_index));
519750f12e5Svisa 	val &= ~SLI_S2M_PORT_CTL_MRRS_M;
520750f12e5Svisa 	val |= 32 << SLI_S2M_PORT_CTL_MRRS_S;
521750f12e5Svisa 	bus_space_write_8(sc->sc_iot, sc->sc_sli_ioh,
522750f12e5Svisa 	    SLI_S2M_PORT_CTL(port->port_index), val);
523750f12e5Svisa 	(void)bus_space_read_8(sc->sc_iot, sc->sc_sli_ioh,
524750f12e5Svisa 	    SLI_S2M_PORT_CTL(port->port_index));
525750f12e5Svisa 
526750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG070);
527750f12e5Svisa 	cr |= PCIERC_CFG070_CE;
528750f12e5Svisa 	cr |= PCIERC_CFG070_GE;
529750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG070, cr);
530750f12e5Svisa 
531750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG001);
532750f12e5Svisa 	cr |= PCIERC_CFG001_I_DIS;
533750f12e5Svisa 	cr |= PCIERC_CFG001_SEE;
534750f12e5Svisa 	cr |= PCIERC_CFG001_ME;
535750f12e5Svisa 	cr |= PCIERC_CFG001_MSAE;
536750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG001, cr);
537750f12e5Svisa 
538750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG066, 0);
539750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG069, 0);
540750f12e5Svisa 
541750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG032);
542750f12e5Svisa 	cr &= ~PCIERC_CFG032_ASLPC_M;
543750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG032, cr);
544750f12e5Svisa 
545750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG006, 0);
546750f12e5Svisa 
547750f12e5Svisa 	cr = 0x100 << PCIERC_CFG008_MBADDR_S;
548750f12e5Svisa 	cr |= 0 << PCIERC_CFG008_MLADDR_S;
549750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG008, cr);
550750f12e5Svisa 
551750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG009);
552750f12e5Svisa 	cr &= ~PCIERC_CFG009_LMEM_BASE_M;
553750f12e5Svisa 	cr |= 0x100 << PCIERC_CFG009_LMEM_BASE_S;
554750f12e5Svisa 	cr &= ~PCIERC_CFG009_LMEM_LIMIT_M;
555750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG009, cr);
556750f12e5Svisa 
557750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG010);
558750f12e5Svisa 	cr &= ~PCIERC_CFG010_UMEM_BASE_M;
559750f12e5Svisa 	cr |= 0x100 << PCIERC_CFG010_UMEM_BASE_S;
560750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG010, cr);
561750f12e5Svisa 
562750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG011);
563750f12e5Svisa 	cr &= ~PCIERC_CFG011_UMEM_LIMIT_M;
564750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG011, cr);
565750f12e5Svisa 
566750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG035);
567750f12e5Svisa 	cr |= PCIERC_CFG035_SECEE;
568750f12e5Svisa 	cr |= PCIERC_CFG035_SEFEE;
569750f12e5Svisa 	cr |= PCIERC_CFG035_SENFEE;
570750f12e5Svisa 	cr |= PCIERC_CFG035_PMEIE;
571750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG035, cr);
572750f12e5Svisa 
573750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG075);
574750f12e5Svisa 	cr |= PCIERC_CFG075_CERE;
575750f12e5Svisa 	cr |= PCIERC_CFG075_NFERE;
576750f12e5Svisa 	cr |= PCIERC_CFG075_FERE;
577750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG075, cr);
578750f12e5Svisa 
579750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG034);
580750f12e5Svisa 	cr |= PCIERC_CFG034_DLLS_EN;
581750f12e5Svisa 	cr |= PCIERC_CFG034_CCINT_EN;
582750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG034, cr);
583750f12e5Svisa 
584750f12e5Svisa 	cr = octpcie_cfgreg_read(port, PCIERC_CFG515);
585750f12e5Svisa 	cr |= PCIERC_CFG515_DSC;
586750f12e5Svisa 	octpcie_cfgreg_write(port, PCIERC_CFG515, cr);
587750f12e5Svisa 
588750f12e5Svisa 	/* Enable the link. */
589750f12e5Svisa 	val = bus_space_read_8(port->port_iot, port->port_pem_ioh,
590750f12e5Svisa 	    PEM_CTL_STATUS);
591750f12e5Svisa 	val |= PEM_CTL_STATUS_LNK_ENB;
592750f12e5Svisa 	bus_space_write_8(port->port_iot, port->port_pem_ioh,
593750f12e5Svisa 	    PEM_CTL_STATUS, val);
594750f12e5Svisa 
595750f12e5Svisa 	/*
596750f12e5Svisa 	 * Wait until link training finishes and
597750f12e5Svisa 	 * data link layer activity begins.
598750f12e5Svisa 	 */
599750f12e5Svisa 	for (timeout = 1000; timeout > 0; timeout--) {
600750f12e5Svisa 		cr = octpcie_cfgreg_read(port, PCIERC_CFG032);
601750f12e5Svisa 		if ((cr & PCIERC_CFG032_DLLA) != 0 &&
602750f12e5Svisa 		    (cr & PCIERC_CFG032_LT) == 0)
603750f12e5Svisa 			break;
604750f12e5Svisa 		delay(1000);
605750f12e5Svisa 	}
606750f12e5Svisa 	if (timeout == 0) {
607750f12e5Svisa 		printf("%s port %d: link timeout\n",
608750f12e5Svisa 		    sc->sc_dev.dv_xname, port->port_index);
609750f12e5Svisa 		return -1;
610750f12e5Svisa 	}
611750f12e5Svisa 
612750f12e5Svisa 	val = (uint64_t)port->port_index << SLI_MEM_ACCESS_SUBID_PORT_S;
613750f12e5Svisa 	val |= 3ULL << SLI_MEM_ACCESS_SUBID_ESR_S;
614750f12e5Svisa 	val |= 3ULL << SLI_MEM_ACCESS_SUBID_ESW_S;
615750f12e5Svisa 	for (i = 0; i < 4; i++) {
616750f12e5Svisa 		bus_space_write_8(sc->sc_iot, sc->sc_sli_ioh,
617750f12e5Svisa 		    SLI_MEM_ACCESS_SUBID(i + port->port_index * 4), val);
618750f12e5Svisa 		val += 1ULL << SLI_MEM_ACCESS_SUBID_BA_S;
619750f12e5Svisa 	}
620750f12e5Svisa 
621750f12e5Svisa 	/* Disable forwarding between ports. */
622750f12e5Svisa 	for (i = 0; i < 4; i++) {
623750f12e5Svisa 		bus_space_write_8(port->port_iot, port->port_pem_ioh,
624750f12e5Svisa 		    PEM_P2P_BAR_START(i), ~0ULL);
625750f12e5Svisa 		bus_space_write_8(port->port_iot, port->port_pem_ioh,
626750f12e5Svisa 		    PEM_P2P_BAR_END(i), ~0ULL);
627750f12e5Svisa 	}
628750f12e5Svisa 
629750f12e5Svisa 	/*
630750f12e5Svisa 	 * Set up forwarding of requests from PCI memory space.
631750f12e5Svisa 	 *
632750f12e5Svisa 	 * BAR0 (size 2^14) forwards to internal CSRs.
633750f12e5Svisa 	 * BAR1 (size configurable) and BAR2 (size 2^41) forward to DRAM.
634750f12e5Svisa 	 *
635750f12e5Svisa 	 * This code relies on BAR2 to forward DRAM requests.
636750f12e5Svisa 	 * Forwarding through BAR1 is disabled.
637750f12e5Svisa 	 */
638750f12e5Svisa 
639750f12e5Svisa 	bus_space_write_8(port->port_iot, port->port_pem_ioh,
640750f12e5Svisa 	    PEM_P2N_BAR_START(0), 0);
641750f12e5Svisa 	bus_space_write_8(port->port_iot, port->port_pem_ioh,
642750f12e5Svisa 	    PEM_P2N_BAR_START(1), PEM_BAR2_SIZE);
643750f12e5Svisa 	bus_space_write_8(port->port_iot, port->port_pem_ioh,
644750f12e5Svisa 	    PEM_P2N_BAR_START(2), 0);
645750f12e5Svisa 
646750f12e5Svisa 	/* Set BAR1 size to 256 MiB, enable BAR2. */
647750f12e5Svisa 	val = bus_space_read_8(port->port_iot, port->port_pem_ioh,
648750f12e5Svisa 	    PEM_BAR_CTL(cfg));
649750f12e5Svisa 	val &= ~PEM_BAR_CTL_BAR1_SIZ_M;
650750f12e5Svisa 	val |= PEM_BAR_CTL_BAR1_SIZ_256M;
651750f12e5Svisa 	val |= PEM_BAR_CTL_BAR2_ENB;
652750f12e5Svisa 	val &= ~PEM_BAR_CTL_BAR2_ESX_M;
653750f12e5Svisa 	val |= 1UL << PEM_BAR_CTL_BAR2_ESX_S;
654750f12e5Svisa 	val |= PEM_BAR_CTL_BAR2_CAX;
655750f12e5Svisa 	bus_space_write_8(port->port_iot, port->port_pem_ioh,
656750f12e5Svisa 	    PEM_BAR_CTL(cfg), val);
657750f12e5Svisa 
658750f12e5Svisa 	/* Disable BAR1 mappings. */
659750f12e5Svisa 	for (i = 0; i < 16; i++) {
660750f12e5Svisa 		bus_space_write_8(port->port_iot, port->port_pem_ioh,
661750f12e5Svisa 		    PEM_BAR1_INDEX(cfg, i), 0);
662750f12e5Svisa 	}
663750f12e5Svisa 
664750f12e5Svisa 	return 0;
665750f12e5Svisa }
666750f12e5Svisa 
667750f12e5Svisa int
octpcie_port_is_host(struct octpcie_port * port)668750f12e5Svisa octpcie_port_is_host(struct octpcie_port *port)
669750f12e5Svisa {
670750f12e5Svisa 	uint32_t chipid;
671750f12e5Svisa 	int host = 0;
672750f12e5Svisa 
673750f12e5Svisa 	chipid = octeon_get_chipid();
674750f12e5Svisa 	switch (octeon_model_family(chipid)) {
675750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN61XX:
676750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN63XX:
677750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN66XX:
678750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN68XX:
679750f12e5Svisa 		if ((octeon_xkphys_read_8(MIO_RST_CTL(port->port_index)) &
680750f12e5Svisa 		    MIO_RST_CTL_PRTMODE) != 0)
681750f12e5Svisa 			host = 1;
682750f12e5Svisa 		break;
683750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN71XX:
684750f12e5Svisa 		if ((octeon_xkphys_read_8(RST_CTL(port->port_index)) &
685750f12e5Svisa 		    RST_CTL_HOST_MODE) != 0)
686750f12e5Svisa 			host = 1;
687750f12e5Svisa 		break;
688750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN73XX:
689750f12e5Svisa 	case OCTEON_MODEL_FAMILY_CN78XX:
690750f12e5Svisa 		if ((bus_space_read_8(port->port_iot, port->port_pem_ioh,
691750f12e5Svisa 		    PEM_STRAP) & PEM_STRAP_PIMODE_M) == PEM_STRAP_PIMODE_RC)
692750f12e5Svisa 			host = 1;
693750f12e5Svisa 	default:
694750f12e5Svisa 		break;
695750f12e5Svisa 	}
696750f12e5Svisa 	return host;
697750f12e5Svisa }
698750f12e5Svisa 
699750f12e5Svisa int
octpcie_print(void * aux,const char * pnp)700750f12e5Svisa octpcie_print(void *aux, const char *pnp)
701750f12e5Svisa {
702750f12e5Svisa 	struct pcibus_attach_args *pba = aux;
703750f12e5Svisa 
704750f12e5Svisa 	if (pnp)
705750f12e5Svisa 		printf("%s at %s", pba->pba_busname, pnp);
706750f12e5Svisa 	printf(" bus %d", pba->pba_bus);
707750f12e5Svisa 
708750f12e5Svisa 	return UNCONF;
709750f12e5Svisa }
710750f12e5Svisa 
711750f12e5Svisa void
octpcie_attach_hook(struct device * parent,struct device * self,struct pcibus_attach_args * pba)712750f12e5Svisa octpcie_attach_hook(struct device *parent, struct device *self,
713750f12e5Svisa     struct pcibus_attach_args *pba)
714750f12e5Svisa {
715750f12e5Svisa }
716750f12e5Svisa 
717750f12e5Svisa int
octpcie_bus_maxdevs(void * v,int busno)718750f12e5Svisa octpcie_bus_maxdevs(void *v, int busno)
719750f12e5Svisa {
720750f12e5Svisa 	return 1;
721750f12e5Svisa }
722750f12e5Svisa 
723750f12e5Svisa pcitag_t
octpcie_make_tag(void * unused,int b,int d,int f)724750f12e5Svisa octpcie_make_tag(void *unused, int b, int d, int f)
725750f12e5Svisa {
726750f12e5Svisa 	return (b << 16) | (d << 11) | (f << 8);
727750f12e5Svisa }
728750f12e5Svisa 
729750f12e5Svisa void
octpcie_decompose_tag(void * unused,pcitag_t tag,int * bp,int * dp,int * fp)730750f12e5Svisa octpcie_decompose_tag(void *unused, pcitag_t tag, int *bp, int *dp, int *fp)
731750f12e5Svisa {
732750f12e5Svisa 	if (bp != NULL)
733750f12e5Svisa 		*bp = (tag >> 16) & 0xff;
734750f12e5Svisa 	if (dp != NULL)
735750f12e5Svisa 		*dp = (tag >> 11) & 0x1f;
736750f12e5Svisa 	if (fp != NULL)
737750f12e5Svisa 		*fp = (tag >> 8) & 0x7;
738750f12e5Svisa }
739750f12e5Svisa 
740750f12e5Svisa int
octpcie_conf_size(void * v,pcitag_t tag)741750f12e5Svisa octpcie_conf_size(void *v, pcitag_t tag)
742750f12e5Svisa {
743750f12e5Svisa 	return PCIE_CONFIG_SPACE_SIZE;
744750f12e5Svisa }
745750f12e5Svisa 
746750f12e5Svisa pcireg_t
octpcie_conf_read(void * v,pcitag_t tag,int offset)747750f12e5Svisa octpcie_conf_read(void *v, pcitag_t tag, int offset)
748750f12e5Svisa {
749750f12e5Svisa 	struct octpcie_port * port = v;
750750f12e5Svisa 	int bus;
751750f12e5Svisa 
752750f12e5Svisa 	octpcie_decompose_tag(NULL, tag, &bus, NULL, NULL);
753750f12e5Svisa 	if (bus == 0) {
754750f12e5Svisa 		return bus_space_read_4(port->port_iot, port->port_pciecfg_ioh,
755750f12e5Svisa 		    tag | (offset & 0xfffc));
756750f12e5Svisa 	}
757750f12e5Svisa 	return 0xffffffff;
758750f12e5Svisa }
759750f12e5Svisa 
760750f12e5Svisa void
octpcie_conf_write(void * v,pcitag_t tag,int offset,pcireg_t data)761750f12e5Svisa octpcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t data)
762750f12e5Svisa {
763750f12e5Svisa 	struct octpcie_port * port = v;
764750f12e5Svisa 	int bus;
765750f12e5Svisa 
766750f12e5Svisa 	octpcie_decompose_tag(NULL, tag, &bus, NULL, NULL);
767750f12e5Svisa 	if (bus == 0) {
768750f12e5Svisa 		bus_space_write_4(port->port_iot, port->port_pciecfg_ioh,
769750f12e5Svisa 		    tag | (offset & 0xfffc), data);
770750f12e5Svisa 	}
771750f12e5Svisa }
772750f12e5Svisa 
773750f12e5Svisa int
octpcie_pci_intr_map(struct pci_attach_args * pa,pci_intr_handle_t * ihp)774750f12e5Svisa octpcie_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
775750f12e5Svisa {
776750f12e5Svisa 	struct octpcie_port *port = pa->pa_pc->pc_conf_v;
777750f12e5Svisa 	struct octpcie_softc *sc = port->port_sc;
778750f12e5Svisa 	int dev, pin;
779750f12e5Svisa 
780750f12e5Svisa 	if (pa->pa_intrpin == 0 || pa->pa_intrpin > PCI_INTERRUPT_PIN_MAX)
781750f12e5Svisa 		return -1;
782750f12e5Svisa 
783750f12e5Svisa 	if (pa->pa_bridgetag != NULL) {
784750f12e5Svisa 		pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, NULL);
785750f12e5Svisa 		pin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev);
786750f12e5Svisa 		if (pa->pa_bridgeih[pin - 1] == (pci_intr_handle_t)-1)
787750f12e5Svisa 			return -1;
788750f12e5Svisa 		*ihp = pa->pa_bridgeih[pin - 1];
789750f12e5Svisa 		return 0;
790750f12e5Svisa 	}
791750f12e5Svisa 
792750f12e5Svisa 	if (sc->sc_cfg->cfg_has_ciu3)
793750f12e5Svisa 		*ihp = pa->pa_intrpin - 1 +
794750f12e5Svisa 		    CIU3_PEM_INTSN_INTA(port->port_index);
795750f12e5Svisa 	else
796750f12e5Svisa 		*ihp = pa->pa_intrpin - 1 + CIU_INT_PCI_INTA;
797750f12e5Svisa 	return 0;
798750f12e5Svisa }
799750f12e5Svisa 
800750f12e5Svisa const char *
octpcie_pci_intr_string(void * cookie,pci_intr_handle_t ih)801750f12e5Svisa octpcie_pci_intr_string(void *cookie, pci_intr_handle_t ih)
802750f12e5Svisa {
803750f12e5Svisa 	static char irqstr[16];
804750f12e5Svisa 
805750f12e5Svisa 	snprintf(irqstr, sizeof(irqstr), "irq %lu", ih);
806750f12e5Svisa 	return irqstr;
807750f12e5Svisa }
808750f12e5Svisa 
809750f12e5Svisa void *
octpcie_pci_intr_establish(void * cookie,pci_intr_handle_t ih,int level,int (* cb)(void *),void * cbarg,char * name)810750f12e5Svisa octpcie_pci_intr_establish(void *cookie, pci_intr_handle_t ih, int level,
811750f12e5Svisa     int (*cb)(void *), void *cbarg, char *name)
812750f12e5Svisa {
813750f12e5Svisa 	return octeon_intr_establish(ih, level, cb, cbarg, name);
814750f12e5Svisa }
815750f12e5Svisa 
816750f12e5Svisa void
octpcie_pci_intr_disestablish(void * cookie,void * ihp)817750f12e5Svisa octpcie_pci_intr_disestablish(void *cookie, void *ihp)
818750f12e5Svisa {
819750f12e5Svisa 	octeon_intr_disestablish(ihp);
820750f12e5Svisa }
821750f12e5Svisa 
822750f12e5Svisa int
octpcie_io_map(bus_space_tag_t t,bus_addr_t offs,bus_size_t size,int flags,bus_space_handle_t * bshp)823750f12e5Svisa octpcie_io_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
824750f12e5Svisa     bus_space_handle_t *bshp)
825750f12e5Svisa {
826750f12e5Svisa 	struct octpcie_port *port = t->bus_private;
827750f12e5Svisa 
828750f12e5Svisa 	if (offs + size > SLI_PCIEIO_SIZE)
829750f12e5Svisa 		return EINVAL;
830750f12e5Svisa 
831750f12e5Svisa 	return bus_space_map(port->port_iot,
832750f12e5Svisa 	    SLI_PCIEIO_BASE(port->port_index) + offs, size, flags, bshp);
833750f12e5Svisa }
834750f12e5Svisa 
835750f12e5Svisa int
octpcie_mem_map(bus_space_tag_t t,bus_addr_t offs,bus_size_t size,int flags,bus_space_handle_t * bshp)836750f12e5Svisa octpcie_mem_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
837750f12e5Svisa     bus_space_handle_t *bshp)
838750f12e5Svisa {
839750f12e5Svisa 	struct octpcie_port *port = t->bus_private;
840750f12e5Svisa 
841750f12e5Svisa 	if (offs + size > SLI_PCIEMEM_SIZE)
842750f12e5Svisa 		return EINVAL;
843750f12e5Svisa 
844750f12e5Svisa 	return bus_space_map(port->port_iot,
845750f12e5Svisa 	    SLI_PCIEMEM_BASE(port->port_index) + offs, size, flags, bshp);
846750f12e5Svisa }
847750f12e5Svisa 
848750f12e5Svisa uint32_t
octpcie_cfgreg_read(struct octpcie_port * port,uint32_t off)849750f12e5Svisa octpcie_cfgreg_read(struct octpcie_port *port, uint32_t off)
850750f12e5Svisa {
851750f12e5Svisa 	uint64_t val;
852750f12e5Svisa 
853750f12e5Svisa 	bus_space_write_8(port->port_iot, port->port_pem_ioh, PEM_CFG_RD, off);
854750f12e5Svisa 	val = bus_space_read_8(port->port_iot, port->port_pem_ioh, PEM_CFG_RD);
855750f12e5Svisa 
856750f12e5Svisa 	return (uint32_t)(val >> 32);
857750f12e5Svisa }
858750f12e5Svisa 
859750f12e5Svisa void
octpcie_cfgreg_write(struct octpcie_port * port,uint32_t off,uint32_t val)860750f12e5Svisa octpcie_cfgreg_write(struct octpcie_port *port, uint32_t off, uint32_t val)
861750f12e5Svisa {
862750f12e5Svisa 	bus_space_write_4(port->port_iot, port->port_pem_ioh, PEM_CFG_WR,
863750f12e5Svisa 	    ((uint64_t)val << 32) | off);
864750f12e5Svisa 	(void)bus_space_read_4(port->port_iot, port->port_pem_ioh, PEM_CFG_WR);
865750f12e5Svisa }
866