Use DEVICE_COMPAT_EOL.diff -r1.16 -r1.17 src/sys/arch/arm/nvidia/tegra_ahcisata.c
(thorpej)
--- src/sys/arch/arm/nvidia/tegra_ahcisata.c 2021/01/25 14:20:38 1.16
+++ src/sys/arch/arm/nvidia/tegra_ahcisata.c 2021/01/27 01:58:15 1.17
@@ -1,427 +1,427 @@ | @@ -1,427 +1,427 @@ | |||
1 | /* $NetBSD: tegra_ahcisata.c,v 1.16 2021/01/25 14:20:38 thorpej Exp $ */ | 1 | /* $NetBSD: tegra_ahcisata.c,v 1.17 2021/01/27 01:58:15 thorpej Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> | 4 | * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
26 | * SUCH DAMAGE. | 26 | * SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: tegra_ahcisata.c,v 1.16 2021/01/25 14:20:38 thorpej Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: tegra_ahcisata.c,v 1.17 2021/01/27 01:58:15 thorpej Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/bus.h> | 33 | #include <sys/bus.h> | |
34 | #include <sys/device.h> | 34 | #include <sys/device.h> | |
35 | #include <sys/intr.h> | 35 | #include <sys/intr.h> | |
36 | #include <sys/systm.h> | 36 | #include <sys/systm.h> | |
37 | #include <sys/kernel.h> | 37 | #include <sys/kernel.h> | |
38 | 38 | |||
39 | #include <dev/ata/atavar.h> | 39 | #include <dev/ata/atavar.h> | |
40 | #include <dev/ic/ahcisatavar.h> | 40 | #include <dev/ic/ahcisatavar.h> | |
41 | 41 | |||
42 | #include <arm/nvidia/tegra_var.h> | 42 | #include <arm/nvidia/tegra_var.h> | |
43 | #include <arm/nvidia/tegra_pmcreg.h> | 43 | #include <arm/nvidia/tegra_pmcreg.h> | |
44 | #include <arm/nvidia/tegra_ahcisatareg.h> | 44 | #include <arm/nvidia/tegra_ahcisatareg.h> | |
45 | #include <arm/nvidia/tegra_xusbpad.h> | 45 | #include <arm/nvidia/tegra_xusbpad.h> | |
46 | 46 | |||
47 | #include <dev/fdt/fdtvar.h> | 47 | #include <dev/fdt/fdtvar.h> | |
48 | 48 | |||
49 | #define TEGRA_AHCISATA_OFFSET 0x7000 | 49 | #define TEGRA_AHCISATA_OFFSET 0x7000 | |
50 | 50 | |||
51 | static int tegra_ahcisata_match(device_t, cfdata_t, void *); | 51 | static int tegra_ahcisata_match(device_t, cfdata_t, void *); | |
52 | static void tegra_ahcisata_attach(device_t, device_t, void *); | 52 | static void tegra_ahcisata_attach(device_t, device_t, void *); | |
53 | 53 | |||
54 | struct tegra_ahcisata_softc { | 54 | struct tegra_ahcisata_softc { | |
55 | struct ahci_softc sc; | 55 | struct ahci_softc sc; | |
56 | bus_space_tag_t sc_bst; | 56 | bus_space_tag_t sc_bst; | |
57 | bus_space_handle_t sc_bsh; | 57 | bus_space_handle_t sc_bsh; | |
58 | void *sc_ih; | 58 | void *sc_ih; | |
59 | 59 | |||
60 | int sc_phandle; | 60 | int sc_phandle; | |
61 | struct clk *sc_clk_sata; | 61 | struct clk *sc_clk_sata; | |
62 | struct clk *sc_clk_sata_oob; | 62 | struct clk *sc_clk_sata_oob; | |
63 | struct clk *sc_clk_cml1; | 63 | struct clk *sc_clk_cml1; | |
64 | struct clk *sc_clk_pll_e; | 64 | struct clk *sc_clk_pll_e; | |
65 | struct fdtbus_reset *sc_rst_sata; | 65 | struct fdtbus_reset *sc_rst_sata; | |
66 | struct fdtbus_reset *sc_rst_sata_oob; | 66 | struct fdtbus_reset *sc_rst_sata_oob; | |
67 | struct fdtbus_reset *sc_rst_sata_cold; | 67 | struct fdtbus_reset *sc_rst_sata_cold; | |
68 | 68 | |||
69 | struct tegra_gpio_pin *sc_pin_power; | 69 | struct tegra_gpio_pin *sc_pin_power; | |
70 | 70 | |||
71 | const struct tegra_ahcisata_data | 71 | const struct tegra_ahcisata_data | |
72 | *sc_tad; | 72 | *sc_tad; | |
73 | }; | 73 | }; | |
74 | 74 | |||
75 | static const char * const tegra124_ahcisata_supplies[] = { | 75 | static const char * const tegra124_ahcisata_supplies[] = { | |
76 | "hvdd-supply", | 76 | "hvdd-supply", | |
77 | "vddio-supply", | 77 | "vddio-supply", | |
78 | "avdd-supply", | 78 | "avdd-supply", | |
79 | "target-5v-supply", | 79 | "target-5v-supply", | |
80 | "target-12v-supply" | 80 | "target-12v-supply" | |
81 | }; | 81 | }; | |
82 | 82 | |||
83 | enum tegra_ahcisata_type { | 83 | enum tegra_ahcisata_type { | |
84 | TEGRA124, | 84 | TEGRA124, | |
85 | TEGRA210 | 85 | TEGRA210 | |
86 | }; | 86 | }; | |
87 | 87 | |||
88 | struct tegra_ahcisata_data { | 88 | struct tegra_ahcisata_data { | |
89 | enum tegra_ahcisata_type tad_type; | 89 | enum tegra_ahcisata_type tad_type; | |
90 | const char * const * tad_supplies; | 90 | const char * const * tad_supplies; | |
91 | size_t tad_nsupplies; | 91 | size_t tad_nsupplies; | |
92 | }; | 92 | }; | |
93 | 93 | |||
94 | struct tegra_ahcisata_data tegra124_ahcisata_data = { | 94 | struct tegra_ahcisata_data tegra124_ahcisata_data = { | |
95 | .tad_type = TEGRA124, | 95 | .tad_type = TEGRA124, | |
96 | .tad_supplies = tegra124_ahcisata_supplies, | 96 | .tad_supplies = tegra124_ahcisata_supplies, | |
97 | .tad_nsupplies = __arraycount(tegra124_ahcisata_supplies), | 97 | .tad_nsupplies = __arraycount(tegra124_ahcisata_supplies), | |
98 | }; | 98 | }; | |
99 | 99 | |||
100 | struct tegra_ahcisata_data tegra210_ahcisata_data = { | 100 | struct tegra_ahcisata_data tegra210_ahcisata_data = { | |
101 | .tad_type = TEGRA210, | 101 | .tad_type = TEGRA210, | |
102 | }; | 102 | }; | |
103 | 103 | |||
104 | 104 | |||
105 | static const struct device_compatible_entry compat_data[] = { | 105 | static const struct device_compatible_entry compat_data[] = { | |
106 | { .compat = "nvidia,tegra124-ahci", .data = &tegra124_ahcisata_data }, | 106 | { .compat = "nvidia,tegra124-ahci", .data = &tegra124_ahcisata_data }, | |
107 | { .compat = "nvidia,tegra210-ahci", .data = &tegra210_ahcisata_data }, | 107 | { .compat = "nvidia,tegra210-ahci", .data = &tegra210_ahcisata_data }, | |
108 | { }, | 108 | DEVICE_COMPAT_EOL, | |
109 | }; | 109 | }; | |
110 | 110 | |||
111 | 111 | |||
112 | static void tegra_ahcisata_init(struct tegra_ahcisata_softc *); | 112 | static void tegra_ahcisata_init(struct tegra_ahcisata_softc *); | |
113 | static int tegra_ahcisata_init_clocks(struct tegra_ahcisata_softc *); | 113 | static int tegra_ahcisata_init_clocks(struct tegra_ahcisata_softc *); | |
114 | 114 | |||
115 | CFATTACH_DECL_NEW(tegra_ahcisata, sizeof(struct tegra_ahcisata_softc), | 115 | CFATTACH_DECL_NEW(tegra_ahcisata, sizeof(struct tegra_ahcisata_softc), | |
116 | tegra_ahcisata_match, tegra_ahcisata_attach, NULL, NULL); | 116 | tegra_ahcisata_match, tegra_ahcisata_attach, NULL, NULL); | |
117 | 117 | |||
118 | static int | 118 | static int | |
119 | tegra_ahcisata_match(device_t parent, cfdata_t cf, void *aux) | 119 | tegra_ahcisata_match(device_t parent, cfdata_t cf, void *aux) | |
120 | { | 120 | { | |
121 | struct fdt_attach_args * const faa = aux; | 121 | struct fdt_attach_args * const faa = aux; | |
122 | 122 | |||
123 | return of_match_compat_data(faa->faa_phandle, compat_data); | 123 | return of_match_compat_data(faa->faa_phandle, compat_data); | |
124 | } | 124 | } | |
125 | 125 | |||
126 | static void | 126 | static void | |
127 | tegra_ahcisata_attach(device_t parent, device_t self, void *aux) | 127 | tegra_ahcisata_attach(device_t parent, device_t self, void *aux) | |
128 | { | 128 | { | |
129 | struct tegra_ahcisata_softc * const sc = device_private(self); | 129 | struct tegra_ahcisata_softc * const sc = device_private(self); | |
130 | struct fdt_attach_args * const faa = aux; | 130 | struct fdt_attach_args * const faa = aux; | |
131 | const int phandle = faa->faa_phandle; | 131 | const int phandle = faa->faa_phandle; | |
132 | bus_addr_t ahci_addr, sata_addr; | 132 | bus_addr_t ahci_addr, sata_addr; | |
133 | bus_size_t ahci_size, sata_size; | 133 | bus_size_t ahci_size, sata_size; | |
134 | struct fdtbus_regulator *reg; | 134 | struct fdtbus_regulator *reg; | |
135 | char intrstr[128]; | 135 | char intrstr[128]; | |
136 | int error, n; | 136 | int error, n; | |
137 | 137 | |||
138 | if (fdtbus_get_reg(phandle, 0, &ahci_addr, &ahci_size) != 0) { | 138 | if (fdtbus_get_reg(phandle, 0, &ahci_addr, &ahci_size) != 0) { | |
139 | aprint_error(": couldn't get ahci registers\n"); | 139 | aprint_error(": couldn't get ahci registers\n"); | |
140 | return; | 140 | return; | |
141 | } | 141 | } | |
142 | if (fdtbus_get_reg(phandle, 1, &sata_addr, &sata_size) != 0) { | 142 | if (fdtbus_get_reg(phandle, 1, &sata_addr, &sata_size) != 0) { | |
143 | aprint_error(": couldn't get sata registers\n"); | 143 | aprint_error(": couldn't get sata registers\n"); | |
144 | return; | 144 | return; | |
145 | } | 145 | } | |
146 | sc->sc_clk_sata = fdtbus_clock_get(phandle, "sata"); | 146 | sc->sc_clk_sata = fdtbus_clock_get(phandle, "sata"); | |
147 | if (sc->sc_clk_sata == NULL) { | 147 | if (sc->sc_clk_sata == NULL) { | |
148 | aprint_error(": couldn't get clock sata\n"); | 148 | aprint_error(": couldn't get clock sata\n"); | |
149 | return; | 149 | return; | |
150 | } | 150 | } | |
151 | sc->sc_clk_sata_oob = fdtbus_clock_get(phandle, "sata-oob"); | 151 | sc->sc_clk_sata_oob = fdtbus_clock_get(phandle, "sata-oob"); | |
152 | if (sc->sc_clk_sata_oob == NULL) { | 152 | if (sc->sc_clk_sata_oob == NULL) { | |
153 | aprint_error(": couldn't get clock sata-oob\n"); | 153 | aprint_error(": couldn't get clock sata-oob\n"); | |
154 | return; | 154 | return; | |
155 | } | 155 | } | |
156 | sc->sc_rst_sata = fdtbus_reset_get(phandle, "sata"); | 156 | sc->sc_rst_sata = fdtbus_reset_get(phandle, "sata"); | |
157 | if (sc->sc_rst_sata == NULL) { | 157 | if (sc->sc_rst_sata == NULL) { | |
158 | aprint_error(": couldn't get reset sata\n"); | 158 | aprint_error(": couldn't get reset sata\n"); | |
159 | return; | 159 | return; | |
160 | } | 160 | } | |
161 | sc->sc_rst_sata_oob = fdtbus_reset_get(phandle, "sata-oob"); | 161 | sc->sc_rst_sata_oob = fdtbus_reset_get(phandle, "sata-oob"); | |
162 | if (sc->sc_rst_sata_oob == NULL) { | 162 | if (sc->sc_rst_sata_oob == NULL) { | |
163 | aprint_error(": couldn't get reset sata-oob\n"); | 163 | aprint_error(": couldn't get reset sata-oob\n"); | |
164 | return; | 164 | return; | |
165 | } | 165 | } | |
166 | sc->sc_rst_sata_cold = fdtbus_reset_get(phandle, "sata-cold"); | 166 | sc->sc_rst_sata_cold = fdtbus_reset_get(phandle, "sata-cold"); | |
167 | if(sc->sc_rst_sata_cold == NULL) { | 167 | if(sc->sc_rst_sata_cold == NULL) { | |
168 | aprint_error(": couldn't get reset sata-cold\n"); | 168 | aprint_error(": couldn't get reset sata-cold\n"); | |
169 | return; | 169 | return; | |
170 | } | 170 | } | |
171 | 171 | |||
172 | sc->sc_tad = of_search_compatible(faa->faa_phandle, compat_data)->data; | 172 | sc->sc_tad = of_search_compatible(faa->faa_phandle, compat_data)->data; | |
173 | if (sc->sc_tad->tad_type == TEGRA124) { | 173 | if (sc->sc_tad->tad_type == TEGRA124) { | |
174 | sc->sc_clk_cml1 = fdtbus_clock_get(phandle, "cml1"); | 174 | sc->sc_clk_cml1 = fdtbus_clock_get(phandle, "cml1"); | |
175 | if (sc->sc_clk_cml1 == NULL) { | 175 | if (sc->sc_clk_cml1 == NULL) { | |
176 | aprint_error(": couldn't get clock cml1\n"); | 176 | aprint_error(": couldn't get clock cml1\n"); | |
177 | return; | 177 | return; | |
178 | } | 178 | } | |
179 | sc->sc_clk_pll_e = fdtbus_clock_get(phandle, "pll_e"); | 179 | sc->sc_clk_pll_e = fdtbus_clock_get(phandle, "pll_e"); | |
180 | if (sc->sc_clk_pll_e == NULL) { | 180 | if (sc->sc_clk_pll_e == NULL) { | |
181 | aprint_error(": couldn't get clock pll_e\n"); | 181 | aprint_error(": couldn't get clock pll_e\n"); | |
182 | return; | 182 | return; | |
183 | } | 183 | } | |
184 | } | 184 | } | |
185 | 185 | |||
186 | sc->sc_bst = faa->faa_bst; | 186 | sc->sc_bst = faa->faa_bst; | |
187 | error = bus_space_map(sc->sc_bst, sata_addr, sata_size, 0, &sc->sc_bsh); | 187 | error = bus_space_map(sc->sc_bst, sata_addr, sata_size, 0, &sc->sc_bsh); | |
188 | if (error) { | 188 | if (error) { | |
189 | aprint_error(": couldn't map sata registers: %d\n", error); | 189 | aprint_error(": couldn't map sata registers: %d\n", error); | |
190 | return; | 190 | return; | |
191 | } | 191 | } | |
192 | 192 | |||
193 | sc->sc_phandle = faa->faa_phandle; | 193 | sc->sc_phandle = faa->faa_phandle; | |
194 | sc->sc.sc_atac.atac_dev = self; | 194 | sc->sc.sc_atac.atac_dev = self; | |
195 | sc->sc.sc_dmat = faa->faa_dmat; | 195 | sc->sc.sc_dmat = faa->faa_dmat; | |
196 | sc->sc.sc_ahcit = faa->faa_bst; | 196 | sc->sc.sc_ahcit = faa->faa_bst; | |
197 | sc->sc.sc_ahcis = ahci_size; | 197 | sc->sc.sc_ahcis = ahci_size; | |
198 | error = bus_space_map(sc->sc.sc_ahcit, ahci_addr, ahci_size, 0, | 198 | error = bus_space_map(sc->sc.sc_ahcit, ahci_addr, ahci_size, 0, | |
199 | &sc->sc.sc_ahcih); | 199 | &sc->sc.sc_ahcih); | |
200 | if (error) { | 200 | if (error) { | |
201 | aprint_error(": couldn't map ahci registers: %d\n", error); | 201 | aprint_error(": couldn't map ahci registers: %d\n", error); | |
202 | return; | 202 | return; | |
203 | } | 203 | } | |
204 | 204 | |||
205 | aprint_naive("\n"); | 205 | aprint_naive("\n"); | |
206 | aprint_normal(": SATA\n"); | 206 | aprint_normal(": SATA\n"); | |
207 | 207 | |||
208 | for (n = 0; n < sc->sc_tad->tad_nsupplies; n++) { | 208 | for (n = 0; n < sc->sc_tad->tad_nsupplies; n++) { | |
209 | const char *supply = sc->sc_tad->tad_supplies[n]; | 209 | const char *supply = sc->sc_tad->tad_supplies[n]; | |
210 | reg = fdtbus_regulator_acquire(phandle, supply); | 210 | reg = fdtbus_regulator_acquire(phandle, supply); | |
211 | if (reg == NULL) { | 211 | if (reg == NULL) { | |
212 | aprint_error_dev(self, "couldn't acquire %s\n", supply); | 212 | aprint_error_dev(self, "couldn't acquire %s\n", supply); | |
213 | continue; | 213 | continue; | |
214 | } | 214 | } | |
215 | if (fdtbus_regulator_enable(reg) != 0) { | 215 | if (fdtbus_regulator_enable(reg) != 0) { | |
216 | aprint_error_dev(self, "couldn't enable %s\n", supply); | 216 | aprint_error_dev(self, "couldn't enable %s\n", supply); | |
217 | } | 217 | } | |
218 | fdtbus_regulator_release(reg); | 218 | fdtbus_regulator_release(reg); | |
219 | } | 219 | } | |
220 | 220 | |||
221 | if (tegra_ahcisata_init_clocks(sc) != 0) | 221 | if (tegra_ahcisata_init_clocks(sc) != 0) | |
222 | return; | 222 | return; | |
223 | 223 | |||
224 | tegra_xusbpad_sata_enable(); | 224 | tegra_xusbpad_sata_enable(); | |
225 | 225 | |||
226 | tegra_ahcisata_init(sc); | 226 | tegra_ahcisata_init(sc); | |
227 | 227 | |||
228 | if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { | 228 | if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { | |
229 | aprint_error_dev(self, "failed to decode interrupt\n"); | 229 | aprint_error_dev(self, "failed to decode interrupt\n"); | |
230 | return; | 230 | return; | |
231 | } | 231 | } | |
232 | 232 | |||
233 | sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 0, | 233 | sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 0, | |
234 | ahci_intr, &sc->sc, device_xname(self)); | 234 | ahci_intr, &sc->sc, device_xname(self)); | |
235 | if (sc->sc_ih == NULL) { | 235 | if (sc->sc_ih == NULL) { | |
236 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | 236 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | |
237 | intrstr); | 237 | intrstr); | |
238 | return; | 238 | return; | |
239 | } | 239 | } | |
240 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | 240 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | |
241 | 241 | |||
242 | ahci_attach(&sc->sc); | 242 | ahci_attach(&sc->sc); | |
243 | } | 243 | } | |
244 | 244 | |||
245 | static void | 245 | static void | |
246 | tegra_ahcisata_init(struct tegra_ahcisata_softc *sc) | 246 | tegra_ahcisata_init(struct tegra_ahcisata_softc *sc) | |
247 | { | 247 | { | |
248 | bus_space_tag_t bst = sc->sc_bst; | 248 | bus_space_tag_t bst = sc->sc_bst; | |
249 | bus_space_handle_t bsh = sc->sc_bsh; | 249 | bus_space_handle_t bsh = sc->sc_bsh; | |
250 | 250 | |||
251 | /* Set RX idle detection source and disable RX idle detection interrupt */ | 251 | /* Set RX idle detection source and disable RX idle detection interrupt */ | |
252 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_MISC_CNTL_1_REG, | 252 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_MISC_CNTL_1_REG, | |
253 | TEGRA_SATA_AUX_MISC_CNTL_1_AUX_OR_CORE_IDLE_STATUS_SEL, 0); | 253 | TEGRA_SATA_AUX_MISC_CNTL_1_AUX_OR_CORE_IDLE_STATUS_SEL, 0); | |
254 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_RX_STAT_INT_REG, | 254 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_RX_STAT_INT_REG, | |
255 | TEGRA_SATA_AUX_RX_STAT_INT_SATA_RX_STAT_INT_DISABLE, 0); | 255 | TEGRA_SATA_AUX_RX_STAT_INT_SATA_RX_STAT_INT_DISABLE, 0); | |
256 | 256 | |||
257 | /* Prevent automatic OOB sequence when coming out of reset */ | 257 | /* Prevent automatic OOB sequence when coming out of reset */ | |
258 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_MISC_CNTL_1_REG, | 258 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_MISC_CNTL_1_REG, | |
259 | 0, TEGRA_SATA_AUX_MISC_CNTL_1_OOB_ON_POR); | 259 | 0, TEGRA_SATA_AUX_MISC_CNTL_1_OOB_ON_POR); | |
260 | 260 | |||
261 | /* Disable device sleep */ | 261 | /* Disable device sleep */ | |
262 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_MISC_CNTL_1_REG, | 262 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_AUX_MISC_CNTL_1_REG, | |
263 | 0, TEGRA_SATA_AUX_MISC_CNTL_1_SDS_SUPPORT); | 263 | 0, TEGRA_SATA_AUX_MISC_CNTL_1_SDS_SUPPORT); | |
264 | 264 | |||
265 | /* Enable IFPS device block */ | 265 | /* Enable IFPS device block */ | |
266 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_CONFIGURATION_REG, | 266 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_CONFIGURATION_REG, | |
267 | TEGRA_SATA_CONFIGURATION_EN_FPCI, 0); | 267 | TEGRA_SATA_CONFIGURATION_EN_FPCI, 0); | |
268 | 268 | |||
269 | /* Electrical settings for better link stability */ | 269 | /* Electrical settings for better link stability */ | |
270 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL17_REG, 0x55010000); | 270 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL17_REG, 0x55010000); | |
271 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL18_REG, 0x55010000); | 271 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL18_REG, 0x55010000); | |
272 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL20_REG, 1); | 272 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL20_REG, 1); | |
273 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL21_REG, 1); | 273 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL21_REG, 1); | |
274 | 274 | |||
275 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_PHY_0_REG, | 275 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_PHY_0_REG, | |
276 | TEGRA_T_SATA0_CFG_PHY_0_MASK_SQUELCH, | 276 | TEGRA_T_SATA0_CFG_PHY_0_MASK_SQUELCH, | |
277 | TEGRA_T_SATA0_CFG_PHY_0_USE_7BIT_ALIGN_DET_FOR_SPD); | 277 | TEGRA_T_SATA0_CFG_PHY_0_USE_7BIT_ALIGN_DET_FOR_SPD); | |
278 | 278 | |||
279 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_NVOOB_REG, | 279 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_NVOOB_REG, | |
280 | __SHIFTIN(0x7, TEGRA_T_SATA0_NVOOB_COMMA_CNT) | | 280 | __SHIFTIN(0x7, TEGRA_T_SATA0_NVOOB_COMMA_CNT) | | |
281 | __SHIFTIN(0x3, TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH) | | 281 | __SHIFTIN(0x3, TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH) | | |
282 | __SHIFTIN(0x1, TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_MODE), | 282 | __SHIFTIN(0x1, TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_MODE), | |
283 | TEGRA_T_SATA0_NVOOB_COMMA_CNT | | 283 | TEGRA_T_SATA0_NVOOB_COMMA_CNT | | |
284 | TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH | | 284 | TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH | | |
285 | TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_MODE); | 285 | TEGRA_T_SATA0_NVOOB_SQUELCH_FILTER_MODE); | |
286 | 286 | |||
287 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_2NVOOB_2_REG, | 287 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_2NVOOB_2_REG, | |
288 | __SHIFTIN(0xc, TEGRA_T_SATA0_CFG_2NVOOB_2_COMWAKE_IDLE_CNT_LOW), | 288 | __SHIFTIN(0xc, TEGRA_T_SATA0_CFG_2NVOOB_2_COMWAKE_IDLE_CNT_LOW), | |
289 | TEGRA_T_SATA0_CFG_2NVOOB_2_COMWAKE_IDLE_CNT_LOW); | 289 | TEGRA_T_SATA0_CFG_2NVOOB_2_COMWAKE_IDLE_CNT_LOW); | |
290 | 290 | |||
291 | if (sc->sc_tad->tad_type == TEGRA124) { | 291 | if (sc->sc_tad->tad_type == TEGRA124) { | |
292 | const u_int gen1_tx_amp = 0x18; | 292 | const u_int gen1_tx_amp = 0x18; | |
293 | const u_int gen1_tx_peak = 0x04; | 293 | const u_int gen1_tx_peak = 0x04; | |
294 | const u_int gen2_tx_amp = 0x18; | 294 | const u_int gen2_tx_amp = 0x18; | |
295 | const u_int gen2_tx_peak = 0x0a; | 295 | const u_int gen2_tx_peak = 0x0a; | |
296 | 296 | |||
297 | /* PHY config */ | 297 | /* PHY config */ | |
298 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_INDEX_REG, | 298 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_INDEX_REG, | |
299 | TEGRA_T_SATA0_INDEX_CH1); | 299 | TEGRA_T_SATA0_INDEX_CH1); | |
300 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_REG, | 300 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_REG, | |
301 | __SHIFTIN(gen1_tx_amp, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP) | | 301 | __SHIFTIN(gen1_tx_amp, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP) | | |
302 | __SHIFTIN(gen1_tx_peak, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK), | 302 | __SHIFTIN(gen1_tx_peak, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK), | |
303 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP | | 303 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP | | |
304 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK); | 304 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK); | |
305 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_REG, | 305 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_REG, | |
306 | __SHIFTIN(gen2_tx_amp, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP) | | 306 | __SHIFTIN(gen2_tx_amp, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP) | | |
307 | __SHIFTIN(gen2_tx_peak, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK), | 307 | __SHIFTIN(gen2_tx_peak, TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK), | |
308 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP | | 308 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP | | |
309 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK); | 309 | TEGRA_T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK); | |
310 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL11_REG, | 310 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL11_REG, | |
311 | __SHIFTIN(0x2800, TEGRA_T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ)); | 311 | __SHIFTIN(0x2800, TEGRA_T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ)); | |
312 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL2_REG, | 312 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CHX_PHY_CTRL2_REG, | |
313 | __SHIFTIN(0x23, TEGRA_T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1)); | 313 | __SHIFTIN(0x23, TEGRA_T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1)); | |
314 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_INDEX_REG, 0); | 314 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_INDEX_REG, 0); | |
315 | } | 315 | } | |
316 | 316 | |||
317 | /* Backdoor update the programming interface field and class code */ | 317 | /* Backdoor update the programming interface field and class code */ | |
318 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_SATA_REG, | 318 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_SATA_REG, | |
319 | TEGRA_T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN, 0); | 319 | TEGRA_T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN, 0); | |
320 | 320 | |||
321 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_BKDOOR_CC_REG, | 321 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_BKDOOR_CC_REG, | |
322 | __SHIFTIN(0x0106, TEGRA_T_SATA0_BKDOOR_CC_CLASS_CODE) | | 322 | __SHIFTIN(0x0106, TEGRA_T_SATA0_BKDOOR_CC_CLASS_CODE) | | |
323 | __SHIFTIN(0x1, TEGRA_T_SATA0_BKDOOR_CC_PROG_IF)); | 323 | __SHIFTIN(0x1, TEGRA_T_SATA0_BKDOOR_CC_PROG_IF)); | |
324 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_SATA_REG, | 324 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_SATA_REG, | |
325 | 0, TEGRA_T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN); | 325 | 0, TEGRA_T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN); | |
326 | 326 | |||
327 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_REG, | 327 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_REG, | |
328 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_SALP | | 328 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_SALP | | |
329 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM | | 329 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM | | |
330 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP | | 330 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP | | |
331 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP, 0); | 331 | TEGRA_T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP, 0); | |
332 | 332 | |||
333 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_PHY_1_REG, | 333 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG_PHY_1_REG, | |
334 | TEGRA_T_SATA0_CFG_PHY_1_PADS_IDDQ_EN | | 334 | TEGRA_T_SATA0_CFG_PHY_1_PADS_IDDQ_EN | | |
335 | TEGRA_T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN, 0); | 335 | TEGRA_T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN, 0); | |
336 | 336 | |||
337 | /* Enable IFPS device block */ | 337 | /* Enable IFPS device block */ | |
338 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_CONFIGURATION_REG, | 338 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_CONFIGURATION_REG, | |
339 | 0, TEGRA_SATA_CONFIGURATION_CLKEN_OVERRIDE); | 339 | 0, TEGRA_SATA_CONFIGURATION_CLKEN_OVERRIDE); | |
340 | 340 | |||
341 | /* Enable access and bus mastering */ | 341 | /* Enable access and bus mastering */ | |
342 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG1_REG, | 342 | tegra_reg_set_clear(bst, bsh, TEGRA_T_SATA0_CFG1_REG, | |
343 | TEGRA_T_SATA0_CFG1_SERR | | 343 | TEGRA_T_SATA0_CFG1_SERR | | |
344 | TEGRA_T_SATA0_CFG1_BUS_MASTER | | 344 | TEGRA_T_SATA0_CFG1_BUS_MASTER | | |
345 | TEGRA_T_SATA0_CFG1_MEM_SPACE | | 345 | TEGRA_T_SATA0_CFG1_MEM_SPACE | | |
346 | TEGRA_T_SATA0_CFG1_IO_SPACE, | 346 | TEGRA_T_SATA0_CFG1_IO_SPACE, | |
347 | 0); | 347 | 0); | |
348 | 348 | |||
349 | /* MMIO setup */ | 349 | /* MMIO setup */ | |
350 | bus_space_write_4(bst, bsh, TEGRA_SATA_FPCI_BAR5_REG, | 350 | bus_space_write_4(bst, bsh, TEGRA_SATA_FPCI_BAR5_REG, | |
351 | __SHIFTIN(0x10000, TEGRA_SATA_FPCI_BAR_START) | | 351 | __SHIFTIN(0x10000, TEGRA_SATA_FPCI_BAR_START) | | |
352 | TEGRA_SATA_FPCI_BAR_ACCESS_TYPE); | 352 | TEGRA_SATA_FPCI_BAR_ACCESS_TYPE); | |
353 | 353 | |||
354 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CFG9_REG, | 354 | bus_space_write_4(bst, bsh, TEGRA_T_SATA0_CFG9_REG, | |
355 | __SHIFTIN(0x8000, TEGRA_T_SATA0_CFG9_BASE_ADDRESS)); | 355 | __SHIFTIN(0x8000, TEGRA_T_SATA0_CFG9_BASE_ADDRESS)); | |
356 | 356 | |||
357 | /* Enable interrupts */ | 357 | /* Enable interrupts */ | |
358 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_INTR_MASK_REG, | 358 | tegra_reg_set_clear(bst, bsh, TEGRA_SATA_INTR_MASK_REG, | |
359 | TEGRA_SATA_INTR_MASK_IP_INT, 0); | 359 | TEGRA_SATA_INTR_MASK_IP_INT, 0); | |
360 | } | 360 | } | |
361 | 361 | |||
362 | static int | 362 | static int | |
363 | tegra_ahcisata_init_clocks(struct tegra_ahcisata_softc *sc) | 363 | tegra_ahcisata_init_clocks(struct tegra_ahcisata_softc *sc) | |
364 | { | 364 | { | |
365 | device_t self = sc->sc.sc_atac.atac_dev; | 365 | device_t self = sc->sc.sc_atac.atac_dev; | |
366 | int error; | 366 | int error; | |
367 | 367 | |||
368 | /* Assert resets */ | 368 | /* Assert resets */ | |
369 | fdtbus_reset_assert(sc->sc_rst_sata); | 369 | fdtbus_reset_assert(sc->sc_rst_sata); | |
370 | fdtbus_reset_assert(sc->sc_rst_sata_cold); | 370 | fdtbus_reset_assert(sc->sc_rst_sata_cold); | |
371 | 371 | |||
372 | /* Set SATA_OOB clock source to 204MHz */ | 372 | /* Set SATA_OOB clock source to 204MHz */ | |
373 | error = clk_set_rate(sc->sc_clk_sata_oob, 204000000); | 373 | error = clk_set_rate(sc->sc_clk_sata_oob, 204000000); | |
374 | if (error) { | 374 | if (error) { | |
375 | aprint_error_dev(self, "couldn't set sata-oob rate: %d\n", | 375 | aprint_error_dev(self, "couldn't set sata-oob rate: %d\n", | |
376 | error); | 376 | error); | |
377 | return error; | 377 | return error; | |
378 | } | 378 | } | |
379 | 379 | |||
380 | /* Set SATA clock source to 102MHz */ | 380 | /* Set SATA clock source to 102MHz */ | |
381 | error = clk_set_rate(sc->sc_clk_sata, 102000000); | 381 | error = clk_set_rate(sc->sc_clk_sata, 102000000); | |
382 | if (error) { | 382 | if (error) { | |
383 | aprint_error_dev(self, "couldn't set sata rate: %d\n", error); | 383 | aprint_error_dev(self, "couldn't set sata rate: %d\n", error); | |
384 | return error; | 384 | return error; | |
385 | } | 385 | } | |
386 | 386 | |||
387 | /* Ungate SAX partition in the PMC */ | 387 | /* Ungate SAX partition in the PMC */ | |
388 | tegra_pmc_power(PMC_PARTID_SAX, true); | 388 | tegra_pmc_power(PMC_PARTID_SAX, true); | |
389 | delay(20); | 389 | delay(20); | |
390 | 390 | |||
391 | /* Remove clamping from SAX partition in the PMC */ | 391 | /* Remove clamping from SAX partition in the PMC */ | |
392 | tegra_pmc_remove_clamping(PMC_PARTID_SAX); | 392 | tegra_pmc_remove_clamping(PMC_PARTID_SAX); | |
393 | delay(20); | 393 | delay(20); | |
394 | 394 | |||
395 | /* Un-gate clocks for SATA */ | 395 | /* Un-gate clocks for SATA */ | |
396 | error = clk_enable(sc->sc_clk_sata); | 396 | error = clk_enable(sc->sc_clk_sata); | |
397 | if (error) { | 397 | if (error) { | |
398 | aprint_error_dev(self, "couldn't enable sata: %d\n", error); | 398 | aprint_error_dev(self, "couldn't enable sata: %d\n", error); | |
399 | return error; | 399 | return error; | |
400 | } | 400 | } | |
401 | error = clk_enable(sc->sc_clk_sata_oob); | 401 | error = clk_enable(sc->sc_clk_sata_oob); | |
402 | if (error) { | 402 | if (error) { | |
403 | aprint_error_dev(self, "couldn't enable sata-oob: %d\n", error); | 403 | aprint_error_dev(self, "couldn't enable sata-oob: %d\n", error); | |
404 | return error; | 404 | return error; | |
405 | } | 405 | } | |
406 | 406 | |||
407 | if (sc->sc_clk_cml1) { | 407 | if (sc->sc_clk_cml1) { | |
408 | /* Enable CML clock for SATA */ | 408 | /* Enable CML clock for SATA */ | |
409 | error = clk_enable(sc->sc_clk_cml1); | 409 | error = clk_enable(sc->sc_clk_cml1); | |
410 | if (error) { | 410 | if (error) { | |
411 | aprint_error_dev(self, "couldn't enable cml1: %d\n", error); | 411 | aprint_error_dev(self, "couldn't enable cml1: %d\n", error); | |
412 | return error; | 412 | return error; | |
413 | } | 413 | } | |
414 | } | 414 | } | |
415 | 415 | |||
416 | /* Enable PHYs */ | 416 | /* Enable PHYs */ | |
417 | struct fdtbus_phy *phy; | 417 | struct fdtbus_phy *phy; | |
418 | for (u_int n = 0; (phy = fdtbus_phy_get_index(sc->sc_phandle, n)) != NULL; n++) | 418 | for (u_int n = 0; (phy = fdtbus_phy_get_index(sc->sc_phandle, n)) != NULL; n++) | |
419 | if (fdtbus_phy_enable(phy, true) != 0) | 419 | if (fdtbus_phy_enable(phy, true) != 0) | |
420 | aprint_error_dev(self, "failed to enable PHY #%d\n", n); | 420 | aprint_error_dev(self, "failed to enable PHY #%d\n", n); | |
421 | 421 | |||
422 | /* De-assert resets */ | 422 | /* De-assert resets */ | |
423 | fdtbus_reset_deassert(sc->sc_rst_sata); | 423 | fdtbus_reset_deassert(sc->sc_rst_sata); | |
424 | fdtbus_reset_deassert(sc->sc_rst_sata_cold); | 424 | fdtbus_reset_deassert(sc->sc_rst_sata_cold); | |
425 | 425 | |||
426 | return 0; | 426 | return 0; | |
427 | } | 427 | } |
--- src/sys/arch/arm/nvidia/tegra_pcie.c 2021/01/25 14:20:38 1.34
+++ src/sys/arch/arm/nvidia/tegra_pcie.c 2021/01/27 01:58:15 1.35
@@ -1,818 +1,818 @@ | @@ -1,818 +1,818 @@ | |||
1 | /* $NetBSD: tegra_pcie.c,v 1.34 2021/01/25 14:20:38 thorpej Exp $ */ | 1 | /* $NetBSD: tegra_pcie.c,v 1.35 2021/01/27 01:58:15 thorpej Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> | 4 | * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
26 | * SUCH DAMAGE. | 26 | * SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.34 2021/01/25 14:20:38 thorpej Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: tegra_pcie.c,v 1.35 2021/01/27 01:58:15 thorpej Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | 33 | |||
34 | #include <sys/bus.h> | 34 | #include <sys/bus.h> | |
35 | #include <sys/device.h> | 35 | #include <sys/device.h> | |
36 | #include <sys/intr.h> | 36 | #include <sys/intr.h> | |
37 | #include <sys/kmem.h> | 37 | #include <sys/kmem.h> | |
38 | #include <sys/kernel.h> | 38 | #include <sys/kernel.h> | |
39 | #include <sys/lwp.h> | 39 | #include <sys/lwp.h> | |
40 | #include <sys/mutex.h> | 40 | #include <sys/mutex.h> | |
41 | #include <sys/queue.h> | 41 | #include <sys/queue.h> | |
42 | #include <sys/systm.h> | 42 | #include <sys/systm.h> | |
43 | 43 | |||
44 | #include <machine/cpu.h> | 44 | #include <machine/cpu.h> | |
45 | 45 | |||
46 | #include <arm/cpufunc.h> | 46 | #include <arm/cpufunc.h> | |
47 | 47 | |||
48 | #include <dev/pci/pcireg.h> | 48 | #include <dev/pci/pcireg.h> | |
49 | #include <dev/pci/pcivar.h> | 49 | #include <dev/pci/pcivar.h> | |
50 | #include <dev/pci/pciconf.h> | 50 | #include <dev/pci/pciconf.h> | |
51 | 51 | |||
52 | #include <arm/nvidia/tegra_reg.h> | 52 | #include <arm/nvidia/tegra_reg.h> | |
53 | #include <arm/nvidia/tegra_pciereg.h> | 53 | #include <arm/nvidia/tegra_pciereg.h> | |
54 | #include <arm/nvidia/tegra_pmcreg.h> | 54 | #include <arm/nvidia/tegra_pmcreg.h> | |
55 | #include <arm/nvidia/tegra_var.h> | 55 | #include <arm/nvidia/tegra_var.h> | |
56 | 56 | |||
57 | #include <dev/fdt/fdtvar.h> | 57 | #include <dev/fdt/fdtvar.h> | |
58 | 58 | |||
59 | /* Interrupt handle flags */ | 59 | /* Interrupt handle flags */ | |
60 | #define IH_MPSAFE 0x80000000 | 60 | #define IH_MPSAFE 0x80000000 | |
61 | 61 | |||
62 | static int tegra_pcie_match(device_t, cfdata_t, void *); | 62 | static int tegra_pcie_match(device_t, cfdata_t, void *); | |
63 | static void tegra_pcie_attach(device_t, device_t, void *); | 63 | static void tegra_pcie_attach(device_t, device_t, void *); | |
64 | 64 | |||
65 | #define TEGRA_PCIE_NBUS 256 | 65 | #define TEGRA_PCIE_NBUS 256 | |
66 | #define TEGRA_PCIE_ECFB (1<<(12 - 8)) /* extended conf frags per bus */ | 66 | #define TEGRA_PCIE_ECFB (1<<(12 - 8)) /* extended conf frags per bus */ | |
67 | 67 | |||
68 | enum tegra_pcie_type { | 68 | enum tegra_pcie_type { | |
69 | TEGRA_PCIE_124 = 0, | 69 | TEGRA_PCIE_124 = 0, | |
70 | TEGRA_PCIE_210 = 1, | 70 | TEGRA_PCIE_210 = 1, | |
71 | }; | 71 | }; | |
72 | 72 | |||
73 | struct tegra_pcie_ih { | 73 | struct tegra_pcie_ih { | |
74 | int (*ih_callback)(void *); | 74 | int (*ih_callback)(void *); | |
75 | void *ih_arg; | 75 | void *ih_arg; | |
76 | int ih_ipl; | 76 | int ih_ipl; | |
77 | int ih_mpsafe; | 77 | int ih_mpsafe; | |
78 | TAILQ_ENTRY(tegra_pcie_ih) ih_entry; | 78 | TAILQ_ENTRY(tegra_pcie_ih) ih_entry; | |
79 | }; | 79 | }; | |
80 | 80 | |||
81 | struct tegra_pcie_softc { | 81 | struct tegra_pcie_softc { | |
82 | device_t sc_dev; | 82 | device_t sc_dev; | |
83 | bus_dma_tag_t sc_dmat; | 83 | bus_dma_tag_t sc_dmat; | |
84 | bus_space_tag_t sc_bst; | 84 | bus_space_tag_t sc_bst; | |
85 | bus_space_handle_t sc_bsh_afi; | 85 | bus_space_handle_t sc_bsh_afi; | |
86 | bus_space_handle_t sc_bsh_pads; | 86 | bus_space_handle_t sc_bsh_pads; | |
87 | bus_space_handle_t sc_bsh_rpconf; | 87 | bus_space_handle_t sc_bsh_rpconf; | |
88 | int sc_phandle; | 88 | int sc_phandle; | |
89 | enum tegra_pcie_type sc_type; | 89 | enum tegra_pcie_type sc_type; | |
90 | 90 | |||
91 | struct arm32_pci_chipset sc_pc; | 91 | struct arm32_pci_chipset sc_pc; | |
92 | 92 | |||
93 | void *sc_ih; | 93 | void *sc_ih; | |
94 | 94 | |||
95 | kmutex_t sc_lock; | 95 | kmutex_t sc_lock; | |
96 | 96 | |||
97 | TAILQ_HEAD(, tegra_pcie_ih) sc_intrs; | 97 | TAILQ_HEAD(, tegra_pcie_ih) sc_intrs; | |
98 | u_int sc_intrgen; | 98 | u_int sc_intrgen; | |
99 | 99 | |||
100 | bus_space_handle_t sc_bsh_extc[TEGRA_PCIE_NBUS-1][TEGRA_PCIE_ECFB]; | 100 | bus_space_handle_t sc_bsh_extc[TEGRA_PCIE_NBUS-1][TEGRA_PCIE_ECFB]; | |
101 | }; | 101 | }; | |
102 | 102 | |||
103 | static int tegra_pcie_intr(void *); | 103 | static int tegra_pcie_intr(void *); | |
104 | static void tegra_pcie_init(pci_chipset_tag_t, void *); | 104 | static void tegra_pcie_init(pci_chipset_tag_t, void *); | |
105 | static void tegra_pcie_enable(struct tegra_pcie_softc *); | 105 | static void tegra_pcie_enable(struct tegra_pcie_softc *); | |
106 | static void tegra_pcie_enable_ports(struct tegra_pcie_softc *); | 106 | static void tegra_pcie_enable_ports(struct tegra_pcie_softc *); | |
107 | static void tegra_pcie_enable_clocks(struct tegra_pcie_softc *); | 107 | static void tegra_pcie_enable_clocks(struct tegra_pcie_softc *); | |
108 | static void tegra_pcie_setup(struct tegra_pcie_softc * const); | 108 | static void tegra_pcie_setup(struct tegra_pcie_softc * const); | |
109 | static void tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const, | 109 | static void tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const, | |
110 | uint, uint); | 110 | uint, uint); | |
111 | static void tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const, uint); | 111 | static void tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const, uint); | |
112 | static void tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const); | 112 | static void tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const); | |
113 | 113 | |||
114 | static void tegra_pcie_attach_hook(device_t, device_t, | 114 | static void tegra_pcie_attach_hook(device_t, device_t, | |
115 | struct pcibus_attach_args *); | 115 | struct pcibus_attach_args *); | |
116 | static int tegra_pcie_bus_maxdevs(void *, int); | 116 | static int tegra_pcie_bus_maxdevs(void *, int); | |
117 | static pcitag_t tegra_pcie_make_tag(void *, int, int, int); | 117 | static pcitag_t tegra_pcie_make_tag(void *, int, int, int); | |
118 | static void tegra_pcie_decompose_tag(void *, pcitag_t, int *, int *, int *); | 118 | static void tegra_pcie_decompose_tag(void *, pcitag_t, int *, int *, int *); | |
119 | static pcireg_t tegra_pcie_conf_read(void *, pcitag_t, int); | 119 | static pcireg_t tegra_pcie_conf_read(void *, pcitag_t, int); | |
120 | static void tegra_pcie_conf_write(void *, pcitag_t, int, pcireg_t); | 120 | static void tegra_pcie_conf_write(void *, pcitag_t, int, pcireg_t); | |
121 | static int tegra_pcie_conf_hook(void *, int, int, int, pcireg_t); | 121 | static int tegra_pcie_conf_hook(void *, int, int, int, pcireg_t); | |
122 | static void tegra_pcie_conf_interrupt(void *, int, int, int, int, int *); | 122 | static void tegra_pcie_conf_interrupt(void *, int, int, int, int, int *); | |
123 | 123 | |||
124 | static int tegra_pcie_intr_map(const struct pci_attach_args *, | 124 | static int tegra_pcie_intr_map(const struct pci_attach_args *, | |
125 | pci_intr_handle_t *); | 125 | pci_intr_handle_t *); | |
126 | static const char *tegra_pcie_intr_string(void *, pci_intr_handle_t, | 126 | static const char *tegra_pcie_intr_string(void *, pci_intr_handle_t, | |
127 | char *, size_t); | 127 | char *, size_t); | |
128 | const struct evcnt *tegra_pcie_intr_evcnt(void *, pci_intr_handle_t); | 128 | const struct evcnt *tegra_pcie_intr_evcnt(void *, pci_intr_handle_t); | |
129 | static int tegra_pcie_intr_setattr(void *, pci_intr_handle_t *, int, | 129 | static int tegra_pcie_intr_setattr(void *, pci_intr_handle_t *, int, | |
130 | uint64_t); | 130 | uint64_t); | |
131 | static void * tegra_pcie_intr_establish(void *, pci_intr_handle_t, | 131 | static void * tegra_pcie_intr_establish(void *, pci_intr_handle_t, | |
132 | int, int (*)(void *), void *, | 132 | int, int (*)(void *), void *, | |
133 | const char *); | 133 | const char *); | |
134 | static void tegra_pcie_intr_disestablish(void *, void *); | 134 | static void tegra_pcie_intr_disestablish(void *, void *); | |
135 | 135 | |||
136 | CFATTACH_DECL_NEW(tegra_pcie, sizeof(struct tegra_pcie_softc), | 136 | CFATTACH_DECL_NEW(tegra_pcie, sizeof(struct tegra_pcie_softc), | |
137 | tegra_pcie_match, tegra_pcie_attach, NULL, NULL); | 137 | tegra_pcie_match, tegra_pcie_attach, NULL, NULL); | |
138 | 138 | |||
139 | static const struct device_compatible_entry compat_data[] = { | 139 | static const struct device_compatible_entry compat_data[] = { | |
140 | { .compat = "nvidia,tegra210-pcie", .value = TEGRA_PCIE_210 }, | 140 | { .compat = "nvidia,tegra210-pcie", .value = TEGRA_PCIE_210 }, | |
141 | { .compat = "nvidia,tegra124-pcie", .value = TEGRA_PCIE_124 }, | 141 | { .compat = "nvidia,tegra124-pcie", .value = TEGRA_PCIE_124 }, | |
142 | { } | 142 | DEVICE_COMPAT_EOL | |
143 | }; | 143 | }; | |
144 | 144 | |||
145 | static int | 145 | static int | |
146 | tegra_pcie_match(device_t parent, cfdata_t cf, void *aux) | 146 | tegra_pcie_match(device_t parent, cfdata_t cf, void *aux) | |
147 | { | 147 | { | |
148 | struct fdt_attach_args * const faa = aux; | 148 | struct fdt_attach_args * const faa = aux; | |
149 | 149 | |||
150 | return of_match_compat_data(faa->faa_phandle, compat_data); | 150 | return of_match_compat_data(faa->faa_phandle, compat_data); | |
151 | } | 151 | } | |
152 | 152 | |||
153 | static void | 153 | static void | |
154 | tegra_pcie_attach(device_t parent, device_t self, void *aux) | 154 | tegra_pcie_attach(device_t parent, device_t self, void *aux) | |
155 | { | 155 | { | |
156 | struct tegra_pcie_softc * const sc = device_private(self); | 156 | struct tegra_pcie_softc * const sc = device_private(self); | |
157 | struct fdt_attach_args * const faa = aux; | 157 | struct fdt_attach_args * const faa = aux; | |
158 | const struct device_compatible_entry *dce; | 158 | const struct device_compatible_entry *dce; | |
159 | struct pciconf_resources *pcires; | 159 | struct pciconf_resources *pcires; | |
160 | struct pcibus_attach_args pba; | 160 | struct pcibus_attach_args pba; | |
161 | bus_addr_t afi_addr, cs_addr, pads_addr; | 161 | bus_addr_t afi_addr, cs_addr, pads_addr; | |
162 | bus_size_t afi_size, cs_size, pads_size; | 162 | bus_size_t afi_size, cs_size, pads_size; | |
163 | char intrstr[128]; | 163 | char intrstr[128]; | |
164 | int error; | 164 | int error; | |
165 | 165 | |||
166 | if (fdtbus_get_reg_byname(faa->faa_phandle, "afi", &afi_addr, &afi_size) != 0) { | 166 | if (fdtbus_get_reg_byname(faa->faa_phandle, "afi", &afi_addr, &afi_size) != 0) { | |
167 | aprint_error(": couldn't get afi registers\n"); | 167 | aprint_error(": couldn't get afi registers\n"); | |
168 | return; | 168 | return; | |
169 | } | 169 | } | |
170 | if (fdtbus_get_reg_byname(faa->faa_phandle, "pads", &pads_addr, &pads_size) != 0) { | 170 | if (fdtbus_get_reg_byname(faa->faa_phandle, "pads", &pads_addr, &pads_size) != 0) { | |
171 | aprint_error(": couldn't get pads registers\n"); | 171 | aprint_error(": couldn't get pads registers\n"); | |
172 | return; | 172 | return; | |
173 | } | 173 | } | |
174 | #if notyet | 174 | #if notyet | |
175 | if (fdtbus_get_reg(faa->faa_phandle, 2, &cs_addr, &cs_size) != 0) { | 175 | if (fdtbus_get_reg(faa->faa_phandle, 2, &cs_addr, &cs_size) != 0) { | |
176 | aprint_error(": couldn't get cs registers\n"); | 176 | aprint_error(": couldn't get cs registers\n"); | |
177 | return; | 177 | return; | |
178 | } | 178 | } | |
179 | #else | 179 | #else | |
180 | cs_addr = TEGRA_PCIE_RPCONF_BASE; | 180 | cs_addr = TEGRA_PCIE_RPCONF_BASE; | |
181 | cs_size = TEGRA_PCIE_RPCONF_SIZE; | 181 | cs_size = TEGRA_PCIE_RPCONF_SIZE; | |
182 | #endif | 182 | #endif | |
183 | 183 | |||
184 | sc->sc_dev = self; | 184 | sc->sc_dev = self; | |
185 | sc->sc_dmat = faa->faa_dmat; | 185 | sc->sc_dmat = faa->faa_dmat; | |
186 | sc->sc_bst = faa->faa_bst; | 186 | sc->sc_bst = faa->faa_bst; | |
187 | sc->sc_phandle = faa->faa_phandle; | 187 | sc->sc_phandle = faa->faa_phandle; | |
188 | error = bus_space_map(sc->sc_bst, afi_addr, afi_size, 0, | 188 | error = bus_space_map(sc->sc_bst, afi_addr, afi_size, 0, | |
189 | &sc->sc_bsh_afi); | 189 | &sc->sc_bsh_afi); | |
190 | if (error) { | 190 | if (error) { | |
191 | aprint_error(": couldn't map afi registers: %d\n", error); | 191 | aprint_error(": couldn't map afi registers: %d\n", error); | |
192 | return; | 192 | return; | |
193 | } | 193 | } | |
194 | error = bus_space_map(sc->sc_bst, pads_addr, pads_size, 0, | 194 | error = bus_space_map(sc->sc_bst, pads_addr, pads_size, 0, | |
195 | &sc->sc_bsh_pads); | 195 | &sc->sc_bsh_pads); | |
196 | if (error) { | 196 | if (error) { | |
197 | aprint_error(": couldn't map pads registers: %d\n", error); | 197 | aprint_error(": couldn't map pads registers: %d\n", error); | |
198 | return; | 198 | return; | |
199 | } | 199 | } | |
200 | error = bus_space_map(sc->sc_bst, cs_addr, cs_size, | 200 | error = bus_space_map(sc->sc_bst, cs_addr, cs_size, | |
201 | _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &sc->sc_bsh_rpconf); | 201 | _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &sc->sc_bsh_rpconf); | |
202 | if (error) { | 202 | if (error) { | |
203 | aprint_error(": couldn't map cs registers: %d\n", error); | 203 | aprint_error(": couldn't map cs registers: %d\n", error); | |
204 | return; | 204 | return; | |
205 | } | 205 | } | |
206 | 206 | |||
207 | dce = of_search_compatible(faa->faa_phandle, compat_data); | 207 | dce = of_search_compatible(faa->faa_phandle, compat_data); | |
208 | KASSERT(dce != NULL); | 208 | KASSERT(dce != NULL); | |
209 | sc->sc_type = dce->value; | 209 | sc->sc_type = dce->value; | |
210 | 210 | |||
211 | tegra_pcie_conf_map_buses(sc); | 211 | tegra_pcie_conf_map_buses(sc); | |
212 | 212 | |||
213 | TAILQ_INIT(&sc->sc_intrs); | 213 | TAILQ_INIT(&sc->sc_intrs); | |
214 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); | 214 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); | |
215 | 215 | |||
216 | aprint_naive("\n"); | 216 | aprint_naive("\n"); | |
217 | aprint_normal(": PCIE\n"); | 217 | aprint_normal(": PCIE\n"); | |
218 | 218 | |||
219 | tegra_pmc_power(PMC_PARTID_PCX, true); | 219 | tegra_pmc_power(PMC_PARTID_PCX, true); | |
220 | tegra_pmc_remove_clamping(PMC_PARTID_PCX); | 220 | tegra_pmc_remove_clamping(PMC_PARTID_PCX); | |
221 | 221 | |||
222 | tegra_pcie_enable_clocks(sc); | 222 | tegra_pcie_enable_clocks(sc); | |
223 | 223 | |||
224 | if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) { | 224 | if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) { | |
225 | aprint_error_dev(self, "failed to decode interrupt\n"); | 225 | aprint_error_dev(self, "failed to decode interrupt\n"); | |
226 | return; | 226 | return; | |
227 | } | 227 | } | |
228 | 228 | |||
229 | sc->sc_ih = fdtbus_intr_establish_xname(faa->faa_phandle, 0, IPL_VM, | 229 | sc->sc_ih = fdtbus_intr_establish_xname(faa->faa_phandle, 0, IPL_VM, | |
230 | FDT_INTR_MPSAFE, tegra_pcie_intr, sc, device_xname(self)); | 230 | FDT_INTR_MPSAFE, tegra_pcie_intr, sc, device_xname(self)); | |
231 | if (sc->sc_ih == NULL) { | 231 | if (sc->sc_ih == NULL) { | |
232 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | 232 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | |
233 | intrstr); | 233 | intrstr); | |
234 | return; | 234 | return; | |
235 | } | 235 | } | |
236 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | 236 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | |
237 | 237 | |||
238 | tegra_pcie_setup(sc); | 238 | tegra_pcie_setup(sc); | |
239 | 239 | |||
240 | tegra_pcie_init(&sc->sc_pc, sc); | 240 | tegra_pcie_init(&sc->sc_pc, sc); | |
241 | 241 | |||
242 | pcires = pciconf_resource_init(); | 242 | pcires = pciconf_resource_init(); | |
243 | 243 | |||
244 | pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, | 244 | pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, | |
245 | TEGRA_PCIE_IO_BASE, TEGRA_PCIE_IO_SIZE); | 245 | TEGRA_PCIE_IO_BASE, TEGRA_PCIE_IO_SIZE); | |
246 | pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, | 246 | pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, | |
247 | TEGRA_PCIE_MEM_BASE, TEGRA_PCIE_MEM_SIZE); | 247 | TEGRA_PCIE_MEM_BASE, TEGRA_PCIE_MEM_SIZE); | |
248 | pciconf_resource_add(pcires, PCICONF_RESOURCE_PREFETCHABLE_MEM, | 248 | pciconf_resource_add(pcires, PCICONF_RESOURCE_PREFETCHABLE_MEM, | |
249 | TEGRA_PCIE_PMEM_BASE, TEGRA_PCIE_PMEM_SIZE); | 249 | TEGRA_PCIE_PMEM_BASE, TEGRA_PCIE_PMEM_SIZE); | |
250 | 250 | |||
251 | error = pci_configure_bus(&sc->sc_pc, pcires, 0, | 251 | error = pci_configure_bus(&sc->sc_pc, pcires, 0, | |
252 | arm_dcache_align); | 252 | arm_dcache_align); | |
253 | 253 | |||
254 | pciconf_resource_fini(pcires); | 254 | pciconf_resource_fini(pcires); | |
255 | 255 | |||
256 | if (error) { | 256 | if (error) { | |
257 | aprint_error_dev(self, "configuration failed (%d)\n", | 257 | aprint_error_dev(self, "configuration failed (%d)\n", | |
258 | error); | 258 | error); | |
259 | return; | 259 | return; | |
260 | } | 260 | } | |
261 | 261 | |||
262 | tegra_pcie_enable(sc); | 262 | tegra_pcie_enable(sc); | |
263 | 263 | |||
264 | tegra_pcie_enable_ports(sc); | 264 | tegra_pcie_enable_ports(sc); | |
265 | 265 | |||
266 | memset(&pba, 0, sizeof(pba)); | 266 | memset(&pba, 0, sizeof(pba)); | |
267 | pba.pba_flags = PCI_FLAGS_MRL_OKAY | | 267 | pba.pba_flags = PCI_FLAGS_MRL_OKAY | | |
268 | PCI_FLAGS_MRM_OKAY | | 268 | PCI_FLAGS_MRM_OKAY | | |
269 | PCI_FLAGS_MWI_OKAY | | 269 | PCI_FLAGS_MWI_OKAY | | |
270 | PCI_FLAGS_MEM_OKAY | | 270 | PCI_FLAGS_MEM_OKAY | | |
271 | PCI_FLAGS_IO_OKAY; | 271 | PCI_FLAGS_IO_OKAY; | |
272 | pba.pba_iot = sc->sc_bst; | 272 | pba.pba_iot = sc->sc_bst; | |
273 | pba.pba_memt = sc->sc_bst; | 273 | pba.pba_memt = sc->sc_bst; | |
274 | pba.pba_dmat = sc->sc_dmat; | 274 | pba.pba_dmat = sc->sc_dmat; | |
275 | pba.pba_pc = &sc->sc_pc; | 275 | pba.pba_pc = &sc->sc_pc; | |
276 | pba.pba_bus = 0; | 276 | pba.pba_bus = 0; | |
277 | 277 | |||
278 | config_found_ia(self, "pcibus", &pba, pcibusprint); | 278 | config_found_ia(self, "pcibus", &pba, pcibusprint); | |
279 | } | 279 | } | |
280 | 280 | |||
281 | static int | 281 | static int | |
282 | tegra_pcie_legacy_intr(struct tegra_pcie_softc *sc) | 282 | tegra_pcie_legacy_intr(struct tegra_pcie_softc *sc) | |
283 | { | 283 | { | |
284 | const uint32_t msg = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, | 284 | const uint32_t msg = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, | |
285 | AFI_MSG_REG); | 285 | AFI_MSG_REG); | |
286 | struct tegra_pcie_ih *pcie_ih; | 286 | struct tegra_pcie_ih *pcie_ih; | |
287 | int rv = 0; | 287 | int rv = 0; | |
288 | 288 | |||
289 | if (msg & (AFI_MSG_INT0|AFI_MSG_INT1)) { | 289 | if (msg & (AFI_MSG_INT0|AFI_MSG_INT1)) { | |
290 | mutex_enter(&sc->sc_lock); | 290 | mutex_enter(&sc->sc_lock); | |
291 | const u_int lastgen = sc->sc_intrgen; | 291 | const u_int lastgen = sc->sc_intrgen; | |
292 | TAILQ_FOREACH(pcie_ih, &sc->sc_intrs, ih_entry) { | 292 | TAILQ_FOREACH(pcie_ih, &sc->sc_intrs, ih_entry) { | |
293 | int (*callback)(void *) = pcie_ih->ih_callback; | 293 | int (*callback)(void *) = pcie_ih->ih_callback; | |
294 | void *arg = pcie_ih->ih_arg; | 294 | void *arg = pcie_ih->ih_arg; | |
295 | const int mpsafe = pcie_ih->ih_mpsafe; | 295 | const int mpsafe = pcie_ih->ih_mpsafe; | |
296 | mutex_exit(&sc->sc_lock); | 296 | mutex_exit(&sc->sc_lock); | |
297 | 297 | |||
298 | if (!mpsafe) | 298 | if (!mpsafe) | |
299 | KERNEL_LOCK(1, curlwp); | 299 | KERNEL_LOCK(1, curlwp); | |
300 | rv += callback(arg); | 300 | rv += callback(arg); | |
301 | if (!mpsafe) | 301 | if (!mpsafe) | |
302 | KERNEL_UNLOCK_ONE(curlwp); | 302 | KERNEL_UNLOCK_ONE(curlwp); | |
303 | 303 | |||
304 | mutex_enter(&sc->sc_lock); | 304 | mutex_enter(&sc->sc_lock); | |
305 | if (lastgen != sc->sc_intrgen) | 305 | if (lastgen != sc->sc_intrgen) | |
306 | break; | 306 | break; | |
307 | } | 307 | } | |
308 | mutex_exit(&sc->sc_lock); | 308 | mutex_exit(&sc->sc_lock); | |
309 | } else if (msg & (AFI_MSG_PM_PME0|AFI_MSG_PM_PME1)) { | 309 | } else if (msg & (AFI_MSG_PM_PME0|AFI_MSG_PM_PME1)) { | |
310 | device_printf(sc->sc_dev, "PM PME message; AFI_MSG=%08x\n", | 310 | device_printf(sc->sc_dev, "PM PME message; AFI_MSG=%08x\n", | |
311 | msg); | 311 | msg); | |
312 | } else { | 312 | } else { | |
313 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_MSG_REG, msg); | 313 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_MSG_REG, msg); | |
314 | rv = 1; | 314 | rv = 1; | |
315 | } | 315 | } | |
316 | 316 | |||
317 | return rv; | 317 | return rv; | |
318 | } | 318 | } | |
319 | 319 | |||
320 | static int | 320 | static int | |
321 | tegra_pcie_intr(void *priv) | 321 | tegra_pcie_intr(void *priv) | |
322 | { | 322 | { | |
323 | struct tegra_pcie_softc *sc = priv; | 323 | struct tegra_pcie_softc *sc = priv; | |
324 | int rv; | 324 | int rv; | |
325 | 325 | |||
326 | const uint32_t code = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, | 326 | const uint32_t code = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, | |
327 | AFI_INTR_CODE_REG); | 327 | AFI_INTR_CODE_REG); | |
328 | const uint32_t sig = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, | 328 | const uint32_t sig = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, | |
329 | AFI_INTR_SIGNATURE_REG); | 329 | AFI_INTR_SIGNATURE_REG); | |
330 | 330 | |||
331 | switch (__SHIFTOUT(code, AFI_INTR_CODE_INT_CODE)) { | 331 | switch (__SHIFTOUT(code, AFI_INTR_CODE_INT_CODE)) { | |
332 | case AFI_INTR_CODE_SM_MSG: | 332 | case AFI_INTR_CODE_SM_MSG: | |
333 | rv = tegra_pcie_legacy_intr(sc); | 333 | rv = tegra_pcie_legacy_intr(sc); | |
334 | break; | 334 | break; | |
335 | default: | 335 | default: | |
336 | device_printf(sc->sc_dev, "intr: code %#x sig %#x\n", | 336 | device_printf(sc->sc_dev, "intr: code %#x sig %#x\n", | |
337 | code, sig); | 337 | code, sig); | |
338 | rv = 1; | 338 | rv = 1; | |
339 | break; | 339 | break; | |
340 | } | 340 | } | |
341 | 341 | |||
342 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0); | 342 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0); | |
343 | 343 | |||
344 | return rv; | 344 | return rv; | |
345 | } | 345 | } | |
346 | 346 | |||
347 | static void | 347 | static void | |
348 | tegra_pcie_enable_clocks(struct tegra_pcie_softc * const sc) | 348 | tegra_pcie_enable_clocks(struct tegra_pcie_softc * const sc) | |
349 | { | 349 | { | |
350 | const char *clock_names[] = { "pex", "afi", "pll_e", "cml" }; | 350 | const char *clock_names[] = { "pex", "afi", "pll_e", "cml" }; | |
351 | const char *reset_names[] = { "pex", "afi", "pcie_x" }; | 351 | const char *reset_names[] = { "pex", "afi", "pcie_x" }; | |
352 | struct fdtbus_reset *rst; | 352 | struct fdtbus_reset *rst; | |
353 | struct clk *clk; | 353 | struct clk *clk; | |
354 | int n; | 354 | int n; | |
355 | 355 | |||
356 | for (n = 0; n < __arraycount(clock_names); n++) { | 356 | for (n = 0; n < __arraycount(clock_names); n++) { | |
357 | clk = fdtbus_clock_get(sc->sc_phandle, clock_names[n]); | 357 | clk = fdtbus_clock_get(sc->sc_phandle, clock_names[n]); | |
358 | if (clk == NULL || clk_enable(clk) != 0) | 358 | if (clk == NULL || clk_enable(clk) != 0) | |
359 | aprint_error_dev(sc->sc_dev, "couldn't enable clock %s\n", | 359 | aprint_error_dev(sc->sc_dev, "couldn't enable clock %s\n", | |
360 | clock_names[n]); | 360 | clock_names[n]); | |
361 | } | 361 | } | |
362 | 362 | |||
363 | for (n = 0; n < __arraycount(reset_names); n++) { | 363 | for (n = 0; n < __arraycount(reset_names); n++) { | |
364 | rst = fdtbus_reset_get(sc->sc_phandle, reset_names[n]); | 364 | rst = fdtbus_reset_get(sc->sc_phandle, reset_names[n]); | |
365 | if (rst == NULL || fdtbus_reset_deassert(rst) != 0) | 365 | if (rst == NULL || fdtbus_reset_deassert(rst) != 0) | |
366 | aprint_error_dev(sc->sc_dev, "couldn't de-assert reset %s\n", | 366 | aprint_error_dev(sc->sc_dev, "couldn't de-assert reset %s\n", | |
367 | reset_names[n]); | 367 | reset_names[n]); | |
368 | } | 368 | } | |
369 | } | 369 | } | |
370 | 370 | |||
371 | #if 0 | 371 | #if 0 | |
372 | static void | 372 | static void | |
373 | tegra_pcie_reset_port(struct tegra_pcie_softc * const sc, int index) | 373 | tegra_pcie_reset_port(struct tegra_pcie_softc * const sc, int index) | |
374 | { | 374 | { | |
375 | uint32_t val; | 375 | uint32_t val; | |
376 | 376 | |||
377 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index)); | 377 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index)); | |
378 | val &= ~AFI_PEXn_CTRL_RST_L; | 378 | val &= ~AFI_PEXn_CTRL_RST_L; | |
379 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index), val); | 379 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index), val); | |
380 | 380 | |||
381 | delay(2000); | 381 | delay(2000); | |
382 | 382 | |||
383 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index)); | 383 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index)); | |
384 | val |= AFI_PEXn_CTRL_RST_L; | 384 | val |= AFI_PEXn_CTRL_RST_L; | |
385 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index), val); | 385 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index), val); | |
386 | } | 386 | } | |
387 | #endif | 387 | #endif | |
388 | 388 | |||
389 | static void | 389 | static void | |
390 | tegra_pcie_enable_ports(struct tegra_pcie_softc * const sc) | 390 | tegra_pcie_enable_ports(struct tegra_pcie_softc * const sc) | |
391 | { | 391 | { | |
392 | struct fdtbus_phy *phy; | 392 | struct fdtbus_phy *phy; | |
393 | const u_int *data; | 393 | const u_int *data; | |
394 | int child, len, n; | 394 | int child, len, n; | |
395 | uint32_t val; | 395 | uint32_t val; | |
396 | 396 | |||
397 | for (child = OF_child(sc->sc_phandle); child; child = OF_peer(child)) { | 397 | for (child = OF_child(sc->sc_phandle); child; child = OF_peer(child)) { | |
398 | if (!fdtbus_status_okay(child)) | 398 | if (!fdtbus_status_okay(child)) | |
399 | continue; | 399 | continue; | |
400 | 400 | |||
401 | /* Enable PHYs */ | 401 | /* Enable PHYs */ | |
402 | for (n = 0; (phy = fdtbus_phy_get_index(child, n)) != NULL; n++) | 402 | for (n = 0; (phy = fdtbus_phy_get_index(child, n)) != NULL; n++) | |
403 | if (fdtbus_phy_enable(phy, true) != 0) | 403 | if (fdtbus_phy_enable(phy, true) != 0) | |
404 | aprint_error_dev(sc->sc_dev, "couldn't enable %s phy #%d\n", | 404 | aprint_error_dev(sc->sc_dev, "couldn't enable %s phy #%d\n", | |
405 | fdtbus_get_string(child, "name"), n); | 405 | fdtbus_get_string(child, "name"), n); | |
406 | 406 | |||
407 | data = fdtbus_get_prop(child, "reg", &len); | 407 | data = fdtbus_get_prop(child, "reg", &len); | |
408 | if (data == NULL || len < 4) | 408 | if (data == NULL || len < 4) | |
409 | continue; | 409 | continue; | |
410 | const u_int index = ((be32toh(data[0]) >> 11) & 0x1f) - 1; | 410 | const u_int index = ((be32toh(data[0]) >> 11) & 0x1f) - 1; | |
411 | 411 | |||
412 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index)); | 412 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index)); | |
413 | val |= AFI_PEXn_CTRL_CLKREQ_EN; | 413 | val |= AFI_PEXn_CTRL_CLKREQ_EN; | |
414 | val |= AFI_PEXn_CTRL_REFCLK_EN; | 414 | val |= AFI_PEXn_CTRL_REFCLK_EN; | |
415 | val |= AFI_PEXn_CTRL_REFCLK_OVERRIDE_EN; | 415 | val |= AFI_PEXn_CTRL_REFCLK_OVERRIDE_EN; | |
416 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index), val); | 416 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXn_CTRL_REG(index), val); | |
417 | 417 | |||
418 | #if 0 | 418 | #if 0 | |
419 | tegra_pcie_reset_port(sc, index); | 419 | tegra_pcie_reset_port(sc, index); | |
420 | #endif | 420 | #endif | |
421 | 421 | |||
422 | } | 422 | } | |
423 | } | 423 | } | |
424 | 424 | |||
425 | static void | 425 | static void | |
426 | tegra_pcie_setup(struct tegra_pcie_softc * const sc) | 426 | tegra_pcie_setup(struct tegra_pcie_softc * const sc) | |
427 | { | 427 | { | |
428 | uint32_t val, cfg, lanes; | 428 | uint32_t val, cfg, lanes; | |
429 | int child, len; | 429 | int child, len; | |
430 | const u_int *data; | 430 | const u_int *data; | |
431 | size_t i; | 431 | size_t i; | |
432 | 432 | |||
433 | /* Enable PLLE control */ | 433 | /* Enable PLLE control */ | |
434 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PLLE_CONTROL_REG); | 434 | val = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PLLE_CONTROL_REG); | |
435 | val &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL; | 435 | val &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL; | |
436 | val |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN; | 436 | val |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN; | |
437 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PLLE_CONTROL_REG, val); | 437 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PLLE_CONTROL_REG, val); | |
438 | 438 | |||
439 | /* Disable PEX clock bias pad power down */ | 439 | /* Disable PEX clock bias pad power down */ | |
440 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXBIAS_CTRL_REG, 0); | 440 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PEXBIAS_CTRL_REG, 0); | |
441 | 441 | |||
442 | /* Configure PCIE mode and enable ports */ | 442 | /* Configure PCIE mode and enable ports */ | |
443 | cfg = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PCIE_CONFIG_REG); | 443 | cfg = bus_space_read_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PCIE_CONFIG_REG); | |
444 | cfg |= AFI_PCIE_CONFIG_PCIECn_DISABLE_DEVICE(0); | 444 | cfg |= AFI_PCIE_CONFIG_PCIECn_DISABLE_DEVICE(0); | |
445 | cfg |= AFI_PCIE_CONFIG_PCIECn_DISABLE_DEVICE(1); | 445 | cfg |= AFI_PCIE_CONFIG_PCIECn_DISABLE_DEVICE(1); | |
446 | cfg &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG; | 446 | cfg &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG; | |
447 | 447 | |||
448 | lanes = 0; | 448 | lanes = 0; | |
449 | for (child = OF_child(sc->sc_phandle); child; child = OF_peer(child)) { | 449 | for (child = OF_child(sc->sc_phandle); child; child = OF_peer(child)) { | |
450 | if (!fdtbus_status_okay(child)) | 450 | if (!fdtbus_status_okay(child)) | |
451 | continue; | 451 | continue; | |
452 | data = fdtbus_get_prop(child, "reg", &len); | 452 | data = fdtbus_get_prop(child, "reg", &len); | |
453 | if (data == NULL || len < 4) | 453 | if (data == NULL || len < 4) | |
454 | continue; | 454 | continue; | |
455 | const u_int index = ((be32toh(data[0]) >> 11) & 0x1f) - 1; | 455 | const u_int index = ((be32toh(data[0]) >> 11) & 0x1f) - 1; | |
456 | if (of_getprop_uint32(child, "nvidia,num-lanes", &val) != 0) | 456 | if (of_getprop_uint32(child, "nvidia,num-lanes", &val) != 0) | |
457 | continue; | 457 | continue; | |
458 | lanes |= (val << (index << 3)); | 458 | lanes |= (val << (index << 3)); | |
459 | cfg &= ~AFI_PCIE_CONFIG_PCIECn_DISABLE_DEVICE(index); | 459 | cfg &= ~AFI_PCIE_CONFIG_PCIECn_DISABLE_DEVICE(index); | |
460 | } | 460 | } | |
461 | 461 | |||
462 | switch (lanes) { | 462 | switch (lanes) { | |
463 | case 0x0104: | 463 | case 0x0104: | |
464 | aprint_normal_dev(sc->sc_dev, "lane config: x4 x1\n"); | 464 | aprint_normal_dev(sc->sc_dev, "lane config: x4 x1\n"); | |
465 | cfg |= __SHIFTIN(AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_4_1, | 465 | cfg |= __SHIFTIN(AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_4_1, | |
466 | AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG); | 466 | AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG); | |
467 | break; | 467 | break; | |
468 | case 0x0102: | 468 | case 0x0102: | |
469 | aprint_normal_dev(sc->sc_dev, "lane config: x2 x1\n"); | 469 | aprint_normal_dev(sc->sc_dev, "lane config: x2 x1\n"); | |
470 | cfg |= __SHIFTIN(AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_2_1, | 470 | cfg |= __SHIFTIN(AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_2_1, | |
471 | AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG); | 471 | AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG); | |
472 | break; | 472 | break; | |
473 | } | 473 | } | |
474 | 474 | |||
475 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PCIE_CONFIG_REG, cfg); | 475 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_PCIE_CONFIG_REG, cfg); | |
476 | 476 | |||
477 | /* Configure refclk pad */ | 477 | /* Configure refclk pad */ | |
478 | if (sc->sc_type == TEGRA_PCIE_124) { | 478 | if (sc->sc_type == TEGRA_PCIE_124) { | |
479 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_pads, | 479 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_pads, | |
480 | PADS_REFCLK_CFG0_REG, 0x44ac44ac); | 480 | PADS_REFCLK_CFG0_REG, 0x44ac44ac); | |
481 | } | 481 | } | |
482 | if (sc->sc_type == TEGRA_PCIE_210) { | 482 | if (sc->sc_type == TEGRA_PCIE_210) { | |
483 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_pads, | 483 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_pads, | |
484 | PADS_REFCLK_CFG0_REG, 0x90b890b8); | 484 | PADS_REFCLK_CFG0_REG, 0x90b890b8); | |
485 | } | 485 | } | |
486 | 486 | |||
487 | /* | 487 | /* | |
488 | * Map PCI address spaces into ARM address space via | 488 | * Map PCI address spaces into ARM address space via | |
489 | * HyperTransport-like "FPCI". | 489 | * HyperTransport-like "FPCI". | |
490 | */ | 490 | */ | |
491 | static const struct { uint32_t size, base, fpci; } pcie_init_table[] = { | 491 | static const struct { uint32_t size, base, fpci; } pcie_init_table[] = { | |
492 | /* | 492 | /* | |
493 | * === BEWARE === | 493 | * === BEWARE === | |
494 | * | 494 | * | |
495 | * We depend on our TEGRA_PCIE_IO window overlaping the | 495 | * We depend on our TEGRA_PCIE_IO window overlaping the | |
496 | * TEGRA_PCIE_A1 window to allow us to use the same | 496 | * TEGRA_PCIE_A1 window to allow us to use the same | |
497 | * bus_space_tag for both PCI IO and Memory spaces. | 497 | * bus_space_tag for both PCI IO and Memory spaces. | |
498 | * | 498 | * | |
499 | * 0xfdfc000000-0xfdfdffffff is the FPCI/HyperTransport | 499 | * 0xfdfc000000-0xfdfdffffff is the FPCI/HyperTransport | |
500 | * mapping for 0x0000000-0x1ffffff of PCI IO space. | 500 | * mapping for 0x0000000-0x1ffffff of PCI IO space. | |
501 | */ | 501 | */ | |
502 | { TEGRA_PCIE_IO_SIZE >> 12, TEGRA_PCIE_IO_BASE, | 502 | { TEGRA_PCIE_IO_SIZE >> 12, TEGRA_PCIE_IO_BASE, | |
503 | (0xfdfc000000 + TEGRA_PCIE_IO_BASE) >> 8 | 0, }, | 503 | (0xfdfc000000 + TEGRA_PCIE_IO_BASE) >> 8 | 0, }, | |
504 | 504 | |||
505 | /* HyperTransport Technology Type 1 Address Format */ | 505 | /* HyperTransport Technology Type 1 Address Format */ | |
506 | { TEGRA_PCIE_CONF_SIZE >> 12, TEGRA_PCIE_CONF_BASE, | 506 | { TEGRA_PCIE_CONF_SIZE >> 12, TEGRA_PCIE_CONF_BASE, | |
507 | 0xfdff000000 >> 8 | 0, }, | 507 | 0xfdff000000 >> 8 | 0, }, | |
508 | 508 | |||
509 | /* 1:1 MMIO mapping */ | 509 | /* 1:1 MMIO mapping */ | |
510 | { TEGRA_PCIE_MEM_SIZE >> 12, TEGRA_PCIE_MEM_BASE, | 510 | { TEGRA_PCIE_MEM_SIZE >> 12, TEGRA_PCIE_MEM_BASE, | |
511 | TEGRA_PCIE_MEM_BASE >> 8 | 1, }, | 511 | TEGRA_PCIE_MEM_BASE >> 8 | 1, }, | |
512 | 512 | |||
513 | /* Extended HyperTransport Technology Type 1 Address Format */ | 513 | /* Extended HyperTransport Technology Type 1 Address Format */ | |
514 | { TEGRA_PCIE_EXTC_SIZE >> 12, TEGRA_PCIE_EXTC_BASE, | 514 | { TEGRA_PCIE_EXTC_SIZE >> 12, TEGRA_PCIE_EXTC_BASE, | |
515 | 0xfe10000000 >> 8 | 0, }, | 515 | 0xfe10000000 >> 8 | 0, }, | |
516 | 516 | |||
517 | /* 1:1 prefetchable MMIO mapping */ | 517 | /* 1:1 prefetchable MMIO mapping */ | |
518 | { TEGRA_PCIE_PMEM_SIZE >> 12, TEGRA_PCIE_PMEM_BASE, | 518 | { TEGRA_PCIE_PMEM_SIZE >> 12, TEGRA_PCIE_PMEM_BASE, | |
519 | TEGRA_PCIE_PMEM_BASE >> 8 | 1, }, | 519 | TEGRA_PCIE_PMEM_BASE >> 8 | 1, }, | |
520 | }; | 520 | }; | |
521 | 521 | |||
522 | for (i = 0; i < AFI_AXI_NBAR; i++) { | 522 | for (i = 0; i < AFI_AXI_NBAR; i++) { | |
523 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 523 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
524 | AFI_AXI_BARi_SZ(i), 0); | 524 | AFI_AXI_BARi_SZ(i), 0); | |
525 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 525 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
526 | AFI_AXI_BARi_START(i), 0); | 526 | AFI_AXI_BARi_START(i), 0); | |
527 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 527 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
528 | AFI_FPCI_BARi(i), 0); | 528 | AFI_FPCI_BARi(i), 0); | |
529 | } | 529 | } | |
530 | 530 | |||
531 | for (i = 0; i < __arraycount(pcie_init_table); i++) { | 531 | for (i = 0; i < __arraycount(pcie_init_table); i++) { | |
532 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 532 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
533 | AFI_AXI_BARi_START(i), pcie_init_table[i].base); | 533 | AFI_AXI_BARi_START(i), pcie_init_table[i].base); | |
534 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 534 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
535 | AFI_FPCI_BARi(i), pcie_init_table[i].fpci); | 535 | AFI_FPCI_BARi(i), pcie_init_table[i].fpci); | |
536 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 536 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
537 | AFI_AXI_BARi_SZ(i), pcie_init_table[i].size); | 537 | AFI_AXI_BARi_SZ(i), pcie_init_table[i].size); | |
538 | } | 538 | } | |
539 | } | 539 | } | |
540 | 540 | |||
541 | static void | 541 | static void | |
542 | tegra_pcie_enable(struct tegra_pcie_softc *sc) | 542 | tegra_pcie_enable(struct tegra_pcie_softc *sc) | |
543 | { | 543 | { | |
544 | /* disable MSI */ | 544 | /* disable MSI */ | |
545 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 545 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
546 | AFI_MSI_BAR_SZ_REG, 0); | 546 | AFI_MSI_BAR_SZ_REG, 0); | |
547 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 547 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
548 | AFI_MSI_FPCI_BAR_ST_REG, 0); | 548 | AFI_MSI_FPCI_BAR_ST_REG, 0); | |
549 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 549 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
550 | AFI_MSI_AXI_BAR_ST_REG, 0); | 550 | AFI_MSI_AXI_BAR_ST_REG, 0); | |
551 | 551 | |||
552 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 552 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
553 | AFI_SM_INTR_ENABLE_REG, 0xffffffff); | 553 | AFI_SM_INTR_ENABLE_REG, 0xffffffff); | |
554 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 554 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
555 | AFI_AFI_INTR_ENABLE_REG, 0); | 555 | AFI_AFI_INTR_ENABLE_REG, 0); | |
556 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0); | 556 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, AFI_INTR_CODE_REG, 0); | |
557 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | 557 | bus_space_write_4(sc->sc_bst, sc->sc_bsh_afi, | |
558 | AFI_INTR_MASK_REG, AFI_INTR_MASK_INT); | 558 | AFI_INTR_MASK_REG, AFI_INTR_MASK_INT); | |
559 | } | 559 | } | |
560 | 560 | |||
561 | static void | 561 | static void | |
562 | tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const sc, uint bus, | 562 | tegra_pcie_conf_frag_map(struct tegra_pcie_softc * const sc, uint bus, | |
563 | uint frg) | 563 | uint frg) | |
564 | { | 564 | { | |
565 | bus_addr_t a; | 565 | bus_addr_t a; | |
566 | 566 | |||
567 | KASSERT(bus >= 1); | 567 | KASSERT(bus >= 1); | |
568 | KASSERT(bus < TEGRA_PCIE_NBUS); | 568 | KASSERT(bus < TEGRA_PCIE_NBUS); | |
569 | KASSERT(frg < TEGRA_PCIE_ECFB); | 569 | KASSERT(frg < TEGRA_PCIE_ECFB); | |
570 | 570 | |||
571 | if (sc->sc_bsh_extc[bus-1][frg] != 0) { | 571 | if (sc->sc_bsh_extc[bus-1][frg] != 0) { | |
572 | device_printf(sc->sc_dev, "bus %u fragment %#x already " | 572 | device_printf(sc->sc_dev, "bus %u fragment %#x already " | |
573 | "mapped\n", bus, frg); | 573 | "mapped\n", bus, frg); | |
574 | return; | 574 | return; | |
575 | } | 575 | } | |
576 | 576 | |||
577 | a = TEGRA_PCIE_EXTC_BASE + (bus << 16) + (frg << 24); | 577 | a = TEGRA_PCIE_EXTC_BASE + (bus << 16) + (frg << 24); | |
578 | if (bus_space_map(sc->sc_bst, a, 1 << 16, | 578 | if (bus_space_map(sc->sc_bst, a, 1 << 16, | |
579 | _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, | 579 | _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, | |
580 | &sc->sc_bsh_extc[bus-1][frg]) != 0) | 580 | &sc->sc_bsh_extc[bus-1][frg]) != 0) | |
581 | device_printf(sc->sc_dev, "couldn't map PCIE " | 581 | device_printf(sc->sc_dev, "couldn't map PCIE " | |
582 | "configuration for bus %u fragment %#x", bus, frg); | 582 | "configuration for bus %u fragment %#x", bus, frg); | |
583 | } | 583 | } | |
584 | 584 | |||
585 | /* map non-non-extended configuration space for full bus range */ | 585 | /* map non-non-extended configuration space for full bus range */ | |
586 | static void | 586 | static void | |
587 | tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const sc, uint bus) | 587 | tegra_pcie_conf_map_bus(struct tegra_pcie_softc * const sc, uint bus) | |
588 | { | 588 | { | |
589 | uint i; | 589 | uint i; | |
590 | 590 | |||
591 | for (i = 1; i < TEGRA_PCIE_ECFB; i++) { | 591 | for (i = 1; i < TEGRA_PCIE_ECFB; i++) { | |
592 | tegra_pcie_conf_frag_map(sc, bus, i); | 592 | tegra_pcie_conf_frag_map(sc, bus, i); | |
593 | } | 593 | } | |
594 | } | 594 | } | |
595 | 595 | |||
596 | /* map non-extended configuration space for full bus range */ | 596 | /* map non-extended configuration space for full bus range */ | |
597 | static void | 597 | static void | |
598 | tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const sc) | 598 | tegra_pcie_conf_map_buses(struct tegra_pcie_softc * const sc) | |
599 | { | 599 | { | |
600 | uint b; | 600 | uint b; | |
601 | 601 | |||
602 | for (b = 1; b < TEGRA_PCIE_NBUS; b++) { | 602 | for (b = 1; b < TEGRA_PCIE_NBUS; b++) { | |
603 | tegra_pcie_conf_frag_map(sc, b, 0); | 603 | tegra_pcie_conf_frag_map(sc, b, 0); | |
604 | } | 604 | } | |
605 | } | 605 | } | |
606 | 606 | |||
607 | void | 607 | void | |
608 | tegra_pcie_init(pci_chipset_tag_t pc, void *priv) | 608 | tegra_pcie_init(pci_chipset_tag_t pc, void *priv) | |
609 | { | 609 | { | |
610 | pc->pc_conf_v = priv; | 610 | pc->pc_conf_v = priv; | |
611 | pc->pc_attach_hook = tegra_pcie_attach_hook; | 611 | pc->pc_attach_hook = tegra_pcie_attach_hook; | |
612 | pc->pc_bus_maxdevs = tegra_pcie_bus_maxdevs; | 612 | pc->pc_bus_maxdevs = tegra_pcie_bus_maxdevs; | |
613 | pc->pc_make_tag = tegra_pcie_make_tag; | 613 | pc->pc_make_tag = tegra_pcie_make_tag; | |
614 | pc->pc_decompose_tag = tegra_pcie_decompose_tag; | 614 | pc->pc_decompose_tag = tegra_pcie_decompose_tag; | |
615 | pc->pc_conf_read = tegra_pcie_conf_read; | 615 | pc->pc_conf_read = tegra_pcie_conf_read; | |
616 | pc->pc_conf_write = tegra_pcie_conf_write; | 616 | pc->pc_conf_write = tegra_pcie_conf_write; | |
617 | pc->pc_conf_hook = tegra_pcie_conf_hook; | 617 | pc->pc_conf_hook = tegra_pcie_conf_hook; | |
618 | pc->pc_conf_interrupt = tegra_pcie_conf_interrupt; | 618 | pc->pc_conf_interrupt = tegra_pcie_conf_interrupt; | |
619 | 619 | |||
620 | pc->pc_intr_v = priv; | 620 | pc->pc_intr_v = priv; | |
621 | pc->pc_intr_map = tegra_pcie_intr_map; | 621 | pc->pc_intr_map = tegra_pcie_intr_map; | |
622 | pc->pc_intr_string = tegra_pcie_intr_string; | 622 | pc->pc_intr_string = tegra_pcie_intr_string; | |
623 | pc->pc_intr_evcnt = tegra_pcie_intr_evcnt; | 623 | pc->pc_intr_evcnt = tegra_pcie_intr_evcnt; | |
624 | pc->pc_intr_setattr = tegra_pcie_intr_setattr; | 624 | pc->pc_intr_setattr = tegra_pcie_intr_setattr; | |
625 | pc->pc_intr_establish = tegra_pcie_intr_establish; | 625 | pc->pc_intr_establish = tegra_pcie_intr_establish; | |
626 | pc->pc_intr_disestablish = tegra_pcie_intr_disestablish; | 626 | pc->pc_intr_disestablish = tegra_pcie_intr_disestablish; | |
627 | } | 627 | } | |
628 | 628 | |||
629 | static void | 629 | static void | |
630 | tegra_pcie_attach_hook(device_t parent, device_t self, | 630 | tegra_pcie_attach_hook(device_t parent, device_t self, | |
631 | struct pcibus_attach_args *pba) | 631 | struct pcibus_attach_args *pba) | |
632 | { | 632 | { | |
633 | const pci_chipset_tag_t pc = pba->pba_pc; | 633 | const pci_chipset_tag_t pc = pba->pba_pc; | |
634 | struct tegra_pcie_softc * const sc = pc->pc_conf_v; | 634 | struct tegra_pcie_softc * const sc = pc->pc_conf_v; | |
635 | 635 | |||
636 | if (pba->pba_bus >= 1) { | 636 | if (pba->pba_bus >= 1) { | |
637 | tegra_pcie_conf_map_bus(sc, pba->pba_bus); | 637 | tegra_pcie_conf_map_bus(sc, pba->pba_bus); | |
638 | } | 638 | } | |
639 | } | 639 | } | |
640 | 640 | |||
641 | static int | 641 | static int | |
642 | tegra_pcie_bus_maxdevs(void *v, int busno) | 642 | tegra_pcie_bus_maxdevs(void *v, int busno) | |
643 | { | 643 | { | |
644 | return busno == 0 ? 2 : 32; | 644 | return busno == 0 ? 2 : 32; | |
645 | } | 645 | } | |
646 | 646 | |||
647 | static pcitag_t | 647 | static pcitag_t | |
648 | tegra_pcie_make_tag(void *v, int b, int d, int f) | 648 | tegra_pcie_make_tag(void *v, int b, int d, int f) | |
649 | { | 649 | { | |
650 | return (b << 16) | (d << 11) | (f << 8); | 650 | return (b << 16) | (d << 11) | (f << 8); | |
651 | } | 651 | } | |
652 | 652 | |||
653 | static void | 653 | static void | |
654 | tegra_pcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) | 654 | tegra_pcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) | |
655 | { | 655 | { | |
656 | if (bp) | 656 | if (bp) | |
657 | *bp = (tag >> 16) & 0xff; | 657 | *bp = (tag >> 16) & 0xff; | |
658 | if (dp) | 658 | if (dp) | |
659 | *dp = (tag >> 11) & 0x1f; | 659 | *dp = (tag >> 11) & 0x1f; | |
660 | if (fp) | 660 | if (fp) | |
661 | *fp = (tag >> 8) & 0x7; | 661 | *fp = (tag >> 8) & 0x7; | |
662 | } | 662 | } | |
663 | 663 | |||
664 | static pcireg_t | 664 | static pcireg_t | |
665 | tegra_pcie_conf_read(void *v, pcitag_t tag, int offset) | 665 | tegra_pcie_conf_read(void *v, pcitag_t tag, int offset) | |
666 | { | 666 | { | |
667 | struct tegra_pcie_softc *sc = v; | 667 | struct tegra_pcie_softc *sc = v; | |
668 | bus_space_handle_t bsh; | 668 | bus_space_handle_t bsh; | |
669 | int b, d, f; | 669 | int b, d, f; | |
670 | u_int reg; | 670 | u_int reg; | |
671 | 671 | |||
672 | if ((unsigned int)offset >= PCI_EXTCONF_SIZE) | 672 | if ((unsigned int)offset >= PCI_EXTCONF_SIZE) | |
673 | return (pcireg_t) -1; | 673 | return (pcireg_t) -1; | |
674 | 674 | |||
675 | tegra_pcie_decompose_tag(v, tag, &b, &d, &f); | 675 | tegra_pcie_decompose_tag(v, tag, &b, &d, &f); | |
676 | 676 | |||
677 | if (b >= TEGRA_PCIE_NBUS) | 677 | if (b >= TEGRA_PCIE_NBUS) | |
678 | return (pcireg_t) -1; | 678 | return (pcireg_t) -1; | |
679 | 679 | |||
680 | if (b == 0) { | 680 | if (b == 0) { | |
681 | if (d >= 2 || f != 0) | 681 | if (d >= 2 || f != 0) | |
682 | return (pcireg_t) -1; | 682 | return (pcireg_t) -1; | |
683 | reg = d * 0x1000 + offset; | 683 | reg = d * 0x1000 + offset; | |
684 | bsh = sc->sc_bsh_rpconf; | 684 | bsh = sc->sc_bsh_rpconf; | |
685 | } else { | 685 | } else { | |
686 | reg = (d << 11) | (f << 8) | (offset & 0xff); | 686 | reg = (d << 11) | (f << 8) | (offset & 0xff); | |
687 | bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf]; | 687 | bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf]; | |
688 | if (bsh == 0) | 688 | if (bsh == 0) | |
689 | return (pcireg_t) -1; | 689 | return (pcireg_t) -1; | |
690 | } | 690 | } | |
691 | 691 | |||
692 | return bus_space_read_4(sc->sc_bst, bsh, reg); | 692 | return bus_space_read_4(sc->sc_bst, bsh, reg); | |
693 | } | 693 | } | |
694 | 694 | |||
695 | static void | 695 | static void | |
696 | tegra_pcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) | 696 | tegra_pcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val) | |
697 | { | 697 | { | |
698 | struct tegra_pcie_softc *sc = v; | 698 | struct tegra_pcie_softc *sc = v; | |
699 | bus_space_handle_t bsh; | 699 | bus_space_handle_t bsh; | |
700 | int b, d, f; | 700 | int b, d, f; | |
701 | u_int reg; | 701 | u_int reg; | |
702 | 702 | |||
703 | if ((unsigned int)offset >= PCI_EXTCONF_SIZE) | 703 | if ((unsigned int)offset >= PCI_EXTCONF_SIZE) | |
704 | return; | 704 | return; | |
705 | 705 | |||
706 | tegra_pcie_decompose_tag(v, tag, &b, &d, &f); | 706 | tegra_pcie_decompose_tag(v, tag, &b, &d, &f); | |
707 | 707 | |||
708 | if (b >= TEGRA_PCIE_NBUS) | 708 | if (b >= TEGRA_PCIE_NBUS) | |
709 | return; | 709 | return; | |
710 | 710 | |||
711 | if (b == 0) { | 711 | if (b == 0) { | |
712 | if (d >= 2 || f != 0) | 712 | if (d >= 2 || f != 0) | |
713 | return; | 713 | return; | |
714 | reg = d * 0x1000 + offset; | 714 | reg = d * 0x1000 + offset; | |
715 | bsh = sc->sc_bsh_rpconf; | 715 | bsh = sc->sc_bsh_rpconf; | |
716 | } else { | 716 | } else { | |
717 | reg = (d << 11) | (f << 8) | (offset & 0xff); | 717 | reg = (d << 11) | (f << 8) | (offset & 0xff); | |
718 | bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf]; | 718 | bsh = sc->sc_bsh_extc[b-1][(offset >> 8) & 0xf]; | |
719 | if (bsh == 0) | 719 | if (bsh == 0) | |
720 | return; | 720 | return; | |
721 | } | 721 | } | |
722 | 722 | |||
723 | bus_space_write_4(sc->sc_bst, bsh, reg, val); | 723 | bus_space_write_4(sc->sc_bst, bsh, reg, val); | |
724 | } | 724 | } | |
725 | 725 | |||
726 | static int | 726 | static int | |
727 | tegra_pcie_conf_hook(void *v, int b, int d, int f, pcireg_t id) | 727 | tegra_pcie_conf_hook(void *v, int b, int d, int f, pcireg_t id) | |
728 | { | 728 | { | |
729 | return PCI_CONF_DEFAULT & ~PCI_CONF_ENABLE_BM; | 729 | return PCI_CONF_DEFAULT & ~PCI_CONF_ENABLE_BM; | |
730 | } | 730 | } | |
731 | 731 | |||
732 | static void | 732 | static void | |
733 | tegra_pcie_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz, | 733 | tegra_pcie_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz, | |
734 | int *ilinep) | 734 | int *ilinep) | |
735 | { | 735 | { | |
736 | *ilinep = 5; | 736 | *ilinep = 5; | |
737 | } | 737 | } | |
738 | 738 | |||
739 | static int | 739 | static int | |
740 | tegra_pcie_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih) | 740 | tegra_pcie_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih) | |
741 | { | 741 | { | |
742 | if (pa->pa_intrpin == 0) | 742 | if (pa->pa_intrpin == 0) | |
743 | return EINVAL; | 743 | return EINVAL; | |
744 | *ih = pa->pa_intrpin; | 744 | *ih = pa->pa_intrpin; | |
745 | return 0; | 745 | return 0; | |
746 | } | 746 | } | |
747 | 747 | |||
748 | static const char * | 748 | static const char * | |
749 | tegra_pcie_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len) | 749 | tegra_pcie_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len) | |
750 | { | 750 | { | |
751 | struct tegra_pcie_softc *sc = v; | 751 | struct tegra_pcie_softc *sc = v; | |
752 | 752 | |||
753 | if (ih == PCI_INTERRUPT_PIN_NONE) | 753 | if (ih == PCI_INTERRUPT_PIN_NONE) | |
754 | return NULL; | 754 | return NULL; | |
755 | 755 | |||
756 | if (!fdtbus_intr_str(sc->sc_phandle, 0, buf, len)) | 756 | if (!fdtbus_intr_str(sc->sc_phandle, 0, buf, len)) | |
757 | return NULL; | 757 | return NULL; | |
758 | 758 | |||
759 | return buf; | 759 | return buf; | |
760 | } | 760 | } | |
761 | 761 | |||
762 | const struct evcnt * | 762 | const struct evcnt * | |
763 | tegra_pcie_intr_evcnt(void *v, pci_intr_handle_t ih) | 763 | tegra_pcie_intr_evcnt(void *v, pci_intr_handle_t ih) | |
764 | { | 764 | { | |
765 | return NULL; | 765 | return NULL; | |
766 | } | 766 | } | |
767 | 767 | |||
768 | static int | 768 | static int | |
769 | tegra_pcie_intr_setattr(void *v, pci_intr_handle_t *ih, int attr, uint64_t data) | 769 | tegra_pcie_intr_setattr(void *v, pci_intr_handle_t *ih, int attr, uint64_t data) | |
770 | { | 770 | { | |
771 | switch (attr) { | 771 | switch (attr) { | |
772 | case PCI_INTR_MPSAFE: | 772 | case PCI_INTR_MPSAFE: | |
773 | if (data) | 773 | if (data) | |
774 | *ih |= IH_MPSAFE; | 774 | *ih |= IH_MPSAFE; | |
775 | else | 775 | else | |
776 | *ih &= ~IH_MPSAFE; | 776 | *ih &= ~IH_MPSAFE; | |
777 | return 0; | 777 | return 0; | |
778 | default: | 778 | default: | |
779 | return ENODEV; | 779 | return ENODEV; | |
780 | } | 780 | } | |
781 | } | 781 | } | |
782 | 782 | |||
783 | static void * | 783 | static void * | |
784 | tegra_pcie_intr_establish(void *v, pci_intr_handle_t ih, int ipl, | 784 | tegra_pcie_intr_establish(void *v, pci_intr_handle_t ih, int ipl, | |
785 | int (*callback)(void *), void *arg, const char *xname) | 785 | int (*callback)(void *), void *arg, const char *xname) | |
786 | { | 786 | { | |
787 | struct tegra_pcie_softc *sc = v; | 787 | struct tegra_pcie_softc *sc = v; | |
788 | struct tegra_pcie_ih *pcie_ih; | 788 | struct tegra_pcie_ih *pcie_ih; | |
789 | 789 | |||
790 | if (ih == 0) | 790 | if (ih == 0) | |
791 | return NULL; | 791 | return NULL; | |
792 | 792 | |||
793 | pcie_ih = kmem_alloc(sizeof(*pcie_ih), KM_SLEEP); | 793 | pcie_ih = kmem_alloc(sizeof(*pcie_ih), KM_SLEEP); | |
794 | pcie_ih->ih_callback = callback; | 794 | pcie_ih->ih_callback = callback; | |
795 | pcie_ih->ih_arg = arg; | 795 | pcie_ih->ih_arg = arg; | |
796 | pcie_ih->ih_ipl = ipl; | 796 | pcie_ih->ih_ipl = ipl; | |
797 | pcie_ih->ih_mpsafe = (ih & IH_MPSAFE) != 0; | 797 | pcie_ih->ih_mpsafe = (ih & IH_MPSAFE) != 0; | |
798 | 798 | |||
799 | mutex_enter(&sc->sc_lock); | 799 | mutex_enter(&sc->sc_lock); | |
800 | TAILQ_INSERT_TAIL(&sc->sc_intrs, pcie_ih, ih_entry); | 800 | TAILQ_INSERT_TAIL(&sc->sc_intrs, pcie_ih, ih_entry); | |
801 | sc->sc_intrgen++; | 801 | sc->sc_intrgen++; | |
802 | mutex_exit(&sc->sc_lock); | 802 | mutex_exit(&sc->sc_lock); | |
803 | 803 | |||
804 | return pcie_ih; | 804 | return pcie_ih; | |
805 | } | 805 | } | |
806 | 806 | |||
807 | static void | 807 | static void | |
808 | tegra_pcie_intr_disestablish(void *v, void *vih) | 808 | tegra_pcie_intr_disestablish(void *v, void *vih) | |
809 | { | 809 | { | |
810 | struct tegra_pcie_softc *sc = v; | 810 | struct tegra_pcie_softc *sc = v; | |
811 | struct tegra_pcie_ih *pcie_ih = vih; | 811 | struct tegra_pcie_ih *pcie_ih = vih; | |
812 | 812 | |||
813 | mutex_enter(&sc->sc_lock); | 813 | mutex_enter(&sc->sc_lock); | |
814 | TAILQ_REMOVE(&sc->sc_intrs, pcie_ih, ih_entry); | 814 | TAILQ_REMOVE(&sc->sc_intrs, pcie_ih, ih_entry); | |
815 | mutex_exit(&sc->sc_lock); | 815 | mutex_exit(&sc->sc_lock); | |
816 | 816 | |||
817 | kmem_free(pcie_ih, sizeof(*pcie_ih)); | 817 | kmem_free(pcie_ih, sizeof(*pcie_ih)); | |
818 | } | 818 | } |
--- src/sys/arch/arm/nvidia/tegra_soctherm.c 2021/01/25 14:20:38 1.11
+++ src/sys/arch/arm/nvidia/tegra_soctherm.c 2021/01/27 01:58:15 1.12
@@ -1,407 +1,407 @@ | @@ -1,407 +1,407 @@ | |||
1 | /* $NetBSD: tegra_soctherm.c,v 1.11 2021/01/25 14:20:38 thorpej Exp $ */ | 1 | /* $NetBSD: tegra_soctherm.c,v 1.12 2021/01/27 01:58:15 thorpej Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> | 4 | * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
26 | * SUCH DAMAGE. | 26 | * SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: tegra_soctherm.c,v 1.11 2021/01/25 14:20:38 thorpej Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: tegra_soctherm.c,v 1.12 2021/01/27 01:58:15 thorpej Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/bus.h> | 33 | #include <sys/bus.h> | |
34 | #include <sys/device.h> | 34 | #include <sys/device.h> | |
35 | #include <sys/intr.h> | 35 | #include <sys/intr.h> | |
36 | #include <sys/systm.h> | 36 | #include <sys/systm.h> | |
37 | #include <sys/kernel.h> | 37 | #include <sys/kernel.h> | |
38 | #include <sys/kmem.h> | 38 | #include <sys/kmem.h> | |
39 | 39 | |||
40 | #include <dev/sysmon/sysmonvar.h> | 40 | #include <dev/sysmon/sysmonvar.h> | |
41 | 41 | |||
42 | #include <arm/nvidia/tegra_reg.h> | 42 | #include <arm/nvidia/tegra_reg.h> | |
43 | #include <arm/nvidia/tegra_socthermreg.h> | 43 | #include <arm/nvidia/tegra_socthermreg.h> | |
44 | #include <arm/nvidia/tegra_var.h> | 44 | #include <arm/nvidia/tegra_var.h> | |
45 | 45 | |||
46 | #include <dev/fdt/fdtvar.h> | 46 | #include <dev/fdt/fdtvar.h> | |
47 | 47 | |||
48 | #define FUSE_TSENSOR_CALIB_CP_TS_BASE __BITS(12,0) | 48 | #define FUSE_TSENSOR_CALIB_CP_TS_BASE __BITS(12,0) | |
49 | #define FUSE_TSENSOR_CALIB_FT_TS_BASE __BITS(25,13) | 49 | #define FUSE_TSENSOR_CALIB_FT_TS_BASE __BITS(25,13) | |
50 | 50 | |||
51 | #define FUSE_TSENSOR8_CALIB_REG 0x180 | 51 | #define FUSE_TSENSOR8_CALIB_REG 0x180 | |
52 | #define FUSE_TSENSOR8_CALIB_CP_TS_BASE __BITS(9,0) | 52 | #define FUSE_TSENSOR8_CALIB_CP_TS_BASE __BITS(9,0) | |
53 | #define FUSE_TSENSOR8_CALIB_FT_TS_BASE __BITS(20,10) | 53 | #define FUSE_TSENSOR8_CALIB_FT_TS_BASE __BITS(20,10) | |
54 | 54 | |||
55 | #define FUSE_SPARE_REALIGNMENT_REG 0x1fc | 55 | #define FUSE_SPARE_REALIGNMENT_REG 0x1fc | |
56 | #define FUSE_SPARE_REALIGNMENT_CP __BITS(5,0) | 56 | #define FUSE_SPARE_REALIGNMENT_CP __BITS(5,0) | |
57 | #define FUSE_SPARE_REALIGNMENT_FT __BITS(25,21) | 57 | #define FUSE_SPARE_REALIGNMENT_FT __BITS(25,21) | |
58 | 58 | |||
59 | static int tegra_soctherm_match(device_t, cfdata_t, void *); | 59 | static int tegra_soctherm_match(device_t, cfdata_t, void *); | |
60 | static void tegra_soctherm_attach(device_t, device_t, void *); | 60 | static void tegra_soctherm_attach(device_t, device_t, void *); | |
61 | 61 | |||
62 | struct tegra_soctherm_config { | 62 | struct tegra_soctherm_config { | |
63 | uint32_t init_pdiv; | 63 | uint32_t init_pdiv; | |
64 | uint32_t init_hotspot_off; | 64 | uint32_t init_hotspot_off; | |
65 | uint32_t nominal_calib_ft; | 65 | uint32_t nominal_calib_ft; | |
66 | uint32_t nominal_calib_cp; | 66 | uint32_t nominal_calib_cp; | |
67 | uint32_t tall; | 67 | uint32_t tall; | |
68 | uint32_t tsample; | 68 | uint32_t tsample; | |
69 | uint32_t tiddq_en; | 69 | uint32_t tiddq_en; | |
70 | uint32_t ten_count; | 70 | uint32_t ten_count; | |
71 | uint32_t pdiv; | 71 | uint32_t pdiv; | |
72 | uint32_t tsample_ate; | 72 | uint32_t tsample_ate; | |
73 | uint32_t pdiv_ate; | 73 | uint32_t pdiv_ate; | |
74 | }; | 74 | }; | |
75 | 75 | |||
76 | static const struct tegra_soctherm_config tegra124_soctherm_config = { | 76 | static const struct tegra_soctherm_config tegra124_soctherm_config = { | |
77 | .init_pdiv = 0x8888, | 77 | .init_pdiv = 0x8888, | |
78 | .init_hotspot_off = 0x60600, | 78 | .init_hotspot_off = 0x60600, | |
79 | .nominal_calib_ft = 105, | 79 | .nominal_calib_ft = 105, | |
80 | .nominal_calib_cp = 25, | 80 | .nominal_calib_cp = 25, | |
81 | .tall = 16300, | 81 | .tall = 16300, | |
82 | .tsample = 120, | 82 | .tsample = 120, | |
83 | .tiddq_en = 1, | 83 | .tiddq_en = 1, | |
84 | .ten_count = 1, | 84 | .ten_count = 1, | |
85 | .pdiv = 8, | 85 | .pdiv = 8, | |
86 | .tsample_ate = 480, | 86 | .tsample_ate = 480, | |
87 | .pdiv_ate = 8 | 87 | .pdiv_ate = 8 | |
88 | }; | 88 | }; | |
89 | 89 | |||
90 | struct tegra_soctherm_sensor { | 90 | struct tegra_soctherm_sensor { | |
91 | envsys_data_t s_data; | 91 | envsys_data_t s_data; | |
92 | u_int s_base; | 92 | u_int s_base; | |
93 | u_int s_fuse; | 93 | u_int s_fuse; | |
94 | int s_fuse_corr_alpha; | 94 | int s_fuse_corr_alpha; | |
95 | int s_fuse_corr_beta; | 95 | int s_fuse_corr_beta; | |
96 | int16_t s_therm_a; | 96 | int16_t s_therm_a; | |
97 | int16_t s_therm_b; | 97 | int16_t s_therm_b; | |
98 | }; | 98 | }; | |
99 | 99 | |||
100 | static const struct tegra_soctherm_sensor tegra_soctherm_sensors[] = { | 100 | static const struct tegra_soctherm_sensor tegra_soctherm_sensors[] = { | |
101 | { .s_data = { .desc = "CPU0" }, .s_base = 0x0c0, .s_fuse = 0x098, | 101 | { .s_data = { .desc = "CPU0" }, .s_base = 0x0c0, .s_fuse = 0x098, | |
102 | .s_fuse_corr_alpha = 1135400, .s_fuse_corr_beta = -6266900 }, | 102 | .s_fuse_corr_alpha = 1135400, .s_fuse_corr_beta = -6266900 }, | |
103 | { .s_data = { .desc = "CPU1" }, .s_base = 0x0e0, .s_fuse = 0x084, | 103 | { .s_data = { .desc = "CPU1" }, .s_base = 0x0e0, .s_fuse = 0x084, | |
104 | .s_fuse_corr_alpha = 1122220, .s_fuse_corr_beta = -5700700 }, | 104 | .s_fuse_corr_alpha = 1122220, .s_fuse_corr_beta = -5700700 }, | |
105 | { .s_data = { .desc = "CPU2" }, .s_base = 0x100, .s_fuse = 0x088, | 105 | { .s_data = { .desc = "CPU2" }, .s_base = 0x100, .s_fuse = 0x088, | |
106 | .s_fuse_corr_alpha = 1127000, .s_fuse_corr_beta = -6768200 }, | 106 | .s_fuse_corr_alpha = 1127000, .s_fuse_corr_beta = -6768200 }, | |
107 | { .s_data = { .desc = "CPU3" }, .s_base = 0x120, .s_fuse = 0x12c, | 107 | { .s_data = { .desc = "CPU3" }, .s_base = 0x120, .s_fuse = 0x12c, | |
108 | .s_fuse_corr_alpha = 1110900, .s_fuse_corr_beta = -6232000 }, | 108 | .s_fuse_corr_alpha = 1110900, .s_fuse_corr_beta = -6232000 }, | |
109 | { .s_data = { .desc = "MEM0" }, .s_base = 0x140, .s_fuse = 0x158, | 109 | { .s_data = { .desc = "MEM0" }, .s_base = 0x140, .s_fuse = 0x158, | |
110 | .s_fuse_corr_alpha = 1122300, .s_fuse_corr_beta = -5936400 }, | 110 | .s_fuse_corr_alpha = 1122300, .s_fuse_corr_beta = -5936400 }, | |
111 | { .s_data = { .desc = "MEM1" }, .s_base = 0x160, .s_fuse = 0x15c, | 111 | { .s_data = { .desc = "MEM1" }, .s_base = 0x160, .s_fuse = 0x15c, | |
112 | .s_fuse_corr_alpha = 1145700, .s_fuse_corr_beta = -7124600 }, | 112 | .s_fuse_corr_alpha = 1145700, .s_fuse_corr_beta = -7124600 }, | |
113 | { .s_data = { .desc = "GPU" }, .s_base = 0x180, .s_fuse = 0x154, | 113 | { .s_data = { .desc = "GPU" }, .s_base = 0x180, .s_fuse = 0x154, | |
114 | .s_fuse_corr_alpha = 1120100, .s_fuse_corr_beta = -6000500 }, | 114 | .s_fuse_corr_alpha = 1120100, .s_fuse_corr_beta = -6000500 }, | |
115 | { .s_data = { .desc = "PLLX" }, .s_base = 0x1a0, .s_fuse = 0x160, | 115 | { .s_data = { .desc = "PLLX" }, .s_base = 0x1a0, .s_fuse = 0x160, | |
116 | .s_fuse_corr_alpha = 1106500, .s_fuse_corr_beta = -6729300 }, | 116 | .s_fuse_corr_alpha = 1106500, .s_fuse_corr_beta = -6729300 }, | |
117 | }; | 117 | }; | |
118 | 118 | |||
119 | struct tegra_soctherm_softc { | 119 | struct tegra_soctherm_softc { | |
120 | device_t sc_dev; | 120 | device_t sc_dev; | |
121 | bus_space_tag_t sc_bst; | 121 | bus_space_tag_t sc_bst; | |
122 | bus_space_handle_t sc_bsh; | 122 | bus_space_handle_t sc_bsh; | |
123 | struct clk *sc_clk_tsensor; | 123 | struct clk *sc_clk_tsensor; | |
124 | struct clk *sc_clk_soctherm; | 124 | struct clk *sc_clk_soctherm; | |
125 | struct fdtbus_reset *sc_rst_soctherm; | 125 | struct fdtbus_reset *sc_rst_soctherm; | |
126 | 126 | |||
127 | struct sysmon_envsys *sc_sme; | 127 | struct sysmon_envsys *sc_sme; | |
128 | struct tegra_soctherm_sensor *sc_sensors; | 128 | struct tegra_soctherm_sensor *sc_sensors; | |
129 | const struct tegra_soctherm_config *sc_config; | 129 | const struct tegra_soctherm_config *sc_config; | |
130 | 130 | |||
131 | uint32_t sc_base_cp; | 131 | uint32_t sc_base_cp; | |
132 | uint32_t sc_base_ft; | 132 | uint32_t sc_base_ft; | |
133 | int32_t sc_actual_temp_cp; | 133 | int32_t sc_actual_temp_cp; | |
134 | int32_t sc_actual_temp_ft; | 134 | int32_t sc_actual_temp_ft; | |
135 | }; | 135 | }; | |
136 | 136 | |||
137 | static int tegra_soctherm_init_clocks(struct tegra_soctherm_softc *); | 137 | static int tegra_soctherm_init_clocks(struct tegra_soctherm_softc *); | |
138 | static void tegra_soctherm_init_sensors(device_t); | 138 | static void tegra_soctherm_init_sensors(device_t); | |
139 | static void tegra_soctherm_init_sensor(struct tegra_soctherm_softc *, | 139 | static void tegra_soctherm_init_sensor(struct tegra_soctherm_softc *, | |
140 | struct tegra_soctherm_sensor *); | 140 | struct tegra_soctherm_sensor *); | |
141 | static void tegra_soctherm_refresh(struct sysmon_envsys *, envsys_data_t *); | 141 | static void tegra_soctherm_refresh(struct sysmon_envsys *, envsys_data_t *); | |
142 | static int tegra_soctherm_decodeint(uint32_t, uint32_t); | 142 | static int tegra_soctherm_decodeint(uint32_t, uint32_t); | |
143 | static int64_t tegra_soctherm_divide(int64_t, int64_t); | 143 | static int64_t tegra_soctherm_divide(int64_t, int64_t); | |
144 | 144 | |||
145 | CFATTACH_DECL_NEW(tegra_soctherm, sizeof(struct tegra_soctherm_softc), | 145 | CFATTACH_DECL_NEW(tegra_soctherm, sizeof(struct tegra_soctherm_softc), | |
146 | tegra_soctherm_match, tegra_soctherm_attach, NULL, NULL); | 146 | tegra_soctherm_match, tegra_soctherm_attach, NULL, NULL); | |
147 | 147 | |||
148 | #define SOCTHERM_READ(sc, reg) \ | 148 | #define SOCTHERM_READ(sc, reg) \ | |
149 | bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) | 149 | bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) | |
150 | #define SOCTHERM_WRITE(sc, reg, val) \ | 150 | #define SOCTHERM_WRITE(sc, reg, val) \ | |
151 | bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) | 151 | bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) | |
152 | #define SOCTHERM_SET_CLEAR(sc, reg, set, clr) \ | 152 | #define SOCTHERM_SET_CLEAR(sc, reg, set, clr) \ | |
153 | tegra_reg_set_clear((sc)->sc_bst, (sc)->sc_bsh, (reg), (set), (clr)) | 153 | tegra_reg_set_clear((sc)->sc_bst, (sc)->sc_bsh, (reg), (set), (clr)) | |
154 | 154 | |||
155 | #define SENSOR_READ(sc, s, reg) \ | 155 | #define SENSOR_READ(sc, s, reg) \ | |
156 | bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (s)->s_base + (reg)) | 156 | bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (s)->s_base + (reg)) | |
157 | #define SENSOR_WRITE(sc, s, reg, val) \ | 157 | #define SENSOR_WRITE(sc, s, reg, val) \ | |
158 | bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (s)->s_base + (reg), (val)) | 158 | bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (s)->s_base + (reg), (val)) | |
159 | #define SENSOR_SET_CLEAR(sc, s, reg, set, clr) \ | 159 | #define SENSOR_SET_CLEAR(sc, s, reg, set, clr) \ | |
160 | tegra_reg_set_clear((sc)->sc_bst, (sc)->sc_bsh, (s)->s_base + (reg), (set), (clr)) | 160 | tegra_reg_set_clear((sc)->sc_bst, (sc)->sc_bsh, (s)->s_base + (reg), (set), (clr)) | |
161 | 161 | |||
162 | static const struct device_compatible_entry compat_data[] = { | 162 | static const struct device_compatible_entry compat_data[] = { | |
163 | { .compat = "nvidia,tegra124-soctherm", | 163 | { .compat = "nvidia,tegra124-soctherm", | |
164 | .data = &tegra124_soctherm_config }, | 164 | .data = &tegra124_soctherm_config }, | |
165 | 165 | |||
166 | { } | 166 | DEVICE_COMPAT_EOL | |
167 | }; | 167 | }; | |
168 | 168 | |||
169 | static int | 169 | static int | |
170 | tegra_soctherm_match(device_t parent, cfdata_t cf, void *aux) | 170 | tegra_soctherm_match(device_t parent, cfdata_t cf, void *aux) | |
171 | { | 171 | { | |
172 | struct fdt_attach_args * const faa = aux; | 172 | struct fdt_attach_args * const faa = aux; | |
173 | 173 | |||
174 | return of_match_compat_data(faa->faa_phandle, compat_data); | 174 | return of_match_compat_data(faa->faa_phandle, compat_data); | |
175 | } | 175 | } | |
176 | 176 | |||
177 | static void | 177 | static void | |
178 | tegra_soctherm_attach(device_t parent, device_t self, void *aux) | 178 | tegra_soctherm_attach(device_t parent, device_t self, void *aux) | |
179 | { | 179 | { | |
180 | struct tegra_soctherm_softc * const sc = device_private(self); | 180 | struct tegra_soctherm_softc * const sc = device_private(self); | |
181 | struct fdt_attach_args * const faa = aux; | 181 | struct fdt_attach_args * const faa = aux; | |
182 | const int phandle = faa->faa_phandle; | 182 | const int phandle = faa->faa_phandle; | |
183 | bus_addr_t addr; | 183 | bus_addr_t addr; | |
184 | bus_size_t size; | 184 | bus_size_t size; | |
185 | int error; | 185 | int error; | |
186 | 186 | |||
187 | if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { | 187 | if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { | |
188 | aprint_error(": couldn't get registers\n"); | 188 | aprint_error(": couldn't get registers\n"); | |
189 | return; | 189 | return; | |
190 | } | 190 | } | |
191 | sc->sc_clk_tsensor = fdtbus_clock_get(phandle, "tsensor"); | 191 | sc->sc_clk_tsensor = fdtbus_clock_get(phandle, "tsensor"); | |
192 | if (sc->sc_clk_tsensor == NULL) { | 192 | if (sc->sc_clk_tsensor == NULL) { | |
193 | aprint_error(": couldn't get clock tsensor\n"); | 193 | aprint_error(": couldn't get clock tsensor\n"); | |
194 | return; | 194 | return; | |
195 | } | 195 | } | |
196 | sc->sc_clk_soctherm = fdtbus_clock_get(phandle, "soctherm"); | 196 | sc->sc_clk_soctherm = fdtbus_clock_get(phandle, "soctherm"); | |
197 | if (sc->sc_clk_soctherm == NULL) { | 197 | if (sc->sc_clk_soctherm == NULL) { | |
198 | aprint_error(": couldn't get clock soctherm\n"); | 198 | aprint_error(": couldn't get clock soctherm\n"); | |
199 | return; | 199 | return; | |
200 | } | 200 | } | |
201 | sc->sc_rst_soctherm = fdtbus_reset_get(phandle, "soctherm"); | 201 | sc->sc_rst_soctherm = fdtbus_reset_get(phandle, "soctherm"); | |
202 | if (sc->sc_rst_soctherm == NULL) { | 202 | if (sc->sc_rst_soctherm == NULL) { | |
203 | aprint_error(": couldn't get reset soctherm\n"); | 203 | aprint_error(": couldn't get reset soctherm\n"); | |
204 | return; | 204 | return; | |
205 | } | 205 | } | |
206 | 206 | |||
207 | sc->sc_dev = self; | 207 | sc->sc_dev = self; | |
208 | sc->sc_bst = faa->faa_bst; | 208 | sc->sc_bst = faa->faa_bst; | |
209 | error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); | 209 | error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); | |
210 | if (error) { | 210 | if (error) { | |
211 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | 211 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | |
212 | return; | 212 | return; | |
213 | } | 213 | } | |
214 | 214 | |||
215 | aprint_naive("\n"); | 215 | aprint_naive("\n"); | |
216 | aprint_normal(": SOC_THERM\n"); | 216 | aprint_normal(": SOC_THERM\n"); | |
217 | 217 | |||
218 | sc->sc_config = of_search_compatible(phandle, compat_data)->data; | 218 | sc->sc_config = of_search_compatible(phandle, compat_data)->data; | |
219 | if (sc->sc_config == NULL) { | 219 | if (sc->sc_config == NULL) { | |
220 | aprint_error_dev(self, "unsupported SoC\n"); | 220 | aprint_error_dev(self, "unsupported SoC\n"); | |
221 | return; | 221 | return; | |
222 | } | 222 | } | |
223 | 223 | |||
224 | if (tegra_soctherm_init_clocks(sc) != 0) | 224 | if (tegra_soctherm_init_clocks(sc) != 0) | |
225 | return; | 225 | return; | |
226 | 226 | |||
227 | config_defer(self, tegra_soctherm_init_sensors); | 227 | config_defer(self, tegra_soctherm_init_sensors); | |
228 | } | 228 | } | |
229 | 229 | |||
230 | static int | 230 | static int | |
231 | tegra_soctherm_init_clocks(struct tegra_soctherm_softc *sc) | 231 | tegra_soctherm_init_clocks(struct tegra_soctherm_softc *sc) | |
232 | { | 232 | { | |
233 | int error; | 233 | int error; | |
234 | 234 | |||
235 | fdtbus_reset_assert(sc->sc_rst_soctherm); | 235 | fdtbus_reset_assert(sc->sc_rst_soctherm); | |
236 | 236 | |||
237 | error = clk_set_rate(sc->sc_clk_soctherm, 51000000); | 237 | error = clk_set_rate(sc->sc_clk_soctherm, 51000000); | |
238 | if (error) { | 238 | if (error) { | |
239 | aprint_error_dev(sc->sc_dev, | 239 | aprint_error_dev(sc->sc_dev, | |
240 | "couldn't set soctherm rate: %d\n", error); | 240 | "couldn't set soctherm rate: %d\n", error); | |
241 | return error; | 241 | return error; | |
242 | } | 242 | } | |
243 | 243 | |||
244 | error = clk_set_rate(sc->sc_clk_tsensor, 400000); | 244 | error = clk_set_rate(sc->sc_clk_tsensor, 400000); | |
245 | if (error) { | 245 | if (error) { | |
246 | aprint_error_dev(sc->sc_dev, | 246 | aprint_error_dev(sc->sc_dev, | |
247 | "couldn't set tsensor rate: %d\n", error); | 247 | "couldn't set tsensor rate: %d\n", error); | |
248 | return error; | 248 | return error; | |
249 | } | 249 | } | |
250 | 250 | |||
251 | error = clk_enable(sc->sc_clk_tsensor); | 251 | error = clk_enable(sc->sc_clk_tsensor); | |
252 | if (error) { | 252 | if (error) { | |
253 | aprint_error_dev(sc->sc_dev, "couldn't enable tsensor: %d\n", | 253 | aprint_error_dev(sc->sc_dev, "couldn't enable tsensor: %d\n", | |
254 | error); | 254 | error); | |
255 | return error; | 255 | return error; | |
256 | } | 256 | } | |
257 | 257 | |||
258 | error = clk_enable(sc->sc_clk_soctherm); | 258 | error = clk_enable(sc->sc_clk_soctherm); | |
259 | if (error) { | 259 | if (error) { | |
260 | aprint_error_dev(sc->sc_dev, "couldn't enable soctherm: %d\n", | 260 | aprint_error_dev(sc->sc_dev, "couldn't enable soctherm: %d\n", | |
261 | error); | 261 | error); | |
262 | return error; | 262 | return error; | |
263 | } | 263 | } | |
264 | 264 | |||
265 | fdtbus_reset_deassert(sc->sc_rst_soctherm); | 265 | fdtbus_reset_deassert(sc->sc_rst_soctherm); | |
266 | 266 | |||
267 | return 0; | 267 | return 0; | |
268 | } | 268 | } | |
269 | 269 | |||
270 | static void | 270 | static void | |
271 | tegra_soctherm_init_sensors(device_t dev) | 271 | tegra_soctherm_init_sensors(device_t dev) | |
272 | { | 272 | { | |
273 | struct tegra_soctherm_softc * const sc = device_private(dev); | 273 | struct tegra_soctherm_softc * const sc = device_private(dev); | |
274 | const struct tegra_soctherm_config *config = sc->sc_config; | 274 | const struct tegra_soctherm_config *config = sc->sc_config; | |
275 | const u_int nsensors = __arraycount(tegra_soctherm_sensors); | 275 | const u_int nsensors = __arraycount(tegra_soctherm_sensors); | |
276 | const size_t len = sizeof(*sc->sc_sensors) * nsensors; | 276 | const size_t len = sizeof(*sc->sc_sensors) * nsensors; | |
277 | uint32_t val; | 277 | uint32_t val; | |
278 | u_int n; | 278 | u_int n; | |
279 | 279 | |||
280 | val = tegra_fuse_read(FUSE_TSENSOR8_CALIB_REG); | 280 | val = tegra_fuse_read(FUSE_TSENSOR8_CALIB_REG); | |
281 | sc->sc_base_cp = __SHIFTOUT(val, FUSE_TSENSOR8_CALIB_CP_TS_BASE); | 281 | sc->sc_base_cp = __SHIFTOUT(val, FUSE_TSENSOR8_CALIB_CP_TS_BASE); | |
282 | sc->sc_base_ft = __SHIFTOUT(val, FUSE_TSENSOR8_CALIB_FT_TS_BASE); | 282 | sc->sc_base_ft = __SHIFTOUT(val, FUSE_TSENSOR8_CALIB_FT_TS_BASE); | |
283 | val = tegra_fuse_read(FUSE_SPARE_REALIGNMENT_REG); | 283 | val = tegra_fuse_read(FUSE_SPARE_REALIGNMENT_REG); | |
284 | const int calib_cp = tegra_soctherm_decodeint(val, | 284 | const int calib_cp = tegra_soctherm_decodeint(val, | |
285 | FUSE_SPARE_REALIGNMENT_CP); | 285 | FUSE_SPARE_REALIGNMENT_CP); | |
286 | const int calib_ft = tegra_soctherm_decodeint(val, | 286 | const int calib_ft = tegra_soctherm_decodeint(val, | |
287 | FUSE_SPARE_REALIGNMENT_FT); | 287 | FUSE_SPARE_REALIGNMENT_FT); | |
288 | sc->sc_actual_temp_cp = 2 * config->nominal_calib_cp + calib_cp; | 288 | sc->sc_actual_temp_cp = 2 * config->nominal_calib_cp + calib_cp; | |
289 | sc->sc_actual_temp_ft = 2 * config->nominal_calib_ft + calib_ft; | 289 | sc->sc_actual_temp_ft = 2 * config->nominal_calib_ft + calib_ft; | |
290 | 290 | |||
291 | sc->sc_sme = sysmon_envsys_create(); | 291 | sc->sc_sme = sysmon_envsys_create(); | |
292 | sc->sc_sme->sme_name = device_xname(sc->sc_dev); | 292 | sc->sc_sme->sme_name = device_xname(sc->sc_dev); | |
293 | sc->sc_sme->sme_cookie = sc; | 293 | sc->sc_sme->sme_cookie = sc; | |
294 | sc->sc_sme->sme_refresh = tegra_soctherm_refresh; | 294 | sc->sc_sme->sme_refresh = tegra_soctherm_refresh; | |
295 | 295 | |||
296 | sc->sc_sensors = kmem_zalloc(len, KM_SLEEP); | 296 | sc->sc_sensors = kmem_zalloc(len, KM_SLEEP); | |
297 | for (n = 0; n < nsensors; n++) { | 297 | for (n = 0; n < nsensors; n++) { | |
298 | sc->sc_sensors[n] = tegra_soctherm_sensors[n]; | 298 | sc->sc_sensors[n] = tegra_soctherm_sensors[n]; | |
299 | tegra_soctherm_init_sensor(sc, &sc->sc_sensors[n]); | 299 | tegra_soctherm_init_sensor(sc, &sc->sc_sensors[n]); | |
300 | } | 300 | } | |
301 | 301 | |||
302 | SOCTHERM_WRITE(sc, SOC_THERM_TSENSOR_PDIV_REG, config->init_pdiv); | 302 | SOCTHERM_WRITE(sc, SOC_THERM_TSENSOR_PDIV_REG, config->init_pdiv); | |
303 | SOCTHERM_WRITE(sc, SOC_THERM_TSENSOR_HOTSPOT_OFF_REG, | 303 | SOCTHERM_WRITE(sc, SOC_THERM_TSENSOR_HOTSPOT_OFF_REG, | |
304 | config->init_hotspot_off); | 304 | config->init_hotspot_off); | |
305 | 305 | |||
306 | sysmon_envsys_register(sc->sc_sme); | 306 | sysmon_envsys_register(sc->sc_sme); | |
307 | } | 307 | } | |
308 | 308 | |||
309 | static void | 309 | static void | |
310 | tegra_soctherm_init_sensor(struct tegra_soctherm_softc *sc, | 310 | tegra_soctherm_init_sensor(struct tegra_soctherm_softc *sc, | |
311 | struct tegra_soctherm_sensor *s) | 311 | struct tegra_soctherm_sensor *s) | |
312 | { | 312 | { | |
313 | const struct tegra_soctherm_config *config = sc->sc_config; | 313 | const struct tegra_soctherm_config *config = sc->sc_config; | |
314 | int64_t temp_a, temp_b, tmp; | 314 | int64_t temp_a, temp_b, tmp; | |
315 | uint32_t val; | 315 | uint32_t val; | |
316 | 316 | |||
317 | val = tegra_fuse_read(s->s_fuse); | 317 | val = tegra_fuse_read(s->s_fuse); | |
318 | const int calib_cp = tegra_soctherm_decodeint(val, | 318 | const int calib_cp = tegra_soctherm_decodeint(val, | |
319 | FUSE_TSENSOR_CALIB_CP_TS_BASE); | 319 | FUSE_TSENSOR_CALIB_CP_TS_BASE); | |
320 | const int calib_ft = tegra_soctherm_decodeint(val, | 320 | const int calib_ft = tegra_soctherm_decodeint(val, | |
321 | FUSE_TSENSOR_CALIB_FT_TS_BASE); | 321 | FUSE_TSENSOR_CALIB_FT_TS_BASE); | |
322 | const int actual_cp = sc->sc_base_cp * 64 + calib_cp; | 322 | const int actual_cp = sc->sc_base_cp * 64 + calib_cp; | |
323 | const int actual_ft = sc->sc_base_ft * 32 + calib_ft; | 323 | const int actual_ft = sc->sc_base_ft * 32 + calib_ft; | |
324 | 324 | |||
325 | const int64_t d_sensor = actual_ft - actual_cp; | 325 | const int64_t d_sensor = actual_ft - actual_cp; | |
326 | const int64_t d_temp = sc->sc_actual_temp_ft - sc->sc_actual_temp_cp; | 326 | const int64_t d_temp = sc->sc_actual_temp_ft - sc->sc_actual_temp_cp; | |
327 | const int mult = config->pdiv * config->tsample_ate; | 327 | const int mult = config->pdiv * config->tsample_ate; | |
328 | const int div = config->tsample * config->pdiv_ate; | 328 | const int div = config->tsample * config->pdiv_ate; | |
329 | 329 | |||
330 | temp_a = tegra_soctherm_divide(d_temp * 0x2000 * mult, | 330 | temp_a = tegra_soctherm_divide(d_temp * 0x2000 * mult, | |
331 | d_sensor * div); | 331 | d_sensor * div); | |
332 | tmp = (int64_t)actual_ft * sc->sc_actual_temp_cp - | 332 | tmp = (int64_t)actual_ft * sc->sc_actual_temp_cp - | |
333 | (int64_t)actual_cp * sc->sc_actual_temp_ft; | 333 | (int64_t)actual_cp * sc->sc_actual_temp_ft; | |
334 | temp_b = tegra_soctherm_divide(tmp, d_sensor); | 334 | temp_b = tegra_soctherm_divide(tmp, d_sensor); | |
335 | temp_a = tegra_soctherm_divide( | 335 | temp_a = tegra_soctherm_divide( | |
336 | temp_a * s->s_fuse_corr_alpha, 1000000); | 336 | temp_a * s->s_fuse_corr_alpha, 1000000); | |
337 | temp_b = (uint16_t)tegra_soctherm_divide( | 337 | temp_b = (uint16_t)tegra_soctherm_divide( | |
338 | temp_b * s->s_fuse_corr_alpha + s->s_fuse_corr_beta, 1000000); | 338 | temp_b * s->s_fuse_corr_alpha + s->s_fuse_corr_beta, 1000000); | |
339 | 339 | |||
340 | s->s_therm_a = (int16_t)temp_a; | 340 | s->s_therm_a = (int16_t)temp_a; | |
341 | s->s_therm_b = (int16_t)temp_b; | 341 | s->s_therm_b = (int16_t)temp_b; | |
342 | 342 | |||
343 | SENSOR_SET_CLEAR(sc, s, SOC_THERM_TSENSOR_CONFIG0_OFFSET, | 343 | SENSOR_SET_CLEAR(sc, s, SOC_THERM_TSENSOR_CONFIG0_OFFSET, | |
344 | SOC_THERM_TSENSOR_CONFIG0_STATUS_CLR | | 344 | SOC_THERM_TSENSOR_CONFIG0_STATUS_CLR | | |
345 | SOC_THERM_TSENSOR_CONFIG0_STOP, 0); | 345 | SOC_THERM_TSENSOR_CONFIG0_STOP, 0); | |
346 | SENSOR_WRITE(sc, s, SOC_THERM_TSENSOR_CONFIG0_OFFSET, | 346 | SENSOR_WRITE(sc, s, SOC_THERM_TSENSOR_CONFIG0_OFFSET, | |
347 | __SHIFTIN(config->tall, SOC_THERM_TSENSOR_CONFIG0_TALL) | | 347 | __SHIFTIN(config->tall, SOC_THERM_TSENSOR_CONFIG0_TALL) | | |
348 | SOC_THERM_TSENSOR_CONFIG0_STOP); | 348 | SOC_THERM_TSENSOR_CONFIG0_STOP); | |
349 | 349 | |||
350 | SENSOR_WRITE(sc, s, SOC_THERM_TSENSOR_CONFIG1_OFFSET, | 350 | SENSOR_WRITE(sc, s, SOC_THERM_TSENSOR_CONFIG1_OFFSET, | |
351 | __SHIFTIN(config->tsample - 1, SOC_THERM_TSENSOR_CONFIG1_TSAMPLE) | | 351 | __SHIFTIN(config->tsample - 1, SOC_THERM_TSENSOR_CONFIG1_TSAMPLE) | | |
352 | __SHIFTIN(config->tiddq_en, SOC_THERM_TSENSOR_CONFIG1_TIDDQ_EN) | | 352 | __SHIFTIN(config->tiddq_en, SOC_THERM_TSENSOR_CONFIG1_TIDDQ_EN) | | |
353 | __SHIFTIN(config->ten_count, SOC_THERM_TSENSOR_CONFIG1_TEN_COUNT) | | 353 | __SHIFTIN(config->ten_count, SOC_THERM_TSENSOR_CONFIG1_TEN_COUNT) | | |
354 | SOC_THERM_TSENSOR_CONFIG1_TEMP_ENABLE); | 354 | SOC_THERM_TSENSOR_CONFIG1_TEMP_ENABLE); | |
355 | 355 | |||
356 | SENSOR_WRITE(sc, s, SOC_THERM_TSENSOR_CONFIG2_OFFSET, | 356 | SENSOR_WRITE(sc, s, SOC_THERM_TSENSOR_CONFIG2_OFFSET, | |
357 | __SHIFTIN((uint16_t)s->s_therm_a, | 357 | __SHIFTIN((uint16_t)s->s_therm_a, | |
358 | SOC_THERM_TSENSOR_CONFIG2_THERM_A) | | 358 | SOC_THERM_TSENSOR_CONFIG2_THERM_A) | | |
359 | __SHIFTIN((uint16_t)s->s_therm_b, | 359 | __SHIFTIN((uint16_t)s->s_therm_b, | |
360 | SOC_THERM_TSENSOR_CONFIG2_THERM_B)); | 360 | SOC_THERM_TSENSOR_CONFIG2_THERM_B)); | |
361 | 361 | |||
362 | SENSOR_SET_CLEAR(sc, s, SOC_THERM_TSENSOR_CONFIG0_OFFSET, | 362 | SENSOR_SET_CLEAR(sc, s, SOC_THERM_TSENSOR_CONFIG0_OFFSET, | |
363 | 0, SOC_THERM_TSENSOR_CONFIG0_STOP); | 363 | 0, SOC_THERM_TSENSOR_CONFIG0_STOP); | |
364 | 364 | |||
365 | s->s_data.units = ENVSYS_STEMP; | 365 | s->s_data.units = ENVSYS_STEMP; | |
366 | s->s_data.state = ENVSYS_SINVALID; | 366 | s->s_data.state = ENVSYS_SINVALID; | |
367 | sysmon_envsys_sensor_attach(sc->sc_sme, &s->s_data); | 367 | sysmon_envsys_sensor_attach(sc->sc_sme, &s->s_data); | |
368 | } | 368 | } | |
369 | 369 | |||
370 | static void | 370 | static void | |
371 | tegra_soctherm_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) | 371 | tegra_soctherm_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) | |
372 | { | 372 | { | |
373 | struct tegra_soctherm_softc * const sc = sme->sme_cookie; | 373 | struct tegra_soctherm_softc * const sc = sme->sme_cookie; | |
374 | struct tegra_soctherm_sensor *s = (struct tegra_soctherm_sensor *)edata; | 374 | struct tegra_soctherm_sensor *s = (struct tegra_soctherm_sensor *)edata; | |
375 | uint32_t status; | 375 | uint32_t status; | |
376 | 376 | |||
377 | status = SENSOR_READ(sc, s, SOC_THERM_TSENSOR_STATUS1_OFFSET); | 377 | status = SENSOR_READ(sc, s, SOC_THERM_TSENSOR_STATUS1_OFFSET); | |
378 | if (status & SOC_THERM_TSENSOR_STATUS1_TEMP_VALID) { | 378 | if (status & SOC_THERM_TSENSOR_STATUS1_TEMP_VALID) { | |
379 | const u_int temp = __SHIFTOUT(status, | 379 | const u_int temp = __SHIFTOUT(status, | |
380 | SOC_THERM_TSENSOR_STATUS1_TEMP); | 380 | SOC_THERM_TSENSOR_STATUS1_TEMP); | |
381 | int64_t val = ((temp >> 8) & 0xff) * 1000000; | 381 | int64_t val = ((temp >> 8) & 0xff) * 1000000; | |
382 | if (temp & 0x80) | 382 | if (temp & 0x80) | |
383 | val += 500000; | 383 | val += 500000; | |
384 | if (temp & 0x02) | 384 | if (temp & 0x02) | |
385 | val = -val; | 385 | val = -val; | |
386 | edata->value_cur = val + 273150000; | 386 | edata->value_cur = val + 273150000; | |
387 | edata->state = ENVSYS_SVALID; | 387 | edata->state = ENVSYS_SVALID; | |
388 | } else { | 388 | } else { | |
389 | edata->state = ENVSYS_SINVALID; | 389 | edata->state = ENVSYS_SINVALID; | |
390 | } | 390 | } | |
391 | } | 391 | } | |
392 | 392 | |||
393 | static int | 393 | static int | |
394 | tegra_soctherm_decodeint(uint32_t val, uint32_t bitmask) | 394 | tegra_soctherm_decodeint(uint32_t val, uint32_t bitmask) | |
395 | { | 395 | { | |
396 | const uint32_t v = __SHIFTOUT(val, bitmask); | 396 | const uint32_t v = __SHIFTOUT(val, bitmask); | |
397 | const int bits = popcount32(bitmask); | 397 | const int bits = popcount32(bitmask); | |
398 | int ret = v << (32 - bits); | 398 | int ret = v << (32 - bits); | |
399 | return ret >> (32 - bits); | 399 | return ret >> (32 - bits); | |
400 | } | 400 | } | |
401 | 401 | |||
402 | static int64_t | 402 | static int64_t | |
403 | tegra_soctherm_divide(int64_t num, int64_t denom) | 403 | tegra_soctherm_divide(int64_t num, int64_t denom) | |
404 | { | 404 | { | |
405 | int64_t ret = ((num << 16) * 2 + 1) / (2 * denom); | 405 | int64_t ret = ((num << 16) * 2 + 1) / (2 * denom); | |
406 | return ret >> 16; | 406 | return ret >> 16; | |
407 | } | 407 | } |
--- src/sys/arch/arm/nvidia/tegra_xusb.c 2021/01/25 14:20:38 1.24
+++ src/sys/arch/arm/nvidia/tegra_xusb.c 2021/01/27 01:58:15 1.25
@@ -1,1008 +1,1008 @@ | @@ -1,1008 +1,1008 @@ | |||
1 | /* $NetBSD: tegra_xusb.c,v 1.24 2021/01/25 14:20:38 thorpej Exp $ */ | 1 | /* $NetBSD: tegra_xusb.c,v 1.25 2021/01/27 01:58:15 thorpej Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2016 Jonathan A. Kollasch | 4 | * Copyright (c) 2016 Jonathan A. Kollasch | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | |
20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include "locators.h" | 29 | #include "locators.h" | |
30 | #include "opt_tegra.h" | 30 | #include "opt_tegra.h" | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: tegra_xusb.c,v 1.24 2021/01/25 14:20:38 thorpej Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: tegra_xusb.c,v 1.25 2021/01/27 01:58:15 thorpej Exp $"); | |
34 | 34 | |||
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/bus.h> | 36 | #include <sys/bus.h> | |
37 | #include <sys/device.h> | 37 | #include <sys/device.h> | |
38 | #include <sys/intr.h> | 38 | #include <sys/intr.h> | |
39 | #include <sys/systm.h> | 39 | #include <sys/systm.h> | |
40 | #include <sys/kernel.h> | 40 | #include <sys/kernel.h> | |
41 | 41 | |||
42 | #include <arm/nvidia/tegra_reg.h> | 42 | #include <arm/nvidia/tegra_reg.h> | |
43 | #include <arm/nvidia/tegra_var.h> | 43 | #include <arm/nvidia/tegra_var.h> | |
44 | #include <arm/nvidia/tegra_xusbpad.h> | 44 | #include <arm/nvidia/tegra_xusbpad.h> | |
45 | #include <arm/nvidia/tegra_xusbreg.h> | 45 | #include <arm/nvidia/tegra_xusbreg.h> | |
46 | #include <arm/nvidia/tegra_pmcreg.h> | 46 | #include <arm/nvidia/tegra_pmcreg.h> | |
47 | 47 | |||
48 | #include <dev/pci/pcireg.h> | 48 | #include <dev/pci/pcireg.h> | |
49 | 49 | |||
50 | #include <dev/fdt/fdtvar.h> | 50 | #include <dev/fdt/fdtvar.h> | |
51 | 51 | |||
52 | #include <dev/firmload.h> | 52 | #include <dev/firmload.h> | |
53 | 53 | |||
54 | #include <dev/usb/usb.h> | 54 | #include <dev/usb/usb.h> | |
55 | #include <dev/usb/usbdi.h> | 55 | #include <dev/usb/usbdi.h> | |
56 | #include <dev/usb/usbdivar.h> | 56 | #include <dev/usb/usbdivar.h> | |
57 | #include <dev/usb/usb_mem.h> | 57 | #include <dev/usb/usb_mem.h> | |
58 | 58 | |||
59 | #include <dev/usb/xhcireg.h> | 59 | #include <dev/usb/xhcireg.h> | |
60 | #include <dev/usb/xhcivar.h> | 60 | #include <dev/usb/xhcivar.h> | |
61 | 61 | |||
62 | #ifdef TEGRA_XUSB_DEBUG | 62 | #ifdef TEGRA_XUSB_DEBUG | |
63 | int tegra_xusb_debug = 1; | 63 | int tegra_xusb_debug = 1; | |
64 | #else | 64 | #else | |
65 | int tegra_xusb_debug = 0; | 65 | int tegra_xusb_debug = 0; | |
66 | #endif | 66 | #endif | |
67 | 67 | |||
68 | #define DPRINTF(...) if (tegra_xusb_debug) device_printf(__VA_ARGS__) | 68 | #define DPRINTF(...) if (tegra_xusb_debug) device_printf(__VA_ARGS__) | |
69 | 69 | |||
70 | static int tegra_xusb_match(device_t, cfdata_t, void *); | 70 | static int tegra_xusb_match(device_t, cfdata_t, void *); | |
71 | static void tegra_xusb_attach(device_t, device_t, void *); | 71 | static void tegra_xusb_attach(device_t, device_t, void *); | |
72 | static void tegra_xusb_mountroot(device_t); | 72 | static void tegra_xusb_mountroot(device_t); | |
73 | 73 | |||
74 | static int tegra_xusb_intr_mbox(void *); | 74 | static int tegra_xusb_intr_mbox(void *); | |
75 | 75 | |||
76 | #ifdef TEGRA124_XUSB_BIN_STATIC | 76 | #ifdef TEGRA124_XUSB_BIN_STATIC | |
77 | extern const char _binary_tegra124_xusb_bin_start[]; | 77 | extern const char _binary_tegra124_xusb_bin_start[]; | |
78 | extern const char _binary_tegra124_xusb_bin_end[]; | 78 | extern const char _binary_tegra124_xusb_bin_end[]; | |
79 | __asm__( | 79 | __asm__( | |
80 | ".section \".rodata\"\n" | 80 | ".section \".rodata\"\n" | |
81 | "_binary_tegra124_xusb_bin_start:\n" | 81 | "_binary_tegra124_xusb_bin_start:\n" | |
82 | ".incbin \"../external/nvidia-firmware/tegra/dist/tegra124/xusb.bin\"\n" | 82 | ".incbin \"../external/nvidia-firmware/tegra/dist/tegra124/xusb.bin\"\n" | |
83 | ".size _binary_tegra124_xusb_bin_start, . - _binary_tegra124_xusb_bin_start\n" | 83 | ".size _binary_tegra124_xusb_bin_start, . - _binary_tegra124_xusb_bin_start\n" | |
84 | "_binary_tegra124_xusb_bin_end:\n" | 84 | "_binary_tegra124_xusb_bin_end:\n" | |
85 | ".previous\n" | 85 | ".previous\n" | |
86 | ); | 86 | ); | |
87 | #endif | 87 | #endif | |
88 | 88 | |||
89 | #ifdef TEGRA210_XUSB_BIN_STATIC | 89 | #ifdef TEGRA210_XUSB_BIN_STATIC | |
90 | extern const char _binary_tegra210_xusb_bin_start[]; | 90 | extern const char _binary_tegra210_xusb_bin_start[]; | |
91 | extern const char _binary_tegra210_xusb_bin_end[]; | 91 | extern const char _binary_tegra210_xusb_bin_end[]; | |
92 | __asm__( | 92 | __asm__( | |
93 | ".section \".rodata\"\n" | 93 | ".section \".rodata\"\n" | |
94 | "_binary_tegra210_xusb_bin_start:\n" | 94 | "_binary_tegra210_xusb_bin_start:\n" | |
95 | ".incbin \"../external/nvidia-firmware/tegra/dist/tegra210/xusb.bin\"\n" | 95 | ".incbin \"../external/nvidia-firmware/tegra/dist/tegra210/xusb.bin\"\n" | |
96 | ".size _binary_tegra210_xusb_bin_start, . - _binary_tegra210_xusb_bin_start\n" | 96 | ".size _binary_tegra210_xusb_bin_start, . - _binary_tegra210_xusb_bin_start\n" | |
97 | "_binary_tegra210_xusb_bin_end:\n" | 97 | "_binary_tegra210_xusb_bin_end:\n" | |
98 | ".previous\n" | 98 | ".previous\n" | |
99 | ); | 99 | ); | |
100 | #endif | 100 | #endif | |
101 | 101 | |||
102 | enum xusb_type { | 102 | enum xusb_type { | |
103 | XUSB_T124 = 1, | 103 | XUSB_T124 = 1, | |
104 | XUSB_T210 | 104 | XUSB_T210 | |
105 | }; | 105 | }; | |
106 | 106 | |||
107 | struct tegra_xhci_data { | 107 | struct tegra_xhci_data { | |
108 | enum xusb_type txd_type; | 108 | enum xusb_type txd_type; | |
109 | const char * const * txd_supplies; | 109 | const char * const * txd_supplies; | |
110 | size_t txd_nsupplies; | 110 | size_t txd_nsupplies; | |
111 | bool txd_scale_ss_clock; | 111 | bool txd_scale_ss_clock; | |
112 | }; | 112 | }; | |
113 | 113 | |||
114 | const char *tegra124_xhci_supplies[] = { | 114 | const char *tegra124_xhci_supplies[] = { | |
115 | "dvddio-pex-supply", | 115 | "dvddio-pex-supply", | |
116 | "hvddio-pex-supply", | 116 | "hvddio-pex-supply", | |
117 | "avdd-usb-supply", | 117 | "avdd-usb-supply", | |
118 | "avdd-pll-utmip-supply", | 118 | "avdd-pll-utmip-supply", | |
119 | "avdd-pll-uerefe-supply", | 119 | "avdd-pll-uerefe-supply", | |
120 | "dvdd-usb-ss-pll-supply", | 120 | "dvdd-usb-ss-pll-supply", | |
121 | "hvdd-usb-ss-pll-e-supply" | 121 | "hvdd-usb-ss-pll-e-supply" | |
122 | }; | 122 | }; | |
123 | 123 | |||
124 | struct tegra_xhci_data tegra124_xhci_data = { | 124 | struct tegra_xhci_data tegra124_xhci_data = { | |
125 | .txd_type = XUSB_T124, | 125 | .txd_type = XUSB_T124, | |
126 | .txd_supplies = tegra124_xhci_supplies, | 126 | .txd_supplies = tegra124_xhci_supplies, | |
127 | .txd_nsupplies = __arraycount(tegra124_xhci_supplies), | 127 | .txd_nsupplies = __arraycount(tegra124_xhci_supplies), | |
128 | .txd_scale_ss_clock = true, | 128 | .txd_scale_ss_clock = true, | |
129 | }; | 129 | }; | |
130 | 130 | |||
131 | const char *tegra210_xhci_supplies[] = { | 131 | const char *tegra210_xhci_supplies[] = { | |
132 | "dvddio-pex", | 132 | "dvddio-pex", | |
133 | "hvddio-pex", | 133 | "hvddio-pex", | |
134 | "avdd-usb", | 134 | "avdd-usb", | |
135 | "avdd-pll-utmip", | 135 | "avdd-pll-utmip", | |
136 | "avdd-pll-uerefe", | 136 | "avdd-pll-uerefe", | |
137 | "dvdd-pex-pll", | 137 | "dvdd-pex-pll", | |
138 | "hvdd-pex-pll-e", | 138 | "hvdd-pex-pll-e", | |
139 | }; | 139 | }; | |
140 | 140 | |||
141 | struct tegra_xhci_data tegra210_xhci_data = { | 141 | struct tegra_xhci_data tegra210_xhci_data = { | |
142 | .txd_type = XUSB_T210, | 142 | .txd_type = XUSB_T210, | |
143 | .txd_supplies = tegra210_xhci_supplies, | 143 | .txd_supplies = tegra210_xhci_supplies, | |
144 | .txd_nsupplies = __arraycount(tegra210_xhci_supplies), | 144 | .txd_nsupplies = __arraycount(tegra210_xhci_supplies), | |
145 | .txd_scale_ss_clock = false, | 145 | .txd_scale_ss_clock = false, | |
146 | }; | 146 | }; | |
147 | 147 | |||
148 | static const struct device_compatible_entry compat_data[] = { | 148 | static const struct device_compatible_entry compat_data[] = { | |
149 | { .compat = "nvidia,tegra124-xusb", .data = &tegra124_xhci_data }, | 149 | { .compat = "nvidia,tegra124-xusb", .data = &tegra124_xhci_data }, | |
150 | { .compat = "nvidia,tegra210-xusb", .data = &tegra210_xhci_data }, | 150 | { .compat = "nvidia,tegra210-xusb", .data = &tegra210_xhci_data }, | |
151 | { } | 151 | DEVICE_COMPAT_EOL | |
152 | }; | 152 | }; | |
153 | 153 | |||
154 | struct fw_dma { | 154 | struct fw_dma { | |
155 | bus_dmamap_t map; | 155 | bus_dmamap_t map; | |
156 | void * addr; | 156 | void * addr; | |
157 | bus_dma_segment_t segs[1]; | 157 | bus_dma_segment_t segs[1]; | |
158 | int nsegs; | 158 | int nsegs; | |
159 | size_t size; | 159 | size_t size; | |
160 | }; | 160 | }; | |
161 | 161 | |||
162 | struct tegra_xusb_softc { | 162 | struct tegra_xusb_softc { | |
163 | struct xhci_softc sc_xhci; | 163 | struct xhci_softc sc_xhci; | |
164 | int sc_phandle; | 164 | int sc_phandle; | |
165 | bus_space_handle_t sc_bsh_xhci; | 165 | bus_space_handle_t sc_bsh_xhci; | |
166 | bus_space_handle_t sc_bsh_fpci; | 166 | bus_space_handle_t sc_bsh_fpci; | |
167 | bus_space_handle_t sc_bsh_ipfs; | 167 | bus_space_handle_t sc_bsh_ipfs; | |
168 | void *sc_ih; | 168 | void *sc_ih; | |
169 | void *sc_ih_mbox; | 169 | void *sc_ih_mbox; | |
170 | struct fw_dma sc_fw_dma; | 170 | struct fw_dma sc_fw_dma; | |
171 | struct clk *sc_clk_ss_src; | 171 | struct clk *sc_clk_ss_src; | |
172 | 172 | |||
173 | const struct tegra_xhci_data *sc_txd; | 173 | const struct tegra_xhci_data *sc_txd; | |
174 | }; | 174 | }; | |
175 | 175 | |||
176 | static uint32_t csb_read_4(struct tegra_xusb_softc * const, bus_size_t); | 176 | static uint32_t csb_read_4(struct tegra_xusb_softc * const, bus_size_t); | |
177 | static void csb_write_4(struct tegra_xusb_softc * const, bus_size_t, | 177 | static void csb_write_4(struct tegra_xusb_softc * const, bus_size_t, | |
178 | uint32_t); | 178 | uint32_t); | |
179 | 179 | |||
180 | static void tegra_xusb_init(struct tegra_xusb_softc * const); | 180 | static void tegra_xusb_init(struct tegra_xusb_softc * const); | |
181 | static int tegra_xusb_open_fw(struct tegra_xusb_softc * const); | 181 | static int tegra_xusb_open_fw(struct tegra_xusb_softc * const); | |
182 | static int tegra_xusb_load_fw(struct tegra_xusb_softc * const, void *, | 182 | static int tegra_xusb_load_fw(struct tegra_xusb_softc * const, void *, | |
183 | size_t); | 183 | size_t); | |
184 | static void tegra_xusb_init_regulators(struct tegra_xusb_softc * const); | 184 | static void tegra_xusb_init_regulators(struct tegra_xusb_softc * const); | |
185 | 185 | |||
186 | static int xusb_mailbox_send(struct tegra_xusb_softc * const, uint32_t); | 186 | static int xusb_mailbox_send(struct tegra_xusb_softc * const, uint32_t); | |
187 | 187 | |||
188 | CFATTACH_DECL_NEW(tegra_xusb, sizeof(struct tegra_xusb_softc), | 188 | CFATTACH_DECL_NEW(tegra_xusb, sizeof(struct tegra_xusb_softc), | |
189 | tegra_xusb_match, tegra_xusb_attach, NULL, NULL); | 189 | tegra_xusb_match, tegra_xusb_attach, NULL, NULL); | |
190 | 190 | |||
191 | static int | 191 | static int | |
192 | tegra_xusb_match(device_t parent, cfdata_t cf, void *aux) | 192 | tegra_xusb_match(device_t parent, cfdata_t cf, void *aux) | |
193 | { | 193 | { | |
194 | struct fdt_attach_args * const faa = aux; | 194 | struct fdt_attach_args * const faa = aux; | |
195 | 195 | |||
196 | return of_match_compat_data(faa->faa_phandle, compat_data); | 196 | return of_match_compat_data(faa->faa_phandle, compat_data); | |
197 | } | 197 | } | |
198 | 198 | |||
199 | #define tegra_xusb_attach_check(sc, cond, fmt, ...) \ | 199 | #define tegra_xusb_attach_check(sc, cond, fmt, ...) \ | |
200 | do { \ | 200 | do { \ | |
201 | if (cond) { \ | 201 | if (cond) { \ | |
202 | aprint_error_dev(sc->sc_dev, fmt, ## __VA_ARGS__); \ | 202 | aprint_error_dev(sc->sc_dev, fmt, ## __VA_ARGS__); \ | |
203 | return; \ | 203 | return; \ | |
204 | } \ | 204 | } \ | |
205 | } while (0) | 205 | } while (0) | |
206 | 206 | |||
207 | static void | 207 | static void | |
208 | tegra_xusb_attach(device_t parent, device_t self, void *aux) | 208 | tegra_xusb_attach(device_t parent, device_t self, void *aux) | |
209 | { | 209 | { | |
210 | struct tegra_xusb_softc * const psc = device_private(self); | 210 | struct tegra_xusb_softc * const psc = device_private(self); | |
211 | struct xhci_softc * const sc = &psc->sc_xhci; | 211 | struct xhci_softc * const sc = &psc->sc_xhci; | |
212 | struct fdt_attach_args * const faa = aux; | 212 | struct fdt_attach_args * const faa = aux; | |
213 | bool wait_for_root = true; | 213 | bool wait_for_root = true; | |
214 | char intrstr[128]; | 214 | char intrstr[128]; | |
215 | bus_addr_t addr; | 215 | bus_addr_t addr; | |
216 | bus_size_t size; | 216 | bus_size_t size; | |
217 | struct fdtbus_reset *rst; | 217 | struct fdtbus_reset *rst; | |
218 | struct fdtbus_phy *phy; | 218 | struct fdtbus_phy *phy; | |
219 | struct clk *clk; | 219 | struct clk *clk; | |
220 | uint32_t rate; | 220 | uint32_t rate; | |
221 | int error, n; | 221 | int error, n; | |
222 | 222 | |||
223 | aprint_naive("\n"); | 223 | aprint_naive("\n"); | |
224 | aprint_normal(": XUSB\n"); | 224 | aprint_normal(": XUSB\n"); | |
225 | 225 | |||
226 | sc->sc_dev = self; | 226 | sc->sc_dev = self; | |
227 | sc->sc_iot = faa->faa_bst; | 227 | sc->sc_iot = faa->faa_bst; | |
228 | sc->sc_bus.ub_hcpriv = sc; | 228 | sc->sc_bus.ub_hcpriv = sc; | |
229 | sc->sc_bus.ub_dmatag = faa->faa_dmat; | 229 | sc->sc_bus.ub_dmatag = faa->faa_dmat; | |
230 | sc->sc_quirks = XHCI_DEFERRED_START; | 230 | sc->sc_quirks = XHCI_DEFERRED_START; | |
231 | psc->sc_phandle = faa->faa_phandle; | 231 | psc->sc_phandle = faa->faa_phandle; | |
232 | 232 | |||
233 | psc->sc_txd = of_search_compatible(faa->faa_phandle, compat_data)->data; | 233 | psc->sc_txd = of_search_compatible(faa->faa_phandle, compat_data)->data; | |
234 | 234 | |||
235 | if (fdtbus_get_reg_byname(faa->faa_phandle, "hcd", &addr, &size) != 0) { | 235 | if (fdtbus_get_reg_byname(faa->faa_phandle, "hcd", &addr, &size) != 0) { | |
236 | aprint_error(": couldn't get registers\n"); | 236 | aprint_error(": couldn't get registers\n"); | |
237 | return; | 237 | return; | |
238 | } | 238 | } | |
239 | error = bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh); | 239 | error = bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh); | |
240 | if (error) { | 240 | if (error) { | |
241 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | 241 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | |
242 | return; | 242 | return; | |
243 | } | 243 | } | |
244 | DPRINTF(sc->sc_dev, "mapped %#" PRIxBUSADDR "\n", addr); | 244 | DPRINTF(sc->sc_dev, "mapped %#" PRIxBUSADDR "\n", addr); | |
245 | sc->sc_ios = size; | 245 | sc->sc_ios = size; | |
246 | 246 | |||
247 | if (fdtbus_get_reg_byname(faa->faa_phandle, "fpci", &addr, &size) != 0) { | 247 | if (fdtbus_get_reg_byname(faa->faa_phandle, "fpci", &addr, &size) != 0) { | |
248 | aprint_error(": couldn't get registers\n"); | 248 | aprint_error(": couldn't get registers\n"); | |
249 | return; | 249 | return; | |
250 | } | 250 | } | |
251 | error = bus_space_map(sc->sc_iot, addr, size, 0, &psc->sc_bsh_fpci); | 251 | error = bus_space_map(sc->sc_iot, addr, size, 0, &psc->sc_bsh_fpci); | |
252 | if (error) { | 252 | if (error) { | |
253 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | 253 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | |
254 | return; | 254 | return; | |
255 | } | 255 | } | |
256 | DPRINTF(sc->sc_dev, "mapped %#" PRIxBUSADDR "\n", addr); | 256 | DPRINTF(sc->sc_dev, "mapped %#" PRIxBUSADDR "\n", addr); | |
257 | 257 | |||
258 | if (fdtbus_get_reg_byname(faa->faa_phandle, "ipfs", &addr, &size) != 0) { | 258 | if (fdtbus_get_reg_byname(faa->faa_phandle, "ipfs", &addr, &size) != 0) { | |
259 | aprint_error(": couldn't get registers\n"); | 259 | aprint_error(": couldn't get registers\n"); | |
260 | return; | 260 | return; | |
261 | } | 261 | } | |
262 | error = bus_space_map(sc->sc_iot, addr, size, 0, &psc->sc_bsh_ipfs); | 262 | error = bus_space_map(sc->sc_iot, addr, size, 0, &psc->sc_bsh_ipfs); | |
263 | if (error) { | 263 | if (error) { | |
264 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | 264 | aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", addr, error); | |
265 | return; | 265 | return; | |
266 | } | 266 | } | |
267 | DPRINTF(sc->sc_dev, "mapped %#" PRIxBUSADDR "\n", addr); | 267 | DPRINTF(sc->sc_dev, "mapped %#" PRIxBUSADDR "\n", addr); | |
268 | 268 | |||
269 | if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) { | 269 | if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) { | |
270 | aprint_error_dev(self, "failed to decode interrupt\n"); | 270 | aprint_error_dev(self, "failed to decode interrupt\n"); | |
271 | return; | 271 | return; | |
272 | } | 272 | } | |
273 | 273 | |||
274 | psc->sc_ih = fdtbus_intr_establish_xname(faa->faa_phandle, 0, IPL_USB, | 274 | psc->sc_ih = fdtbus_intr_establish_xname(faa->faa_phandle, 0, IPL_USB, | |
275 | FDT_INTR_MPSAFE, xhci_intr, sc, device_xname(self)); | 275 | FDT_INTR_MPSAFE, xhci_intr, sc, device_xname(self)); | |
276 | if (psc->sc_ih == NULL) { | 276 | if (psc->sc_ih == NULL) { | |
277 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | 277 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | |
278 | intrstr); | 278 | intrstr); | |
279 | return; | 279 | return; | |
280 | } | 280 | } | |
281 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | 281 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | |
282 | 282 | |||
283 | if (!fdtbus_intr_str(faa->faa_phandle, 1, intrstr, sizeof(intrstr))) { | 283 | if (!fdtbus_intr_str(faa->faa_phandle, 1, intrstr, sizeof(intrstr))) { | |
284 | aprint_error_dev(self, "failed to decode interrupt\n"); | 284 | aprint_error_dev(self, "failed to decode interrupt\n"); | |
285 | return; | 285 | return; | |
286 | } | 286 | } | |
287 | 287 | |||
288 | psc->sc_ih_mbox = fdtbus_intr_establish_xname(faa->faa_phandle, 1, | 288 | psc->sc_ih_mbox = fdtbus_intr_establish_xname(faa->faa_phandle, 1, | |
289 | IPL_VM, FDT_INTR_MPSAFE, tegra_xusb_intr_mbox, psc, | 289 | IPL_VM, FDT_INTR_MPSAFE, tegra_xusb_intr_mbox, psc, | |
290 | device_xname(self)); | 290 | device_xname(self)); | |
291 | if (psc->sc_ih_mbox == NULL) { | 291 | if (psc->sc_ih_mbox == NULL) { | |
292 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | 292 | aprint_error_dev(self, "failed to establish interrupt on %s\n", | |
293 | intrstr); | 293 | intrstr); | |
294 | return; | 294 | return; | |
295 | } | 295 | } | |
296 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | 296 | aprint_normal_dev(self, "interrupting on %s\n", intrstr); | |
297 | 297 | |||
298 | /* Enable PHYs */ | 298 | /* Enable PHYs */ | |
299 | for (n = 0; (phy = fdtbus_phy_get_index(faa->faa_phandle, n)) != NULL; n++) | 299 | for (n = 0; (phy = fdtbus_phy_get_index(faa->faa_phandle, n)) != NULL; n++) | |
300 | if (fdtbus_phy_enable(phy, true) != 0) | 300 | if (fdtbus_phy_enable(phy, true) != 0) | |
301 | aprint_error_dev(self, "failed to enable PHY #%d\n", n); | 301 | aprint_error_dev(self, "failed to enable PHY #%d\n", n); | |
302 | 302 | |||
303 | /* Enable XUSB power rails */ | 303 | /* Enable XUSB power rails */ | |
304 | 304 | |||
305 | tegra_pmc_power(PMC_PARTID_XUSBC, true); /* Host/USB2.0 */ | 305 | tegra_pmc_power(PMC_PARTID_XUSBC, true); /* Host/USB2.0 */ | |
306 | tegra_pmc_remove_clamping(PMC_PARTID_XUSBC); | 306 | tegra_pmc_remove_clamping(PMC_PARTID_XUSBC); | |
307 | tegra_pmc_power(PMC_PARTID_XUSBA, true); /* SuperSpeed */ | 307 | tegra_pmc_power(PMC_PARTID_XUSBA, true); /* SuperSpeed */ | |
308 | tegra_pmc_remove_clamping(PMC_PARTID_XUSBA); | 308 | tegra_pmc_remove_clamping(PMC_PARTID_XUSBA); | |
309 | 309 | |||
310 | /* Enable XUSB clocks */ | 310 | /* Enable XUSB clocks */ | |
311 | 311 | |||
312 | clk = fdtbus_clock_get(faa->faa_phandle, "pll_e"); | 312 | clk = fdtbus_clock_get(faa->faa_phandle, "pll_e"); | |
313 | rate = clk_get_rate(clk); | 313 | rate = clk_get_rate(clk); | |
314 | error = clk_enable(clk); /* XXX set frequency */ | 314 | error = clk_enable(clk); /* XXX set frequency */ | |
315 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 315 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
316 | tegra_xusb_attach_check(sc, error, "failed to enable pll_e clock"); | 316 | tegra_xusb_attach_check(sc, error, "failed to enable pll_e clock"); | |
317 | 317 | |||
318 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_host_src"); | 318 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_host_src"); | |
319 | rate = clk_get_rate(clk); | 319 | rate = clk_get_rate(clk); | |
320 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 320 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
321 | error = clk_set_rate(clk, 102000000); | 321 | error = clk_set_rate(clk, 102000000); | |
322 | tegra_xusb_attach_check(sc, error, "failed to set xusb_host_src clock rate"); | 322 | tegra_xusb_attach_check(sc, error, "failed to set xusb_host_src clock rate"); | |
323 | 323 | |||
324 | rate = clk_get_rate(clk); | 324 | rate = clk_get_rate(clk); | |
325 | error = clk_enable(clk); /* XXX set frequency */ | 325 | error = clk_enable(clk); /* XXX set frequency */ | |
326 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 326 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
327 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_host_src clock"); | 327 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_host_src clock"); | |
328 | 328 | |||
329 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_falcon_src"); | 329 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_falcon_src"); | |
330 | rate = clk_get_rate(clk); | 330 | rate = clk_get_rate(clk); | |
331 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 331 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
332 | error = clk_set_rate(clk, 204000000); | 332 | error = clk_set_rate(clk, 204000000); | |
333 | tegra_xusb_attach_check(sc, error, "failed to set xusb_falcon_src clock rate"); | 333 | tegra_xusb_attach_check(sc, error, "failed to set xusb_falcon_src clock rate"); | |
334 | 334 | |||
335 | rate = clk_get_rate(clk); | 335 | rate = clk_get_rate(clk); | |
336 | error = clk_enable(clk); | 336 | error = clk_enable(clk); | |
337 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 337 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
338 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_falcon_src clock"); | 338 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_falcon_src clock"); | |
339 | 339 | |||
340 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_host"); | 340 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_host"); | |
341 | rate = clk_get_rate(clk); | 341 | rate = clk_get_rate(clk); | |
342 | error = clk_enable(clk); /* XXX set frequency */ | 342 | error = clk_enable(clk); /* XXX set frequency */ | |
343 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 343 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
344 | 344 | |||
345 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_ss"); | 345 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_ss"); | |
346 | rate = clk_get_rate(clk); | 346 | rate = clk_get_rate(clk); | |
347 | error = clk_enable(clk); /* XXX set frequency */ | 347 | error = clk_enable(clk); /* XXX set frequency */ | |
348 | DPRINTF(sc->sc_dev, "xusb_ss rate %u error %d\n", rate, error); | 348 | DPRINTF(sc->sc_dev, "xusb_ss rate %u error %d\n", rate, error); | |
349 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_ss clock"); | 349 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_ss clock"); | |
350 | 350 | |||
351 | psc->sc_clk_ss_src = fdtbus_clock_get(faa->faa_phandle, "xusb_ss_src"); | 351 | psc->sc_clk_ss_src = fdtbus_clock_get(faa->faa_phandle, "xusb_ss_src"); | |
352 | tegra_xusb_attach_check(sc, psc->sc_clk_ss_src == NULL, | 352 | tegra_xusb_attach_check(sc, psc->sc_clk_ss_src == NULL, | |
353 | "failed to get xusb_ss_src clock"); | 353 | "failed to get xusb_ss_src clock"); | |
354 | 354 | |||
355 | if (psc->sc_txd->txd_scale_ss_clock) { | 355 | if (psc->sc_txd->txd_scale_ss_clock) { | |
356 | rate = clk_get_rate(psc->sc_clk_ss_src); | 356 | rate = clk_get_rate(psc->sc_clk_ss_src); | |
357 | DPRINTF(sc->sc_dev, "xusb_ss_src rate %u\n", rate); | 357 | DPRINTF(sc->sc_dev, "xusb_ss_src rate %u\n", rate); | |
358 | error = clk_set_rate(psc->sc_clk_ss_src, 2000000); | 358 | error = clk_set_rate(psc->sc_clk_ss_src, 2000000); | |
359 | rate = clk_get_rate(psc->sc_clk_ss_src); | 359 | rate = clk_get_rate(psc->sc_clk_ss_src); | |
360 | DPRINTF(sc->sc_dev, "xusb_ss_src rate %u error %d\n", rate, error); | 360 | DPRINTF(sc->sc_dev, "xusb_ss_src rate %u error %d\n", rate, error); | |
361 | tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate"); | 361 | tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate"); | |
362 | 362 | |||
363 | rate = clk_get_rate(psc->sc_clk_ss_src); | 363 | rate = clk_get_rate(psc->sc_clk_ss_src); | |
364 | DPRINTF(sc->sc_dev, "ss_src rate %u\n", rate); | 364 | DPRINTF(sc->sc_dev, "ss_src rate %u\n", rate); | |
365 | tegra_xusb_attach_check(sc, error, "failed to set xusb_ss_src clock rate"); | 365 | tegra_xusb_attach_check(sc, error, "failed to set xusb_ss_src clock rate"); | |
366 | 366 | |||
367 | error = clk_set_rate(psc->sc_clk_ss_src, 120000000); | 367 | error = clk_set_rate(psc->sc_clk_ss_src, 120000000); | |
368 | rate = clk_get_rate(psc->sc_clk_ss_src); | 368 | rate = clk_get_rate(psc->sc_clk_ss_src); | |
369 | DPRINTF(sc->sc_dev, "ss_src rate %u error %d\n", rate, error); | 369 | DPRINTF(sc->sc_dev, "ss_src rate %u error %d\n", rate, error); | |
370 | tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate"); | 370 | tegra_xusb_attach_check(sc, error, "failed to get xusb_ss_src clock rate"); | |
371 | } | 371 | } | |
372 | 372 | |||
373 | rate = clk_get_rate(psc->sc_clk_ss_src); | 373 | rate = clk_get_rate(psc->sc_clk_ss_src); | |
374 | error = clk_enable(psc->sc_clk_ss_src); | 374 | error = clk_enable(psc->sc_clk_ss_src); | |
375 | DPRINTF(sc->sc_dev, "ss_src rate %u error %d\n", rate, error); | 375 | DPRINTF(sc->sc_dev, "ss_src rate %u error %d\n", rate, error); | |
376 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_ss_src clock"); | 376 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_ss_src clock"); | |
377 | 377 | |||
378 | #if 0 | 378 | #if 0 | |
379 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_hs_src"); | 379 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_hs_src"); | |
380 | error = 0; | 380 | error = 0; | |
381 | rate = clk_get_rate(clk); | 381 | rate = clk_get_rate(clk); | |
382 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 382 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
383 | #endif | 383 | #endif | |
384 | 384 | |||
385 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_fs_src"); | 385 | clk = fdtbus_clock_get(faa->faa_phandle, "xusb_fs_src"); | |
386 | rate = clk_get_rate(clk); | 386 | rate = clk_get_rate(clk); | |
387 | error = clk_enable(clk); /* XXX set frequency */ | 387 | error = clk_enable(clk); /* XXX set frequency */ | |
388 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 388 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
389 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_fs_src clock"); | 389 | tegra_xusb_attach_check(sc, error, "failed to enable xusb_fs_src clock"); | |
390 | 390 | |||
391 | rst = fdtbus_reset_get(faa->faa_phandle, "xusb_host"); | 391 | rst = fdtbus_reset_get(faa->faa_phandle, "xusb_host"); | |
392 | fdtbus_reset_deassert(rst); | 392 | fdtbus_reset_deassert(rst); | |
393 | 393 | |||
394 | rst = fdtbus_reset_get(faa->faa_phandle, "xusb_src"); | 394 | rst = fdtbus_reset_get(faa->faa_phandle, "xusb_src"); | |
395 | fdtbus_reset_deassert(rst); | 395 | fdtbus_reset_deassert(rst); | |
396 | 396 | |||
397 | rst = fdtbus_reset_get(faa->faa_phandle, "xusb_ss"); | 397 | rst = fdtbus_reset_get(faa->faa_phandle, "xusb_ss"); | |
398 | fdtbus_reset_deassert(rst); | 398 | fdtbus_reset_deassert(rst); | |
399 | 399 | |||
400 | DELAY(1); | 400 | DELAY(1); | |
401 | 401 | |||
402 | tegra_xusb_init_regulators(psc); | 402 | tegra_xusb_init_regulators(psc); | |
403 | 403 | |||
404 | tegra_xusb_init(psc); | 404 | tegra_xusb_init(psc); | |
405 | 405 | |||
406 | #if defined(TEGRA124_XUSB_BIN_STATIC) | 406 | #if defined(TEGRA124_XUSB_BIN_STATIC) | |
407 | if (psc->sc_txd->txd_type == XUSB_T124) | 407 | if (psc->sc_txd->txd_type == XUSB_T124) | |
408 | wait_for_root = false; | 408 | wait_for_root = false; | |
409 | #endif | 409 | #endif | |
410 | #if defined(TEGRA210_XUSB_BIN_STATIC) | 410 | #if defined(TEGRA210_XUSB_BIN_STATIC) | |
411 | if (psc->sc_txd->txd_type == XUSB_T210) | 411 | if (psc->sc_txd->txd_type == XUSB_T210) | |
412 | wait_for_root = false; | 412 | wait_for_root = false; | |
413 | #endif | 413 | #endif | |
414 | 414 | |||
415 | if (wait_for_root) | 415 | if (wait_for_root) | |
416 | config_mountroot(sc->sc_dev, tegra_xusb_mountroot); | 416 | config_mountroot(sc->sc_dev, tegra_xusb_mountroot); | |
417 | else | 417 | else | |
418 | tegra_xusb_mountroot(sc->sc_dev); | 418 | tegra_xusb_mountroot(sc->sc_dev); | |
419 | } | 419 | } | |
420 | 420 | |||
421 | static void | 421 | static void | |
422 | tegra_xusb_mountroot(device_t self) | 422 | tegra_xusb_mountroot(device_t self) | |
423 | { | 423 | { | |
424 | struct tegra_xusb_softc * const psc = device_private(self); | 424 | struct tegra_xusb_softc * const psc = device_private(self); | |
425 | struct xhci_softc * const sc = &psc->sc_xhci; | 425 | struct xhci_softc * const sc = &psc->sc_xhci; | |
426 | const bus_space_tag_t bst = sc->sc_iot; | 426 | const bus_space_tag_t bst = sc->sc_iot; | |
427 | const bus_space_handle_t ipfsh = psc->sc_bsh_ipfs; | 427 | const bus_space_handle_t ipfsh = psc->sc_bsh_ipfs; | |
428 | struct clk *clk; | 428 | struct clk *clk; | |
429 | struct fdtbus_reset *rst; | 429 | struct fdtbus_reset *rst; | |
430 | uint32_t rate; | 430 | uint32_t rate; | |
431 | uint32_t val; | 431 | uint32_t val; | |
432 | int error; | 432 | int error; | |
433 | 433 | |||
434 | DPRINTF(sc->sc_dev, "%s()\n", __func__); | 434 | DPRINTF(sc->sc_dev, "%s()\n", __func__); | |
435 | 435 | |||
436 | val = bus_space_read_4(bst, ipfsh, 0x0); | 436 | val = bus_space_read_4(bst, ipfsh, 0x0); | |
437 | DPRINTF(sc->sc_dev, "%s ipfs 0x0 = 0x%x\n", __func__, val); | 437 | DPRINTF(sc->sc_dev, "%s ipfs 0x0 = 0x%x\n", __func__, val); | |
438 | 438 | |||
439 | if (tegra_xusb_open_fw(psc) != 0) | 439 | if (tegra_xusb_open_fw(psc) != 0) | |
440 | return; | 440 | return; | |
441 | DPRINTF(sc->sc_dev, "post fw\n"); | 441 | DPRINTF(sc->sc_dev, "post fw\n"); | |
442 | 442 | |||
443 | tegra_xusbpad_xhci_enable(); | 443 | tegra_xusbpad_xhci_enable(); | |
444 | 444 | |||
445 | clk = fdtbus_clock_get(psc->sc_phandle, "xusb_falcon_src"); | 445 | clk = fdtbus_clock_get(psc->sc_phandle, "xusb_falcon_src"); | |
446 | rate = clk_get_rate(clk); | 446 | rate = clk_get_rate(clk); | |
447 | error = clk_enable(clk); | 447 | error = clk_enable(clk); | |
448 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 448 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
449 | 449 | |||
450 | clk = fdtbus_clock_get(psc->sc_phandle, "xusb_host_src"); | 450 | clk = fdtbus_clock_get(psc->sc_phandle, "xusb_host_src"); | |
451 | rate = clk_get_rate(clk); | 451 | rate = clk_get_rate(clk); | |
452 | error = clk_enable(clk); | 452 | error = clk_enable(clk); | |
453 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | 453 | DPRINTF(sc->sc_dev, "rate %u error %d\n", rate, error); | |
454 | 454 | |||
455 | val = bus_space_read_4(bst, ipfsh, 0x0); | 455 | val = bus_space_read_4(bst, ipfsh, 0x0); | |
456 | DPRINTF(sc->sc_dev, "%s ipfs 0x0 = 0x%x\n", __func__, val); | 456 | DPRINTF(sc->sc_dev, "%s ipfs 0x0 = 0x%x\n", __func__, val); | |
457 | 457 | |||
458 | rst = fdtbus_reset_get(psc->sc_phandle, "xusb_host"); | 458 | rst = fdtbus_reset_get(psc->sc_phandle, "xusb_host"); | |
459 | fdtbus_reset_deassert(rst); | 459 | fdtbus_reset_deassert(rst); | |
460 | 460 | |||
461 | rst = fdtbus_reset_get(psc->sc_phandle, "xusb_src"); | 461 | rst = fdtbus_reset_get(psc->sc_phandle, "xusb_src"); | |
462 | fdtbus_reset_deassert(rst); | 462 | fdtbus_reset_deassert(rst); | |
463 | 463 | |||
464 | rst = fdtbus_reset_get(psc->sc_phandle, "xusb_ss"); | 464 | rst = fdtbus_reset_get(psc->sc_phandle, "xusb_ss"); | |
465 | fdtbus_reset_deassert(rst); | 465 | fdtbus_reset_deassert(rst); | |
466 | 466 | |||
467 | val = csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG); | 467 | val = csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG); | |
468 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", val); | 468 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", val); | |
469 | 469 | |||
470 | val = bus_space_read_4(bst, psc->sc_bsh_fpci, PCI_USBREV) | 470 | val = bus_space_read_4(bst, psc->sc_bsh_fpci, PCI_USBREV) | |
471 | & PCI_USBREV_MASK; | 471 | & PCI_USBREV_MASK; | |
472 | switch (val) { | 472 | switch (val) { | |
473 | case PCI_USBREV_3_0: | 473 | case PCI_USBREV_3_0: | |
474 | sc->sc_bus.ub_revision = USBREV_3_0; | 474 | sc->sc_bus.ub_revision = USBREV_3_0; | |
475 | break; | 475 | break; | |
476 | case PCI_USBREV_3_1: | 476 | case PCI_USBREV_3_1: | |
477 | sc->sc_bus.ub_revision = USBREV_3_1; | 477 | sc->sc_bus.ub_revision = USBREV_3_1; | |
478 | break; | 478 | break; | |
479 | default: | 479 | default: | |
480 | if (val < PCI_USBREV_3_0) { | 480 | if (val < PCI_USBREV_3_0) { | |
481 | aprint_error_dev(self, "Unknown revision (%02x)\n", val); | 481 | aprint_error_dev(self, "Unknown revision (%02x)\n", val); | |
482 | sc->sc_bus.ub_revision = USBREV_UNKNOWN; | 482 | sc->sc_bus.ub_revision = USBREV_UNKNOWN; | |
483 | } else { | 483 | } else { | |
484 | /* Default to the latest revision */ | 484 | /* Default to the latest revision */ | |
485 | aprint_normal_dev(self, | 485 | aprint_normal_dev(self, | |
486 | "Unknown revision (%02x). Set to 3.1.\n", val); | 486 | "Unknown revision (%02x). Set to 3.1.\n", val); | |
487 | sc->sc_bus.ub_revision = USBREV_3_1; | 487 | sc->sc_bus.ub_revision = USBREV_3_1; | |
488 | } | 488 | } | |
489 | break; | 489 | break; | |
490 | } | 490 | } | |
491 | 491 | |||
492 | error = xhci_init(sc); | 492 | error = xhci_init(sc); | |
493 | if (error) { | 493 | if (error) { | |
494 | aprint_error_dev(self, "init failed, error=%d\n", error); | 494 | aprint_error_dev(self, "init failed, error=%d\n", error); | |
495 | return; | 495 | return; | |
496 | } | 496 | } | |
497 | 497 | |||
498 | sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint); | 498 | sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint); | |
499 | 499 | |||
500 | sc->sc_child2 = config_found(self, &sc->sc_bus2, usbctlprint); | 500 | sc->sc_child2 = config_found(self, &sc->sc_bus2, usbctlprint); | |
501 | 501 | |||
502 | xhci_start(sc); | 502 | xhci_start(sc); | |
503 | 503 | |||
504 | error = xusb_mailbox_send(psc, 0x01000000); | 504 | error = xusb_mailbox_send(psc, 0x01000000); | |
505 | if (error) { | 505 | if (error) { | |
506 | aprint_error_dev(self, "send failed, error=%d\n", error); | 506 | aprint_error_dev(self, "send failed, error=%d\n", error); | |
507 | } | 507 | } | |
508 | } | 508 | } | |
509 | 509 | |||
510 | static int | 510 | static int | |
511 | tegra_xusb_intr_mbox(void *v) | 511 | tegra_xusb_intr_mbox(void *v) | |
512 | { | 512 | { | |
513 | struct tegra_xusb_softc * const psc = v; | 513 | struct tegra_xusb_softc * const psc = v; | |
514 | struct xhci_softc * const sc = &psc->sc_xhci; | 514 | struct xhci_softc * const sc = &psc->sc_xhci; | |
515 | const bus_space_tag_t bst = sc->sc_iot; | 515 | const bus_space_tag_t bst = sc->sc_iot; | |
516 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | 516 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | |
517 | uint32_t val; | 517 | uint32_t val; | |
518 | uint32_t irv; | 518 | uint32_t irv; | |
519 | uint32_t msg; | 519 | uint32_t msg; | |
520 | int error; | 520 | int error; | |
521 | 521 | |||
522 | DPRINTF(sc->sc_dev, "%s()\n", __func__); | 522 | DPRINTF(sc->sc_dev, "%s()\n", __func__); | |
523 | 523 | |||
524 | irv = bus_space_read_4(bst, fpcih, T_XUSB_CFG_ARU_SMI_INTR_REG); | 524 | irv = bus_space_read_4(bst, fpcih, T_XUSB_CFG_ARU_SMI_INTR_REG); | |
525 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_SMI_INTR 0x%x\n", irv); | 525 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_SMI_INTR 0x%x\n", irv); | |
526 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_SMI_INTR_REG, irv); | 526 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_SMI_INTR_REG, irv); | |
527 | 527 | |||
528 | if (irv & T_XUSB_CFG_ARU_SMI_INTR_FW_HANG) | 528 | if (irv & T_XUSB_CFG_ARU_SMI_INTR_FW_HANG) | |
529 | aprint_error_dev(sc->sc_dev, "firmware hang\n"); | 529 | aprint_error_dev(sc->sc_dev, "firmware hang\n"); | |
530 | 530 | |||
531 | msg = bus_space_read_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_DATA_OUT_REG); | 531 | msg = bus_space_read_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_DATA_OUT_REG); | |
532 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_DATA_OUT 0x%x\n", msg); | 532 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_DATA_OUT 0x%x\n", msg); | |
533 | 533 | |||
534 | val = bus_space_read_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_CMD_REG); | 534 | val = bus_space_read_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_CMD_REG); | |
535 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_CMD 0x%x\n", val); | 535 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_CMD 0x%x\n", val); | |
536 | val &= ~T_XUSB_CFG_ARU_MAILBOX_CMD_DEST_SMI; | 536 | val &= ~T_XUSB_CFG_ARU_MAILBOX_CMD_DEST_SMI; | |
537 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_CMD_REG, val); | 537 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_CMD_REG, val); | |
538 | 538 | |||
539 | bool sendresp = true; | 539 | bool sendresp = true; | |
540 | u_int rate; | 540 | u_int rate; | |
541 | 541 | |||
542 | const uint32_t data = __SHIFTOUT(msg, MAILBOX_DATA_DATA); | 542 | const uint32_t data = __SHIFTOUT(msg, MAILBOX_DATA_DATA); | |
543 | const uint8_t type = __SHIFTOUT(msg, MAILBOX_DATA_TYPE); | 543 | const uint8_t type = __SHIFTOUT(msg, MAILBOX_DATA_TYPE); | |
544 | 544 | |||
545 | switch (type) { | 545 | switch (type) { | |
546 | case 2: | 546 | case 2: | |
547 | case 3: | 547 | case 3: | |
548 | DPRINTF(sc->sc_dev, "FALC_CLOCK %u\n", data * 1000); | 548 | DPRINTF(sc->sc_dev, "FALC_CLOCK %u\n", data * 1000); | |
549 | break; | 549 | break; | |
550 | case 4: | 550 | case 4: | |
551 | case 5: | 551 | case 5: | |
552 | if (psc->sc_txd->txd_scale_ss_clock) { | 552 | if (psc->sc_txd->txd_scale_ss_clock) { | |
553 | DPRINTF(sc->sc_dev, "SSPI_CLOCK %u\n", data * 1000); | 553 | DPRINTF(sc->sc_dev, "SSPI_CLOCK %u\n", data * 1000); | |
554 | rate = clk_get_rate(psc->sc_clk_ss_src); | 554 | rate = clk_get_rate(psc->sc_clk_ss_src); | |
555 | DPRINTF(sc->sc_dev, "rate of psc->sc_clk_ss_src %u\n", | 555 | DPRINTF(sc->sc_dev, "rate of psc->sc_clk_ss_src %u\n", | |
556 | rate); | 556 | rate); | |
557 | error = clk_set_rate(psc->sc_clk_ss_src, data * 1000); | 557 | error = clk_set_rate(psc->sc_clk_ss_src, data * 1000); | |
558 | if (error != 0) | 558 | if (error != 0) | |
559 | goto clk_fail; | 559 | goto clk_fail; | |
560 | rate = clk_get_rate(psc->sc_clk_ss_src); | 560 | rate = clk_get_rate(psc->sc_clk_ss_src); | |
561 | DPRINTF(sc->sc_dev, | 561 | DPRINTF(sc->sc_dev, | |
562 | "rate of psc->sc_clk_ss_src %u after\n", rate); | 562 | "rate of psc->sc_clk_ss_src %u after\n", rate); | |
563 | if (data == (rate / 1000)) { | 563 | if (data == (rate / 1000)) { | |
564 | msg = __SHIFTIN(128, MAILBOX_DATA_TYPE) | | 564 | msg = __SHIFTIN(128, MAILBOX_DATA_TYPE) | | |
565 | __SHIFTIN(rate / 1000, MAILBOX_DATA_DATA); | 565 | __SHIFTIN(rate / 1000, MAILBOX_DATA_DATA); | |
566 | } else | 566 | } else | |
567 | clk_fail: | 567 | clk_fail: | |
568 | msg = __SHIFTIN(129, MAILBOX_DATA_TYPE) | | 568 | msg = __SHIFTIN(129, MAILBOX_DATA_TYPE) | | |
569 | __SHIFTIN(rate / 1000, MAILBOX_DATA_DATA); | 569 | __SHIFTIN(rate / 1000, MAILBOX_DATA_DATA); | |
570 | } else { | 570 | } else { | |
571 | msg = __SHIFTIN(128, MAILBOX_DATA_TYPE) | | 571 | msg = __SHIFTIN(128, MAILBOX_DATA_TYPE) | | |
572 | __SHIFTIN(data, MAILBOX_DATA_DATA); | 572 | __SHIFTIN(data, MAILBOX_DATA_DATA); | |
573 | } | 573 | } | |
574 | xusb_mailbox_send(psc, msg); | 574 | xusb_mailbox_send(psc, msg); | |
575 | break; | 575 | break; | |
576 | case 9: | 576 | case 9: | |
577 | msg = __SHIFTIN(data, MAILBOX_DATA_DATA) | | 577 | msg = __SHIFTIN(data, MAILBOX_DATA_DATA) | | |
578 | __SHIFTIN(128, MAILBOX_DATA_TYPE); | 578 | __SHIFTIN(128, MAILBOX_DATA_TYPE); | |
579 | xusb_mailbox_send(psc, msg); | 579 | xusb_mailbox_send(psc, msg); | |
580 | break; | 580 | break; | |
581 | case 6: | 581 | case 6: | |
582 | case 128: | 582 | case 128: | |
583 | case 129: | 583 | case 129: | |
584 | sendresp = false; | 584 | sendresp = false; | |
585 | break; | 585 | break; | |
586 | default: | 586 | default: | |
587 | sendresp = false; | 587 | sendresp = false; | |
588 | break; | 588 | break; | |
589 | } | 589 | } | |
590 | 590 | |||
591 | if (sendresp == false) | 591 | if (sendresp == false) | |
592 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_OWNER_REG, | 592 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_OWNER_REG, | |
593 | MAILBOX_OWNER_NONE); | 593 | MAILBOX_OWNER_NONE); | |
594 | 594 | |||
595 | return irv; | 595 | return irv; | |
596 | } | 596 | } | |
597 | 597 | |||
598 | static void | 598 | static void | |
599 | tegra_xusb_init_regulators(struct tegra_xusb_softc * const psc) | 599 | tegra_xusb_init_regulators(struct tegra_xusb_softc * const psc) | |
600 | { | 600 | { | |
601 | 601 | |||
602 | device_t dev = psc->sc_xhci.sc_dev; | 602 | device_t dev = psc->sc_xhci.sc_dev; | |
603 | const int phandle = psc->sc_phandle; | 603 | const int phandle = psc->sc_phandle; | |
604 | struct fdtbus_regulator *reg; | 604 | struct fdtbus_regulator *reg; | |
605 | int n, error; | 605 | int n, error; | |
606 | 606 | |||
607 | for (n = 0; n < psc->sc_txd->txd_nsupplies; n++) { | 607 | for (n = 0; n < psc->sc_txd->txd_nsupplies; n++) { | |
608 | if (!of_hasprop(phandle, psc->sc_txd->txd_supplies[n])) | 608 | if (!of_hasprop(phandle, psc->sc_txd->txd_supplies[n])) | |
609 | continue; | 609 | continue; | |
610 | reg = fdtbus_regulator_acquire(phandle, psc->sc_txd->txd_supplies[n]); | 610 | reg = fdtbus_regulator_acquire(phandle, psc->sc_txd->txd_supplies[n]); | |
611 | if (reg == NULL) { | 611 | if (reg == NULL) { | |
612 | aprint_error_dev(dev, "couldn't acquire supply '%s'\n", | 612 | aprint_error_dev(dev, "couldn't acquire supply '%s'\n", | |
613 | psc->sc_txd->txd_supplies[n]); | 613 | psc->sc_txd->txd_supplies[n]); | |
614 | continue; | 614 | continue; | |
615 | } | 615 | } | |
616 | error = fdtbus_regulator_enable(reg); | 616 | error = fdtbus_regulator_enable(reg); | |
617 | if (error != 0) | 617 | if (error != 0) | |
618 | aprint_error_dev(dev, "couldn't enable supply '%s': %d\n", | 618 | aprint_error_dev(dev, "couldn't enable supply '%s': %d\n", | |
619 | psc->sc_txd->txd_supplies[n], error); | 619 | psc->sc_txd->txd_supplies[n], error); | |
620 | } | 620 | } | |
621 | } | 621 | } | |
622 | 622 | |||
623 | static void | 623 | static void | |
624 | tegra_xusb_init(struct tegra_xusb_softc * const psc) | 624 | tegra_xusb_init(struct tegra_xusb_softc * const psc) | |
625 | { | 625 | { | |
626 | struct xhci_softc * const sc = &psc->sc_xhci; | 626 | struct xhci_softc * const sc = &psc->sc_xhci; | |
627 | const bus_space_tag_t bst = sc->sc_iot; | 627 | const bus_space_tag_t bst = sc->sc_iot; | |
628 | const bus_space_handle_t ipfsh = psc->sc_bsh_ipfs; | 628 | const bus_space_handle_t ipfsh = psc->sc_bsh_ipfs; | |
629 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | 629 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | |
630 | 630 | |||
631 | DPRINTF(sc->sc_dev, "%s()\n", __func__); | 631 | DPRINTF(sc->sc_dev, "%s()\n", __func__); | |
632 | 632 | |||
633 | DPRINTF(sc->sc_dev, "%s ipfs 0x0 = 0x%x\n", __func__, | 633 | DPRINTF(sc->sc_dev, "%s ipfs 0x0 = 0x%x\n", __func__, | |
634 | bus_space_read_4(bst, ipfsh, 0x0)); | 634 | bus_space_read_4(bst, ipfsh, 0x0)); | |
635 | 635 | |||
636 | DPRINTF(sc->sc_dev, "%s ipfs 0x40 = 0x%x\n", __func__, | 636 | DPRINTF(sc->sc_dev, "%s ipfs 0x40 = 0x%x\n", __func__, | |
637 | bus_space_read_4(bst, ipfsh, 0x40)); | 637 | bus_space_read_4(bst, ipfsh, 0x40)); | |
638 | 638 | |||
639 | DPRINTF(sc->sc_dev, "%s ipfs 0x80 = 0x%x\n", __func__, | 639 | DPRINTF(sc->sc_dev, "%s ipfs 0x80 = 0x%x\n", __func__, | |
640 | bus_space_read_4(bst, ipfsh, 0x80)); | 640 | bus_space_read_4(bst, ipfsh, 0x80)); | |
641 | /* FPCI_BAR0_START and FPCI_BAR0_ACCESS_TYPE */ | 641 | /* FPCI_BAR0_START and FPCI_BAR0_ACCESS_TYPE */ | |
642 | bus_space_write_4(bst, ipfsh, 0x80, 0x00100000); | 642 | bus_space_write_4(bst, ipfsh, 0x80, 0x00100000); | |
643 | DPRINTF(sc->sc_dev, "%s ipfs 0x80 = 0x%x\n", __func__, | 643 | DPRINTF(sc->sc_dev, "%s ipfs 0x80 = 0x%x\n", __func__, | |
644 | bus_space_read_4(bst, ipfsh, 0x80)); | 644 | bus_space_read_4(bst, ipfsh, 0x80)); | |
645 | 645 | |||
646 | DPRINTF(sc->sc_dev, "%s ipfs 0x180 = 0x%x\n", __func__, | 646 | DPRINTF(sc->sc_dev, "%s ipfs 0x180 = 0x%x\n", __func__, | |
647 | bus_space_read_4(bst, ipfsh, 0x180)); | 647 | bus_space_read_4(bst, ipfsh, 0x180)); | |
648 | /* EN_FPCI */ | 648 | /* EN_FPCI */ | |
649 | tegra_reg_set_clear(bst, ipfsh, 0x180, 1, 0); | 649 | tegra_reg_set_clear(bst, ipfsh, 0x180, 1, 0); | |
650 | DPRINTF(sc->sc_dev, "%s ipfs 0x180 = 0x%x\n", __func__, | 650 | DPRINTF(sc->sc_dev, "%s ipfs 0x180 = 0x%x\n", __func__, | |
651 | bus_space_read_4(bst, ipfsh, 0x180)); | 651 | bus_space_read_4(bst, ipfsh, 0x180)); | |
652 | 652 | |||
653 | DPRINTF(sc->sc_dev, "%s fpci PCI_COMMAND_STATUS_REG = 0x%x\n", | 653 | DPRINTF(sc->sc_dev, "%s fpci PCI_COMMAND_STATUS_REG = 0x%x\n", | |
654 | __func__, bus_space_read_4(bst, fpcih, PCI_COMMAND_STATUS_REG)); | 654 | __func__, bus_space_read_4(bst, fpcih, PCI_COMMAND_STATUS_REG)); | |
655 | tegra_reg_set_clear(bst, fpcih, PCI_COMMAND_STATUS_REG, | 655 | tegra_reg_set_clear(bst, fpcih, PCI_COMMAND_STATUS_REG, | |
656 | PCI_COMMAND_MASTER_ENABLE|PCI_COMMAND_MEM_ENABLE, 0x0); | 656 | PCI_COMMAND_MASTER_ENABLE|PCI_COMMAND_MEM_ENABLE, 0x0); | |
657 | DPRINTF(sc->sc_dev, "%s fpci PCI_COMMAND_STATUS_REG = 0x%x\n", | 657 | DPRINTF(sc->sc_dev, "%s fpci PCI_COMMAND_STATUS_REG = 0x%x\n", | |
658 | __func__, bus_space_read_4(bst, fpcih, PCI_COMMAND_STATUS_REG)); | 658 | __func__, bus_space_read_4(bst, fpcih, PCI_COMMAND_STATUS_REG)); | |
659 | 659 | |||
660 | DPRINTF(sc->sc_dev, "%s fpci PCI_BAR0 = 0x%x\n", __func__, | 660 | DPRINTF(sc->sc_dev, "%s fpci PCI_BAR0 = 0x%x\n", __func__, | |
661 | bus_space_read_4(bst, fpcih, PCI_BAR0)); | 661 | bus_space_read_4(bst, fpcih, PCI_BAR0)); | |
662 | /* match FPCI BAR0 to above */ | 662 | /* match FPCI BAR0 to above */ | |
663 | bus_space_write_4(bst, fpcih, PCI_BAR0, 0x10000000); | 663 | bus_space_write_4(bst, fpcih, PCI_BAR0, 0x10000000); | |
664 | DPRINTF(sc->sc_dev, "%s fpci PCI_BAR0 = 0x%x\n", __func__, | 664 | DPRINTF(sc->sc_dev, "%s fpci PCI_BAR0 = 0x%x\n", __func__, | |
665 | bus_space_read_4(bst, fpcih, PCI_BAR0)); | 665 | bus_space_read_4(bst, fpcih, PCI_BAR0)); | |
666 | 666 | |||
667 | DPRINTF(sc->sc_dev, "%s ipfs 0x188 = 0x%x\n", __func__, | 667 | DPRINTF(sc->sc_dev, "%s ipfs 0x188 = 0x%x\n", __func__, | |
668 | bus_space_read_4(bst, ipfsh, 0x188)); | 668 | bus_space_read_4(bst, ipfsh, 0x188)); | |
669 | tegra_reg_set_clear(bst, ipfsh, 0x188, __BIT(16), 0); | 669 | tegra_reg_set_clear(bst, ipfsh, 0x188, __BIT(16), 0); | |
670 | DPRINTF(sc->sc_dev, "%s ipfs 0x188 = 0x%x\n", __func__, | 670 | DPRINTF(sc->sc_dev, "%s ipfs 0x188 = 0x%x\n", __func__, | |
671 | bus_space_read_4(bst, ipfsh, 0x188)); | 671 | bus_space_read_4(bst, ipfsh, 0x188)); | |
672 | 672 | |||
673 | DPRINTF(sc->sc_dev, "%s fpci 0x1bc = 0x%x\n", __func__, | 673 | DPRINTF(sc->sc_dev, "%s fpci 0x1bc = 0x%x\n", __func__, | |
674 | bus_space_read_4(bst, fpcih, 0x1bc)); | 674 | bus_space_read_4(bst, fpcih, 0x1bc)); | |
675 | bus_space_write_4(bst, fpcih, 0x1bc, 0x80); | 675 | bus_space_write_4(bst, fpcih, 0x1bc, 0x80); | |
676 | DPRINTF(sc->sc_dev, "%s fpci 0x1bc = 0x%x\n", __func__, | 676 | DPRINTF(sc->sc_dev, "%s fpci 0x1bc = 0x%x\n", __func__, | |
677 | bus_space_read_4(bst, fpcih, 0x1bc)); | 677 | bus_space_read_4(bst, fpcih, 0x1bc)); | |
678 | } | 678 | } | |
679 | 679 | |||
680 | static int | 680 | static int | |
681 | fw_dma_alloc(struct tegra_xusb_softc * const psc, size_t size, size_t align, | 681 | fw_dma_alloc(struct tegra_xusb_softc * const psc, size_t size, size_t align, | |
682 | struct fw_dma * const p) | 682 | struct fw_dma * const p) | |
683 | { | 683 | { | |
684 | struct xhci_softc * const sc = &psc->sc_xhci; | 684 | struct xhci_softc * const sc = &psc->sc_xhci; | |
685 | const bus_dma_tag_t dmat = sc->sc_bus.ub_dmatag; | 685 | const bus_dma_tag_t dmat = sc->sc_bus.ub_dmatag; | |
686 | int err; | 686 | int err; | |
687 | 687 | |||
688 | p->size = size; | 688 | p->size = size; | |
689 | err = bus_dmamem_alloc(dmat, p->size, align, 0, p->segs, | 689 | err = bus_dmamem_alloc(dmat, p->size, align, 0, p->segs, | |
690 | sizeof(p->segs) / sizeof(p->segs[0]), &p->nsegs, BUS_DMA_NOWAIT); | 690 | sizeof(p->segs) / sizeof(p->segs[0]), &p->nsegs, BUS_DMA_NOWAIT); | |
691 | if (err) | 691 | if (err) | |
692 | return err; | 692 | return err; | |
693 | err = bus_dmamem_map(dmat, p->segs, p->nsegs, p->size, &p->addr, | 693 | err = bus_dmamem_map(dmat, p->segs, p->nsegs, p->size, &p->addr, | |
694 | BUS_DMA_NOWAIT|BUS_DMA_COHERENT); | 694 | BUS_DMA_NOWAIT|BUS_DMA_COHERENT); | |
695 | if (err) | 695 | if (err) | |
696 | goto free; | 696 | goto free; | |
697 | err = bus_dmamap_create(dmat, p->size, 1, p->size, 0, BUS_DMA_NOWAIT, | 697 | err = bus_dmamap_create(dmat, p->size, 1, p->size, 0, BUS_DMA_NOWAIT, | |
698 | &p->map); | 698 | &p->map); | |
699 | if (err) | 699 | if (err) | |
700 | goto unmap; | 700 | goto unmap; | |
701 | err = bus_dmamap_load(dmat, p->map, p->addr, p->size, NULL, | 701 | err = bus_dmamap_load(dmat, p->map, p->addr, p->size, NULL, | |
702 | BUS_DMA_NOWAIT); | 702 | BUS_DMA_NOWAIT); | |
703 | if (err) | 703 | if (err) | |
704 | goto destroy; | 704 | goto destroy; | |
705 | 705 | |||
706 | return 0; | 706 | return 0; | |
707 | 707 | |||
708 | destroy: | 708 | destroy: | |
709 | bus_dmamap_destroy(dmat, p->map); | 709 | bus_dmamap_destroy(dmat, p->map); | |
710 | unmap: | 710 | unmap: | |
711 | bus_dmamem_unmap(dmat, p->addr, p->size); | 711 | bus_dmamem_unmap(dmat, p->addr, p->size); | |
712 | free: | 712 | free: | |
713 | bus_dmamem_free(dmat, p->segs, p->nsegs); | 713 | bus_dmamem_free(dmat, p->segs, p->nsegs); | |
714 | 714 | |||
715 | return err; | 715 | return err; | |
716 | } | 716 | } | |
717 | 717 | |||
718 | static void | 718 | static void | |
719 | fw_dma_free(struct tegra_xusb_softc * const psc, struct fw_dma * const p) | 719 | fw_dma_free(struct tegra_xusb_softc * const psc, struct fw_dma * const p) | |
720 | { | 720 | { | |
721 | const struct xhci_softc * const sc = &psc->sc_xhci; | 721 | const struct xhci_softc * const sc = &psc->sc_xhci; | |
722 | const bus_dma_tag_t dmat = sc->sc_bus.ub_dmatag; | 722 | const bus_dma_tag_t dmat = sc->sc_bus.ub_dmatag; | |
723 | 723 | |||
724 | bus_dmamap_unload(dmat, p->map); | 724 | bus_dmamap_unload(dmat, p->map); | |
725 | bus_dmamap_destroy(dmat, p->map); | 725 | bus_dmamap_destroy(dmat, p->map); | |
726 | bus_dmamem_unmap(dmat, p->addr, p->size); | 726 | bus_dmamem_unmap(dmat, p->addr, p->size); | |
727 | bus_dmamem_free(dmat, p->segs, p->nsegs); | 727 | bus_dmamem_free(dmat, p->segs, p->nsegs); | |
728 | } | 728 | } | |
729 | 729 | |||
730 | #define FWHEADER_BOOT_CODETAG 8 | 730 | #define FWHEADER_BOOT_CODETAG 8 | |
731 | #define FWHEADER_BOOT_CODESIZE 12 | 731 | #define FWHEADER_BOOT_CODESIZE 12 | |
732 | #define FWHEADER_FWIMG_LEN 100 | 732 | #define FWHEADER_FWIMG_LEN 100 | |
733 | #define FWHEADER__LEN 256 | 733 | #define FWHEADER__LEN 256 | |
734 | 734 | |||
735 | static int | 735 | static int | |
736 | tegra_xusb_open_fw(struct tegra_xusb_softc * const psc) | 736 | tegra_xusb_open_fw(struct tegra_xusb_softc * const psc) | |
737 | { | 737 | { | |
738 | struct xhci_softc * const sc = &psc->sc_xhci; | 738 | struct xhci_softc * const sc = &psc->sc_xhci; | |
739 | firmware_handle_t fw; | 739 | firmware_handle_t fw; | |
740 | size_t firmware_size = 0; | 740 | size_t firmware_size = 0; | |
741 | void *firmware_image; | 741 | void *firmware_image; | |
742 | const char *fw_path = NULL; | 742 | const char *fw_path = NULL; | |
743 | void *fw_static = NULL; | 743 | void *fw_static = NULL; | |
744 | int error; | 744 | int error; | |
745 | 745 | |||
746 | switch (psc->sc_txd->txd_type) { | 746 | switch (psc->sc_txd->txd_type) { | |
747 | case XUSB_T124: | 747 | case XUSB_T124: | |
748 | #if defined(TEGRA124_XUSB_BIN_STATIC) | 748 | #if defined(TEGRA124_XUSB_BIN_STATIC) | |
749 | firmware_size = (uintptr_t)&_binary_tegra124_xusb_bin_end | 749 | firmware_size = (uintptr_t)&_binary_tegra124_xusb_bin_end | |
750 | - (uintptr_t)&_binary_tegra124_xusb_bin_start; | 750 | - (uintptr_t)&_binary_tegra124_xusb_bin_start; | |
751 | fw_static = __UNCONST(_binary_tegra124_xusb_bin_start); | 751 | fw_static = __UNCONST(_binary_tegra124_xusb_bin_start); | |
752 | #else | 752 | #else | |
753 | fw_path = "nvidia/tegra124"; | 753 | fw_path = "nvidia/tegra124"; | |
754 | #endif | 754 | #endif | |
755 | break; | 755 | break; | |
756 | case XUSB_T210: | 756 | case XUSB_T210: | |
757 | #if defined(TEGRA210_XUSB_BIN_STATIC) | 757 | #if defined(TEGRA210_XUSB_BIN_STATIC) | |
758 | firmware_size = (uintptr_t)&_binary_tegra210_xusb_bin_end | 758 | firmware_size = (uintptr_t)&_binary_tegra210_xusb_bin_end | |
759 | - (uintptr_t)&_binary_tegra210_xusb_bin_start; | 759 | - (uintptr_t)&_binary_tegra210_xusb_bin_start; | |
760 | fw_static = __UNCONST(_binary_tegra210_xusb_bin_start); | 760 | fw_static = __UNCONST(_binary_tegra210_xusb_bin_start); | |
761 | #else | 761 | #else | |
762 | fw_path = "nvidia/tegra210"; | 762 | fw_path = "nvidia/tegra210"; | |
763 | #endif | 763 | #endif | |
764 | break; | 764 | break; | |
765 | default: | 765 | default: | |
766 | return EINVAL; | 766 | return EINVAL; | |
767 | } | 767 | } | |
768 | 768 | |||
769 | if (fw_path != NULL) { | 769 | if (fw_path != NULL) { | |
770 | error = firmware_open(fw_path, "xusb.bin", &fw); | 770 | error = firmware_open(fw_path, "xusb.bin", &fw); | |
771 | if (error != 0) { | 771 | if (error != 0) { | |
772 | aprint_error_dev(sc->sc_dev, | 772 | aprint_error_dev(sc->sc_dev, | |
773 | "couldn't load firmware from %s/xusb.bin: %d\n", | 773 | "couldn't load firmware from %s/xusb.bin: %d\n", | |
774 | fw_path, error); | 774 | fw_path, error); | |
775 | return error; | 775 | return error; | |
776 | } | 776 | } | |
777 | firmware_size = firmware_get_size(fw); | 777 | firmware_size = firmware_get_size(fw); | |
778 | } | 778 | } | |
779 | 779 | |||
780 | error = fw_dma_alloc(psc, firmware_size, PAGE_SIZE, | 780 | error = fw_dma_alloc(psc, firmware_size, PAGE_SIZE, | |
781 | &psc->sc_fw_dma); | 781 | &psc->sc_fw_dma); | |
782 | if (error != 0) | 782 | if (error != 0) | |
783 | return error; | 783 | return error; | |
784 | firmware_image = psc->sc_fw_dma.addr; | 784 | firmware_image = psc->sc_fw_dma.addr; | |
785 | 785 | |||
786 | if (fw_path != NULL) { | 786 | if (fw_path != NULL) { | |
787 | error = firmware_read(fw, 0, firmware_image, firmware_size); | 787 | error = firmware_read(fw, 0, firmware_image, firmware_size); | |
788 | if (error != 0) { | 788 | if (error != 0) { | |
789 | fw_dma_free(psc, &psc->sc_fw_dma); | 789 | fw_dma_free(psc, &psc->sc_fw_dma); | |
790 | firmware_close(fw); | 790 | firmware_close(fw); | |
791 | return error; | 791 | return error; | |
792 | } | 792 | } | |
793 | firmware_close(fw); | 793 | firmware_close(fw); | |
794 | } else { | 794 | } else { | |
795 | memcpy(firmware_image, fw_static, firmware_size); | 795 | memcpy(firmware_image, fw_static, firmware_size); | |
796 | } | 796 | } | |
797 | 797 | |||
798 | return tegra_xusb_load_fw(psc, firmware_image, firmware_size); | 798 | return tegra_xusb_load_fw(psc, firmware_image, firmware_size); | |
799 | } | 799 | } | |
800 | 800 | |||
801 | static int | 801 | static int | |
802 | tegra_xusb_load_fw(struct tegra_xusb_softc * const psc, void *firmware_image, | 802 | tegra_xusb_load_fw(struct tegra_xusb_softc * const psc, void *firmware_image, | |
803 | size_t firmware_size) | 803 | size_t firmware_size) | |
804 | { | 804 | { | |
805 | struct xhci_softc * const sc = &psc->sc_xhci; | 805 | struct xhci_softc * const sc = &psc->sc_xhci; | |
806 | const uint8_t *header; | 806 | const uint8_t *header; | |
807 | 807 | |||
808 | header = firmware_image; | 808 | header = firmware_image; | |
809 | 809 | |||
810 | const uint32_t fwimg_len = le32dec(&header[FWHEADER_FWIMG_LEN]); | 810 | const uint32_t fwimg_len = le32dec(&header[FWHEADER_FWIMG_LEN]); | |
811 | const uint32_t boot_codetag = le32dec(&header[FWHEADER_BOOT_CODETAG]); | 811 | const uint32_t boot_codetag = le32dec(&header[FWHEADER_BOOT_CODETAG]); | |
812 | const uint32_t boot_codesize = le32dec(&header[FWHEADER_BOOT_CODESIZE]); | 812 | const uint32_t boot_codesize = le32dec(&header[FWHEADER_BOOT_CODESIZE]); | |
813 | 813 | |||
814 | if (fwimg_len != firmware_size) | 814 | if (fwimg_len != firmware_size) | |
815 | aprint_error_dev(sc->sc_dev, "fwimg_len mismatch %u != %zu\n", | 815 | aprint_error_dev(sc->sc_dev, "fwimg_len mismatch %u != %zu\n", | |
816 | fwimg_len, firmware_size); | 816 | fwimg_len, firmware_size); | |
817 | 817 | |||
818 | bus_dmamap_sync(sc->sc_bus.ub_dmatag, psc->sc_fw_dma.map, 0, | 818 | bus_dmamap_sync(sc->sc_bus.ub_dmatag, psc->sc_fw_dma.map, 0, | |
819 | firmware_size, BUS_DMASYNC_PREWRITE); | 819 | firmware_size, BUS_DMASYNC_PREWRITE); | |
820 | 820 | |||
821 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", | 821 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", | |
822 | csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG)); | 822 | csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG)); | |
823 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_BASE_LO 0x%x\n", | 823 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_BASE_LO 0x%x\n", | |
824 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO_REG)); | 824 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO_REG)); | |
825 | 825 | |||
826 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_ATTR 0x%x\n", | 826 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_ATTR 0x%x\n", | |
827 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_ATTR_REG)); | 827 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_ATTR_REG)); | |
828 | csb_write_4(psc, XUSB_CSB_MEMPOOL_ILOAD_ATTR_REG, | 828 | csb_write_4(psc, XUSB_CSB_MEMPOOL_ILOAD_ATTR_REG, | |
829 | fwimg_len); | 829 | fwimg_len); | |
830 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_ATTR 0x%x\n", | 830 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_ATTR 0x%x\n", | |
831 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_ATTR_REG)); | 831 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_ATTR_REG)); | |
832 | 832 | |||
833 | const uint64_t fwbase = psc->sc_fw_dma.map->dm_segs[0].ds_addr + | 833 | const uint64_t fwbase = psc->sc_fw_dma.map->dm_segs[0].ds_addr + | |
834 | FWHEADER__LEN; | 834 | FWHEADER__LEN; | |
835 | 835 | |||
836 | csb_write_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI_REG, fwbase >> 32); | 836 | csb_write_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI_REG, fwbase >> 32); | |
837 | csb_write_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO_REG, fwbase); | 837 | csb_write_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO_REG, fwbase); | |
838 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_BASE_LO 0x%x\n", | 838 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_BASE_LO 0x%x\n", | |
839 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO_REG)); | 839 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO_REG)); | |
840 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_BASE_HI 0x%x\n", | 840 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_ILOAD_BASE_HI 0x%x\n", | |
841 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI_REG)); | 841 | csb_read_4(psc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI_REG)); | |
842 | 842 | |||
843 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_APMAP 0x%x\n", | 843 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_APMAP 0x%x\n", | |
844 | csb_read_4(psc, XUSB_CSB_MEMPOOL_APMAP_REG)); | 844 | csb_read_4(psc, XUSB_CSB_MEMPOOL_APMAP_REG)); | |
845 | csb_write_4(psc, XUSB_CSB_MEMPOOL_APMAP_REG, | 845 | csb_write_4(psc, XUSB_CSB_MEMPOOL_APMAP_REG, | |
846 | XUSB_CSB_MEMPOOL_APMAP_BOOTPATH); | 846 | XUSB_CSB_MEMPOOL_APMAP_BOOTPATH); | |
847 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_APMAP 0x%x\n", | 847 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_APMAP 0x%x\n", | |
848 | csb_read_4(psc, XUSB_CSB_MEMPOOL_APMAP_REG)); | 848 | csb_read_4(psc, XUSB_CSB_MEMPOOL_APMAP_REG)); | |
849 | 849 | |||
850 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | 850 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | |
851 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | 851 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | |
852 | csb_write_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG, | 852 | csb_write_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG, | |
853 | __SHIFTIN(ACTION_L2IMEM_INVALIDATE_ALL, | 853 | __SHIFTIN(ACTION_L2IMEM_INVALIDATE_ALL, | |
854 | XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_ACTION)); | 854 | XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_ACTION)); | |
855 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | 855 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | |
856 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | 856 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | |
857 | 857 | |||
858 | const u_int code_tag_blocks = | 858 | const u_int code_tag_blocks = | |
859 | howmany(boot_codetag, IMEM_BLOCK_SIZE); | 859 | howmany(boot_codetag, IMEM_BLOCK_SIZE); | |
860 | const u_int code_size_blocks = | 860 | const u_int code_size_blocks = | |
861 | howmany(boot_codesize, IMEM_BLOCK_SIZE); | 861 | howmany(boot_codesize, IMEM_BLOCK_SIZE); | |
862 | const u_int code_blocks = code_tag_blocks + code_size_blocks; | 862 | const u_int code_blocks = code_tag_blocks + code_size_blocks; | |
863 | 863 | |||
864 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_SIZE 0x%x\n", | 864 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_SIZE 0x%x\n", | |
865 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_REG)); | 865 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_REG)); | |
866 | csb_write_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_REG, | 866 | csb_write_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_REG, | |
867 | __SHIFTIN(code_tag_blocks, | 867 | __SHIFTIN(code_tag_blocks, | |
868 | XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_SRC_OFFSET) | | 868 | XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_SRC_OFFSET) | | |
869 | __SHIFTIN(code_size_blocks, | 869 | __SHIFTIN(code_size_blocks, | |
870 | XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_SRC_COUNT)); | 870 | XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_SRC_COUNT)); | |
871 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_SIZE 0x%x\n", | 871 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_SIZE 0x%x\n", | |
872 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_REG)); | 872 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE_REG)); | |
873 | 873 | |||
874 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | 874 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | |
875 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | 875 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | |
876 | csb_write_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG, | 876 | csb_write_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG, | |
877 | __SHIFTIN(ACTION_L2IMEM_LOAD_LOCKED_RESULT, | 877 | __SHIFTIN(ACTION_L2IMEM_LOAD_LOCKED_RESULT, | |
878 | XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_ACTION)); | 878 | XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_ACTION)); | |
879 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | 879 | DPRINTF(sc->sc_dev, "XUSB_CSB_MP_L2IMEMOP_TRIG 0x%x\n", | |
880 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | 880 | csb_read_4(psc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG_REG)); | |
881 | 881 | |||
882 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLCTL 0x%x\n", | 882 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLCTL 0x%x\n", | |
883 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLCTL_REG)); | 883 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLCTL_REG)); | |
884 | csb_write_4(psc, XUSB_CSB_FALCON_IMFILLCTL_REG, code_size_blocks); | 884 | csb_write_4(psc, XUSB_CSB_FALCON_IMFILLCTL_REG, code_size_blocks); | |
885 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLCTL 0x%x\n", | 885 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLCTL 0x%x\n", | |
886 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLCTL_REG)); | 886 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLCTL_REG)); | |
887 | 887 | |||
888 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLRNG1 0x%x\n", | 888 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLRNG1 0x%x\n", | |
889 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLRNG1_REG)); | 889 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLRNG1_REG)); | |
890 | csb_write_4(psc, XUSB_CSB_FALCON_IMFILLRNG1_REG, | 890 | csb_write_4(psc, XUSB_CSB_FALCON_IMFILLRNG1_REG, | |
891 | __SHIFTIN(code_tag_blocks, XUSB_CSB_FALCON_IMFILLRNG1_TAG_LO) | | 891 | __SHIFTIN(code_tag_blocks, XUSB_CSB_FALCON_IMFILLRNG1_TAG_LO) | | |
892 | __SHIFTIN(code_blocks, XUSB_CSB_FALCON_IMFILLRNG1_TAG_HI)); | 892 | __SHIFTIN(code_blocks, XUSB_CSB_FALCON_IMFILLRNG1_TAG_HI)); | |
893 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLRNG1 0x%x\n", | 893 | DPRINTF(sc->sc_dev, "XUSB_FALC_IMFILLRNG1 0x%x\n", | |
894 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLRNG1_REG)); | 894 | csb_read_4(psc, XUSB_CSB_FALCON_IMFILLRNG1_REG)); | |
895 | 895 | |||
896 | DPRINTF(sc->sc_dev, "XUSB_FALC_DMACTL 0x%x\n", | 896 | DPRINTF(sc->sc_dev, "XUSB_FALC_DMACTL 0x%x\n", | |
897 | csb_read_4(psc, XUSB_CSB_FALCON_DMACTL_REG)); | 897 | csb_read_4(psc, XUSB_CSB_FALCON_DMACTL_REG)); | |
898 | csb_write_4(psc, XUSB_CSB_FALCON_DMACTL_REG, 0); | 898 | csb_write_4(psc, XUSB_CSB_FALCON_DMACTL_REG, 0); | |
899 | DPRINTF(sc->sc_dev, "XUSB_FALC_DMACTL 0x%x\n", | 899 | DPRINTF(sc->sc_dev, "XUSB_FALC_DMACTL 0x%x\n", | |
900 | csb_read_4(psc, XUSB_CSB_FALCON_DMACTL_REG)); | 900 | csb_read_4(psc, XUSB_CSB_FALCON_DMACTL_REG)); | |
901 | 901 | |||
902 | DPRINTF(sc->sc_dev, "XUSB_FALC_BOOTVEC 0x%x\n", | 902 | DPRINTF(sc->sc_dev, "XUSB_FALC_BOOTVEC 0x%x\n", | |
903 | csb_read_4(psc, XUSB_CSB_FALCON_BOOTVEC_REG)); | 903 | csb_read_4(psc, XUSB_CSB_FALCON_BOOTVEC_REG)); | |
904 | csb_write_4(psc, XUSB_CSB_FALCON_BOOTVEC_REG, | 904 | csb_write_4(psc, XUSB_CSB_FALCON_BOOTVEC_REG, | |
905 | boot_codetag); | 905 | boot_codetag); | |
906 | DPRINTF(sc->sc_dev, "XUSB_FALC_BOOTVEC 0x%x\n", | 906 | DPRINTF(sc->sc_dev, "XUSB_FALC_BOOTVEC 0x%x\n", | |
907 | csb_read_4(psc, XUSB_CSB_FALCON_BOOTVEC_REG)); | 907 | csb_read_4(psc, XUSB_CSB_FALCON_BOOTVEC_REG)); | |
908 | 908 | |||
909 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", | 909 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", | |
910 | csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG)); | 910 | csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG)); | |
911 | csb_write_4(psc, XUSB_CSB_FALCON_CPUCTL_REG, | 911 | csb_write_4(psc, XUSB_CSB_FALCON_CPUCTL_REG, | |
912 | XUSB_CSB_FALCON_CPUCTL_STARTCPU); | 912 | XUSB_CSB_FALCON_CPUCTL_STARTCPU); | |
913 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", | 913 | DPRINTF(sc->sc_dev, "XUSB_FALC_CPUCTL 0x%x\n", | |
914 | csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG)); | 914 | csb_read_4(psc, XUSB_CSB_FALCON_CPUCTL_REG)); | |
915 | 915 | |||
916 | return 0; | 916 | return 0; | |
917 | } | 917 | } | |
918 | 918 | |||
919 | static uint32_t | 919 | static uint32_t | |
920 | csb_read_4(struct tegra_xusb_softc * const psc, bus_size_t csb_offset) | 920 | csb_read_4(struct tegra_xusb_softc * const psc, bus_size_t csb_offset) | |
921 | { | 921 | { | |
922 | const uint32_t range = __SHIFTOUT(csb_offset, XUSB_CSB_RANGE); | 922 | const uint32_t range = __SHIFTOUT(csb_offset, XUSB_CSB_RANGE); | |
923 | const bus_size_t offset = __SHIFTOUT(csb_offset, XUSB_CSB_OFFSET); | 923 | const bus_size_t offset = __SHIFTOUT(csb_offset, XUSB_CSB_OFFSET); | |
924 | const bus_space_tag_t bst = psc->sc_xhci.sc_iot; | 924 | const bus_space_tag_t bst = psc->sc_xhci.sc_iot; | |
925 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | 925 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | |
926 | 926 | |||
927 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_C11_CSBRANGE_REG, range); | 927 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_C11_CSBRANGE_REG, range); | |
928 | return bus_space_read_4(bst, fpcih, T_XUSB_CFG_CSB_BASE_ADDR + offset); | 928 | return bus_space_read_4(bst, fpcih, T_XUSB_CFG_CSB_BASE_ADDR + offset); | |
929 | } | 929 | } | |
930 | 930 | |||
931 | static void | 931 | static void | |
932 | csb_write_4(struct tegra_xusb_softc * const psc, bus_size_t csb_offset, | 932 | csb_write_4(struct tegra_xusb_softc * const psc, bus_size_t csb_offset, | |
933 | uint32_t value) | 933 | uint32_t value) | |
934 | { | 934 | { | |
935 | const uint32_t range = __SHIFTOUT(csb_offset, XUSB_CSB_RANGE); | 935 | const uint32_t range = __SHIFTOUT(csb_offset, XUSB_CSB_RANGE); | |
936 | const bus_size_t offset = __SHIFTOUT(csb_offset, XUSB_CSB_OFFSET); | 936 | const bus_size_t offset = __SHIFTOUT(csb_offset, XUSB_CSB_OFFSET); | |
937 | const bus_space_tag_t bst = psc->sc_xhci.sc_iot; | 937 | const bus_space_tag_t bst = psc->sc_xhci.sc_iot; | |
938 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | 938 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | |
939 | 939 | |||
940 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_C11_CSBRANGE_REG, range); | 940 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_C11_CSBRANGE_REG, range); | |
941 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_CSB_BASE_ADDR + offset, value); | 941 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_CSB_BASE_ADDR + offset, value); | |
942 | } | 942 | } | |
943 | 943 | |||
944 | static int | 944 | static int | |
945 | xusb_mailbox_send(struct tegra_xusb_softc * const psc, uint32_t msg) | 945 | xusb_mailbox_send(struct tegra_xusb_softc * const psc, uint32_t msg) | |
946 | { | 946 | { | |
947 | struct xhci_softc * const sc = &psc->sc_xhci; | 947 | struct xhci_softc * const sc = &psc->sc_xhci; | |
948 | const bus_space_tag_t bst = psc->sc_xhci.sc_iot; | 948 | const bus_space_tag_t bst = psc->sc_xhci.sc_iot; | |
949 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | 949 | const bus_space_handle_t fpcih = psc->sc_bsh_fpci; | |
950 | uint32_t val; | 950 | uint32_t val; | |
951 | bool wait = false; | 951 | bool wait = false; | |
952 | 952 | |||
953 | const uint8_t type = __SHIFTOUT(msg, MAILBOX_DATA_TYPE); | 953 | const uint8_t type = __SHIFTOUT(msg, MAILBOX_DATA_TYPE); | |
954 | 954 | |||
955 | if (!(type == 128 || type == 129)) { | 955 | if (!(type == 128 || type == 129)) { | |
956 | val = bus_space_read_4(bst, fpcih, | 956 | val = bus_space_read_4(bst, fpcih, | |
957 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | 957 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | |
958 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", | 958 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", | |
959 | val); | 959 | val); | |
960 | if (val != MAILBOX_OWNER_NONE) { | 960 | if (val != MAILBOX_OWNER_NONE) { | |
961 | return EBUSY; | 961 | return EBUSY; | |
962 | } | 962 | } | |
963 | 963 | |||
964 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_OWNER_REG, | 964 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_OWNER_REG, | |
965 | MAILBOX_OWNER_SW); | 965 | MAILBOX_OWNER_SW); | |
966 | 966 | |||
967 | val = bus_space_read_4(bst, fpcih, | 967 | val = bus_space_read_4(bst, fpcih, | |
968 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | 968 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | |
969 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", | 969 | DPRINTF(sc->sc_dev, "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", | |
970 | val); | 970 | val); | |
971 | if (val != MAILBOX_OWNER_SW) { | 971 | if (val != MAILBOX_OWNER_SW) { | |
972 | return EBUSY; | 972 | return EBUSY; | |
973 | } | 973 | } | |
974 | 974 | |||
975 | wait = true; | 975 | wait = true; | |
976 | } | 976 | } | |
977 | 977 | |||
978 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_DATA_IN_REG, msg); | 978 | bus_space_write_4(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_DATA_IN_REG, msg); | |
979 | 979 | |||
980 | tegra_reg_set_clear(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_CMD_REG, | 980 | tegra_reg_set_clear(bst, fpcih, T_XUSB_CFG_ARU_MAILBOX_CMD_REG, | |
981 | T_XUSB_CFG_ARU_MAILBOX_CMD_INT_EN | | 981 | T_XUSB_CFG_ARU_MAILBOX_CMD_INT_EN | | |
982 | T_XUSB_CFG_ARU_MAILBOX_CMD_DEST_FALCON, 0); | 982 | T_XUSB_CFG_ARU_MAILBOX_CMD_DEST_FALCON, 0); | |
983 | 983 | |||
984 | if (wait) { | 984 | if (wait) { | |
985 | 985 | |||
986 | for (u_int i = 0; i < 2500; i++) { | 986 | for (u_int i = 0; i < 2500; i++) { | |
987 | val = bus_space_read_4(bst, fpcih, | 987 | val = bus_space_read_4(bst, fpcih, | |
988 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | 988 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | |
989 | DPRINTF(sc->sc_dev, | 989 | DPRINTF(sc->sc_dev, | |
990 | "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", val); | 990 | "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", val); | |
991 | if (val == MAILBOX_OWNER_NONE) { | 991 | if (val == MAILBOX_OWNER_NONE) { | |
992 | break; | 992 | break; | |
993 | } | 993 | } | |
994 | DELAY(10); | 994 | DELAY(10); | |
995 | } | 995 | } | |
996 | 996 | |||
997 | val = bus_space_read_4(bst, fpcih, | 997 | val = bus_space_read_4(bst, fpcih, | |
998 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | 998 | T_XUSB_CFG_ARU_MAILBOX_OWNER_REG); | |
999 | DPRINTF(sc->sc_dev, | 999 | DPRINTF(sc->sc_dev, | |
1000 | "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", val); | 1000 | "XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", val); | |
1001 | if (val != MAILBOX_OWNER_NONE) { | 1001 | if (val != MAILBOX_OWNER_NONE) { | |
1002 | aprint_error_dev(sc->sc_dev, | 1002 | aprint_error_dev(sc->sc_dev, | |
1003 | "timeout, XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", val); | 1003 | "timeout, XUSB_CFG_ARU_MBOX_OWNER 0x%x\n", val); | |
1004 | } | 1004 | } | |
1005 | } | 1005 | } | |
1006 | 1006 | |||
1007 | return 0; | 1007 | return 0; | |
1008 | } | 1008 | } |