xref: /openbsd/sys/arch/octeon/dev/octeon_iobus.c (revision a81120d9)
1*a81120d9Sjasper /*	$OpenBSD: octeon_iobus.c,v 1.4 2013/06/02 20:29:36 jasper Exp $ */
261e15267Ssyuu 
361e15267Ssyuu /*
461e15267Ssyuu  * Copyright (c) 2000-2004 Opsycon AB  (www.opsycon.se)
561e15267Ssyuu  *
661e15267Ssyuu  * Redistribution and use in source and binary forms, with or without
761e15267Ssyuu  * modification, are permitted provided that the following conditions
861e15267Ssyuu  * are met:
961e15267Ssyuu  * 1. Redistributions of source code must retain the above copyright
1061e15267Ssyuu  *    notice, this list of conditions and the following disclaimer.
1161e15267Ssyuu  * 2. Redistributions in binary form must reproduce the above copyright
1261e15267Ssyuu  *    notice, this list of conditions and the following disclaimer in the
1361e15267Ssyuu  *    documentation and/or other materials provided with the distribution.
1461e15267Ssyuu  *
1561e15267Ssyuu  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1661e15267Ssyuu  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1761e15267Ssyuu  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1861e15267Ssyuu  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
1961e15267Ssyuu  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2061e15267Ssyuu  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2161e15267Ssyuu  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2261e15267Ssyuu  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2361e15267Ssyuu  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2461e15267Ssyuu  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2561e15267Ssyuu  * SUCH DAMAGE.
2661e15267Ssyuu  *
2761e15267Ssyuu  */
2861e15267Ssyuu 
2961e15267Ssyuu /*
3061e15267Ssyuu  * This is a iobus driver.
3161e15267Ssyuu  * It handles configuration of all devices on the processor bus except UART.
3261e15267Ssyuu  */
3361e15267Ssyuu 
3461e15267Ssyuu #include <sys/param.h>
3561e15267Ssyuu #include <sys/systm.h>
3661e15267Ssyuu #include <sys/kernel.h>
3761e15267Ssyuu #include <sys/conf.h>
3861e15267Ssyuu #include <sys/malloc.h>
3961e15267Ssyuu #include <sys/device.h>
4061e15267Ssyuu #include <sys/proc.h>
4161e15267Ssyuu 
4261e15267Ssyuu #include <machine/autoconf.h>
4361e15267Ssyuu #include <machine/atomic.h>
4461e15267Ssyuu #include <machine/intr.h>
454a04f2fdSsyuu #include <machine/octeonvar.h>
46*a81120d9Sjasper #include <machine/octeonreg.h>
4761e15267Ssyuu 
4861e15267Ssyuu #include <octeon/dev/iobusvar.h>
494a04f2fdSsyuu #include <octeon/dev/cn30xxgmxreg.h>
5061e15267Ssyuu 
5161e15267Ssyuu int	 iobusmatch(struct device *, void *, void *);
5261e15267Ssyuu void	 iobusattach(struct device *, struct device *, void *);
5361e15267Ssyuu int	 iobusprint(void *, const char *);
5461e15267Ssyuu int	 iobussubmatch(struct device *, void *, void *);
5561e15267Ssyuu 
5661e15267Ssyuu u_int8_t iobus_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
5761e15267Ssyuu u_int16_t iobus_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
5861e15267Ssyuu u_int32_t iobus_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
5961e15267Ssyuu u_int64_t iobus_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t);
6061e15267Ssyuu 
6161e15267Ssyuu void	 iobus_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
6261e15267Ssyuu 	    u_int8_t);
6361e15267Ssyuu void	 iobus_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
6461e15267Ssyuu 	    u_int16_t);
6561e15267Ssyuu void	 iobus_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
6661e15267Ssyuu 	    u_int32_t);
6761e15267Ssyuu void	 iobus_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t,
6861e15267Ssyuu 	    u_int64_t);
6961e15267Ssyuu 
7061e15267Ssyuu void	 iobus_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
7161e15267Ssyuu 	    u_int8_t *, bus_size_t);
7261e15267Ssyuu void	 iobus_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
7361e15267Ssyuu 	    const u_int8_t *, bus_size_t);
7461e15267Ssyuu void	 iobus_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
7561e15267Ssyuu 	    u_int8_t *, bus_size_t);
7661e15267Ssyuu void	 iobus_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
7761e15267Ssyuu 	    const u_int8_t *, bus_size_t);
7861e15267Ssyuu void	 iobus_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
7961e15267Ssyuu 	    u_int8_t *, bus_size_t);
8061e15267Ssyuu void	 iobus_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
8161e15267Ssyuu 	    const u_int8_t *, bus_size_t);
8261e15267Ssyuu 
8361e15267Ssyuu int	 iobus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
8461e15267Ssyuu 	    bus_space_handle_t *);
8561e15267Ssyuu void	 iobus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
8661e15267Ssyuu int	 iobus_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t,
8761e15267Ssyuu 	    bus_size_t, bus_space_handle_t *);
8861e15267Ssyuu 
8961e15267Ssyuu void	*iobus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
9061e15267Ssyuu 
9161e15267Ssyuu bus_addr_t iobus_pa_to_device(paddr_t);
9261e15267Ssyuu paddr_t	 iobus_device_to_pa(bus_addr_t);
9361e15267Ssyuu 
9461e15267Ssyuu struct cfattach iobus_ca = {
9561e15267Ssyuu 	sizeof(struct device), iobusmatch, iobusattach
9661e15267Ssyuu };
9761e15267Ssyuu 
9861e15267Ssyuu struct cfdriver iobus_cd = {
9961e15267Ssyuu 	NULL, "iobus", DV_DULL
10061e15267Ssyuu };
10161e15267Ssyuu 
10261e15267Ssyuu bus_space_t iobus_tag = {
10361e15267Ssyuu 	.bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
10461e15267Ssyuu 	.bus_private = NULL,
10561e15267Ssyuu 	._space_read_1 =	generic_space_read_1,
10661e15267Ssyuu 	._space_write_1 =	generic_space_write_1,
10761e15267Ssyuu 	._space_read_2 =	generic_space_read_2,
10861e15267Ssyuu 	._space_write_2 =	generic_space_write_2,
10961e15267Ssyuu 	._space_read_4 =	generic_space_read_4,
11061e15267Ssyuu 	._space_write_4 =	generic_space_write_4,
11161e15267Ssyuu 	._space_read_8 =	generic_space_read_8,
11261e15267Ssyuu 	._space_write_8 =	generic_space_write_8,
11361e15267Ssyuu 	._space_read_raw_2 =	generic_space_read_raw_2,
11461e15267Ssyuu 	._space_write_raw_2 =	generic_space_write_raw_2,
11561e15267Ssyuu 	._space_read_raw_4 =	generic_space_read_raw_4,
11661e15267Ssyuu 	._space_write_raw_4 =	generic_space_write_raw_4,
11761e15267Ssyuu 	._space_read_raw_8 =	generic_space_read_raw_8,
11861e15267Ssyuu 	._space_write_raw_8 =	generic_space_write_raw_8,
11961e15267Ssyuu 	._space_map =		iobus_space_map,
12061e15267Ssyuu 	._space_unmap =		iobus_space_unmap,
12161e15267Ssyuu 	._space_subregion =	generic_space_region,
12261e15267Ssyuu 	._space_vaddr =		generic_space_vaddr
12361e15267Ssyuu };
12461e15267Ssyuu 
12561e15267Ssyuu bus_space_handle_t iobus_h;
12661e15267Ssyuu 
12761e15267Ssyuu struct machine_bus_dma_tag iobus_bus_dma_tag = {
12861e15267Ssyuu 	NULL,			/* _cookie */
12961e15267Ssyuu 	_dmamap_create,
13061e15267Ssyuu 	_dmamap_destroy,
13161e15267Ssyuu 	_dmamap_load,
13261e15267Ssyuu 	_dmamap_load_mbuf,
13361e15267Ssyuu 	_dmamap_load_uio,
13461e15267Ssyuu 	_dmamap_load_raw,
13561e15267Ssyuu 	_dmamap_load_buffer,
13661e15267Ssyuu 	_dmamap_unload,
13761e15267Ssyuu 	_dmamap_sync,
13861e15267Ssyuu 	_dmamem_alloc,
13961e15267Ssyuu 	_dmamem_free,
14061e15267Ssyuu 	_dmamem_map,
14161e15267Ssyuu 	_dmamem_unmap,
14261e15267Ssyuu 	_dmamem_mmap,
14361e15267Ssyuu 	iobus_pa_to_device,
14461e15267Ssyuu 	iobus_device_to_pa,
14561e15267Ssyuu 	0
14661e15267Ssyuu };
14761e15267Ssyuu 
14861e15267Ssyuu /*
14961e15267Ssyuu  * List of iobus child devices.
15061e15267Ssyuu  */
15161e15267Ssyuu 
15261e15267Ssyuu #define	IOBUSDEV(name, unitno, unit)	\
15361e15267Ssyuu 	{ name, unitno, unit, &iobus_tag, &iobus_bus_dma_tag }
15461e15267Ssyuu const struct iobus_unit iobus_units[] = {
15561e15267Ssyuu 	{ OCTEON_CF_BASE, 0 },			/* octcf */
15661e15267Ssyuu 	{ 0, 0 },				/* pcibus */
1574a04f2fdSsyuu 	{ GMX0_BASE_PORT0, CIU_INT_GMX_DRP0 }	/* cn30xxgmx */
15861e15267Ssyuu };
15961e15267Ssyuu struct iobus_attach_args iobus_children[] = {
16061e15267Ssyuu 	IOBUSDEV("octcf", 0, &iobus_units[0]),
16161e15267Ssyuu 	IOBUSDEV("pcibus", 0, &iobus_units[1]),
1624a04f2fdSsyuu 	IOBUSDEV("cn30xxgmx", 0, &iobus_units[2])
16361e15267Ssyuu };
16461e15267Ssyuu #undef	IOBUSDEV
16561e15267Ssyuu 
16661e15267Ssyuu /*
16761e15267Ssyuu  * Match bus only to targets which have this bus.
16861e15267Ssyuu  */
16961e15267Ssyuu int
17061e15267Ssyuu iobusmatch(struct device *parent, void *match, void *aux)
17161e15267Ssyuu {
17261e15267Ssyuu 	return (1);
17361e15267Ssyuu }
17461e15267Ssyuu 
17561e15267Ssyuu int
17661e15267Ssyuu iobusprint(void *aux, const char *iobus)
17761e15267Ssyuu {
17861e15267Ssyuu 	struct iobus_attach_args *aa = aux;
17961e15267Ssyuu 
18061e15267Ssyuu 	if (iobus != NULL)
18161e15267Ssyuu 		printf("%s at %s", aa->aa_name, iobus);
18261e15267Ssyuu 
18361e15267Ssyuu 	if (aa->aa_unit->addr != 0)
18461e15267Ssyuu 		printf(" base 0x%llx", aa->aa_unit->addr);
18561e15267Ssyuu 	if (aa->aa_unit->irq >= 0)
18661e15267Ssyuu 		printf(" irq %d", aa->aa_unit->irq);
18761e15267Ssyuu 
18861e15267Ssyuu 	return (UNCONF);
18961e15267Ssyuu }
19061e15267Ssyuu 
19161e15267Ssyuu int
19261e15267Ssyuu iobussubmatch(struct device *parent, void *vcf, void *args)
19361e15267Ssyuu {
19461e15267Ssyuu 	struct cfdata *cf = vcf;
19561e15267Ssyuu 	struct iobus_attach_args *aa = args;
19661e15267Ssyuu 
19761e15267Ssyuu 	if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0)
19861e15267Ssyuu 		return 0;
19961e15267Ssyuu 
20061e15267Ssyuu 	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)aa->aa_unit->addr)
20161e15267Ssyuu 		return 0;
20261e15267Ssyuu 
20361e15267Ssyuu 	return (*cf->cf_attach->ca_match)(parent, cf, aa);
20461e15267Ssyuu }
20561e15267Ssyuu 
20661e15267Ssyuu void
20761e15267Ssyuu iobusattach(struct device *parent, struct device *self, void *aux)
20861e15267Ssyuu {
2094a04f2fdSsyuu 	struct octeon_config oc;
21061e15267Ssyuu 	uint i;
21161e15267Ssyuu 
21261e15267Ssyuu 	/*
21361e15267Ssyuu 	 * Map and setup CRIME control registers.
21461e15267Ssyuu 	 */
21561e15267Ssyuu 	if (bus_space_map(&iobus_tag, OCTEON_CIU_BASE, OCTEON_CIU_SIZE, 0,
21661e15267Ssyuu 		&iobus_h)) {
21761e15267Ssyuu 		printf(": can't map CIU control registers\n");
21861e15267Ssyuu 		return;
21961e15267Ssyuu 	}
22061e15267Ssyuu 
22161e15267Ssyuu 	printf("\n");
22261e15267Ssyuu 
22361e15267Ssyuu 	octeon_intr_init();
22461e15267Ssyuu 
2254a04f2fdSsyuu 	/* XXX */
2264a04f2fdSsyuu 	oc.mc_iobus_bust = &iobus_tag;
2274a04f2fdSsyuu 	oc.mc_iobus_dmat = &iobus_bus_dma_tag;
2284a04f2fdSsyuu 	void	cn30xxfpa_bootstrap(struct octeon_config *);
2294a04f2fdSsyuu 	cn30xxfpa_bootstrap(&oc);
2304a04f2fdSsyuu 	void	cn30xxpow_bootstrap(struct octeon_config *);
2314a04f2fdSsyuu 	cn30xxpow_bootstrap(&oc);
2324a04f2fdSsyuu 
23361e15267Ssyuu 	/*
23461e15267Ssyuu 	 * Attach subdevices.
23561e15267Ssyuu 	 */
23661e15267Ssyuu 	for (i = 0; i < nitems(iobus_children); i++)
23761e15267Ssyuu 		config_found_sm(self, iobus_children + i,
23861e15267Ssyuu 		    iobusprint, iobussubmatch);
23961e15267Ssyuu }
24061e15267Ssyuu 
24161e15267Ssyuu int
24261e15267Ssyuu iobus_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
24361e15267Ssyuu     int flags, bus_space_handle_t *bshp)
24461e15267Ssyuu {
24561e15267Ssyuu 	if (ISSET(flags, BUS_SPACE_MAP_KSEG0)) {
24661e15267Ssyuu 		*bshp = PHYS_TO_CKSEG0(offs);
24761e15267Ssyuu 		return 0;
24861e15267Ssyuu 	}
24961e15267Ssyuu 	if (ISSET(flags, BUS_SPACE_MAP_CACHEABLE))
25061e15267Ssyuu 		offs +=
25161e15267Ssyuu 		    PHYS_TO_XKPHYS(0, CCA_CACHED) - PHYS_TO_XKPHYS(0, CCA_NC);
25261e15267Ssyuu 	*bshp = t->bus_base + offs;
25361e15267Ssyuu 	return 0;
25461e15267Ssyuu }
25561e15267Ssyuu 
25661e15267Ssyuu void
25761e15267Ssyuu iobus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
25861e15267Ssyuu {
25961e15267Ssyuu }
26061e15267Ssyuu 
26161e15267Ssyuu /*
26261e15267Ssyuu  * Iobus bus_dma helpers.
26361e15267Ssyuu  */
26461e15267Ssyuu 
26561e15267Ssyuu bus_addr_t
26661e15267Ssyuu iobus_pa_to_device(paddr_t pa)
26761e15267Ssyuu {
26861e15267Ssyuu 	return (bus_addr_t)pa;
26961e15267Ssyuu }
27061e15267Ssyuu 
27161e15267Ssyuu paddr_t
27261e15267Ssyuu iobus_device_to_pa(bus_addr_t addr)
27361e15267Ssyuu {
27461e15267Ssyuu 	return (paddr_t)addr;
27561e15267Ssyuu }
276