xref: /openbsd/sys/arch/armv7/imx/imxahci.c (revision cecf84d4)
1 /* $OpenBSD: imxahci.c,v 1.3 2014/04/14 04:42:22 dlg 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/buf.h>
21 #include <sys/kernel.h>
22 #include <sys/malloc.h>
23 #include <sys/device.h>
24 #include <sys/queue.h>
25 
26 #include <machine/bus.h>
27 
28 #include <dev/ic/ahcireg.h>
29 #include <dev/ic/ahcivar.h>
30 
31 #include <armv7/armv7/armv7var.h>
32 #include <armv7/imx/imxccmvar.h>
33 #include <armv7/imx/imxiomuxcvar.h>
34 
35 /* registers */
36 #define SATA_CAP		0x000
37 #define SATA_GHC		0x004
38 #define SATA_IS			0x008
39 #define SATA_PI			0x00C
40 #define SATA_VS			0x010
41 #define SATA_CCC_CTL		0x014
42 #define SATA_CCC_PORTS		0x018
43 #define SATA_CAP2		0x024
44 #define SATA_BISTAFR		0x0A0
45 #define SATA_BISTCR		0x0A4
46 #define SATA_BISTFCTR		0x0A8
47 #define SATA_BSTSR		0x0AC
48 #define SATA_OOBR		0x0BC
49 #define SATA_GPCR		0x0D0
50 #define SATA_GPSR		0x0D4
51 #define SATA_TIMER1MS		0x0E0
52 #define SATA_TESTR		0x0F4
53 #define SATA_VERSIONR		0x0F8
54 #define SATA_P0CLB		0x100
55 #define SATA_P0FB		0x108
56 #define SATA_P0IS		0x110
57 #define SATA_P0IE		0x114
58 #define SATA_P0CMD		0x118
59 #define SATA_P0TFD		0x120
60 #define SATA_P0SIG		0x124
61 #define SATA_P0SSTS		0x128
62 #define SATA_P0SCTL		0x12C
63 #define SATA_P0SERR		0x130
64 #define SATA_P0SACT		0x134
65 #define SATA_P0CI		0x138
66 #define SATA_P0SNTF		0x13C
67 #define SATA_P0DMACR		0x170
68 #define SATA_P0PHYCR		0x178
69 #define SATA_P0PHYSR		0x17C
70 
71 #define SATA_CAP_SSS		(1 << 27)
72 #define SATA_GHC_HR		(1 << 0)
73 #define SATA_P0PHYCR_TEST_PDDQ	(1 << 20)
74 
75 void	imxahci_attach(struct device *, struct device *, void *);
76 int	imxahci_detach(struct device *, int);
77 int	imxahci_activate(struct device *, int);
78 
79 extern int ahci_intr(void *);
80 
81 struct imxahci_softc {
82 	struct ahci_softc	sc;
83 };
84 
85 struct cfattach imxahci_ca = {
86 	sizeof(struct imxahci_softc),
87 	NULL,
88 	imxahci_attach,
89 	imxahci_detach,
90 	imxahci_activate
91 };
92 
93 struct cfdriver imxahci_cd = {
94 	NULL, "ahci", DV_DULL
95 };
96 
97 void
98 imxahci_attach(struct device *parent, struct device *self, void *args)
99 {
100 	struct armv7_attach_args *aa = args;
101 	struct imxahci_softc *imxsc = (struct imxahci_softc *) self;
102 	struct ahci_softc *sc = &imxsc->sc;
103 	uint32_t timeout = 0x100000;
104 
105 	sc->sc_iot = aa->aa_iot;
106 	sc->sc_ios = aa->aa_dev->mem[0].size;
107 	sc->sc_dmat = aa->aa_dmat;
108 
109 	if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
110 	    aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
111 		panic("imxahci_attach: bus_space_map failed!");
112 
113 	sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_BIO,
114 	    ahci_intr, sc, sc->sc_dev.dv_xname);
115 	if (sc->sc_ih == NULL) {
116 		printf(": unable to establish interrupt\n");
117 		goto unmap;
118 	}
119 
120 	/* power it up */
121 	imxccm_enable_sata();
122 	delay(100);
123 
124 	/* power phy up */
125 	imxiomuxc_enable_sata();
126 
127 	/* setup */
128 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR,
129 	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR) & ~SATA_P0PHYCR_TEST_PDDQ);
130 
131 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_GHC, SATA_GHC_HR);
132 
133 	while (!bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_VERSIONR));
134 
135 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP,
136 	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP) | SATA_CAP_SSS);
137 
138 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, 1);
139 
140 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS, imxccm_get_ahbclk());
141 
142 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0SSTS) & 0xF) && timeout--);
143 
144 	if (ahci_attach(sc) != 0) {
145 		/* error printed by ahci_attach */
146 		goto irq;
147 	}
148 
149 	return;
150 irq:
151 	arm_intr_disestablish(sc->sc_ih);
152 unmap:
153 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
154 }
155 
156 int
157 imxahci_detach(struct device *self, int flags)
158 {
159 	struct imxahci_softc *imxsc = (struct imxahci_softc *) self;
160 	struct ahci_softc *sc = &imxsc->sc;
161 
162 	ahci_detach(sc, flags);
163 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
164 	return 0;
165 }
166 
167 int
168 imxahci_activate(struct device *self, int act)
169 {
170 	struct imxahci_softc *imxsc = (struct imxahci_softc *) self;
171 	struct ahci_softc *sc = &imxsc->sc;
172 
173 	return ahci_activate((struct device *)sc, act);
174 }
175