xref: /openbsd-src/sys/arch/octeon/dev/octsctl.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: octsctl.c,v 1.1 2017/07/28 14:54:13 visa Exp $	*/
2 
3 /*
4  * Copyright (c) 2017 Visa Hankala
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Driver for OCTEON SATA controller bridge.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 
27 #include <machine/bus.h>
28 #include <machine/fdt.h>
29 
30 #include <dev/ofw/fdt.h>
31 #include <dev/ofw/openfirm.h>
32 
33 #define SCTL_SHIM_CFG			0xe8
34 #define   SCTL_SHIM_CFG_READ_CMD		0x0000000000001000ul
35 #define   SCTL_SHIM_CFG_DMA_BYTE_SWAP		0x0000000000000300ul
36 #define   SCTL_SHIM_CFG_DMA_BYTE_SWAP_SHIFT	8
37 #define   SCTL_SHIM_CFG_CSR_BYTE_SWAP		0x0000000000000003ul
38 #define   SCTL_SHIM_CFG_CSR_BYTE_SWAP_SHIFT	0
39 
40 struct octsctl_softc {
41 	struct device		sc_dev;
42 	bus_space_tag_t		sc_iot;
43 	bus_space_handle_t	sc_ioh;
44 };
45 
46 int	octsctl_match(struct device *, void *, void *);
47 void	octsctl_attach(struct device *, struct device *, void *);
48 
49 const struct cfattach octsctl_ca = {
50 	sizeof(struct octsctl_softc), octsctl_match, octsctl_attach
51 };
52 
53 struct cfdriver octsctl_cd = {
54 	NULL, "octsctl", DV_DULL
55 };
56 
57 int
58 octsctl_match(struct device *parent, void *match, void *aux)
59 {
60 	struct fdt_attach_args *faa = aux;
61 
62 	/*
63 	 * On some machines, the bridge controller node does not have
64 	 * an AHCI controller node as a child.
65 	 */
66 
67 	return OF_is_compatible(faa->fa_node, "cavium,octeon-7130-sata-uctl") &&
68 	    OF_child(faa->fa_node) != 0;
69 }
70 
71 void
72 octsctl_attach(struct device *parent, struct device *self, void *aux)
73 {
74 	struct fdt_reg child_reg;
75 	struct fdt_attach_args child_faa;
76 	struct fdt_attach_args *faa = aux;
77 	struct octsctl_softc *sc = (struct octsctl_softc *)self;
78 	uint64_t val;
79 	uint32_t reg[4];
80 	int child;
81 
82 	if (faa->fa_nreg != 1) {
83 		printf(": expected one IO space, got %d\n", faa->fa_nreg);
84 		return;
85 	}
86 
87 	child = OF_child(faa->fa_node);
88 	if (OF_getpropint(faa->fa_node, "#address-cells", 0) != 2 ||
89 	    OF_getpropint(faa->fa_node, "#size-cells", 0) != 2) {
90 		printf(": invalid fdt reg cells\n");
91 		return;
92 	}
93 	if (OF_getproplen(child, "reg") != sizeof(reg)) {
94 		printf(": invalid child fdt reg\n");
95 		return;
96 	}
97 	OF_getpropintarray(child, "reg", reg, sizeof(reg));
98 	child_reg.addr = ((uint64_t)reg[0] << 32) | reg[1];
99 	child_reg.size = ((uint64_t)reg[2] << 32) | reg[3];
100 
101 	sc->sc_iot = faa->fa_iot;
102 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size,
103 	    0, &sc->sc_ioh)) {
104 		printf(": could not map registers\n");
105 		goto error;
106 	}
107 
108 	val = bus_space_read_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG);
109 	val &= ~SCTL_SHIM_CFG_CSR_BYTE_SWAP;
110 	val &= ~SCTL_SHIM_CFG_DMA_BYTE_SWAP;
111 	val |= 3ul << SCTL_SHIM_CFG_CSR_BYTE_SWAP_SHIFT;
112 	val |= 1ul << SCTL_SHIM_CFG_DMA_BYTE_SWAP_SHIFT;
113 	val |= SCTL_SHIM_CFG_READ_CMD;
114 	bus_space_write_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG, val);
115 	(void)bus_space_read_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG);
116 
117 	printf("\n");
118 
119 	memset(&child_faa, 0, sizeof(child_faa));
120 	child_faa.fa_name = "";
121 	child_faa.fa_node = child;
122 	child_faa.fa_iot = faa->fa_iot;
123 	child_faa.fa_dmat = faa->fa_dmat;
124 	child_faa.fa_reg = &child_reg;
125 	child_faa.fa_nreg = 1;
126 	/* child_faa.fa_intr is not utilized. */
127 
128 	config_found(self, &child_faa, NULL);
129 
130 	return;
131 
132 error:
133 	if (sc->sc_ioh != 0)
134 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
135 }
136