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