xref: /openbsd/sys/arch/armv7/imx/imxahci.c (revision 097a140d)
1 /* $OpenBSD: imxahci.c,v 1.12 2021/03/25 04:12:01 jsg Exp $ */
2 /*
3  * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 
22 #include <machine/bus.h>
23 #include <machine/fdt.h>
24 
25 #include <dev/ic/ahcireg.h>
26 #include <dev/ic/ahcivar.h>
27 
28 #include <dev/ofw/openfirm.h>
29 #include <dev/ofw/ofw_clock.h>
30 #include <dev/ofw/ofw_misc.h>
31 #include <dev/ofw/fdt.h>
32 
33 /* registers */
34 #define SATA_CAP		0x000
35 #define SATA_GHC		0x004
36 #define SATA_IS			0x008
37 #define SATA_PI			0x00C
38 #define SATA_VS			0x010
39 #define SATA_CCC_CTL		0x014
40 #define SATA_CCC_PORTS		0x018
41 #define SATA_CAP2		0x024
42 #define SATA_BISTAFR		0x0A0
43 #define SATA_BISTCR		0x0A4
44 #define SATA_BISTFCTR		0x0A8
45 #define SATA_BSTSR		0x0AC
46 #define SATA_OOBR		0x0BC
47 #define SATA_GPCR		0x0D0
48 #define SATA_GPSR		0x0D4
49 #define SATA_TIMER1MS		0x0E0
50 #define SATA_TESTR		0x0F4
51 #define SATA_VERSIONR		0x0F8
52 #define SATA_P0CLB		0x100
53 #define SATA_P0FB		0x108
54 #define SATA_P0IS		0x110
55 #define SATA_P0IE		0x114
56 #define SATA_P0CMD		0x118
57 #define SATA_P0TFD		0x120
58 #define SATA_P0SIG		0x124
59 #define SATA_P0SSTS		0x128
60 #define SATA_P0SCTL		0x12C
61 #define SATA_P0SERR		0x130
62 #define SATA_P0SACT		0x134
63 #define SATA_P0CI		0x138
64 #define SATA_P0SNTF		0x13C
65 #define SATA_P0DMACR		0x170
66 #define SATA_P0PHYCR		0x178
67 #define SATA_P0PHYSR		0x17C
68 
69 #define SATA_CAP_SSS		(1 << 27)
70 #define SATA_GHC_HR		(1 << 0)
71 #define SATA_P0PHYCR_TEST_PDDQ	(1 << 20)
72 
73 /* iomuxc */
74 #define IOMUXC_GPR13				0x034
75 #define  IOMUXC_GPR13_SATA_PHY_1_TX_EDGE_RATE		(1 << 0)
76 #define  IOMUXC_GPR13_SATA_PHY_1_MPLL_CLK_EN		(1 << 1)
77 #define  IOMUXC_GPR13_SATA_PHY_2_1104V			(0x11 << 2)
78 #define  IOMUXC_GPR13_SATA_PHY_3_333DB			(0x00 << 7)
79 #define  IOMUXC_GPR13_SATA_PHY_4_9_16			(0x04 << 11)
80 #define  IOMUXC_GPR13_SATA_PHY_5_SS			(0x01 << 14)
81 #define  IOMUXC_GPR13_SATA_SPEED_3G			(0x01 << 15)
82 #define  IOMUXC_GPR13_SATA_PHY_6				(0x03 << 16)
83 #define  IOMUXC_GPR13_SATA_PHY_7_SATA2M			(0x12 << 19)
84 #define  IOMUXC_GPR13_SATA_PHY_8_30DB			(0x05 << 24)
85 #define  IOMUXC_GPR13_SATA_MASK				0x07FFFFFF
86 
87 int	imxahci_match(struct device *, void *, void *);
88 void	imxahci_attach(struct device *, struct device *, void *);
89 int	imxahci_detach(struct device *, int);
90 int	imxahci_activate(struct device *, int);
91 
92 extern int ahci_intr(void *);
93 
94 struct imxahci_softc {
95 	struct ahci_softc	sc;
96 };
97 
98 struct cfattach imxahci_ca = {
99 	sizeof(struct imxahci_softc),
100 	imxahci_match,
101 	imxahci_attach,
102 	imxahci_detach,
103 	imxahci_activate
104 };
105 
106 struct cfdriver imxahci_cd = {
107 	NULL, "imxahci", DV_DULL
108 };
109 
110 int
111 imxahci_match(struct device *parent, void *match, void *aux)
112 {
113 	struct fdt_attach_args *faa = aux;
114 
115 	return OF_is_compatible(faa->fa_node, "fsl,imx6q-ahci");
116 }
117 
118 void
119 imxahci_attach(struct device *parent, struct device *self, void *aux)
120 {
121 	struct imxahci_softc *imxsc = (struct imxahci_softc *) self;
122 	struct ahci_softc *sc = &imxsc->sc;
123 	struct fdt_attach_args *faa = aux;
124 	uint32_t timeout = 0x100000;
125 	struct regmap *rm;
126 	uint32_t reg;
127 
128 	if (faa->fa_nreg < 1)
129 		return;
130 
131 	sc->sc_iot = faa->fa_iot;
132 	sc->sc_ios = faa->fa_reg[0].size;
133 	sc->sc_dmat = faa->fa_dmat;
134 
135 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
136 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
137 		panic("imxahci_attach: bus_space_map failed!");
138 
139 	sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO,
140 	    ahci_intr, sc, sc->sc_dev.dv_xname);
141 	if (sc->sc_ih == NULL) {
142 		printf(": unable to establish interrupt\n");
143 		goto unmap;
144 	}
145 
146 	/* power it up */
147 	clock_enable(faa->fa_node, "sata_ref");
148 	clock_enable(faa->fa_node, "sata");
149 	delay(100);
150 
151 	/* power phy up */
152 	rm = regmap_bycompatible("fsl,imx6q-iomuxc-gpr");
153 	if (rm != NULL) {
154 		reg = regmap_read_4(rm, IOMUXC_GPR13);
155 		reg &= ~IOMUXC_GPR13_SATA_MASK;
156 		reg |= IOMUXC_GPR13_SATA_PHY_2_1104V |
157 		    IOMUXC_GPR13_SATA_PHY_3_333DB |
158 		    IOMUXC_GPR13_SATA_PHY_4_9_16 |
159 		    IOMUXC_GPR13_SATA_SPEED_3G |
160 		    IOMUXC_GPR13_SATA_PHY_6 |
161 		    IOMUXC_GPR13_SATA_PHY_7_SATA2M |
162 		    IOMUXC_GPR13_SATA_PHY_8_30DB;
163 		regmap_write_4(rm, IOMUXC_GPR13, reg);
164 		reg = regmap_read_4(rm, IOMUXC_GPR13);
165 		reg |= IOMUXC_GPR13_SATA_PHY_1_MPLL_CLK_EN;
166 		regmap_write_4(rm, IOMUXC_GPR13, reg);
167 	}
168 
169 	/* setup */
170 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR,
171 	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR) & ~SATA_P0PHYCR_TEST_PDDQ);
172 
173 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_GHC, SATA_GHC_HR);
174 
175 	while (!bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_VERSIONR));
176 
177 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP,
178 	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP) | SATA_CAP_SSS);
179 
180 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, 1);
181 
182 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS,
183 	    clock_get_frequency(faa->fa_node, "ahb"));
184 
185 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0SSTS) & 0xF) && timeout--);
186 
187 	printf(":");
188 
189 	if (ahci_attach(sc) != 0) {
190 		/* error printed by ahci_attach */
191 		goto irq;
192 	}
193 
194 	return;
195 irq:
196 	arm_intr_disestablish(sc->sc_ih);
197 unmap:
198 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
199 }
200 
201 int
202 imxahci_detach(struct device *self, int flags)
203 {
204 	struct imxahci_softc *imxsc = (struct imxahci_softc *) self;
205 	struct ahci_softc *sc = &imxsc->sc;
206 
207 	ahci_detach(sc, flags);
208 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
209 	return 0;
210 }
211 
212 int
213 imxahci_activate(struct device *self, int act)
214 {
215 	struct imxahci_softc *imxsc = (struct imxahci_softc *) self;
216 	struct ahci_softc *sc = &imxsc->sc;
217 
218 	return ahci_activate((struct device *)sc, act);
219 }
220