xref: /openbsd/sys/arch/octeon/dev/octeon_iobus.c (revision 61e15267)
1*61e15267Ssyuu /*	$OpenBSD: octeon_iobus.c,v 1.1 2011/05/08 13:24:55 syuu Exp $ */
2*61e15267Ssyuu 
3*61e15267Ssyuu /*
4*61e15267Ssyuu  * Copyright (c) 2000-2004 Opsycon AB  (www.opsycon.se)
5*61e15267Ssyuu  *
6*61e15267Ssyuu  * Redistribution and use in source and binary forms, with or without
7*61e15267Ssyuu  * modification, are permitted provided that the following conditions
8*61e15267Ssyuu  * are met:
9*61e15267Ssyuu  * 1. Redistributions of source code must retain the above copyright
10*61e15267Ssyuu  *    notice, this list of conditions and the following disclaimer.
11*61e15267Ssyuu  * 2. Redistributions in binary form must reproduce the above copyright
12*61e15267Ssyuu  *    notice, this list of conditions and the following disclaimer in the
13*61e15267Ssyuu  *    documentation and/or other materials provided with the distribution.
14*61e15267Ssyuu  *
15*61e15267Ssyuu  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16*61e15267Ssyuu  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17*61e15267Ssyuu  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*61e15267Ssyuu  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19*61e15267Ssyuu  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*61e15267Ssyuu  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*61e15267Ssyuu  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*61e15267Ssyuu  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*61e15267Ssyuu  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*61e15267Ssyuu  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*61e15267Ssyuu  * SUCH DAMAGE.
26*61e15267Ssyuu  *
27*61e15267Ssyuu  */
28*61e15267Ssyuu 
29*61e15267Ssyuu /*
30*61e15267Ssyuu  * This is a iobus driver.
31*61e15267Ssyuu  * It handles configuration of all devices on the processor bus except UART.
32*61e15267Ssyuu  */
33*61e15267Ssyuu 
34*61e15267Ssyuu #include <sys/param.h>
35*61e15267Ssyuu #include <sys/systm.h>
36*61e15267Ssyuu #include <sys/kernel.h>
37*61e15267Ssyuu #include <sys/conf.h>
38*61e15267Ssyuu #include <sys/malloc.h>
39*61e15267Ssyuu #include <sys/device.h>
40*61e15267Ssyuu #include <sys/proc.h>
41*61e15267Ssyuu 
42*61e15267Ssyuu #include <mips64/archtype.h>
43*61e15267Ssyuu 
44*61e15267Ssyuu #include <machine/autoconf.h>
45*61e15267Ssyuu #include <machine/atomic.h>
46*61e15267Ssyuu #include <machine/intr.h>
47*61e15267Ssyuu 
48*61e15267Ssyuu #include <octeon/dev/octeonreg.h>
49*61e15267Ssyuu #include <octeon/dev/iobusvar.h>
50*61e15267Ssyuu 
51*61e15267Ssyuu int	 iobusmatch(struct device *, void *, void *);
52*61e15267Ssyuu void	 iobusattach(struct device *, struct device *, void *);
53*61e15267Ssyuu int	 iobusprint(void *, const char *);
54*61e15267Ssyuu int	 iobussubmatch(struct device *, void *, void *);
55*61e15267Ssyuu 
56*61e15267Ssyuu u_int8_t iobus_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
57*61e15267Ssyuu u_int16_t iobus_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
58*61e15267Ssyuu u_int32_t iobus_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
59*61e15267Ssyuu u_int64_t iobus_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t);
60*61e15267Ssyuu 
61*61e15267Ssyuu void	 iobus_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
62*61e15267Ssyuu 	    u_int8_t);
63*61e15267Ssyuu void	 iobus_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
64*61e15267Ssyuu 	    u_int16_t);
65*61e15267Ssyuu void	 iobus_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
66*61e15267Ssyuu 	    u_int32_t);
67*61e15267Ssyuu void	 iobus_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t,
68*61e15267Ssyuu 	    u_int64_t);
69*61e15267Ssyuu 
70*61e15267Ssyuu void	 iobus_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
71*61e15267Ssyuu 	    u_int8_t *, bus_size_t);
72*61e15267Ssyuu void	 iobus_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
73*61e15267Ssyuu 	    const u_int8_t *, bus_size_t);
74*61e15267Ssyuu void	 iobus_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
75*61e15267Ssyuu 	    u_int8_t *, bus_size_t);
76*61e15267Ssyuu void	 iobus_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
77*61e15267Ssyuu 	    const u_int8_t *, bus_size_t);
78*61e15267Ssyuu void	 iobus_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
79*61e15267Ssyuu 	    u_int8_t *, bus_size_t);
80*61e15267Ssyuu void	 iobus_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
81*61e15267Ssyuu 	    const u_int8_t *, bus_size_t);
82*61e15267Ssyuu 
83*61e15267Ssyuu int	 iobus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
84*61e15267Ssyuu 	    bus_space_handle_t *);
85*61e15267Ssyuu void	 iobus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
86*61e15267Ssyuu int	 iobus_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t,
87*61e15267Ssyuu 	    bus_size_t, bus_space_handle_t *);
88*61e15267Ssyuu 
89*61e15267Ssyuu void	*iobus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
90*61e15267Ssyuu 
91*61e15267Ssyuu bus_addr_t iobus_pa_to_device(paddr_t);
92*61e15267Ssyuu paddr_t	 iobus_device_to_pa(bus_addr_t);
93*61e15267Ssyuu 
94*61e15267Ssyuu struct cfattach iobus_ca = {
95*61e15267Ssyuu 	sizeof(struct device), iobusmatch, iobusattach
96*61e15267Ssyuu };
97*61e15267Ssyuu 
98*61e15267Ssyuu struct cfdriver iobus_cd = {
99*61e15267Ssyuu 	NULL, "iobus", DV_DULL
100*61e15267Ssyuu };
101*61e15267Ssyuu 
102*61e15267Ssyuu bus_space_t iobus_tag = {
103*61e15267Ssyuu 	.bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
104*61e15267Ssyuu 	.bus_private = NULL,
105*61e15267Ssyuu 	._space_read_1 =	generic_space_read_1,
106*61e15267Ssyuu 	._space_write_1 =	generic_space_write_1,
107*61e15267Ssyuu 	._space_read_2 =	generic_space_read_2,
108*61e15267Ssyuu 	._space_write_2 =	generic_space_write_2,
109*61e15267Ssyuu 	._space_read_4 =	generic_space_read_4,
110*61e15267Ssyuu 	._space_write_4 =	generic_space_write_4,
111*61e15267Ssyuu 	._space_read_8 =	generic_space_read_8,
112*61e15267Ssyuu 	._space_write_8 =	generic_space_write_8,
113*61e15267Ssyuu 	._space_read_raw_2 =	generic_space_read_raw_2,
114*61e15267Ssyuu 	._space_write_raw_2 =	generic_space_write_raw_2,
115*61e15267Ssyuu 	._space_read_raw_4 =	generic_space_read_raw_4,
116*61e15267Ssyuu 	._space_write_raw_4 =	generic_space_write_raw_4,
117*61e15267Ssyuu 	._space_read_raw_8 =	generic_space_read_raw_8,
118*61e15267Ssyuu 	._space_write_raw_8 =	generic_space_write_raw_8,
119*61e15267Ssyuu 	._space_map =		iobus_space_map,
120*61e15267Ssyuu 	._space_unmap =		iobus_space_unmap,
121*61e15267Ssyuu 	._space_subregion =	generic_space_region,
122*61e15267Ssyuu 	._space_vaddr =		generic_space_vaddr
123*61e15267Ssyuu };
124*61e15267Ssyuu 
125*61e15267Ssyuu bus_space_handle_t iobus_h;
126*61e15267Ssyuu 
127*61e15267Ssyuu struct machine_bus_dma_tag iobus_bus_dma_tag = {
128*61e15267Ssyuu 	NULL,			/* _cookie */
129*61e15267Ssyuu 	_dmamap_create,
130*61e15267Ssyuu 	_dmamap_destroy,
131*61e15267Ssyuu 	_dmamap_load,
132*61e15267Ssyuu 	_dmamap_load_mbuf,
133*61e15267Ssyuu 	_dmamap_load_uio,
134*61e15267Ssyuu 	_dmamap_load_raw,
135*61e15267Ssyuu 	_dmamap_load_buffer,
136*61e15267Ssyuu 	_dmamap_unload,
137*61e15267Ssyuu 	_dmamap_sync,
138*61e15267Ssyuu 	_dmamem_alloc,
139*61e15267Ssyuu 	_dmamem_free,
140*61e15267Ssyuu 	_dmamem_map,
141*61e15267Ssyuu 	_dmamem_unmap,
142*61e15267Ssyuu 	_dmamem_mmap,
143*61e15267Ssyuu 	iobus_pa_to_device,
144*61e15267Ssyuu 	iobus_device_to_pa,
145*61e15267Ssyuu 	0
146*61e15267Ssyuu };
147*61e15267Ssyuu 
148*61e15267Ssyuu /*
149*61e15267Ssyuu  * List of iobus child devices.
150*61e15267Ssyuu  */
151*61e15267Ssyuu 
152*61e15267Ssyuu #define	IOBUSDEV(name, unitno, unit)	\
153*61e15267Ssyuu 	{ name, unitno, unit, &iobus_tag, &iobus_bus_dma_tag }
154*61e15267Ssyuu const struct iobus_unit iobus_units[] = {
155*61e15267Ssyuu 	{ OCTEON_CF_BASE, 0 }, /* octcf */
156*61e15267Ssyuu 	{ 0, 0 }, /* pcibus */
157*61e15267Ssyuu };
158*61e15267Ssyuu struct iobus_attach_args iobus_children[] = {
159*61e15267Ssyuu 	IOBUSDEV("octcf", 0, &iobus_units[0]),
160*61e15267Ssyuu 	IOBUSDEV("pcibus", 0, &iobus_units[1]),
161*61e15267Ssyuu };
162*61e15267Ssyuu #undef	IOBUSDEV
163*61e15267Ssyuu 
164*61e15267Ssyuu /*
165*61e15267Ssyuu  * Match bus only to targets which have this bus.
166*61e15267Ssyuu  */
167*61e15267Ssyuu int
168*61e15267Ssyuu iobusmatch(struct device *parent, void *match, void *aux)
169*61e15267Ssyuu {
170*61e15267Ssyuu 	return (1);
171*61e15267Ssyuu }
172*61e15267Ssyuu 
173*61e15267Ssyuu int
174*61e15267Ssyuu iobusprint(void *aux, const char *iobus)
175*61e15267Ssyuu {
176*61e15267Ssyuu 	struct iobus_attach_args *aa = aux;
177*61e15267Ssyuu 
178*61e15267Ssyuu 	if (iobus != NULL)
179*61e15267Ssyuu 		printf("%s at %s", aa->aa_name, iobus);
180*61e15267Ssyuu 
181*61e15267Ssyuu 	if (aa->aa_unit->addr != 0)
182*61e15267Ssyuu 		printf(" base 0x%llx", aa->aa_unit->addr);
183*61e15267Ssyuu 	if (aa->aa_unit->irq >= 0)
184*61e15267Ssyuu 		printf(" irq %d", aa->aa_unit->irq);
185*61e15267Ssyuu 
186*61e15267Ssyuu 	return (UNCONF);
187*61e15267Ssyuu }
188*61e15267Ssyuu 
189*61e15267Ssyuu int
190*61e15267Ssyuu iobussubmatch(struct device *parent, void *vcf, void *args)
191*61e15267Ssyuu {
192*61e15267Ssyuu 	struct cfdata *cf = vcf;
193*61e15267Ssyuu 	struct iobus_attach_args *aa = args;
194*61e15267Ssyuu 
195*61e15267Ssyuu 	if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0)
196*61e15267Ssyuu 		return 0;
197*61e15267Ssyuu 
198*61e15267Ssyuu 	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)aa->aa_unit->addr)
199*61e15267Ssyuu 		return 0;
200*61e15267Ssyuu 
201*61e15267Ssyuu 	return (*cf->cf_attach->ca_match)(parent, cf, aa);
202*61e15267Ssyuu }
203*61e15267Ssyuu 
204*61e15267Ssyuu void
205*61e15267Ssyuu iobusattach(struct device *parent, struct device *self, void *aux)
206*61e15267Ssyuu {
207*61e15267Ssyuu 	uint i;
208*61e15267Ssyuu 
209*61e15267Ssyuu 	/*
210*61e15267Ssyuu 	 * Map and setup CRIME control registers.
211*61e15267Ssyuu 	 */
212*61e15267Ssyuu 	if (bus_space_map(&iobus_tag, OCTEON_CIU_BASE, OCTEON_CIU_SIZE, 0,
213*61e15267Ssyuu 		&iobus_h)) {
214*61e15267Ssyuu 		printf(": can't map CIU control registers\n");
215*61e15267Ssyuu 		return;
216*61e15267Ssyuu 	}
217*61e15267Ssyuu 
218*61e15267Ssyuu 	printf("\n");
219*61e15267Ssyuu 
220*61e15267Ssyuu 	octeon_intr_init();
221*61e15267Ssyuu 
222*61e15267Ssyuu 	/*
223*61e15267Ssyuu 	 * Attach subdevices.
224*61e15267Ssyuu 	 */
225*61e15267Ssyuu 	for (i = 0; i < nitems(iobus_children); i++)
226*61e15267Ssyuu 		config_found_sm(self, iobus_children + i,
227*61e15267Ssyuu 		    iobusprint, iobussubmatch);
228*61e15267Ssyuu }
229*61e15267Ssyuu 
230*61e15267Ssyuu int
231*61e15267Ssyuu iobus_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
232*61e15267Ssyuu     int flags, bus_space_handle_t *bshp)
233*61e15267Ssyuu {
234*61e15267Ssyuu 	if (ISSET(flags, BUS_SPACE_MAP_KSEG0)) {
235*61e15267Ssyuu 		*bshp = PHYS_TO_CKSEG0(offs);
236*61e15267Ssyuu 		return 0;
237*61e15267Ssyuu 	}
238*61e15267Ssyuu 	if (ISSET(flags, BUS_SPACE_MAP_CACHEABLE))
239*61e15267Ssyuu 		offs +=
240*61e15267Ssyuu 		    PHYS_TO_XKPHYS(0, CCA_CACHED) - PHYS_TO_XKPHYS(0, CCA_NC);
241*61e15267Ssyuu 	*bshp = t->bus_base + offs;
242*61e15267Ssyuu 	return 0;
243*61e15267Ssyuu }
244*61e15267Ssyuu 
245*61e15267Ssyuu void
246*61e15267Ssyuu iobus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
247*61e15267Ssyuu {
248*61e15267Ssyuu }
249*61e15267Ssyuu 
250*61e15267Ssyuu /*
251*61e15267Ssyuu  * Iobus bus_dma helpers.
252*61e15267Ssyuu  */
253*61e15267Ssyuu 
254*61e15267Ssyuu bus_addr_t
255*61e15267Ssyuu iobus_pa_to_device(paddr_t pa)
256*61e15267Ssyuu {
257*61e15267Ssyuu 	return (bus_addr_t)pa;
258*61e15267Ssyuu }
259*61e15267Ssyuu 
260*61e15267Ssyuu paddr_t
261*61e15267Ssyuu iobus_device_to_pa(bus_addr_t addr)
262*61e15267Ssyuu {
263*61e15267Ssyuu 	return (paddr_t)addr;
264*61e15267Ssyuu }
265