xref: /openbsd-src/sys/arch/octeon/dev/octeon_iobus.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: octeon_iobus.c,v 1.7 2014/07/09 23:03:22 pirofti 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 
42 #include <machine/autoconf.h>
43 #include <machine/atomic.h>
44 #include <machine/intr.h>
45 #include <machine/octeonvar.h>
46 #include <machine/octeonreg.h>
47 
48 #include <octeon/dev/iobusvar.h>
49 #include <octeon/dev/cn30xxgmxreg.h>
50 
51 int	 iobusmatch(struct device *, void *, void *);
52 void	 iobusattach(struct device *, struct device *, void *);
53 int	 iobusprint(void *, const char *);
54 int	 iobussubmatch(struct device *, void *, void *);
55 
56 u_int8_t iobus_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
57 u_int16_t iobus_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
58 u_int32_t iobus_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
59 u_int64_t iobus_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t);
60 
61 void	 iobus_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
62 	    u_int8_t);
63 void	 iobus_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
64 	    u_int16_t);
65 void	 iobus_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
66 	    u_int32_t);
67 void	 iobus_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t,
68 	    u_int64_t);
69 
70 void	 iobus_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
71 	    u_int8_t *, bus_size_t);
72 void	 iobus_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
73 	    const u_int8_t *, bus_size_t);
74 void	 iobus_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
75 	    u_int8_t *, bus_size_t);
76 void	 iobus_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
77 	    const u_int8_t *, bus_size_t);
78 void	 iobus_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
79 	    u_int8_t *, bus_size_t);
80 void	 iobus_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
81 	    const u_int8_t *, bus_size_t);
82 
83 int	 iobus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
84 	    bus_space_handle_t *);
85 void	 iobus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
86 int	 iobus_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t,
87 	    bus_size_t, bus_space_handle_t *);
88 
89 void	*iobus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
90 
91 bus_addr_t iobus_pa_to_device(paddr_t);
92 paddr_t	 iobus_device_to_pa(bus_addr_t);
93 
94 struct cfattach iobus_ca = {
95 	sizeof(struct device), iobusmatch, iobusattach
96 };
97 
98 struct cfdriver iobus_cd = {
99 	NULL, "iobus", DV_DULL
100 };
101 
102 bus_space_t iobus_tag = {
103 	.bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
104 	.bus_private = NULL,
105 	._space_read_1 =	generic_space_read_1,
106 	._space_write_1 =	generic_space_write_1,
107 	._space_read_2 =	generic_space_read_2,
108 	._space_write_2 =	generic_space_write_2,
109 	._space_read_4 =	generic_space_read_4,
110 	._space_write_4 =	generic_space_write_4,
111 	._space_read_8 =	generic_space_read_8,
112 	._space_write_8 =	generic_space_write_8,
113 	._space_read_raw_2 =	generic_space_read_raw_2,
114 	._space_write_raw_2 =	generic_space_write_raw_2,
115 	._space_read_raw_4 =	generic_space_read_raw_4,
116 	._space_write_raw_4 =	generic_space_write_raw_4,
117 	._space_read_raw_8 =	generic_space_read_raw_8,
118 	._space_write_raw_8 =	generic_space_write_raw_8,
119 	._space_map =		iobus_space_map,
120 	._space_unmap =		iobus_space_unmap,
121 	._space_subregion =	generic_space_region,
122 	._space_vaddr =		generic_space_vaddr
123 };
124 
125 bus_space_handle_t iobus_h;
126 
127 struct machine_bus_dma_tag iobus_bus_dma_tag = {
128 	NULL,			/* _cookie */
129 	_dmamap_create,
130 	_dmamap_destroy,
131 	_dmamap_load,
132 	_dmamap_load_mbuf,
133 	_dmamap_load_uio,
134 	_dmamap_load_raw,
135 	_dmamap_load_buffer,
136 	_dmamap_unload,
137 	_dmamap_sync,
138 	_dmamem_alloc,
139 	_dmamem_free,
140 	_dmamem_map,
141 	_dmamem_unmap,
142 	_dmamem_mmap,
143 	iobus_pa_to_device,
144 	iobus_device_to_pa,
145 	0
146 };
147 
148 /*
149  * List of iobus child devices.
150  */
151 
152 #define	IOBUSDEV(name, unitno, unit)	\
153 	{ name, unitno, unit, &iobus_tag, &iobus_bus_dma_tag }
154 const struct iobus_unit iobus_units[] = {
155 	{ OCTEON_CF_BASE, 0 },			/* octcf */
156 	{ 0, 0 },				/* pcibus */
157 	{ GMX0_BASE_PORT0, CIU_INT_GMX_DRP0 },	/* cn30xxgmx */
158 	{ OCTEON_RNG_BASE, 0 },			/* octrng */
159 	{ 0, CIU_INT_USB },			/* octhci */
160 };
161 struct iobus_attach_args iobus_children[] = {
162 	IOBUSDEV("octcf", 0, &iobus_units[0]),
163 	IOBUSDEV("pcibus", 0, &iobus_units[1]),
164 	IOBUSDEV("cn30xxgmx", 0, &iobus_units[2]),
165 	IOBUSDEV("octrng", 0, &iobus_units[3]),
166 	IOBUSDEV("octhci", 0, &iobus_units[4]),
167 };
168 #undef	IOBUSDEV
169 
170 /*
171  * Match bus only to targets which have this bus.
172  */
173 int
174 iobusmatch(struct device *parent, void *match, void *aux)
175 {
176 	return (1);
177 }
178 
179 int
180 iobusprint(void *aux, const char *iobus)
181 {
182 	struct iobus_attach_args *aa = aux;
183 
184 	if (iobus != NULL)
185 		printf("%s at %s", aa->aa_name, iobus);
186 
187 	if (aa->aa_unit->addr != 0)
188 		printf(" base 0x%lx", aa->aa_unit->addr);
189 	if (aa->aa_unit->irq >= 0)
190 		printf(" irq %d", aa->aa_unit->irq);
191 
192 	return (UNCONF);
193 }
194 
195 int
196 iobussubmatch(struct device *parent, void *vcf, void *args)
197 {
198 	struct cfdata *cf = vcf;
199 	struct iobus_attach_args *aa = args;
200 
201 	if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0)
202 		return 0;
203 
204 	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)aa->aa_unit->addr)
205 		return 0;
206 
207 	return (*cf->cf_attach->ca_match)(parent, cf, aa);
208 }
209 
210 void
211 iobusattach(struct device *parent, struct device *self, void *aux)
212 {
213 	struct octeon_config oc;
214 	uint i;
215 
216 	/*
217 	 * Map and setup CRIME control registers.
218 	 */
219 	if (bus_space_map(&iobus_tag, OCTEON_CIU_BASE, OCTEON_CIU_SIZE, 0,
220 		&iobus_h)) {
221 		printf(": can't map CIU control registers\n");
222 		return;
223 	}
224 
225 	printf("\n");
226 
227 	octeon_intr_init();
228 
229 	/* XXX */
230 	oc.mc_iobus_bust = &iobus_tag;
231 	oc.mc_iobus_dmat = &iobus_bus_dma_tag;
232 	void	cn30xxfpa_bootstrap(struct octeon_config *);
233 	cn30xxfpa_bootstrap(&oc);
234 	void	cn30xxpow_bootstrap(struct octeon_config *);
235 	cn30xxpow_bootstrap(&oc);
236 
237 	/*
238 	 * Attach subdevices.
239 	 */
240 	for (i = 0; i < nitems(iobus_children); i++)
241 		config_found_sm(self, iobus_children + i,
242 		    iobusprint, iobussubmatch);
243 }
244 
245 int
246 iobus_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
247     int flags, bus_space_handle_t *bshp)
248 {
249 	if (ISSET(flags, BUS_SPACE_MAP_KSEG0)) {
250 		*bshp = PHYS_TO_CKSEG0(offs);
251 		return 0;
252 	}
253 	if (ISSET(flags, BUS_SPACE_MAP_CACHEABLE))
254 		offs +=
255 		    PHYS_TO_XKPHYS(0, CCA_CACHED) - PHYS_TO_XKPHYS(0, CCA_NC);
256 	*bshp = t->bus_base + offs;
257 	return 0;
258 }
259 
260 void
261 iobus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
262 {
263 }
264 
265 /*
266  * Iobus bus_dma helpers.
267  */
268 
269 bus_addr_t
270 iobus_pa_to_device(paddr_t pa)
271 {
272 	return (bus_addr_t)pa;
273 }
274 
275 paddr_t
276 iobus_device_to_pa(bus_addr_t addr)
277 {
278 	return (paddr_t)addr;
279 }
280