xref: /openbsd/sys/arch/armv7/marvell/mvpxa.c (revision bfa5fdb5)
1 /*	$OpenBSD: mvpxa.c,v 1.4 2022/01/18 11:36:21 patrick Exp $	*/
2 /*
3  * Copyright (c) 2017 Mark Kettenis
4  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
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 #include <sys/param.h>
20 #include <sys/systm.h>
21 
22 #include <machine/bus.h>
23 #include <machine/fdt.h>
24 #include <machine/intr.h>
25 
26 #include <armv7/marvell/mvmbusvar.h>
27 
28 #include <dev/ofw/openfirm.h>
29 #include <dev/ofw/ofw_clock.h>
30 #include <dev/ofw/ofw_pinctrl.h>
31 #include <dev/ofw/fdt.h>
32 
33 #include <dev/sdmmc/sdhcreg.h>
34 #include <dev/sdmmc/sdhcvar.h>
35 
36 #define MVPXA_READ(sc, reg) \
37 	bus_space_read_4((sc)->sc_iot, (sc)->mbus_ioh, (reg))
38 #define MVPXA_WRITE(sc, reg, val) \
39 	bus_space_write_4((sc)->sc_iot, (sc)->mbus_ioh, (reg), (val))
40 
41 #define MVPXA_NWINDOW			8
42 #define MVPXA_CTRL(x)			(0x80 + ((x) << 3))
43 #define MVPXA_BASE(x)			(0x84 + ((x) << 3))
44 
45 #define MVPXA_TARGET(target)		(((target) & 0xf) << 4)
46 #define MVPXA_ATTR(attr)		(((attr) & 0xff) << 8)
47 #define MVPXA_SIZE(size)		(((size) - 1) & 0xffff0000)
48 #define MVPXA_WINEN			(1 << 0)
49 
50 struct mvpxa_softc {
51 	struct sdhc_softc	sc;
52 	bus_space_tag_t		sc_iot;
53 	bus_space_handle_t	sc_ioh;
54 	bus_space_handle_t	mbus_ioh;
55 	bus_space_handle_t	conf_ioh;
56 	bus_size_t		sc_size;
57 	void			*sc_ih;
58 
59 	struct sdhc_host 	*sc_host;
60 };
61 
62 int	mvpxa_match(struct device *, void *, void *);
63 void	mvpxa_attach(struct device *, struct device *, void *);
64 
65 struct cfdriver mvpxa_cd = {
66 	NULL, "mvpxa", DV_DULL
67 };
68 
69 const struct cfattach mvpxa_ca = {
70 	sizeof(struct mvpxa_softc), mvpxa_match, mvpxa_attach
71 };
72 
73 void	mvpxa_wininit(struct mvpxa_softc *);
74 
75 void
mvpxa_wininit(struct mvpxa_softc * sc)76 mvpxa_wininit(struct mvpxa_softc *sc)
77 {
78 	int i;
79 
80 	if (mvmbus_dram_info == NULL)
81 		panic("%s: mbus dram information not set up", __func__);
82 
83 	for (i = 0; i < MVPXA_NWINDOW; i++) {
84 		MVPXA_WRITE(sc, MVPXA_CTRL(i), 0);
85 		MVPXA_WRITE(sc, MVPXA_BASE(i), 0);
86 	}
87 
88 	for (i = 0; i < mvmbus_dram_info->numcs; i++) {
89 		struct mbus_dram_window *win = &mvmbus_dram_info->cs[i];
90 
91 		MVPXA_WRITE(sc, MVPXA_CTRL(i),
92 		    MVPXA_WINEN |
93 		    MVPXA_TARGET(mvmbus_dram_info->targetid) |
94 		    MVPXA_ATTR(win->attr) |
95 		    MVPXA_SIZE(win->size));
96 		MVPXA_WRITE(sc, MVPXA_BASE(i), win->base);
97 	}
98 }
99 
100 
101 int
mvpxa_match(struct device * parent,void * match,void * aux)102 mvpxa_match(struct device *parent, void *match, void *aux)
103 {
104 	struct fdt_attach_args *faa = aux;
105 
106 	return OF_is_compatible(faa->fa_node, "marvell,armada-380-sdhci");
107 }
108 
109 void
mvpxa_attach(struct device * parent,struct device * self,void * aux)110 mvpxa_attach(struct device *parent, struct device *self, void *aux)
111 {
112 	struct mvpxa_softc *sc = (struct mvpxa_softc *)self;
113 	struct fdt_attach_args *faa = aux;
114 	uint64_t capmask = 0, capset = 0;
115 
116 	if (faa->fa_nreg < 3) {
117 		printf(": not enough registers\n");
118 		return;
119 	}
120 
121 	sc->sc_iot = faa->fa_iot;
122 	sc->sc_size = faa->fa_reg[0].size;
123 
124 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
125 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
126 		printf(": can't map registers\n");
127 		return;
128 	}
129 
130 	if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
131 	    faa->fa_reg[1].size, 0, &sc->mbus_ioh)) {
132 		printf(": can't map registers\n");
133 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
134 		return;
135 	}
136 
137 	if (bus_space_map(sc->sc_iot, faa->fa_reg[2].addr,
138 	    faa->fa_reg[2].size, 0, &sc->conf_ioh)) {
139 		printf(": can't map registers\n");
140 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
141 		bus_space_unmap(sc->sc_iot, sc->mbus_ioh, faa->fa_reg[1].size);
142 		return;
143 	}
144 
145 	pinctrl_byname(faa->fa_node, "default");
146 
147 	clock_enable_all(faa->fa_node);
148 	reset_deassert_all(faa->fa_node);
149 
150 	/* Set up MBUS windows. */
151 	mvpxa_wininit(sc);
152 
153 	sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO,
154 	    sdhc_intr, sc, sc->sc.sc_dev.dv_xname);
155 	if (sc->sc_ih == NULL) {
156 		printf(": can't establish interrupt\n");
157 		goto unmap;
158 	}
159 
160 	printf("\n");
161 
162 	sc->sc.sc_host = &sc->sc_host;
163 	sc->sc.sc_dmat = faa->fa_dmat;
164 
165 	if (OF_getproplen(faa->fa_node, "no-1-8-v") >= 0)
166 		capmask |= SDHC_VOLTAGE_SUPP_1_8V;
167 
168 	sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1,
169 	    capmask, capset);
170 	return;
171 
172 unmap:
173 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
174 	bus_space_unmap(sc->sc_iot, sc->mbus_ioh, faa->fa_reg[1].size);
175 	bus_space_unmap(sc->sc_iot, sc->conf_ioh, faa->fa_reg[2].size);
176 }
177