1 /* $OpenBSD: imxahci.c,v 1.13 2021/10/24 17:52:27 mpi 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 const 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
imxahci_match(struct device * parent,void * match,void * aux)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
imxahci_attach(struct device * parent,struct device * self,void * aux)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
imxahci_detach(struct device * self,int flags)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
imxahci_activate(struct device * self,int act)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