dwlpx_pci.c revision 1.20 1 /* $NetBSD: dwlpx_pci.c,v 1.20 2021/05/07 16:58:34 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1997 by Matthew Jacob
5 * NASA AMES Research Center.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice immediately at the beginning of the file, without modification,
13 * this list of conditions, and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34
35 __KERNEL_RCSID(0, "$NetBSD: dwlpx_pci.c,v 1.20 2021/05/07 16:58:34 thorpej Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/pcivar.h>
44 #include <alpha/tlsb/tlsbreg.h>
45 #include <alpha/pci/dwlpxreg.h>
46 #include <alpha/pci/dwlpxvar.h>
47
48 #define KV(_addr) ((void *)ALPHA_PHYS_TO_K0SEG((_addr)))
49
50 static void dwlpx_attach_hook(device_t, device_t,
51 struct pcibus_attach_args *);
52 static int dwlpx_bus_maxdevs(void *, int);
53 static pcitag_t dwlpx_make_tag(void *, int, int, int);
54 static void dwlpx_decompose_tag(void *, pcitag_t, int *, int *,
55 int *);
56 static pcireg_t dwlpx_conf_read(void *, pcitag_t, int);
57 static void dwlpx_conf_write(void *, pcitag_t, int, pcireg_t);
58
59 void
60 dwlpx_pci_init(pci_chipset_tag_t pc, void *v)
61 {
62 pc->pc_conf_v = v;
63 pc->pc_attach_hook = dwlpx_attach_hook;
64 pc->pc_bus_maxdevs = dwlpx_bus_maxdevs;
65 pc->pc_make_tag = dwlpx_make_tag;
66 pc->pc_decompose_tag = dwlpx_decompose_tag;
67 pc->pc_conf_read = dwlpx_conf_read;
68 pc->pc_conf_write = dwlpx_conf_write;
69 }
70
71 static void
72 dwlpx_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba)
73 {
74 }
75
76 static int
77 dwlpx_bus_maxdevs(void *cpv, int busno)
78 {
79 return DWLPX_MAXDEV;
80 }
81
82 static pcitag_t
83 dwlpx_make_tag(void *cpv, int b, int d, int f)
84 {
85 pcitag_t tag;
86 int hpcdev, pci_idsel;
87
88 pci_idsel = (1 << ((d & 0x3) + 2));
89 hpcdev = d >> 2;
90 tag = (b << 24) | (hpcdev << 22) | (pci_idsel << 16) | (f << 13);
91 return (tag);
92 }
93
94 static void
95 dwlpx_decompose_tag(void *cpv, pcitag_t tag, int *bp, int *dp, int *fp)
96 {
97
98 if (bp != NULL)
99 *bp = (tag >> 24) & 0xff;
100 if (dp != NULL) {
101 int j, i = (tag >> 18) & 0xf;
102 j = -1;
103 while (i != 0) {
104 j++;
105 i >>= 1;
106 }
107 j += (((tag >> 22) & 3) << 2);
108 *dp = j;
109 }
110 if (fp != NULL)
111 *fp = (tag >> 13) & 0x7;
112 }
113
114 static pcireg_t
115 dwlpx_conf_read(void *cpv, pcitag_t tag, int offset)
116 {
117 struct dwlpx_config *ccp = cpv;
118 struct dwlpx_softc *sc;
119 pcireg_t *dp, data = (pcireg_t) -1;
120 unsigned long paddr;
121 int secondary, i, s = 0;
122 uint32_t rvp;
123
124 if ((unsigned int)offset >= PCI_CONF_SIZE)
125 return (data);
126
127 if (ccp == NULL) {
128 panic("NULL ccp in dwlpx_conf_read");
129 }
130 sc = ccp->cc_sc;
131 secondary = tag >> 24;
132 if (secondary) {
133 tag &= 0x1fffff;
134 tag |= (secondary << 21);
135
136 #if 0
137 printf("read secondary %d reg %x (tag %x)",
138 secondary, offset, tag);
139 #endif
140
141 alpha_pal_draina();
142 s = splhigh();
143 /*
144 * Set up HPCs for type 1 cycles.
145 */
146 for (i = 0; i < sc->dwlpx_nhpc; i++) {
147 rvp = REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) |
148 PCIA_CTL_T1CYC;
149 alpha_mb();
150 REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) = rvp;
151 alpha_mb();
152 }
153 }
154 paddr = (unsigned long) tag;
155 paddr |= DWLPX_PCI_CONF;
156 paddr |= ((unsigned long) ((offset >> 2) << 7));
157 paddr |= (((unsigned long) sc->dwlpx_hosenum) << 34);
158 paddr |= (((u_long) sc->dwlpx_node - 4) << 36);
159 paddr |= (1LL << 39);
160 paddr |= (3LL << 3); /* 32 Bit PCI byte enables */
161
162 dp = (pcireg_t *)KV(paddr);
163 if (badaddr(dp, sizeof (*dp)) == 0) {
164 data = *dp;
165 }
166 if (secondary) {
167 alpha_pal_draina();
168 for (i = 0; i < sc->dwlpx_nhpc; i++) {
169 rvp = REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) &
170 ~PCIA_CTL_T1CYC;
171 alpha_mb();
172 REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) = rvp;
173 alpha_mb();
174 }
175 (void) splx(s);
176 #if 0
177 printf("=%x\n", data);
178 #endif
179 }
180 return (data);
181 }
182
183 static void
184 dwlpx_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
185 {
186 struct dwlpx_config *ccp = cpv;
187 struct dwlpx_softc *sc;
188 pcireg_t *dp;
189 unsigned long paddr;
190 int secondary, i, s = 0;
191 uint32_t rvp;
192
193 if ((unsigned int)offset >= PCI_CONF_SIZE)
194 return;
195
196 if (ccp == NULL) {
197 panic("NULL ccp in dwlpx_conf_write");
198 }
199 sc = ccp->cc_sc;
200 secondary = tag >> 24;
201 if (secondary) {
202 tag &= 0x1fffff;
203 tag |= (secondary << 21);
204 #if 0
205 printf("write secondary %d reg %x (tag %x) with %x\n",
206 secondary, offset, tag, data);
207 #endif
208
209 alpha_pal_draina();
210 s = splhigh();
211 /*
212 * Set up HPCs for type 1 cycles.
213 */
214 for (i = 0; i < sc->dwlpx_nhpc; i++) {
215 rvp = REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) |
216 PCIA_CTL_T1CYC;
217 alpha_mb();
218 REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) = rvp;
219 alpha_mb();
220 }
221 }
222 paddr = (unsigned long) tag;
223 paddr |= DWLPX_PCI_CONF;
224 paddr |= ((unsigned long) ((offset >> 2) << 7));
225 paddr |= (((unsigned long) sc->dwlpx_hosenum) << 34);
226 paddr |= (((u_long) sc->dwlpx_node - 4) << 36);
227 paddr |= (1LL << 39);
228 paddr |= (3LL << 3); /* 32 bit PCI byte enables */
229
230 dp = (pcireg_t *)KV(paddr);
231 *dp = data;
232 alpha_mb();
233 if (secondary) {
234 alpha_pal_draina();
235 for (i = 0; i < sc->dwlpx_nhpc; i++) {
236 rvp = REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) &
237 ~PCIA_CTL_T1CYC;
238 alpha_mb();
239 REGVAL(PCIA_CTL(i) + ccp->cc_sysbase) = rvp;
240 alpha_mb();
241 }
242 (void) splx(s);
243 }
244 }
245