xref: /openbsd-src/sys/arch/octeon/dev/octeon_iobus.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: octeon_iobus.c,v 1.16 2016/06/22 13:09:35 visa Exp $ */
2 
3 /*
4  * Copyright (c) 2000-2004 Opsycon AB  (www.opsycon.se)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 /*
30  * This is a iobus driver.
31  * It handles configuration of all devices on the processor bus except UART.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/conf.h>
38 #include <sys/malloc.h>
39 #include <sys/device.h>
40 #include <sys/proc.h>
41 #include <sys/atomic.h>
42 
43 #include <machine/autoconf.h>
44 #include <machine/intr.h>
45 #include <machine/octeonvar.h>
46 #include <machine/octeonreg.h>
47 #include <machine/octeon_model.h>
48 
49 #include <octeon/dev/iobusvar.h>
50 #include <octeon/dev/cn30xxgmxreg.h>
51 #include <octeon/dev/octhcireg.h>	/* USBN_BASE */
52 #include <octeon/dev/octuctlreg.h>
53 
54 int	iobusmatch(struct device *, void *, void *);
55 void	iobusattach(struct device *, struct device *, void *);
56 int	iobusprint(void *, const char *);
57 int	iobussubmatch(struct device *, void *, void *);
58 int	iobussearch(struct device *, void *, void *);
59 
60 u_int8_t iobus_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
61 u_int16_t iobus_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
62 u_int32_t iobus_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
63 u_int64_t iobus_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t);
64 
65 void	 iobus_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
66 	    u_int8_t);
67 void	 iobus_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
68 	    u_int16_t);
69 void	 iobus_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
70 	    u_int32_t);
71 void	 iobus_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t,
72 	    u_int64_t);
73 
74 void	 iobus_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
75 	    u_int8_t *, bus_size_t);
76 void	 iobus_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
77 	    const u_int8_t *, bus_size_t);
78 void	 iobus_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
79 	    u_int8_t *, bus_size_t);
80 void	 iobus_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
81 	    const u_int8_t *, bus_size_t);
82 void	 iobus_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
83 	    u_int8_t *, bus_size_t);
84 void	 iobus_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
85 	    const u_int8_t *, bus_size_t);
86 
87 bus_addr_t iobus_pa_to_device(paddr_t);
88 paddr_t	 iobus_device_to_pa(bus_addr_t);
89 
90 struct cfattach iobus_ca = {
91 	sizeof(struct device), iobusmatch, iobusattach
92 };
93 
94 struct cfdriver iobus_cd = {
95 	NULL, "iobus", DV_DULL
96 };
97 
98 bus_space_t iobus_tag = {
99 	.bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
100 	.bus_private = NULL,
101 	._space_read_1 =	generic_space_read_1,
102 	._space_write_1 =	generic_space_write_1,
103 	._space_read_2 =	generic_space_read_2,
104 	._space_write_2 =	generic_space_write_2,
105 	._space_read_4 =	generic_space_read_4,
106 	._space_write_4 =	generic_space_write_4,
107 	._space_read_8 =	generic_space_read_8,
108 	._space_write_8 =	generic_space_write_8,
109 	._space_read_raw_2 =	generic_space_read_raw_2,
110 	._space_write_raw_2 =	generic_space_write_raw_2,
111 	._space_read_raw_4 =	generic_space_read_raw_4,
112 	._space_write_raw_4 =	generic_space_write_raw_4,
113 	._space_read_raw_8 =	generic_space_read_raw_8,
114 	._space_write_raw_8 =	generic_space_write_raw_8,
115 	._space_map =		iobus_space_map,
116 	._space_unmap =		iobus_space_unmap,
117 	._space_subregion =	generic_space_region,
118 	._space_vaddr =		generic_space_vaddr
119 };
120 
121 bus_space_handle_t iobus_h;
122 
123 struct machine_bus_dma_tag iobus_bus_dma_tag = {
124 	NULL,			/* _cookie */
125 	_dmamap_create,
126 	_dmamap_destroy,
127 	_dmamap_load,
128 	_dmamap_load_mbuf,
129 	_dmamap_load_uio,
130 	_dmamap_load_raw,
131 	_dmamap_load_buffer,
132 	_dmamap_unload,
133 	_dmamap_sync,
134 	_dmamem_alloc,
135 	_dmamem_free,
136 	_dmamem_map,
137 	_dmamem_unmap,
138 	_dmamem_mmap,
139 	iobus_pa_to_device,
140 	iobus_device_to_pa,
141 	0
142 };
143 
144 /*
145  * List of iobus child devices whose base addresses are too large to be
146  * recorded in the kernel configuration file. So look them up from here instead.
147  */
148 
149 static const struct octeon_iobus_addrs iobus_addrs[] = {
150 	{ "octcf",	OCTEON_CF_BASE  },
151 	{ "octrng",	OCTEON_RNG_BASE },
152 	{ "dwctwo",	USBN_BASE       },
153 	{ "amdcf",	OCTEON_AMDCF_BASE},
154 	{ "octuctl",	UCTL_BASE	},
155 };
156 
157 /* There can only be one. */
158 int	iobus_found;
159 
160 /*
161  * Match bus only to targets which have this bus.
162  */
163 int
164 iobusmatch(struct device *parent, void *match, void *aux)
165 {
166 	if (iobus_found)
167 		return (0);
168 
169 	return (1);
170 }
171 
172 int
173 iobusprint(void *aux, const char *iobus)
174 {
175 	struct iobus_attach_args *aa = aux;
176 
177 	if (iobus != NULL)
178 		printf("%s at %s", aa->aa_name, iobus);
179 
180 	if (aa->aa_addr != 0)
181 		printf(" base 0x%lx", aa->aa_addr);
182 	if (aa->aa_irq >= 0)
183 		printf(" irq %d", aa->aa_irq);
184 
185 	return (UNCONF);
186 }
187 
188 int
189 iobussubmatch(struct device *parent, void *vcf, void *args)
190 {
191 	struct cfdata *cf = vcf;
192 	struct iobus_attach_args *aa = args;
193 
194 	if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0)
195 		return 0;
196 
197 	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)aa->aa_addr)
198 		return 0;
199 
200 	return (*cf->cf_attach->ca_match)(parent, cf, aa);
201 }
202 
203 void
204 iobusattach(struct device *parent, struct device *self, void *aux)
205 {
206 	struct iobus_attach_args aa;
207 	struct octeon_config oc;
208 	struct device *sc = self;
209 	int chipid, i, ngmx;
210 
211 	/*
212 	 * Map and setup CIU control registers.
213 	 */
214 	if (bus_space_map(&iobus_tag, OCTEON_CIU_BASE, OCTEON_CIU_SIZE, 0,
215 		&iobus_h)) {
216 		printf(": can't map CIU control registers\n");
217 		return;
218 	}
219 
220 	iobus_found = 1;
221 
222 	printf("\n");
223 
224 	octeon_intr_init();
225 
226 	/* XXX */
227 	oc.mc_iobus_bust = &iobus_tag;
228 	oc.mc_iobus_dmat = &iobus_bus_dma_tag;
229 	void	cn30xxfpa_bootstrap(struct octeon_config *);
230 	cn30xxfpa_bootstrap(&oc);
231 	void	cn30xxpow_bootstrap(struct octeon_config *);
232 	cn30xxpow_bootstrap(&oc);
233 
234 	/*
235 	 * Attach all subdevices as described in the config file.
236 	 */
237 	config_search(iobussearch, self, sc);
238 
239 	chipid = octeon_get_chipid();
240 	switch (octeon_model_family(chipid)) {
241 	case OCTEON_MODEL_FAMILY_CN30XX:
242 	case OCTEON_MODEL_FAMILY_CN50XX:
243 	default:
244 		ngmx = 1;
245 		break;
246 	case OCTEON_MODEL_FAMILY_CN61XX:
247 		ngmx = 2;
248 		break;
249 	}
250 	for (i = 0; i < ngmx; i++) {
251 		aa.aa_name = "cn30xxgmx";
252 		aa.aa_bust = &iobus_tag;
253 		aa.aa_dmat = &iobus_bus_dma_tag;
254 		aa.aa_addr = GMX0_BASE_PORT0 + GMX_BLOCK_SIZE * i;
255 		aa.aa_irq = -1;
256 		aa.aa_unitno = i;
257 		config_found_sm(self, &aa, iobusprint, iobussubmatch);
258 	}
259 }
260 
261 int
262 iobussearch(struct device *parent, void *v, void *aux)
263 {
264 	struct iobus_attach_args aa;
265 	struct cfdata *cf = v;
266 	int i;
267 
268 	aa.aa_name = cf->cf_driver->cd_name;
269 	aa.aa_bust = &iobus_tag;
270 	aa.aa_dmat = &iobus_bus_dma_tag;
271 	aa.aa_addr = cf->cf_loc[0];
272 	aa.aa_irq  = cf->cf_loc[1];
273 	aa.aa_unitno = cf->cf_unit;
274 
275 	/* No address specified, try to look it up. */
276 	if (aa.aa_addr == -1) {
277 		for (i = 0; i < nitems(iobus_addrs); i++) {
278 			if (strcmp(iobus_addrs[i].name, cf->cf_driver->cd_name) == 0)
279 				aa.aa_addr = iobus_addrs[i].address;
280 		}
281 		if (aa.aa_addr == -1)
282 			return 0;
283 	}
284 
285 	if (cf->cf_attach->ca_match(parent, cf, &aa) == 0)
286 		return 0;
287 
288 	config_attach(parent, cf, &aa, iobusprint);
289 	return 1;
290 }
291 
292 int
293 iobus_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
294     int flags, bus_space_handle_t *bshp)
295 {
296 	if (ISSET(flags, BUS_SPACE_MAP_KSEG0)) {
297 		*bshp = PHYS_TO_CKSEG0(offs);
298 		return 0;
299 	}
300 	if (ISSET(flags, BUS_SPACE_MAP_CACHEABLE))
301 		offs +=
302 		    PHYS_TO_XKPHYS(0, CCA_CACHED) - PHYS_TO_XKPHYS(0, CCA_NC);
303 	*bshp = t->bus_base + offs;
304 	return 0;
305 }
306 
307 void
308 iobus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
309 {
310 }
311 
312 /*
313  * Iobus bus_dma helpers.
314  */
315 
316 bus_addr_t
317 iobus_pa_to_device(paddr_t pa)
318 {
319 	return (bus_addr_t)pa;
320 }
321 
322 paddr_t
323 iobus_device_to_pa(bus_addr_t addr)
324 {
325 	return (paddr_t)addr;
326 }
327