| @@ -1,1429 +1,1429 @@ | | | @@ -1,1429 +1,1429 @@ |
1 | /* $NetBSD: tegra124_car.c,v 1.4 2016/08/17 19:08:18 jakllsch Exp $ */ | | 1 | /* $NetBSD: tegra124_car.c,v 1.5 2016/09/02 19:06:58 jakllsch 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: tegra124_car.c,v 1.4 2016/08/17 19:08:18 jakllsch Exp $"); | | 30 | __KERNEL_RCSID(0, "$NetBSD: tegra124_car.c,v 1.5 2016/09/02 19:06:58 jakllsch 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/rndpool.h> | | 38 | #include <sys/rndpool.h> |
39 | #include <sys/rndsource.h> | | 39 | #include <sys/rndsource.h> |
40 | #include <sys/atomic.h> | | 40 | #include <sys/atomic.h> |
41 | #include <sys/kmem.h> | | 41 | #include <sys/kmem.h> |
42 | | | 42 | |
43 | #include <dev/clk/clk_backend.h> | | 43 | #include <dev/clk/clk_backend.h> |
44 | | | 44 | |
45 | #include <arm/nvidia/tegra_reg.h> | | 45 | #include <arm/nvidia/tegra_reg.h> |
46 | #include <arm/nvidia/tegra124_carreg.h> | | 46 | #include <arm/nvidia/tegra124_carreg.h> |
47 | #include <arm/nvidia/tegra_clock.h> | | 47 | #include <arm/nvidia/tegra_clock.h> |
48 | #include <arm/nvidia/tegra_pmcreg.h> | | 48 | #include <arm/nvidia/tegra_pmcreg.h> |
49 | #include <arm/nvidia/tegra_var.h> | | 49 | #include <arm/nvidia/tegra_var.h> |
50 | | | 50 | |
51 | #include <dev/fdt/fdtvar.h> | | 51 | #include <dev/fdt/fdtvar.h> |
52 | | | 52 | |
53 | static int tegra124_car_match(device_t, cfdata_t, void *); | | 53 | static int tegra124_car_match(device_t, cfdata_t, void *); |
54 | static void tegra124_car_attach(device_t, device_t, void *); | | 54 | static void tegra124_car_attach(device_t, device_t, void *); |
55 | | | 55 | |
56 | static struct clk *tegra124_car_clock_decode(device_t, const void *, size_t); | | 56 | static struct clk *tegra124_car_clock_decode(device_t, const void *, size_t); |
57 | | | 57 | |
58 | static const struct fdtbus_clock_controller_func tegra124_car_fdtclock_funcs = { | | 58 | static const struct fdtbus_clock_controller_func tegra124_car_fdtclock_funcs = { |
59 | .decode = tegra124_car_clock_decode | | 59 | .decode = tegra124_car_clock_decode |
60 | }; | | 60 | }; |
61 | | | 61 | |
62 | /* DT clock ID to clock name mappings */ | | 62 | /* DT clock ID to clock name mappings */ |
63 | static struct tegra124_car_clock_id { | | 63 | static struct tegra124_car_clock_id { |
64 | u_int id; | | 64 | u_int id; |
65 | const char *name; | | 65 | const char *name; |
66 | } tegra124_car_clock_ids[] = { | | 66 | } tegra124_car_clock_ids[] = { |
67 | { 3, "ispb" }, | | 67 | { 3, "ispb" }, |
68 | { 4, "rtc" }, | | 68 | { 4, "rtc" }, |
69 | { 5, "timer" }, | | 69 | { 5, "timer" }, |
70 | { 6, "uarta" }, | | 70 | { 6, "uarta" }, |
71 | { 9, "sdmmc2" }, | | 71 | { 9, "sdmmc2" }, |
72 | { 11, "i2s1" }, | | 72 | { 11, "i2s1" }, |
73 | { 12, "i2c1" }, | | 73 | { 12, "i2c1" }, |
74 | { 14, "sdmmc1" }, | | 74 | { 14, "sdmmc1" }, |
75 | { 15, "sdmmc4" }, | | 75 | { 15, "sdmmc4" }, |
76 | { 17, "pwm" }, | | 76 | { 17, "pwm" }, |
77 | { 18, "i2s2" }, | | 77 | { 18, "i2s2" }, |
78 | { 22, "usbd" }, | | 78 | { 22, "usbd" }, |
79 | { 23, "isp" }, | | 79 | { 23, "isp" }, |
80 | { 26, "disp2" }, | | 80 | { 26, "disp2" }, |
81 | { 27, "disp1" }, | | 81 | { 27, "disp1" }, |
82 | { 28, "host1x" }, | | 82 | { 28, "host1x" }, |
83 | { 29, "vcp" }, | | 83 | { 29, "vcp" }, |
84 | { 30, "i2s0" }, | | 84 | { 30, "i2s0" }, |
85 | { 32, "mc" }, | | 85 | { 32, "mc" }, |
86 | { 34, "apbdma" }, | | 86 | { 34, "apbdma" }, |
87 | { 36, "kbc" }, | | 87 | { 36, "kbc" }, |
88 | { 40, "kfuse" }, | | 88 | { 40, "kfuse" }, |
89 | { 41, "spi1" }, | | 89 | { 41, "spi1" }, |
90 | { 42, "nor" }, | | 90 | { 42, "nor" }, |
91 | { 44, "spi2" }, | | 91 | { 44, "spi2" }, |
92 | { 46, "spi3" }, | | 92 | { 46, "spi3" }, |
93 | { 47, "i2c5" }, | | 93 | { 47, "i2c5" }, |
94 | { 48, "dsia" }, | | 94 | { 48, "dsia" }, |
95 | { 50, "mipi" }, | | 95 | { 50, "mipi" }, |
96 | { 51, "hdmi" }, | | 96 | { 51, "hdmi" }, |
97 | { 52, "csi" }, | | 97 | { 52, "csi" }, |
98 | { 54, "i2c2" }, | | 98 | { 54, "i2c2" }, |
99 | { 55, "uartc" }, | | 99 | { 55, "uartc" }, |
100 | { 56, "mipi_cal" }, | | 100 | { 56, "mipi_cal" }, |
101 | { 57, "emc" }, | | 101 | { 57, "emc" }, |
102 | { 58, "usb2" }, | | 102 | { 58, "usb2" }, |
103 | { 59, "usb3" }, | | 103 | { 59, "usb3" }, |
104 | { 61, "vde" }, | | 104 | { 61, "vde" }, |
105 | { 62, "bsea" }, | | 105 | { 62, "bsea" }, |
106 | { 63, "bsev" }, | | 106 | { 63, "bsev" }, |
107 | { 65, "uartd" }, | | 107 | { 65, "uartd" }, |
108 | { 67, "i2c3" }, | | 108 | { 67, "i2c3" }, |
109 | { 68, "spi4" }, | | 109 | { 68, "spi4" }, |
110 | { 69, "sdmmc3" }, | | 110 | { 69, "sdmmc3" }, |
111 | { 70, "pcie" }, | | 111 | { 70, "pcie" }, |
112 | { 71, "owr" }, | | 112 | { 71, "owr" }, |
113 | { 72, "afi" }, | | 113 | { 72, "afi" }, |
114 | { 73, "csite" }, | | 114 | { 73, "csite" }, |
115 | { 76, "la" }, | | 115 | { 76, "la" }, |
116 | { 77, "trace" }, | | 116 | { 77, "trace" }, |
117 | { 78, "soc_therm" }, | | 117 | { 78, "soc_therm" }, |
118 | { 79, "dtv" }, | | 118 | { 79, "dtv" }, |
119 | { 81, "i2cslow" }, | | 119 | { 81, "i2cslow" }, |
120 | { 82, "dsib" }, | | 120 | { 82, "dsib" }, |
121 | { 83, "tsec" }, | | 121 | { 83, "tsec" }, |
122 | { 89, "xusb_host" }, | | 122 | { 89, "xusb_host" }, |
123 | { 91, "msenc" }, | | 123 | { 91, "msenc" }, |
124 | { 92, "csus" }, | | 124 | { 92, "csus" }, |
125 | { 99, "mselect" }, | | 125 | { 99, "mselect" }, |
126 | { 100, "tsensor" }, | | 126 | { 100, "tsensor" }, |
127 | { 101, "i2s3" }, | | 127 | { 101, "i2s3" }, |
128 | { 102, "i2s4" }, | | 128 | { 102, "i2s4" }, |
129 | { 103, "i2c4" }, | | 129 | { 103, "i2c4" }, |
130 | { 104, "spi5" }, | | 130 | { 104, "spi5" }, |
131 | { 105, "spi6" }, | | 131 | { 105, "spi6" }, |
132 | { 106, "d_audio" }, | | 132 | { 106, "d_audio" }, |
133 | { 107, "apbif" }, | | 133 | { 107, "apbif" }, |
134 | { 108, "dam0" }, | | 134 | { 108, "dam0" }, |
135 | { 109, "dam1" }, | | 135 | { 109, "dam1" }, |
136 | { 110, "dam2" }, | | 136 | { 110, "dam2" }, |
137 | { 111, "hda2codec_2x" }, | | 137 | { 111, "hda2codec_2x" }, |
138 | { 113, "audio0_2x" }, | | 138 | { 113, "audio0_2x" }, |
139 | { 114, "audio1_2x" }, | | 139 | { 114, "audio1_2x" }, |
140 | { 115, "audio2_2x" }, | | 140 | { 115, "audio2_2x" }, |
141 | { 116, "audio3_2x" }, | | 141 | { 116, "audio3_2x" }, |
142 | { 117, "audio4_2x" }, | | 142 | { 117, "audio4_2x" }, |
143 | { 118, "spdif_2x" }, | | 143 | { 118, "spdif_2x" }, |
144 | { 119, "actmon" }, | | 144 | { 119, "actmon" }, |
145 | { 120, "extern1" }, | | 145 | { 120, "extern1" }, |
146 | { 121, "extern2" }, | | 146 | { 121, "extern2" }, |
147 | { 122, "extern3" }, | | 147 | { 122, "extern3" }, |
148 | { 123, "sata_oob" }, | | 148 | { 123, "sata_oob" }, |
149 | { 124, "sata" }, | | 149 | { 124, "sata" }, |
150 | { 125, "hda" }, | | 150 | { 125, "hda" }, |
151 | { 127, "se" }, | | 151 | { 127, "se" }, |
152 | { 128, "hda2hdmi" }, | | 152 | { 128, "hda2hdmi" }, |
153 | { 129, "sata_cold" }, | | 153 | { 129, "sata_cold" }, |
154 | { 144, "cilab" }, | | 154 | { 144, "cilab" }, |
155 | { 145, "cilcd" }, | | 155 | { 145, "cilcd" }, |
156 | { 146, "cile" }, | | 156 | { 146, "cile" }, |
157 | { 147, "dsialp" }, | | 157 | { 147, "dsialp" }, |
158 | { 148, "dsiblp" }, | | 158 | { 148, "dsiblp" }, |
159 | { 149, "entropy" }, | | 159 | { 149, "entropy" }, |
160 | { 150, "dds" }, | | 160 | { 150, "dds" }, |
161 | { 152, "dp2" }, | | 161 | { 152, "dp2" }, |
162 | { 153, "amx" }, | | 162 | { 153, "amx" }, |
163 | { 154, "adx" }, | | 163 | { 154, "adx" }, |
164 | { 156, "xusb_ss" }, | | 164 | { 156, "xusb_ss" }, |
165 | { 166, "i2c6" }, | | 165 | { 166, "i2c6" }, |
166 | { 171, "vim2_clk" }, | | 166 | { 171, "vim2_clk" }, |
167 | { 176, "hdmi_audio" }, | | 167 | { 176, "hdmi_audio" }, |
168 | { 177, "clk72mhz" }, | | 168 | { 177, "clk72mhz" }, |
169 | { 178, "vic03" }, | | 169 | { 178, "vic03" }, |
170 | { 180, "adx1" }, | | 170 | { 180, "adx1" }, |
171 | { 181, "dpaux" }, | | 171 | { 181, "dpaux" }, |
172 | { 182, "sor0" }, | | 172 | { 182, "sor0" }, |
173 | { 184, "gpu" }, | | 173 | { 184, "gpu" }, |
174 | { 185, "amx1" }, | | 174 | { 185, "amx1" }, |
175 | { 192, "uartb" }, | | 175 | { 192, "uartb" }, |
176 | { 193, "vfir" }, | | 176 | { 193, "vfir" }, |
177 | { 194, "spdif_in" }, | | 177 | { 194, "spdif_in" }, |
178 | { 195, "spdif_out" }, | | 178 | { 195, "spdif_out" }, |
179 | { 196, "vi" }, | | 179 | { 196, "vi" }, |
180 | { 197, "vi_sensor" }, | | 180 | { 197, "vi_sensor" }, |
181 | { 198, "fuse" }, | | 181 | { 198, "fuse" }, |
182 | { 199, "fuse_burn" }, | | 182 | { 199, "fuse_burn" }, |
183 | { 200, "clk_32k" }, | | 183 | { 200, "clk_32k" }, |
184 | { 201, "clk_m" }, | | 184 | { 201, "clk_m" }, |
185 | { 202, "clk_m_div2" }, | | 185 | { 202, "clk_m_div2" }, |
186 | { 203, "clk_m_div4" }, | | 186 | { 203, "clk_m_div4" }, |
187 | { 204, "pll_ref" }, | | 187 | { 204, "pll_ref" }, |
188 | { 205, "pll_c" }, | | 188 | { 205, "pll_c" }, |
189 | { 206, "pll_c_out1" }, | | 189 | { 206, "pll_c_out1" }, |
190 | { 207, "pll_c2" }, | | 190 | { 207, "pll_c2" }, |
191 | { 208, "pll_c3" }, | | 191 | { 208, "pll_c3" }, |
192 | { 209, "pll_m" }, | | 192 | { 209, "pll_m" }, |
193 | { 210, "pll_m_out1" }, | | 193 | { 210, "pll_m_out1" }, |
194 | { 211, "pll_p_out0" }, | | 194 | { 211, "pll_p_out0" }, |
195 | { 212, "pll_p_out1" }, | | 195 | { 212, "pll_p_out1" }, |
196 | { 213, "pll_p_out2" }, | | 196 | { 213, "pll_p_out2" }, |
197 | { 214, "pll_p_out3" }, | | 197 | { 214, "pll_p_out3" }, |
198 | { 215, "pll_p_out4" }, | | 198 | { 215, "pll_p_out4" }, |
199 | { 216, "pll_a" }, | | 199 | { 216, "pll_a" }, |
200 | { 217, "pll_a_out0" }, | | 200 | { 217, "pll_a_out0" }, |
201 | { 218, "pll_d" }, | | 201 | { 218, "pll_d" }, |
202 | { 219, "pll_d_out0" }, | | 202 | { 219, "pll_d_out0" }, |
203 | { 220, "pll_d2" }, | | 203 | { 220, "pll_d2" }, |
204 | { 221, "pll_d2_out0" }, | | 204 | { 221, "pll_d2_out0" }, |
205 | { 222, "pll_u" }, | | 205 | { 222, "pll_u" }, |
206 | { 223, "pll_u_480m" }, | | 206 | { 223, "pll_u_480m" }, |
207 | { 224, "pll_u_60m" }, | | 207 | { 224, "pll_u_60m" }, |
208 | { 225, "pll_u_48m" }, | | 208 | { 225, "pll_u_48m" }, |
209 | { 226, "pll_u_12m" }, | | 209 | { 226, "pll_u_12m" }, |
210 | { 229, "pll_re_vco" }, | | 210 | { 229, "pll_re_vco" }, |
211 | { 230, "pll_re_out" }, | | 211 | { 230, "pll_re_out" }, |
212 | { 231, "pll_e" }, | | 212 | { 231, "pll_e" }, |
213 | { 232, "spdif_in_sync" }, | | 213 | { 232, "spdif_in_sync" }, |
214 | { 233, "i2s0_sync" }, | | 214 | { 233, "i2s0_sync" }, |
215 | { 234, "i2s1_sync" }, | | 215 | { 234, "i2s1_sync" }, |
216 | { 235, "i2s2_sync" }, | | 216 | { 235, "i2s2_sync" }, |
217 | { 236, "i2s3_sync" }, | | 217 | { 236, "i2s3_sync" }, |
218 | { 237, "i2s4_sync" }, | | 218 | { 237, "i2s4_sync" }, |
219 | { 238, "vimclk_sync" }, | | 219 | { 238, "vimclk_sync" }, |
220 | { 239, "audio0" }, | | 220 | { 239, "audio0" }, |
221 | { 240, "audio1" }, | | 221 | { 240, "audio1" }, |
222 | { 241, "audio2" }, | | 222 | { 241, "audio2" }, |
223 | { 242, "audio3" }, | | 223 | { 242, "audio3" }, |
224 | { 243, "audio4" }, | | 224 | { 243, "audio4" }, |
225 | { 244, "spdif" }, | | 225 | { 244, "spdif" }, |
226 | { 245, "clk_out_1" }, | | 226 | { 245, "clk_out_1" }, |
227 | { 246, "clk_out_2" }, | | 227 | { 246, "clk_out_2" }, |
228 | { 247, "clk_out_3" }, | | 228 | { 247, "clk_out_3" }, |
229 | { 248, "blink" }, | | 229 | { 248, "blink" }, |
230 | { 252, "xusb_host_src" }, | | 230 | { 252, "xusb_host_src" }, |
231 | { 253, "xusb_falcon_src" }, | | 231 | { 253, "xusb_falcon_src" }, |
232 | { 254, "xusb_fs_src" }, | | 232 | { 254, "xusb_fs_src" }, |
233 | { 255, "xusb_ss_src" }, | | 233 | { 255, "xusb_ss_src" }, |
234 | { 256, "xusb_dev_src" }, | | 234 | { 256, "xusb_dev_src" }, |
235 | { 257, "xusb_dev" }, | | 235 | { 257, "xusb_dev" }, |
236 | { 258, "xusb_hs_src" }, | | 236 | { 258, "xusb_hs_src" }, |
237 | { 259, "sclk" }, | | 237 | { 259, "sclk" }, |
238 | { 260, "hclk" }, | | 238 | { 260, "hclk" }, |
239 | { 261, "pclk" }, | | 239 | { 261, "pclk" }, |
240 | { 264, "dfll_ref" }, | | 240 | { 264, "dfll_ref" }, |
241 | { 265, "dfll_soc" }, | | 241 | { 265, "dfll_soc" }, |
242 | { 266, "vi_sensor2" }, | | 242 | { 266, "vi_sensor2" }, |
243 | { 267, "pll_p_out5" }, | | 243 | { 267, "pll_p_out5" }, |
244 | { 268, "cml0" }, | | 244 | { 268, "cml0" }, |
245 | { 269, "cml1" }, | | 245 | { 269, "cml1" }, |
246 | { 270, "pll_c4" }, | | 246 | { 270, "pll_c4" }, |
247 | { 271, "pll_dp" }, | | 247 | { 271, "pll_dp" }, |
248 | { 272, "pll_e_mux" }, | | 248 | { 272, "pll_e_mux" }, |
249 | { 273, "pll_d_dsi_out" }, | | 249 | { 273, "pll_d_dsi_out" }, |
250 | { 300, "audio0_mux" }, | | 250 | { 300, "audio0_mux" }, |
251 | { 301, "audio1_mux" }, | | 251 | { 301, "audio1_mux" }, |
252 | { 302, "audio2_mux" }, | | 252 | { 302, "audio2_mux" }, |
253 | { 303, "audio3_mux" }, | | 253 | { 303, "audio3_mux" }, |
254 | { 304, "audio4_mux" }, | | 254 | { 304, "audio4_mux" }, |
255 | { 305, "spdif_mux" }, | | 255 | { 305, "spdif_mux" }, |
256 | { 306, "clk_out_1_mux" }, | | 256 | { 306, "clk_out_1_mux" }, |
257 | { 307, "clk_out_2_mux" }, | | 257 | { 307, "clk_out_2_mux" }, |
258 | { 308, "clk_out_3_mux" }, | | 258 | { 308, "clk_out_3_mux" }, |
259 | { 311, "sor0_lvds" }, | | 259 | { 311, "sor0_lvds" }, |
260 | { 312, "xusb_ss_div2" }, | | 260 | { 312, "xusb_ss_div2" }, |
261 | { 313, "pll_m_ud" }, | | 261 | { 313, "pll_m_ud" }, |
262 | { 314, "pll_c_ud" }, | | 262 | { 314, "pll_c_ud" }, |
263 | { 227, "pll_x" }, | | 263 | { 227, "pll_x" }, |
264 | { 228, "pll_x_out0" }, | | 264 | { 228, "pll_x_out0" }, |
265 | { 262, "cclk_g" }, | | 265 | { 262, "cclk_g" }, |
266 | { 263, "cclk_lp" }, | | 266 | { 263, "cclk_lp" }, |
267 | { 315, "clk_max" }, | | 267 | { 315, "clk_max" }, |
268 | }; | | 268 | }; |
269 | | | 269 | |
270 | static struct clk *tegra124_car_clock_get(void *, const char *); | | 270 | static struct clk *tegra124_car_clock_get(void *, const char *); |
271 | static void tegra124_car_clock_put(void *, struct clk *); | | 271 | static void tegra124_car_clock_put(void *, struct clk *); |
272 | static u_int tegra124_car_clock_get_rate(void *, struct clk *); | | 272 | static u_int tegra124_car_clock_get_rate(void *, struct clk *); |
273 | static int tegra124_car_clock_set_rate(void *, struct clk *, u_int); | | 273 | static int tegra124_car_clock_set_rate(void *, struct clk *, u_int); |
274 | static int tegra124_car_clock_enable(void *, struct clk *); | | 274 | static int tegra124_car_clock_enable(void *, struct clk *); |
275 | static int tegra124_car_clock_disable(void *, struct clk *); | | 275 | static int tegra124_car_clock_disable(void *, struct clk *); |
276 | static int tegra124_car_clock_set_parent(void *, struct clk *, | | 276 | static int tegra124_car_clock_set_parent(void *, struct clk *, |
277 | struct clk *); | | 277 | struct clk *); |
278 | static struct clk *tegra124_car_clock_get_parent(void *, struct clk *); | | 278 | static struct clk *tegra124_car_clock_get_parent(void *, struct clk *); |
279 | | | 279 | |
280 | static const struct clk_funcs tegra124_car_clock_funcs = { | | 280 | static const struct clk_funcs tegra124_car_clock_funcs = { |
281 | .get = tegra124_car_clock_get, | | 281 | .get = tegra124_car_clock_get, |
282 | .put = tegra124_car_clock_put, | | 282 | .put = tegra124_car_clock_put, |
283 | .get_rate = tegra124_car_clock_get_rate, | | 283 | .get_rate = tegra124_car_clock_get_rate, |
284 | .set_rate = tegra124_car_clock_set_rate, | | 284 | .set_rate = tegra124_car_clock_set_rate, |
285 | .enable = tegra124_car_clock_enable, | | 285 | .enable = tegra124_car_clock_enable, |
286 | .disable = tegra124_car_clock_disable, | | 286 | .disable = tegra124_car_clock_disable, |
287 | .set_parent = tegra124_car_clock_set_parent, | | 287 | .set_parent = tegra124_car_clock_set_parent, |
288 | .get_parent = tegra124_car_clock_get_parent, | | 288 | .get_parent = tegra124_car_clock_get_parent, |
289 | }; | | 289 | }; |
290 | | | 290 | |
291 | #define CLK_FIXED(_name, _rate) { \ | | 291 | #define CLK_FIXED(_name, _rate) { \ |
292 | .base = { .name = (_name) }, .type = TEGRA_CLK_FIXED, \ | | 292 | .base = { .name = (_name) }, .type = TEGRA_CLK_FIXED, \ |
293 | .u = { .fixed = { .rate = (_rate) } } \ | | 293 | .u = { .fixed = { .rate = (_rate) } } \ |
294 | } | | 294 | } |
295 | | | 295 | |
296 | #define CLK_PLL(_name, _parent, _base, _divm, _divn, _divp) { \ | | 296 | #define CLK_PLL(_name, _parent, _base, _divm, _divn, _divp) { \ |
297 | .base = { .name = (_name) }, .type = TEGRA_CLK_PLL, \ | | 297 | .base = { .name = (_name) }, .type = TEGRA_CLK_PLL, \ |
298 | .parent = (_parent), \ | | 298 | .parent = (_parent), \ |
299 | .u = { \ | | 299 | .u = { \ |
300 | .pll = { \ | | 300 | .pll = { \ |
301 | .base_reg = (_base), \ | | 301 | .base_reg = (_base), \ |
302 | .divm_mask = (_divm), \ | | 302 | .divm_mask = (_divm), \ |
303 | .divn_mask = (_divn), \ | | 303 | .divn_mask = (_divn), \ |
304 | .divp_mask = (_divp), \ | | 304 | .divp_mask = (_divp), \ |
305 | } \ | | 305 | } \ |
306 | } \ | | 306 | } \ |
307 | } | | 307 | } |
308 | | | 308 | |
309 | #define CLK_MUX(_name, _reg, _bits, _p) { \ | | 309 | #define CLK_MUX(_name, _reg, _bits, _p) { \ |
310 | .base = { .name = (_name) }, .type = TEGRA_CLK_MUX, \ | | 310 | .base = { .name = (_name) }, .type = TEGRA_CLK_MUX, \ |
311 | .u = { \ | | 311 | .u = { \ |
312 | .mux = { \ | | 312 | .mux = { \ |
313 | .nparents = __arraycount(_p), \ | | 313 | .nparents = __arraycount(_p), \ |
314 | .parents = (_p), \ | | 314 | .parents = (_p), \ |
315 | .reg = (_reg), \ | | 315 | .reg = (_reg), \ |
316 | .bits = (_bits) \ | | 316 | .bits = (_bits) \ |
317 | } \ | | 317 | } \ |
318 | } \ | | 318 | } \ |
319 | } | | 319 | } |
320 | | | 320 | |
321 | #define CLK_FIXED_DIV(_name, _parent, _div) { \ | | 321 | #define CLK_FIXED_DIV(_name, _parent, _div) { \ |
322 | .base = { .name = (_name) }, .type = TEGRA_CLK_FIXED_DIV, \ | | 322 | .base = { .name = (_name) }, .type = TEGRA_CLK_FIXED_DIV, \ |
323 | .parent = (_parent), \ | | 323 | .parent = (_parent), \ |
324 | .u = { \ | | 324 | .u = { \ |
325 | .fixed_div = { \ | | 325 | .fixed_div = { \ |
326 | .div = (_div) \ | | 326 | .div = (_div) \ |
327 | } \ | | 327 | } \ |
328 | } \ | | 328 | } \ |
329 | } | | 329 | } |
330 | | | 330 | |
331 | #define CLK_DIV(_name, _parent, _reg, _bits) { \ | | 331 | #define CLK_DIV(_name, _parent, _reg, _bits) { \ |
332 | .base = { .name = (_name) }, .type = TEGRA_CLK_DIV, \ | | 332 | .base = { .name = (_name) }, .type = TEGRA_CLK_DIV, \ |
333 | .parent = (_parent), \ | | 333 | .parent = (_parent), \ |
334 | .u = { \ | | 334 | .u = { \ |
335 | .div = { \ | | 335 | .div = { \ |
336 | .reg = (_reg), \ | | 336 | .reg = (_reg), \ |
337 | .bits = (_bits) \ | | 337 | .bits = (_bits) \ |
338 | } \ | | 338 | } \ |
339 | } \ | | 339 | } \ |
340 | } | | 340 | } |
341 | | | 341 | |
342 | #define CLK_GATE(_name, _parent, _set, _clr, _bits) { \ | | 342 | #define CLK_GATE(_name, _parent, _set, _clr, _bits) { \ |
343 | .base = { .name = (_name), .flags = CLK_SET_RATE_PARENT }, \ | | 343 | .base = { .name = (_name), .flags = CLK_SET_RATE_PARENT }, \ |
344 | .type = TEGRA_CLK_GATE, \ | | 344 | .type = TEGRA_CLK_GATE, \ |
345 | .parent = (_parent), \ | | 345 | .parent = (_parent), \ |
346 | .u = { \ | | 346 | .u = { \ |
347 | .gate = { \ | | 347 | .gate = { \ |
348 | .set_reg = (_set), \ | | 348 | .set_reg = (_set), \ |
349 | .clr_reg = (_clr), \ | | 349 | .clr_reg = (_clr), \ |
350 | .bits = (_bits), \ | | 350 | .bits = (_bits), \ |
351 | } \ | | 351 | } \ |
352 | } \ | | 352 | } \ |
353 | } | | 353 | } |
354 | | | 354 | |
355 | #define CLK_GATE_L(_name, _parent, _bits) \ | | 355 | #define CLK_GATE_L(_name, _parent, _bits) \ |
356 | CLK_GATE(_name, _parent, \ | | 356 | CLK_GATE(_name, _parent, \ |
357 | CAR_CLK_ENB_L_SET_REG, CAR_CLK_ENB_L_CLR_REG, \ | | 357 | CAR_CLK_ENB_L_SET_REG, CAR_CLK_ENB_L_CLR_REG, \ |
358 | _bits) | | 358 | _bits) |
359 | | | 359 | |
360 | #define CLK_GATE_H(_name, _parent, _bits) \ | | 360 | #define CLK_GATE_H(_name, _parent, _bits) \ |
361 | CLK_GATE(_name, _parent, \ | | 361 | CLK_GATE(_name, _parent, \ |
362 | CAR_CLK_ENB_H_SET_REG, CAR_CLK_ENB_H_CLR_REG, \ | | 362 | CAR_CLK_ENB_H_SET_REG, CAR_CLK_ENB_H_CLR_REG, \ |
363 | _bits) | | 363 | _bits) |
364 | | | 364 | |
365 | #define CLK_GATE_U(_name, _parent, _bits) \ | | 365 | #define CLK_GATE_U(_name, _parent, _bits) \ |
366 | CLK_GATE(_name, _parent, \ | | 366 | CLK_GATE(_name, _parent, \ |
367 | CAR_CLK_ENB_U_SET_REG, CAR_CLK_ENB_U_CLR_REG, \ | | 367 | CAR_CLK_ENB_U_SET_REG, CAR_CLK_ENB_U_CLR_REG, \ |
368 | _bits) | | 368 | _bits) |
369 | | | 369 | |
370 | #define CLK_GATE_V(_name, _parent, _bits) \ | | 370 | #define CLK_GATE_V(_name, _parent, _bits) \ |
371 | CLK_GATE(_name, _parent, \ | | 371 | CLK_GATE(_name, _parent, \ |
372 | CAR_CLK_ENB_V_SET_REG, CAR_CLK_ENB_V_CLR_REG, \ | | 372 | CAR_CLK_ENB_V_SET_REG, CAR_CLK_ENB_V_CLR_REG, \ |
373 | _bits) | | 373 | _bits) |
374 | | | 374 | |
375 | #define CLK_GATE_W(_name, _parent, _bits) \ | | 375 | #define CLK_GATE_W(_name, _parent, _bits) \ |
376 | CLK_GATE(_name, _parent, \ | | 376 | CLK_GATE(_name, _parent, \ |
377 | CAR_CLK_ENB_W_SET_REG, CAR_CLK_ENB_W_CLR_REG, \ | | 377 | CAR_CLK_ENB_W_SET_REG, CAR_CLK_ENB_W_CLR_REG, \ |
378 | _bits) | | 378 | _bits) |
379 | | | 379 | |
380 | #define CLK_GATE_X(_name, _parent, _bits) \ | | 380 | #define CLK_GATE_X(_name, _parent, _bits) \ |
381 | CLK_GATE(_name, _parent, \ | | 381 | CLK_GATE(_name, _parent, \ |
382 | CAR_CLK_ENB_X_SET_REG, CAR_CLK_ENB_X_CLR_REG, \ | | 382 | CAR_CLK_ENB_X_SET_REG, CAR_CLK_ENB_X_CLR_REG, \ |
383 | _bits) | | 383 | _bits) |
384 | | | 384 | |
385 | #define CLK_GATE_SIMPLE(_name, _parent, _reg, _bits) \ | | 385 | #define CLK_GATE_SIMPLE(_name, _parent, _reg, _bits) \ |
386 | CLK_GATE(_name, _parent, _reg, _reg, _bits) | | 386 | CLK_GATE(_name, _parent, _reg, _reg, _bits) |
387 | | | 387 | |
388 | static const char *mux_uart_p[] = | | 388 | static const char *mux_uart_p[] = |
389 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", | | 389 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", |
390 | "pll_m_out0", NULL, "clk_m" }; | | 390 | "pll_m_out0", NULL, "clk_m" }; |
391 | static const char *mux_sdmmc_p[] = | | 391 | static const char *mux_sdmmc_p[] = |
392 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", | | 392 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", |
393 | "pll_m_out0", "pll_e_out0", "clk_m" }; | | 393 | "pll_m_out0", "pll_e_out0", "clk_m" }; |
394 | static const char *mux_i2c_p[] = | | 394 | static const char *mux_i2c_p[] = |
395 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", | | 395 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", |
396 | "pll_m_out0", NULL, "clk_m" }; | | 396 | "pll_m_out0", NULL, "clk_m" }; |
397 | static const char *mux_spi_p[] = | | 397 | static const char *mux_spi_p[] = |
398 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", | | 398 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", |
399 | "pll_m_out0", NULL, "clk_m" }; | | 399 | "pll_m_out0", NULL, "clk_m" }; |
400 | static const char *mux_sata_p[] = | | 400 | static const char *mux_sata_p[] = |
401 | { "pll_p_out0", NULL, "pll_c_out0", NULL, "pll_m_out0", NULL, "clk_m" }; | | 401 | { "pll_p_out0", NULL, "pll_c_out0", NULL, "pll_m_out0", NULL, "clk_m" }; |
402 | static const char *mux_hda_p[] = | | 402 | static const char *mux_hda_p[] = |
403 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", | | 403 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", |
404 | "pll_m_out0", NULL, "clk_m" }; | | 404 | "pll_m_out0", NULL, "clk_m" }; |
405 | static const char *mux_tsensor_p[] = | | 405 | static const char *mux_tsensor_p[] = |
406 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", "clk_m", | | 406 | { "pll_p_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", "clk_m", |
407 | NULL, "clk_s" }; | | 407 | NULL, "clk_s" }; |
408 | static const char *mux_soc_therm_p[] = | | 408 | static const char *mux_soc_therm_p[] = |
409 | { "pll_m_out0", "pll_c_out0", "pll_p_out0", "pll_a_out0", "pll_c2_out0", | | 409 | { "pll_m_out0", "pll_c_out0", "pll_p_out0", "pll_a_out0", "pll_c2_out0", |
410 | "pll_c3_out0" }; | | 410 | "pll_c3_out0" }; |
411 | static const char *mux_host1x_p[] = | | 411 | static const char *mux_host1x_p[] = |
412 | { "pll_m_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", | | 412 | { "pll_m_out0", "pll_c2_out0", "pll_c_out0", "pll_c3_out0", |
413 | "pll_p_out0", NULL, "pll_a_out0" }; | | 413 | "pll_p_out0", NULL, "pll_a_out0" }; |
414 | static const char *mux_disp_p[] = | | 414 | static const char *mux_disp_p[] = |
415 | { "pll_p_out0", "pll_m_out0", "pll_d_out0", "pll_a_out0", "pll_c_out0", | | 415 | { "pll_p_out0", "pll_m_out0", "pll_d_out0", "pll_a_out0", "pll_c_out0", |
416 | "pll_d2_out0", "clk_m" }; | | 416 | "pll_d2_out0", "clk_m" }; |
417 | static const char *mux_hdmi_p[] = | | 417 | static const char *mux_hdmi_p[] = |
418 | { "pll_p_out0", "pll_m_out0", "pll_d_out0", "pll_a_out0", "pll_c_out0", | | 418 | { "pll_p_out0", "pll_m_out0", "pll_d_out0", "pll_a_out0", "pll_c_out0", |
419 | "pll_d2_out0", "clk_m" }; | | 419 | "pll_d2_out0", "clk_m" }; |
420 | | | 420 | |
421 | static struct tegra_clk tegra124_car_clocks[] = { | | 421 | static struct tegra_clk tegra124_car_clocks[] = { |
422 | CLK_FIXED("clk_m", TEGRA_REF_FREQ), | | 422 | CLK_FIXED("clk_m", TEGRA_REF_FREQ), |
423 | | | 423 | |
424 | CLK_PLL("pll_p", "clk_m", CAR_PLLP_BASE_REG, | | 424 | CLK_PLL("pll_p", "clk_m", CAR_PLLP_BASE_REG, |
425 | CAR_PLLP_BASE_DIVM, CAR_PLLP_BASE_DIVN, CAR_PLLP_BASE_DIVP), | | 425 | CAR_PLLP_BASE_DIVM, CAR_PLLP_BASE_DIVN, CAR_PLLP_BASE_DIVP), |
426 | CLK_PLL("pll_c", "clk_m", CAR_PLLC_BASE_REG, | | 426 | CLK_PLL("pll_c", "clk_m", CAR_PLLC_BASE_REG, |
427 | CAR_PLLC_BASE_DIVM, CAR_PLLC_BASE_DIVN, CAR_PLLC_BASE_DIVP), | | 427 | CAR_PLLC_BASE_DIVM, CAR_PLLC_BASE_DIVN, CAR_PLLC_BASE_DIVP), |
428 | CLK_PLL("pll_u", "clk_m", CAR_PLLU_BASE_REG, | | 428 | CLK_PLL("pll_u", "clk_m", CAR_PLLU_BASE_REG, |
429 | CAR_PLLU_BASE_DIVM, CAR_PLLU_BASE_DIVN, CAR_PLLU_BASE_VCO_FREQ), | | 429 | CAR_PLLU_BASE_DIVM, CAR_PLLU_BASE_DIVN, CAR_PLLU_BASE_VCO_FREQ), |
430 | CLK_PLL("pll_x", "clk_m", CAR_PLLX_BASE_REG, | | 430 | CLK_PLL("pll_x", "clk_m", CAR_PLLX_BASE_REG, |
431 | CAR_PLLX_BASE_DIVM, CAR_PLLX_BASE_DIVN, CAR_PLLX_BASE_DIVP), | | 431 | CAR_PLLX_BASE_DIVM, CAR_PLLX_BASE_DIVN, CAR_PLLX_BASE_DIVP), |
432 | CLK_PLL("pll_e", "clk_m", CAR_PLLE_BASE_REG, | | 432 | CLK_PLL("pll_e", "clk_m", CAR_PLLE_BASE_REG, |
433 | CAR_PLLE_BASE_DIVM, CAR_PLLE_BASE_DIVN, CAR_PLLE_BASE_DIVP_CML), | | 433 | CAR_PLLE_BASE_DIVM, CAR_PLLE_BASE_DIVN, CAR_PLLE_BASE_DIVP_CML), |
434 | CLK_PLL("pll_d", "clk_m", CAR_PLLD_BASE_REG, | | 434 | CLK_PLL("pll_d", "clk_m", CAR_PLLD_BASE_REG, |
435 | CAR_PLLD_BASE_DIVM, CAR_PLLD_BASE_DIVN, CAR_PLLD_BASE_DIVP), | | 435 | CAR_PLLD_BASE_DIVM, CAR_PLLD_BASE_DIVN, CAR_PLLD_BASE_DIVP), |
436 | CLK_PLL("pll_d2", "clk_m", CAR_PLLD2_BASE_REG, | | 436 | CLK_PLL("pll_d2", "clk_m", CAR_PLLD2_BASE_REG, |
437 | CAR_PLLD2_BASE_DIVM, CAR_PLLD2_BASE_DIVN, CAR_PLLD2_BASE_DIVP), | | 437 | CAR_PLLD2_BASE_DIVM, CAR_PLLD2_BASE_DIVN, CAR_PLLD2_BASE_DIVP), |
438 | | | 438 | |
439 | CLK_FIXED_DIV("pll_p_out0", "pll_p", 1), | | 439 | CLK_FIXED_DIV("pll_p_out0", "pll_p", 1), |
440 | CLK_FIXED_DIV("pll_u_480", "pll_u", 1), | | 440 | CLK_FIXED_DIV("pll_u_480", "pll_u", 1), |
441 | CLK_FIXED_DIV("pll_u_60", "pll_u", 8), | | 441 | CLK_FIXED_DIV("pll_u_60", "pll_u", 8), |
442 | CLK_FIXED_DIV("pll_u_48", "pll_u", 10), | | 442 | CLK_FIXED_DIV("pll_u_48", "pll_u", 10), |
443 | CLK_FIXED_DIV("pll_u_12", "pll_u", 40), | | 443 | CLK_FIXED_DIV("pll_u_12", "pll_u", 40), |
444 | CLK_FIXED_DIV("pll_d_out", "pll_d", 1), | | 444 | CLK_FIXED_DIV("pll_d_out", "pll_d", 1), |
445 | CLK_FIXED_DIV("pll_d_out0", "pll_d", 2), | | 445 | CLK_FIXED_DIV("pll_d_out0", "pll_d", 2), |
446 | CLK_FIXED_DIV("pll_d2_out0", "pll_d2", 1), | | 446 | CLK_FIXED_DIV("pll_d2_out0", "pll_d2", 1), |
447 | | | 447 | |
448 | CLK_MUX("mux_uarta", CAR_CLKSRC_UARTA_REG, CAR_CLKSRC_UART_SRC, | | 448 | CLK_MUX("mux_uarta", CAR_CLKSRC_UARTA_REG, CAR_CLKSRC_UART_SRC, |
449 | mux_uart_p), | | 449 | mux_uart_p), |
450 | CLK_MUX("mux_uartb", CAR_CLKSRC_UARTB_REG, CAR_CLKSRC_UART_SRC, | | 450 | CLK_MUX("mux_uartb", CAR_CLKSRC_UARTB_REG, CAR_CLKSRC_UART_SRC, |
451 | mux_uart_p), | | 451 | mux_uart_p), |
452 | CLK_MUX("mux_uartc", CAR_CLKSRC_UARTC_REG, CAR_CLKSRC_UART_SRC, | | 452 | CLK_MUX("mux_uartc", CAR_CLKSRC_UARTC_REG, CAR_CLKSRC_UART_SRC, |
453 | mux_uart_p), | | 453 | mux_uart_p), |
454 | CLK_MUX("mux_uartd", CAR_CLKSRC_UARTD_REG, CAR_CLKSRC_UART_SRC, | | 454 | CLK_MUX("mux_uartd", CAR_CLKSRC_UARTD_REG, CAR_CLKSRC_UART_SRC, |
455 | mux_uart_p), | | 455 | mux_uart_p), |
456 | CLK_MUX("mux_sdmmc1", CAR_CLKSRC_SDMMC1_REG, CAR_CLKSRC_SDMMC_SRC, | | 456 | CLK_MUX("mux_sdmmc1", CAR_CLKSRC_SDMMC1_REG, CAR_CLKSRC_SDMMC_SRC, |
457 | mux_sdmmc_p), | | 457 | mux_sdmmc_p), |
458 | CLK_MUX("mux_sdmmc2", CAR_CLKSRC_SDMMC2_REG, CAR_CLKSRC_SDMMC_SRC, | | 458 | CLK_MUX("mux_sdmmc2", CAR_CLKSRC_SDMMC2_REG, CAR_CLKSRC_SDMMC_SRC, |
459 | mux_sdmmc_p), | | 459 | mux_sdmmc_p), |
460 | CLK_MUX("mux_sdmmc3", CAR_CLKSRC_SDMMC3_REG, CAR_CLKSRC_SDMMC_SRC, | | 460 | CLK_MUX("mux_sdmmc3", CAR_CLKSRC_SDMMC3_REG, CAR_CLKSRC_SDMMC_SRC, |
461 | mux_sdmmc_p), | | 461 | mux_sdmmc_p), |
462 | CLK_MUX("mux_sdmmc4", CAR_CLKSRC_SDMMC4_REG, CAR_CLKSRC_SDMMC_SRC, | | 462 | CLK_MUX("mux_sdmmc4", CAR_CLKSRC_SDMMC4_REG, CAR_CLKSRC_SDMMC_SRC, |
463 | mux_sdmmc_p), | | 463 | mux_sdmmc_p), |
464 | CLK_MUX("mux_i2c1", CAR_CLKSRC_I2C1_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), | | 464 | CLK_MUX("mux_i2c1", CAR_CLKSRC_I2C1_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), |
465 | CLK_MUX("mux_i2c2", CAR_CLKSRC_I2C2_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), | | 465 | CLK_MUX("mux_i2c2", CAR_CLKSRC_I2C2_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), |
466 | CLK_MUX("mux_i2c3", CAR_CLKSRC_I2C3_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), | | 466 | CLK_MUX("mux_i2c3", CAR_CLKSRC_I2C3_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), |
467 | CLK_MUX("mux_i2c4", CAR_CLKSRC_I2C4_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), | | 467 | CLK_MUX("mux_i2c4", CAR_CLKSRC_I2C4_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), |
468 | CLK_MUX("mux_i2c5", CAR_CLKSRC_I2C5_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), | | 468 | CLK_MUX("mux_i2c5", CAR_CLKSRC_I2C5_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), |
469 | CLK_MUX("mux_i2c6", CAR_CLKSRC_I2C6_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), | | 469 | CLK_MUX("mux_i2c6", CAR_CLKSRC_I2C6_REG, CAR_CLKSRC_I2C_SRC, mux_i2c_p), |
470 | CLK_MUX("mux_spi1", CAR_CLKSRC_SPI1_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), | | 470 | CLK_MUX("mux_spi1", CAR_CLKSRC_SPI1_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), |
471 | CLK_MUX("mux_spi2", CAR_CLKSRC_SPI2_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), | | 471 | CLK_MUX("mux_spi2", CAR_CLKSRC_SPI2_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), |
472 | CLK_MUX("mux_spi3", CAR_CLKSRC_SPI3_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), | | 472 | CLK_MUX("mux_spi3", CAR_CLKSRC_SPI3_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), |
473 | CLK_MUX("mux_spi4", CAR_CLKSRC_SPI4_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), | | 473 | CLK_MUX("mux_spi4", CAR_CLKSRC_SPI4_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), |
474 | CLK_MUX("mux_spi5", CAR_CLKSRC_SPI5_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), | | 474 | CLK_MUX("mux_spi5", CAR_CLKSRC_SPI5_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), |
475 | CLK_MUX("mux_spi6", CAR_CLKSRC_SPI6_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), | | 475 | CLK_MUX("mux_spi6", CAR_CLKSRC_SPI6_REG, CAR_CLKSRC_SPI_SRC, mux_spi_p), |
476 | CLK_MUX("mux_sata_oob", | | 476 | CLK_MUX("mux_sata_oob", |
477 | CAR_CLKSRC_SATA_OOB_REG, CAR_CLKSRC_SATA_OOB_SRC, mux_sata_p), | | 477 | CAR_CLKSRC_SATA_OOB_REG, CAR_CLKSRC_SATA_OOB_SRC, mux_sata_p), |
478 | CLK_MUX("mux_sata", | | 478 | CLK_MUX("mux_sata", |
479 | CAR_CLKSRC_SATA_REG, CAR_CLKSRC_SATA_SRC, mux_sata_p), | | 479 | CAR_CLKSRC_SATA_REG, CAR_CLKSRC_SATA_SRC, mux_sata_p), |
480 | CLK_MUX("mux_hda2codec_2x", | | 480 | CLK_MUX("mux_hda2codec_2x", |
481 | CAR_CLKSRC_HDA2CODEC_2X_REG, CAR_CLKSRC_HDA2CODEC_2X_SRC, | | 481 | CAR_CLKSRC_HDA2CODEC_2X_REG, CAR_CLKSRC_HDA2CODEC_2X_SRC, |
482 | mux_hda_p), | | 482 | mux_hda_p), |
483 | CLK_MUX("mux_hda", | | 483 | CLK_MUX("mux_hda", |
484 | CAR_CLKSRC_HDA_REG, CAR_CLKSRC_HDA_SRC, mux_hda_p), | | 484 | CAR_CLKSRC_HDA_REG, CAR_CLKSRC_HDA_SRC, mux_hda_p), |
485 | CLK_MUX("mux_soc_therm", | | 485 | CLK_MUX("mux_soc_therm", |
486 | CAR_CLKSRC_SOC_THERM_REG, CAR_CLKSRC_SOC_THERM_SRC, | | 486 | CAR_CLKSRC_SOC_THERM_REG, CAR_CLKSRC_SOC_THERM_SRC, |
487 | mux_soc_therm_p), | | 487 | mux_soc_therm_p), |
488 | CLK_MUX("mux_tsensor", | | 488 | CLK_MUX("mux_tsensor", |
489 | CAR_CLKSRC_TSENSOR_REG, CAR_CLKSRC_TSENSOR_SRC, | | 489 | CAR_CLKSRC_TSENSOR_REG, CAR_CLKSRC_TSENSOR_SRC, |
490 | mux_tsensor_p), | | 490 | mux_tsensor_p), |
491 | CLK_MUX("mux_host1x", | | 491 | CLK_MUX("mux_host1x", |
492 | CAR_CLKSRC_HOST1X_REG, CAR_CLKSRC_HOST1X_SRC, | | 492 | CAR_CLKSRC_HOST1X_REG, CAR_CLKSRC_HOST1X_SRC, |
493 | mux_host1x_p), | | 493 | mux_host1x_p), |
494 | CLK_MUX("mux_disp1", | | 494 | CLK_MUX("mux_disp1", |
495 | CAR_CLKSRC_DISP1_REG, CAR_CLKSRC_DISP_SRC, | | 495 | CAR_CLKSRC_DISP1_REG, CAR_CLKSRC_DISP_SRC, |
496 | mux_disp_p), | | 496 | mux_disp_p), |
497 | CLK_MUX("mux_disp2", | | 497 | CLK_MUX("mux_disp2", |
498 | CAR_CLKSRC_DISP2_REG, CAR_CLKSRC_DISP_SRC, | | 498 | CAR_CLKSRC_DISP2_REG, CAR_CLKSRC_DISP_SRC, |
499 | mux_disp_p), | | 499 | mux_disp_p), |
500 | CLK_MUX("mux_hdmi", | | 500 | CLK_MUX("mux_hdmi", |
501 | CAR_CLKSRC_HDMI_REG, CAR_CLKSRC_HDMI_SRC, | | 501 | CAR_CLKSRC_HDMI_REG, CAR_CLKSRC_HDMI_SRC, |
502 | mux_hdmi_p), | | 502 | mux_hdmi_p), |
503 | | | 503 | |
504 | CLK_DIV("div_uarta", "mux_uarta", | | 504 | CLK_DIV("div_uarta", "mux_uarta", |
505 | CAR_CLKSRC_UARTA_REG, CAR_CLKSRC_UART_DIV), | | 505 | CAR_CLKSRC_UARTA_REG, CAR_CLKSRC_UART_DIV), |
506 | CLK_DIV("div_uartb", "mux_uartb", | | 506 | CLK_DIV("div_uartb", "mux_uartb", |
507 | CAR_CLKSRC_UARTB_REG, CAR_CLKSRC_UART_DIV), | | 507 | CAR_CLKSRC_UARTB_REG, CAR_CLKSRC_UART_DIV), |
508 | CLK_DIV("div_uartc", "mux_uartc", | | 508 | CLK_DIV("div_uartc", "mux_uartc", |
509 | CAR_CLKSRC_UARTC_REG, CAR_CLKSRC_UART_DIV), | | 509 | CAR_CLKSRC_UARTC_REG, CAR_CLKSRC_UART_DIV), |
510 | CLK_DIV("div_uartd", "mux_uartd", | | 510 | CLK_DIV("div_uartd", "mux_uartd", |
511 | CAR_CLKSRC_UARTD_REG, CAR_CLKSRC_UART_DIV), | | 511 | CAR_CLKSRC_UARTD_REG, CAR_CLKSRC_UART_DIV), |
512 | CLK_DIV("div_sdmmc1", "mux_sdmmc1", | | 512 | CLK_DIV("div_sdmmc1", "mux_sdmmc1", |
513 | CAR_CLKSRC_SDMMC1_REG, CAR_CLKSRC_SDMMC_DIV), | | 513 | CAR_CLKSRC_SDMMC1_REG, CAR_CLKSRC_SDMMC_DIV), |
514 | CLK_DIV("div_sdmmc2", "mux_sdmmc2", | | 514 | CLK_DIV("div_sdmmc2", "mux_sdmmc2", |
515 | CAR_CLKSRC_SDMMC2_REG, CAR_CLKSRC_SDMMC_DIV), | | 515 | CAR_CLKSRC_SDMMC2_REG, CAR_CLKSRC_SDMMC_DIV), |
516 | CLK_DIV("div_sdmmc3", "mux_sdmmc3", | | 516 | CLK_DIV("div_sdmmc3", "mux_sdmmc3", |
517 | CAR_CLKSRC_SDMMC3_REG, CAR_CLKSRC_SDMMC_DIV), | | 517 | CAR_CLKSRC_SDMMC3_REG, CAR_CLKSRC_SDMMC_DIV), |
518 | CLK_DIV("div_sdmmc4", "mux_sdmmc4", | | 518 | CLK_DIV("div_sdmmc4", "mux_sdmmc4", |
519 | CAR_CLKSRC_SDMMC4_REG, CAR_CLKSRC_SDMMC_DIV), | | 519 | CAR_CLKSRC_SDMMC4_REG, CAR_CLKSRC_SDMMC_DIV), |
520 | CLK_DIV("div_i2c1", "mux_i2c1", | | 520 | CLK_DIV("div_i2c1", "mux_i2c1", |
521 | CAR_CLKSRC_I2C1_REG, CAR_CLKSRC_I2C_DIV), | | 521 | CAR_CLKSRC_I2C1_REG, CAR_CLKSRC_I2C_DIV), |
522 | CLK_DIV("div_i2c2", "mux_i2c2", | | 522 | CLK_DIV("div_i2c2", "mux_i2c2", |
523 | CAR_CLKSRC_I2C2_REG, CAR_CLKSRC_I2C_DIV), | | 523 | CAR_CLKSRC_I2C2_REG, CAR_CLKSRC_I2C_DIV), |
524 | CLK_DIV("div_i2c3", "mux_i2c3", | | 524 | CLK_DIV("div_i2c3", "mux_i2c3", |
525 | CAR_CLKSRC_I2C3_REG, CAR_CLKSRC_I2C_DIV), | | 525 | CAR_CLKSRC_I2C3_REG, CAR_CLKSRC_I2C_DIV), |
526 | CLK_DIV("div_i2c4", "mux_i2c4", | | 526 | CLK_DIV("div_i2c4", "mux_i2c4", |
527 | CAR_CLKSRC_I2C4_REG, CAR_CLKSRC_I2C_DIV), | | 527 | CAR_CLKSRC_I2C4_REG, CAR_CLKSRC_I2C_DIV), |
528 | CLK_DIV("div_i2c5", "mux_i2c5", | | 528 | CLK_DIV("div_i2c5", "mux_i2c5", |
529 | CAR_CLKSRC_I2C5_REG, CAR_CLKSRC_I2C_DIV), | | 529 | CAR_CLKSRC_I2C5_REG, CAR_CLKSRC_I2C_DIV), |
530 | CLK_DIV("div_i2c6", "mux_i2c6", | | 530 | CLK_DIV("div_i2c6", "mux_i2c6", |
531 | CAR_CLKSRC_I2C6_REG, CAR_CLKSRC_I2C_DIV), | | 531 | CAR_CLKSRC_I2C6_REG, CAR_CLKSRC_I2C_DIV), |
532 | CLK_DIV("div_spi1", "mux_spi1", | | 532 | CLK_DIV("div_spi1", "mux_spi1", |
533 | CAR_CLKSRC_SPI1_REG, CAR_CLKSRC_SPI_DIV), | | 533 | CAR_CLKSRC_SPI1_REG, CAR_CLKSRC_SPI_DIV), |
534 | CLK_DIV("div_spi2", "mux_spi2", | | 534 | CLK_DIV("div_spi2", "mux_spi2", |
535 | CAR_CLKSRC_SPI2_REG, CAR_CLKSRC_SPI_DIV), | | 535 | CAR_CLKSRC_SPI2_REG, CAR_CLKSRC_SPI_DIV), |
536 | CLK_DIV("div_spi3", "mux_spi3", | | 536 | CLK_DIV("div_spi3", "mux_spi3", |
537 | CAR_CLKSRC_SPI3_REG, CAR_CLKSRC_SPI_DIV), | | 537 | CAR_CLKSRC_SPI3_REG, CAR_CLKSRC_SPI_DIV), |
538 | CLK_DIV("div_spi4", "mux_spi4", | | 538 | CLK_DIV("div_spi4", "mux_spi4", |
539 | CAR_CLKSRC_SPI4_REG, CAR_CLKSRC_SPI_DIV), | | 539 | CAR_CLKSRC_SPI4_REG, CAR_CLKSRC_SPI_DIV), |
540 | CLK_DIV("div_spi5", "mux_spi5", | | 540 | CLK_DIV("div_spi5", "mux_spi5", |
541 | CAR_CLKSRC_SPI5_REG, CAR_CLKSRC_SPI_DIV), | | 541 | CAR_CLKSRC_SPI5_REG, CAR_CLKSRC_SPI_DIV), |
542 | CLK_DIV("div_spi6", "mux_spi6", | | 542 | CLK_DIV("div_spi6", "mux_spi6", |
543 | CAR_CLKSRC_SPI6_REG, CAR_CLKSRC_SPI_DIV), | | 543 | CAR_CLKSRC_SPI6_REG, CAR_CLKSRC_SPI_DIV), |
544 | CLK_DIV("div_sata_oob", "mux_sata_oob", | | 544 | CLK_DIV("div_sata_oob", "mux_sata_oob", |
545 | CAR_CLKSRC_SATA_OOB_REG, CAR_CLKSRC_SATA_OOB_DIV), | | 545 | CAR_CLKSRC_SATA_OOB_REG, CAR_CLKSRC_SATA_OOB_DIV), |
546 | CLK_DIV("div_sata", "mux_sata", | | 546 | CLK_DIV("div_sata", "mux_sata", |
547 | CAR_CLKSRC_SATA_REG, CAR_CLKSRC_SATA_DIV), | | 547 | CAR_CLKSRC_SATA_REG, CAR_CLKSRC_SATA_DIV), |
548 | CLK_DIV("div_hda2codec_2x", "mux_hda2codec_2x", | | 548 | CLK_DIV("div_hda2codec_2x", "mux_hda2codec_2x", |
549 | CAR_CLKSRC_HDA2CODEC_2X_REG, CAR_CLKSRC_HDA2CODEC_2X_DIV), | | 549 | CAR_CLKSRC_HDA2CODEC_2X_REG, CAR_CLKSRC_HDA2CODEC_2X_DIV), |
550 | CLK_DIV("div_hda", "mux_hda", | | 550 | CLK_DIV("div_hda", "mux_hda", |
551 | CAR_CLKSRC_HDA_REG, CAR_CLKSRC_HDA_DIV), | | 551 | CAR_CLKSRC_HDA_REG, CAR_CLKSRC_HDA_DIV), |
552 | CLK_DIV("div_soc_therm", "mux_soc_therm", | | 552 | CLK_DIV("div_soc_therm", "mux_soc_therm", |
553 | CAR_CLKSRC_SOC_THERM_REG, CAR_CLKSRC_SOC_THERM_DIV), | | 553 | CAR_CLKSRC_SOC_THERM_REG, CAR_CLKSRC_SOC_THERM_DIV), |
554 | CLK_DIV("div_tsensor", "mux_tsensor", | | 554 | CLK_DIV("div_tsensor", "mux_tsensor", |
555 | CAR_CLKSRC_TSENSOR_REG, CAR_CLKSRC_TSENSOR_DIV), | | 555 | CAR_CLKSRC_TSENSOR_REG, CAR_CLKSRC_TSENSOR_DIV), |
556 | CLK_DIV("div_host1x", "mux_host1x", | | 556 | CLK_DIV("div_host1x", "mux_host1x", |
557 | CAR_CLKSRC_HOST1X_REG, CAR_CLKSRC_HOST1X_CLK_DIVISOR), | | 557 | CAR_CLKSRC_HOST1X_REG, CAR_CLKSRC_HOST1X_CLK_DIVISOR), |
558 | CLK_DIV("div_hdmi", "mux_hdmi", | | 558 | CLK_DIV("div_hdmi", "mux_hdmi", |
559 | CAR_CLKSRC_HDMI_REG, CAR_CLKSRC_HDMI_DIV), | | 559 | CAR_CLKSRC_HDMI_REG, CAR_CLKSRC_HDMI_DIV), |
560 | CLK_DIV("div_pll_p_out5", "pll_p", | | 560 | CLK_DIV("div_pll_p_out5", "pll_p", |
561 | CAR_PLLP_OUTC_REG, CAR_PLLP_OUTC_OUT5_RATIO), | | 561 | CAR_PLLP_OUTC_REG, CAR_PLLP_OUTC_OUT5_RATIO), |
562 | | | 562 | |
563 | CLK_GATE_L("uarta", "div_uarta", CAR_DEV_L_UARTA), | | 563 | CLK_GATE_L("uarta", "div_uarta", CAR_DEV_L_UARTA), |
564 | CLK_GATE_L("uartb", "div_uartb", CAR_DEV_L_UARTB), | | 564 | CLK_GATE_L("uartb", "div_uartb", CAR_DEV_L_UARTB), |
565 | CLK_GATE_H("uartc", "div_uartc", CAR_DEV_H_UARTC), | | 565 | CLK_GATE_H("uartc", "div_uartc", CAR_DEV_H_UARTC), |
566 | CLK_GATE_U("uartd", "div_uartd", CAR_DEV_U_UARTD), | | 566 | CLK_GATE_U("uartd", "div_uartd", CAR_DEV_U_UARTD), |
567 | CLK_GATE_L("sdmmc1", "div_sdmmc1", CAR_DEV_L_SDMMC1), | | 567 | CLK_GATE_L("sdmmc1", "div_sdmmc1", CAR_DEV_L_SDMMC1), |
568 | CLK_GATE_L("sdmmc2", "div_sdmmc2", CAR_DEV_L_SDMMC2), | | 568 | CLK_GATE_L("sdmmc2", "div_sdmmc2", CAR_DEV_L_SDMMC2), |
569 | CLK_GATE_U("sdmmc3", "div_sdmmc3", CAR_DEV_U_SDMMC3), | | 569 | CLK_GATE_U("sdmmc3", "div_sdmmc3", CAR_DEV_U_SDMMC3), |
570 | CLK_GATE_L("sdmmc4", "div_sdmmc4", CAR_DEV_L_SDMMC4), | | 570 | CLK_GATE_L("sdmmc4", "div_sdmmc4", CAR_DEV_L_SDMMC4), |
571 | CLK_GATE_L("i2c1", "div_i2c1", CAR_DEV_L_I2C1), | | 571 | CLK_GATE_L("i2c1", "div_i2c1", CAR_DEV_L_I2C1), |
572 | CLK_GATE_H("i2c2", "div_i2c2", CAR_DEV_H_I2C2), | | 572 | CLK_GATE_H("i2c2", "div_i2c2", CAR_DEV_H_I2C2), |
573 | CLK_GATE_U("i2c3", "div_i2c3", CAR_DEV_U_I2C3), | | 573 | CLK_GATE_U("i2c3", "div_i2c3", CAR_DEV_U_I2C3), |
574 | CLK_GATE_V("i2c4", "div_i2c4", CAR_DEV_V_I2C4), | | 574 | CLK_GATE_V("i2c4", "div_i2c4", CAR_DEV_V_I2C4), |
575 | CLK_GATE_H("i2c5", "div_i2c5", CAR_DEV_H_I2C5), | | 575 | CLK_GATE_H("i2c5", "div_i2c5", CAR_DEV_H_I2C5), |
576 | CLK_GATE_X("i2c6", "div_i2c6", CAR_DEV_X_I2C6), | | 576 | CLK_GATE_X("i2c6", "div_i2c6", CAR_DEV_X_I2C6), |
577 | CLK_GATE_H("spi1", "div_spi1", CAR_DEV_H_SPI1), | | 577 | CLK_GATE_H("spi1", "div_spi1", CAR_DEV_H_SPI1), |
578 | CLK_GATE_H("spi2", "div_spi2", CAR_DEV_H_SPI2), | | 578 | CLK_GATE_H("spi2", "div_spi2", CAR_DEV_H_SPI2), |
579 | CLK_GATE_H("spi3", "div_spi3", CAR_DEV_H_SPI3), | | 579 | CLK_GATE_H("spi3", "div_spi3", CAR_DEV_H_SPI3), |
580 | CLK_GATE_U("spi4", "div_spi4", CAR_DEV_U_SPI4), | | 580 | CLK_GATE_U("spi4", "div_spi4", CAR_DEV_U_SPI4), |
581 | CLK_GATE_V("spi5", "div_spi5", CAR_DEV_V_SPI5), | | 581 | CLK_GATE_V("spi5", "div_spi5", CAR_DEV_V_SPI5), |
582 | CLK_GATE_V("spi6", "div_spi6", CAR_DEV_V_SPI6), | | 582 | CLK_GATE_V("spi6", "div_spi6", CAR_DEV_V_SPI6), |
583 | CLK_GATE_L("usbd", "pll_u_480", CAR_DEV_L_USBD), | | 583 | CLK_GATE_L("usbd", "pll_u_480", CAR_DEV_L_USBD), |
584 | CLK_GATE_H("usb2", "pll_u_480", CAR_DEV_H_USB2), | | 584 | CLK_GATE_H("usb2", "pll_u_480", CAR_DEV_H_USB2), |
585 | CLK_GATE_H("usb3", "pll_u_480", CAR_DEV_H_USB3), | | 585 | CLK_GATE_H("usb3", "pll_u_480", CAR_DEV_H_USB3), |
586 | CLK_GATE_V("sata_oob", "div_sata_oob", CAR_DEV_V_SATA_OOB), | | 586 | CLK_GATE_V("sata_oob", "div_sata_oob", CAR_DEV_V_SATA_OOB), |
587 | CLK_GATE_V("sata", "div_sata", CAR_DEV_V_SATA), | | 587 | CLK_GATE_V("sata", "div_sata", CAR_DEV_V_SATA), |
588 | CLK_GATE_SIMPLE("cml0", "pll_e", | | 588 | CLK_GATE_SIMPLE("cml0", "pll_e", |
589 | CAR_PLLE_AUX_REG, CAR_PLLE_AUX_CML0_OEN), | | 589 | CAR_PLLE_AUX_REG, CAR_PLLE_AUX_CML0_OEN), |
590 | CLK_GATE_SIMPLE("cml1", "pll_e", | | 590 | CLK_GATE_SIMPLE("cml1", "pll_e", |
591 | CAR_PLLE_AUX_REG, CAR_PLLE_AUX_CML1_OEN), | | 591 | CAR_PLLE_AUX_REG, CAR_PLLE_AUX_CML1_OEN), |
592 | CLK_GATE_V("hda2codec_2x", "div_hda2codec_2x", CAR_DEV_V_HDA2CODEC_2X), | | 592 | CLK_GATE_V("hda2codec_2x", "div_hda2codec_2x", CAR_DEV_V_HDA2CODEC_2X), |
593 | CLK_GATE_V("hda", "div_hda", CAR_DEV_V_HDA), | | 593 | CLK_GATE_V("hda", "div_hda", CAR_DEV_V_HDA), |
594 | CLK_GATE_W("hda2hdmi", "clk_m", CAR_DEV_W_HDA2HDMICODEC), | | 594 | CLK_GATE_W("hda2hdmi", "clk_m", CAR_DEV_W_HDA2HDMICODEC), |
595 | CLK_GATE_H("fuse", "clk_m", CAR_DEV_H_FUSE), | | 595 | CLK_GATE_H("fuse", "clk_m", CAR_DEV_H_FUSE), |
596 | CLK_GATE_U("soc_therm", "div_soc_therm", CAR_DEV_U_SOC_THERM), | | 596 | CLK_GATE_U("soc_therm", "div_soc_therm", CAR_DEV_U_SOC_THERM), |
597 | CLK_GATE_V("tsensor", "div_tsensor", CAR_DEV_V_TSENSOR), | | 597 | CLK_GATE_V("tsensor", "div_tsensor", CAR_DEV_V_TSENSOR), |
598 | CLK_GATE_SIMPLE("watchdog", "clk_m", CAR_RST_SOURCE_REG, | | 598 | CLK_GATE_SIMPLE("watchdog", "clk_m", CAR_RST_SOURCE_REG, |
599 | CAR_RST_SOURCE_WDT_EN|CAR_RST_SOURCE_WDT_SYS_RST_EN), | | 599 | CAR_RST_SOURCE_WDT_EN|CAR_RST_SOURCE_WDT_SYS_RST_EN), |
600 | CLK_GATE_L("host1x", "div_host1x", CAR_DEV_L_HOST1X), | | 600 | CLK_GATE_L("host1x", "div_host1x", CAR_DEV_L_HOST1X), |
601 | CLK_GATE_L("disp1", "mux_disp1", CAR_DEV_L_DISP1), | | 601 | CLK_GATE_L("disp1", "mux_disp1", CAR_DEV_L_DISP1), |
602 | CLK_GATE_L("disp2", "mux_disp2", CAR_DEV_L_DISP2), | | 602 | CLK_GATE_L("disp2", "mux_disp2", CAR_DEV_L_DISP2), |
603 | CLK_GATE_H("hdmi", "div_hdmi", CAR_DEV_H_HDMI), | | 603 | CLK_GATE_H("hdmi", "div_hdmi", CAR_DEV_H_HDMI), |
604 | CLK_GATE_SIMPLE("pll_p_out5", "div_pllp_out5", | | 604 | CLK_GATE_SIMPLE("pll_p_out5", "div_pll_p_out5", |
605 | CAR_PLLP_OUTC_REG, CAR_PLLP_OUTC_OUT5_CLKEN), | | 605 | CAR_PLLP_OUTC_REG, CAR_PLLP_OUTC_OUT5_CLKEN), |
606 | }; | | 606 | }; |
607 | | | 607 | |
608 | struct tegra124_car_rst { | | 608 | struct tegra124_car_rst { |
609 | u_int set_reg; | | 609 | u_int set_reg; |
610 | u_int clr_reg; | | 610 | u_int clr_reg; |
611 | u_int mask; | | 611 | u_int mask; |
612 | }; | | 612 | }; |
613 | | | 613 | |
614 | static struct tegra124_car_reset_reg { | | 614 | static struct tegra124_car_reset_reg { |
615 | u_int set_reg; | | 615 | u_int set_reg; |
616 | u_int clr_reg; | | 616 | u_int clr_reg; |
617 | } tegra124_car_reset_regs[] = { | | 617 | } tegra124_car_reset_regs[] = { |
618 | { CAR_RST_DEV_L_SET_REG, CAR_RST_DEV_L_CLR_REG }, | | 618 | { CAR_RST_DEV_L_SET_REG, CAR_RST_DEV_L_CLR_REG }, |
619 | { CAR_RST_DEV_H_SET_REG, CAR_RST_DEV_H_CLR_REG }, | | 619 | { CAR_RST_DEV_H_SET_REG, CAR_RST_DEV_H_CLR_REG }, |
620 | { CAR_RST_DEV_U_SET_REG, CAR_RST_DEV_U_CLR_REG }, | | 620 | { CAR_RST_DEV_U_SET_REG, CAR_RST_DEV_U_CLR_REG }, |
621 | { CAR_RST_DEV_V_SET_REG, CAR_RST_DEV_V_CLR_REG }, | | 621 | { CAR_RST_DEV_V_SET_REG, CAR_RST_DEV_V_CLR_REG }, |
622 | { CAR_RST_DEV_W_SET_REG, CAR_RST_DEV_W_CLR_REG }, | | 622 | { CAR_RST_DEV_W_SET_REG, CAR_RST_DEV_W_CLR_REG }, |
623 | { CAR_RST_DEV_X_SET_REG, CAR_RST_DEV_X_CLR_REG }, | | 623 | { CAR_RST_DEV_X_SET_REG, CAR_RST_DEV_X_CLR_REG }, |
624 | }; | | 624 | }; |
625 | | | 625 | |
626 | static void * tegra124_car_reset_acquire(device_t, const void *, size_t); | | 626 | static void * tegra124_car_reset_acquire(device_t, const void *, size_t); |
627 | static void tegra124_car_reset_release(device_t, void *); | | 627 | static void tegra124_car_reset_release(device_t, void *); |
628 | static int tegra124_car_reset_assert(device_t, void *); | | 628 | static int tegra124_car_reset_assert(device_t, void *); |
629 | static int tegra124_car_reset_deassert(device_t, void *); | | 629 | static int tegra124_car_reset_deassert(device_t, void *); |
630 | | | 630 | |
631 | static const struct fdtbus_reset_controller_func tegra124_car_fdtreset_funcs = { | | 631 | static const struct fdtbus_reset_controller_func tegra124_car_fdtreset_funcs = { |
632 | .acquire = tegra124_car_reset_acquire, | | 632 | .acquire = tegra124_car_reset_acquire, |
633 | .release = tegra124_car_reset_release, | | 633 | .release = tegra124_car_reset_release, |
634 | .reset_assert = tegra124_car_reset_assert, | | 634 | .reset_assert = tegra124_car_reset_assert, |
635 | .reset_deassert = tegra124_car_reset_deassert, | | 635 | .reset_deassert = tegra124_car_reset_deassert, |
636 | }; | | 636 | }; |
637 | | | 637 | |
638 | struct tegra124_car_softc { | | 638 | struct tegra124_car_softc { |
639 | device_t sc_dev; | | 639 | device_t sc_dev; |
640 | bus_space_tag_t sc_bst; | | 640 | bus_space_tag_t sc_bst; |
641 | bus_space_handle_t sc_bsh; | | 641 | bus_space_handle_t sc_bsh; |
642 | | | 642 | |
643 | u_int sc_clock_cells; | | 643 | u_int sc_clock_cells; |
644 | u_int sc_reset_cells; | | 644 | u_int sc_reset_cells; |
645 | | | 645 | |
646 | kmutex_t sc_intr_lock; | | 646 | kmutex_t sc_intr_lock; |
647 | kmutex_t sc_rnd_lock; | | 647 | kmutex_t sc_rnd_lock; |
648 | u_int sc_bytes_wanted; | | 648 | u_int sc_bytes_wanted; |
649 | void *sc_sih; | | 649 | void *sc_sih; |
650 | krndsource_t sc_rndsource; | | 650 | krndsource_t sc_rndsource; |
651 | }; | | 651 | }; |
652 | | | 652 | |
653 | static void tegra124_car_init(struct tegra124_car_softc *); | | 653 | static void tegra124_car_init(struct tegra124_car_softc *); |
654 | static void tegra124_car_utmip_init(struct tegra124_car_softc *); | | 654 | static void tegra124_car_utmip_init(struct tegra124_car_softc *); |
655 | | | 655 | |
656 | static void tegra124_car_rnd_attach(device_t); | | 656 | static void tegra124_car_rnd_attach(device_t); |
657 | static void tegra124_car_rnd_intr(void *); | | 657 | static void tegra124_car_rnd_intr(void *); |
658 | static void tegra124_car_rnd_callback(size_t, void *); | | 658 | static void tegra124_car_rnd_callback(size_t, void *); |
659 | | | 659 | |
660 | CFATTACH_DECL_NEW(tegra124_car, sizeof(struct tegra124_car_softc), | | 660 | CFATTACH_DECL_NEW(tegra124_car, sizeof(struct tegra124_car_softc), |
661 | tegra124_car_match, tegra124_car_attach, NULL, NULL); | | 661 | tegra124_car_match, tegra124_car_attach, NULL, NULL); |
662 | | | 662 | |
663 | static int | | 663 | static int |
664 | tegra124_car_match(device_t parent, cfdata_t cf, void *aux) | | 664 | tegra124_car_match(device_t parent, cfdata_t cf, void *aux) |
665 | { | | 665 | { |
666 | const char * const compatible[] = { "nvidia,tegra124-car", NULL }; | | 666 | const char * const compatible[] = { "nvidia,tegra124-car", NULL }; |
667 | struct fdt_attach_args * const faa = aux; | | 667 | struct fdt_attach_args * const faa = aux; |
668 | | | 668 | |
669 | #if 0 | | 669 | #if 0 |
670 | return of_match_compatible(faa->faa_phandle, compatible); | | 670 | return of_match_compatible(faa->faa_phandle, compatible); |
671 | #else | | 671 | #else |
672 | if (of_match_compatible(faa->faa_phandle, compatible) == 0) | | 672 | if (of_match_compatible(faa->faa_phandle, compatible) == 0) |
673 | return 0; | | 673 | return 0; |
674 | | | 674 | |
675 | return 999; | | 675 | return 999; |
676 | #endif | | 676 | #endif |
677 | } | | 677 | } |
678 | | | 678 | |
679 | static void | | 679 | static void |
680 | tegra124_car_attach(device_t parent, device_t self, void *aux) | | 680 | tegra124_car_attach(device_t parent, device_t self, void *aux) |
681 | { | | 681 | { |
682 | struct tegra124_car_softc * const sc = device_private(self); | | 682 | struct tegra124_car_softc * const sc = device_private(self); |
683 | struct fdt_attach_args * const faa = aux; | | 683 | struct fdt_attach_args * const faa = aux; |
684 | const int phandle = faa->faa_phandle; | | 684 | const int phandle = faa->faa_phandle; |
685 | bus_addr_t addr; | | 685 | bus_addr_t addr; |
686 | bus_size_t size; | | 686 | bus_size_t size; |
687 | int error; | | 687 | int error; |
688 | | | 688 | |
689 | if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { | | 689 | if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { |
690 | aprint_error(": couldn't get registers\n"); | | 690 | aprint_error(": couldn't get registers\n"); |
691 | return; | | 691 | return; |
692 | } | | 692 | } |
693 | | | 693 | |
694 | sc->sc_dev = self; | | 694 | sc->sc_dev = self; |
695 | sc->sc_bst = faa->faa_bst; | | 695 | sc->sc_bst = faa->faa_bst; |
696 | error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); | | 696 | error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); |
697 | if (error) { | | 697 | if (error) { |
698 | aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error); | | 698 | aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error); |
699 | return; | | 699 | return; |
700 | } | | 700 | } |
701 | if (of_getprop_uint32(phandle, "#clock-cells", &sc->sc_clock_cells)) | | 701 | if (of_getprop_uint32(phandle, "#clock-cells", &sc->sc_clock_cells)) |
702 | sc->sc_clock_cells = 1; | | 702 | sc->sc_clock_cells = 1; |
703 | if (of_getprop_uint32(phandle, "#reset-cells", &sc->sc_reset_cells)) | | 703 | if (of_getprop_uint32(phandle, "#reset-cells", &sc->sc_reset_cells)) |
704 | sc->sc_reset_cells = 1; | | 704 | sc->sc_reset_cells = 1; |
705 | | | 705 | |
706 | aprint_naive("\n"); | | 706 | aprint_naive("\n"); |
707 | aprint_normal(": CAR\n"); | | 707 | aprint_normal(": CAR\n"); |
708 | | | 708 | |
709 | clk_backend_register("tegra124", &tegra124_car_clock_funcs, sc); | | 709 | clk_backend_register("tegra124", &tegra124_car_clock_funcs, sc); |
710 | | | 710 | |
711 | fdtbus_register_clock_controller(self, phandle, | | 711 | fdtbus_register_clock_controller(self, phandle, |
712 | &tegra124_car_fdtclock_funcs); | | 712 | &tegra124_car_fdtclock_funcs); |
713 | fdtbus_register_reset_controller(self, phandle, | | 713 | fdtbus_register_reset_controller(self, phandle, |
714 | &tegra124_car_fdtreset_funcs); | | 714 | &tegra124_car_fdtreset_funcs); |
715 | | | 715 | |
716 | tegra124_car_init(sc); | | 716 | tegra124_car_init(sc); |
717 | | | 717 | |
718 | config_interrupts(self, tegra124_car_rnd_attach); | | 718 | config_interrupts(self, tegra124_car_rnd_attach); |
719 | } | | 719 | } |
720 | | | 720 | |
721 | static void | | 721 | static void |
722 | tegra124_car_init(struct tegra124_car_softc *sc) | | 722 | tegra124_car_init(struct tegra124_car_softc *sc) |
723 | { | | 723 | { |
724 | tegra124_car_utmip_init(sc); | | 724 | tegra124_car_utmip_init(sc); |
725 | } | | 725 | } |
726 | | | 726 | |
727 | static void | | 727 | static void |
728 | tegra124_car_utmip_init(struct tegra124_car_softc *sc) | | 728 | tegra124_car_utmip_init(struct tegra124_car_softc *sc) |
729 | { | | 729 | { |
730 | bus_space_tag_t bst = sc->sc_bst; | | 730 | bus_space_tag_t bst = sc->sc_bst; |
731 | bus_space_handle_t bsh = sc->sc_bsh; | | 731 | bus_space_handle_t bsh = sc->sc_bsh; |
732 | | | 732 | |
733 | const u_int enable_dly_count = 0x02; | | 733 | const u_int enable_dly_count = 0x02; |
734 | const u_int stable_count = 0x2f; | | 734 | const u_int stable_count = 0x2f; |
735 | const u_int active_dly_count = 0x04; | | 735 | const u_int active_dly_count = 0x04; |
736 | const u_int xtal_freq_count = 0x76; | | 736 | const u_int xtal_freq_count = 0x76; |
737 | | | 737 | |
738 | tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG, | | 738 | tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG2_REG, |
739 | __SHIFTIN(stable_count, CAR_UTMIP_PLL_CFG2_STABLE_COUNT) | | | 739 | __SHIFTIN(stable_count, CAR_UTMIP_PLL_CFG2_STABLE_COUNT) | |
740 | __SHIFTIN(active_dly_count, CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT), | | 740 | __SHIFTIN(active_dly_count, CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT), |
741 | CAR_UTMIP_PLL_CFG2_PD_SAMP_A_POWERDOWN | | | 741 | CAR_UTMIP_PLL_CFG2_PD_SAMP_A_POWERDOWN | |
742 | CAR_UTMIP_PLL_CFG2_PD_SAMP_B_POWERDOWN | | | 742 | CAR_UTMIP_PLL_CFG2_PD_SAMP_B_POWERDOWN | |
743 | CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERDOWN | | | 743 | CAR_UTMIP_PLL_CFG2_PD_SAMP_C_POWERDOWN | |
744 | CAR_UTMIP_PLL_CFG2_STABLE_COUNT | | | 744 | CAR_UTMIP_PLL_CFG2_STABLE_COUNT | |
745 | CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT); | | 745 | CAR_UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT); |
746 | | | 746 | |
747 | tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, | | 747 | tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, |
748 | __SHIFTIN(enable_dly_count, CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT) | | | 748 | __SHIFTIN(enable_dly_count, CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT) | |
749 | __SHIFTIN(xtal_freq_count, CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT), | | 749 | __SHIFTIN(xtal_freq_count, CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT), |
750 | CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT | | | 750 | CAR_UTMIP_PLL_CFG1_ENABLE_DLY_COUNT | |
751 | CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT); | | 751 | CAR_UTMIP_PLL_CFG1_XTAL_FREQ_COUNT); |
752 | | | 752 | |
753 | tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, | | 753 | tegra_reg_set_clear(bst, bsh, CAR_UTMIP_PLL_CFG1_REG, |
754 | 0, | | 754 | 0, |
755 | CAR_UTMIP_PLL_CFG1_PLLU_POWERDOWN | | | 755 | CAR_UTMIP_PLL_CFG1_PLLU_POWERDOWN | |
756 | CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERDOWN); | | 756 | CAR_UTMIP_PLL_CFG1_PLL_ENABLE_POWERDOWN); |
757 | | | 757 | |
758 | } | | 758 | } |
759 | | | 759 | |
760 | static void | | 760 | static void |
761 | tegra124_car_rnd_attach(device_t self) | | 761 | tegra124_car_rnd_attach(device_t self) |
762 | { | | 762 | { |
763 | struct tegra124_car_softc * const sc = device_private(self); | | 763 | struct tegra124_car_softc * const sc = device_private(self); |
764 | | | 764 | |
765 | mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SERIAL); | | 765 | mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SERIAL); |
766 | mutex_init(&sc->sc_rnd_lock, MUTEX_DEFAULT, IPL_SERIAL); | | 766 | mutex_init(&sc->sc_rnd_lock, MUTEX_DEFAULT, IPL_SERIAL); |
767 | sc->sc_bytes_wanted = 0; | | 767 | sc->sc_bytes_wanted = 0; |
768 | sc->sc_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, | | 768 | sc->sc_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, |
769 | tegra124_car_rnd_intr, sc); | | 769 | tegra124_car_rnd_intr, sc); |
770 | if (sc->sc_sih == NULL) { | | 770 | if (sc->sc_sih == NULL) { |
771 | aprint_error_dev(sc->sc_dev, "couldn't establish softint\n"); | | 771 | aprint_error_dev(sc->sc_dev, "couldn't establish softint\n"); |
772 | return; | | 772 | return; |
773 | } | | 773 | } |
774 | | | 774 | |
775 | rndsource_setcb(&sc->sc_rndsource, tegra124_car_rnd_callback, sc); | | 775 | rndsource_setcb(&sc->sc_rndsource, tegra124_car_rnd_callback, sc); |
776 | rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev), | | 776 | rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev), |
777 | RND_TYPE_RNG, RND_FLAG_COLLECT_VALUE|RND_FLAG_HASCB); | | 777 | RND_TYPE_RNG, RND_FLAG_COLLECT_VALUE|RND_FLAG_HASCB); |
778 | } | | 778 | } |
779 | | | 779 | |
780 | static void | | 780 | static void |
781 | tegra124_car_rnd_intr(void *priv) | | 781 | tegra124_car_rnd_intr(void *priv) |
782 | { | | 782 | { |
783 | struct tegra124_car_softc * const sc = priv; | | 783 | struct tegra124_car_softc * const sc = priv; |
784 | uint16_t buf[512]; | | 784 | uint16_t buf[512]; |
785 | uint32_t cnt; | | 785 | uint32_t cnt; |
786 | | | 786 | |
787 | mutex_enter(&sc->sc_intr_lock); | | 787 | mutex_enter(&sc->sc_intr_lock); |
788 | while (sc->sc_bytes_wanted) { | | 788 | while (sc->sc_bytes_wanted) { |
789 | const u_int nbytes = MIN(sc->sc_bytes_wanted, 1024); | | 789 | const u_int nbytes = MIN(sc->sc_bytes_wanted, 1024); |
790 | for (cnt = 0; cnt < sc->sc_bytes_wanted / 2; cnt++) { | | 790 | for (cnt = 0; cnt < sc->sc_bytes_wanted / 2; cnt++) { |
791 | buf[cnt] = bus_space_read_4(sc->sc_bst, sc->sc_bsh, | | 791 | buf[cnt] = bus_space_read_4(sc->sc_bst, sc->sc_bsh, |
792 | CAR_PLL_LFSR_REG) & 0xffff; | | 792 | CAR_PLL_LFSR_REG) & 0xffff; |
793 | } | | 793 | } |
794 | mutex_exit(&sc->sc_intr_lock); | | 794 | mutex_exit(&sc->sc_intr_lock); |
795 | mutex_enter(&sc->sc_rnd_lock); | | 795 | mutex_enter(&sc->sc_rnd_lock); |
796 | rnd_add_data(&sc->sc_rndsource, buf, nbytes, nbytes * NBBY); | | 796 | rnd_add_data(&sc->sc_rndsource, buf, nbytes, nbytes * NBBY); |
797 | mutex_exit(&sc->sc_rnd_lock); | | 797 | mutex_exit(&sc->sc_rnd_lock); |
798 | mutex_enter(&sc->sc_intr_lock); | | 798 | mutex_enter(&sc->sc_intr_lock); |
799 | sc->sc_bytes_wanted -= MIN(sc->sc_bytes_wanted, nbytes); | | 799 | sc->sc_bytes_wanted -= MIN(sc->sc_bytes_wanted, nbytes); |
800 | } | | 800 | } |
801 | explicit_memset(buf, 0, sizeof(buf)); | | 801 | explicit_memset(buf, 0, sizeof(buf)); |
802 | mutex_exit(&sc->sc_intr_lock); | | 802 | mutex_exit(&sc->sc_intr_lock); |
803 | } | | 803 | } |
804 | | | 804 | |
805 | static void | | 805 | static void |
806 | tegra124_car_rnd_callback(size_t bytes_wanted, void *priv) | | 806 | tegra124_car_rnd_callback(size_t bytes_wanted, void *priv) |
807 | { | | 807 | { |
808 | struct tegra124_car_softc * const sc = priv; | | 808 | struct tegra124_car_softc * const sc = priv; |
809 | | | 809 | |
810 | mutex_enter(&sc->sc_intr_lock); | | 810 | mutex_enter(&sc->sc_intr_lock); |
811 | if (sc->sc_bytes_wanted == 0) { | | 811 | if (sc->sc_bytes_wanted == 0) { |
812 | softint_schedule(sc->sc_sih); | | 812 | softint_schedule(sc->sc_sih); |
813 | } | | 813 | } |
814 | if (bytes_wanted > (UINT_MAX - sc->sc_bytes_wanted)) { | | 814 | if (bytes_wanted > (UINT_MAX - sc->sc_bytes_wanted)) { |
815 | sc->sc_bytes_wanted = UINT_MAX; | | 815 | sc->sc_bytes_wanted = UINT_MAX; |
816 | } else { | | 816 | } else { |
817 | sc->sc_bytes_wanted += bytes_wanted; | | 817 | sc->sc_bytes_wanted += bytes_wanted; |
818 | } | | 818 | } |
819 | mutex_exit(&sc->sc_intr_lock); | | 819 | mutex_exit(&sc->sc_intr_lock); |
820 | } | | 820 | } |
821 | | | 821 | |
822 | static struct tegra_clk * | | 822 | static struct tegra_clk * |
823 | tegra124_car_clock_find(const char *name) | | 823 | tegra124_car_clock_find(const char *name) |
824 | { | | 824 | { |
825 | u_int n; | | 825 | u_int n; |
826 | | | 826 | |
827 | for (n = 0; n < __arraycount(tegra124_car_clocks); n++) { | | 827 | for (n = 0; n < __arraycount(tegra124_car_clocks); n++) { |
828 | if (strcmp(tegra124_car_clocks[n].base.name, name) == 0) { | | 828 | if (strcmp(tegra124_car_clocks[n].base.name, name) == 0) { |
829 | return &tegra124_car_clocks[n]; | | 829 | return &tegra124_car_clocks[n]; |
830 | } | | 830 | } |
831 | } | | 831 | } |
832 | | | 832 | |
833 | return NULL; | | 833 | return NULL; |
834 | } | | 834 | } |
835 | | | 835 | |
836 | static struct tegra_clk * | | 836 | static struct tegra_clk * |
837 | tegra124_car_clock_find_by_id(u_int clock_id) | | 837 | tegra124_car_clock_find_by_id(u_int clock_id) |
838 | { | | 838 | { |
839 | u_int n; | | 839 | u_int n; |
840 | | | 840 | |
841 | for (n = 0; n < __arraycount(tegra124_car_clock_ids); n++) { | | 841 | for (n = 0; n < __arraycount(tegra124_car_clock_ids); n++) { |
842 | if (tegra124_car_clock_ids[n].id == clock_id) { | | 842 | if (tegra124_car_clock_ids[n].id == clock_id) { |
843 | const char *name = tegra124_car_clock_ids[n].name; | | 843 | const char *name = tegra124_car_clock_ids[n].name; |
844 | return tegra124_car_clock_find(name); | | 844 | return tegra124_car_clock_find(name); |
845 | } | | 845 | } |
846 | } | | 846 | } |
847 | | | 847 | |
848 | return NULL; | | 848 | return NULL; |
849 | } | | 849 | } |
850 | | | 850 | |
851 | static struct clk * | | 851 | static struct clk * |
852 | tegra124_car_clock_decode(device_t dev, const void *data, size_t len) | | 852 | tegra124_car_clock_decode(device_t dev, const void *data, size_t len) |
853 | { | | 853 | { |
854 | struct tegra124_car_softc * const sc = device_private(dev); | | 854 | struct tegra124_car_softc * const sc = device_private(dev); |
855 | struct tegra_clk *tclk; | | 855 | struct tegra_clk *tclk; |
856 | | | 856 | |
857 | if (len != sc->sc_clock_cells * 4) { | | 857 | if (len != sc->sc_clock_cells * 4) { |
858 | return NULL; | | 858 | return NULL; |
859 | } | | 859 | } |
860 | | | 860 | |
861 | const u_int clock_id = be32dec(data); | | 861 | const u_int clock_id = be32dec(data); |
862 | | | 862 | |
863 | tclk = tegra124_car_clock_find_by_id(clock_id); | | 863 | tclk = tegra124_car_clock_find_by_id(clock_id); |
864 | if (tclk) | | 864 | if (tclk) |
865 | return TEGRA_CLK_BASE(tclk); | | 865 | return TEGRA_CLK_BASE(tclk); |
866 | | | 866 | |
867 | return NULL; | | 867 | return NULL; |
868 | } | | 868 | } |
869 | | | 869 | |
870 | static struct clk * | | 870 | static struct clk * |
871 | tegra124_car_clock_get(void *priv, const char *name) | | 871 | tegra124_car_clock_get(void *priv, const char *name) |
872 | { | | 872 | { |
873 | struct tegra_clk *tclk; | | 873 | struct tegra_clk *tclk; |
874 | | | 874 | |
875 | tclk = tegra124_car_clock_find(name); | | 875 | tclk = tegra124_car_clock_find(name); |
876 | if (tclk == NULL) | | 876 | if (tclk == NULL) |
877 | return NULL; | | 877 | return NULL; |
878 | | | 878 | |
879 | atomic_inc_uint(&tclk->refcnt); | | 879 | atomic_inc_uint(&tclk->refcnt); |
880 | | | 880 | |
881 | return TEGRA_CLK_BASE(tclk); | | 881 | return TEGRA_CLK_BASE(tclk); |
882 | } | | 882 | } |
883 | | | 883 | |
884 | static void | | 884 | static void |
885 | tegra124_car_clock_put(void *priv, struct clk *clk) | | 885 | tegra124_car_clock_put(void *priv, struct clk *clk) |
886 | { | | 886 | { |
887 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); | | 887 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); |
888 | | | 888 | |
889 | KASSERT(tclk->refcnt > 0); | | 889 | KASSERT(tclk->refcnt > 0); |
890 | | | 890 | |
891 | atomic_dec_uint(&tclk->refcnt); | | 891 | atomic_dec_uint(&tclk->refcnt); |
892 | } | | 892 | } |
893 | | | 893 | |
894 | static u_int | | 894 | static u_int |
895 | tegra124_car_clock_get_rate_pll(struct tegra124_car_softc *sc, | | 895 | tegra124_car_clock_get_rate_pll(struct tegra124_car_softc *sc, |
896 | struct tegra_clk *tclk) | | 896 | struct tegra_clk *tclk) |
897 | { | | 897 | { |
898 | struct tegra_pll_clk *tpll = &tclk->u.pll; | | 898 | struct tegra_pll_clk *tpll = &tclk->u.pll; |
899 | struct tegra_clk *tclk_parent; | | 899 | struct tegra_clk *tclk_parent; |
900 | bus_space_tag_t bst = sc->sc_bst; | | 900 | bus_space_tag_t bst = sc->sc_bst; |
901 | bus_space_handle_t bsh = sc->sc_bsh; | | 901 | bus_space_handle_t bsh = sc->sc_bsh; |
902 | u_int divm, divn, divp; | | 902 | u_int divm, divn, divp; |
903 | uint64_t rate; | | 903 | uint64_t rate; |
904 | | | 904 | |
905 | KASSERT(tclk->type == TEGRA_CLK_PLL); | | 905 | KASSERT(tclk->type == TEGRA_CLK_PLL); |
906 | | | 906 | |
907 | tclk_parent = tegra124_car_clock_find(tclk->parent); | | 907 | tclk_parent = tegra124_car_clock_find(tclk->parent); |
908 | KASSERT(tclk_parent != NULL); | | 908 | KASSERT(tclk_parent != NULL); |
909 | | | 909 | |
910 | const u_int rate_parent = tegra124_car_clock_get_rate(sc, | | 910 | const u_int rate_parent = tegra124_car_clock_get_rate(sc, |
911 | TEGRA_CLK_BASE(tclk_parent)); | | 911 | TEGRA_CLK_BASE(tclk_parent)); |
912 | | | 912 | |
913 | const uint32_t base = bus_space_read_4(bst, bsh, tpll->base_reg); | | 913 | const uint32_t base = bus_space_read_4(bst, bsh, tpll->base_reg); |
914 | divm = __SHIFTOUT(base, tpll->divm_mask); | | 914 | divm = __SHIFTOUT(base, tpll->divm_mask); |
915 | divn = __SHIFTOUT(base, tpll->divn_mask); | | 915 | divn = __SHIFTOUT(base, tpll->divn_mask); |
916 | if (tpll->base_reg == CAR_PLLU_BASE_REG) { | | 916 | if (tpll->base_reg == CAR_PLLU_BASE_REG) { |
917 | divp = __SHIFTOUT(base, tpll->divp_mask) ? 0 : 1; | | 917 | divp = __SHIFTOUT(base, tpll->divp_mask) ? 0 : 1; |
918 | } else { | | 918 | } else { |
919 | divp = __SHIFTOUT(base, tpll->divp_mask); | | 919 | divp = __SHIFTOUT(base, tpll->divp_mask); |
920 | } | | 920 | } |
921 | | | 921 | |
922 | rate = (uint64_t)rate_parent * divn; | | 922 | rate = (uint64_t)rate_parent * divn; |
923 | return rate / (divm << divp); | | 923 | return rate / (divm << divp); |
924 | } | | 924 | } |
925 | | | 925 | |
926 | static int | | 926 | static int |
927 | tegra124_car_clock_set_rate_pll(struct tegra124_car_softc *sc, | | 927 | tegra124_car_clock_set_rate_pll(struct tegra124_car_softc *sc, |
928 | struct tegra_clk *tclk, u_int rate) | | 928 | struct tegra_clk *tclk, u_int rate) |
929 | { | | 929 | { |
930 | struct tegra_pll_clk *tpll = &tclk->u.pll; | | 930 | struct tegra_pll_clk *tpll = &tclk->u.pll; |
931 | bus_space_tag_t bst = sc->sc_bst; | | 931 | bus_space_tag_t bst = sc->sc_bst; |
932 | bus_space_handle_t bsh = sc->sc_bsh; | | 932 | bus_space_handle_t bsh = sc->sc_bsh; |
933 | struct clk *clk_parent; | | 933 | struct clk *clk_parent; |
934 | uint32_t bp, base; | | 934 | uint32_t bp, base; |
935 | | | 935 | |
936 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); | | 936 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); |
937 | if (clk_parent == NULL) | | 937 | if (clk_parent == NULL) |
938 | return EIO; | | 938 | return EIO; |
939 | const u_int rate_parent = tegra124_car_clock_get_rate(sc, clk_parent); | | 939 | const u_int rate_parent = tegra124_car_clock_get_rate(sc, clk_parent); |
940 | if (rate_parent == 0) | | 940 | if (rate_parent == 0) |
941 | return EIO; | | 941 | return EIO; |
942 | | | 942 | |
943 | if (tpll->base_reg == CAR_PLLX_BASE_REG) { | | 943 | if (tpll->base_reg == CAR_PLLX_BASE_REG) { |
944 | const u_int divm = 1; | | 944 | const u_int divm = 1; |
945 | const u_int divn = rate / rate_parent; | | 945 | const u_int divn = rate / rate_parent; |
946 | const u_int divp = 0; | | 946 | const u_int divp = 0; |
947 | | | 947 | |
948 | bp = bus_space_read_4(bst, bsh, CAR_CCLKG_BURST_POLICY_REG); | | 948 | bp = bus_space_read_4(bst, bsh, CAR_CCLKG_BURST_POLICY_REG); |
949 | bp &= ~CAR_CCLKG_BURST_POLICY_CPU_STATE; | | 949 | bp &= ~CAR_CCLKG_BURST_POLICY_CPU_STATE; |
950 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CPU_STATE_IDLE, | | 950 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CPU_STATE_IDLE, |
951 | CAR_CCLKG_BURST_POLICY_CPU_STATE); | | 951 | CAR_CCLKG_BURST_POLICY_CPU_STATE); |
952 | bp &= ~CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE; | | 952 | bp &= ~CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE; |
953 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CWAKEUP_SOURCE_CLKM, | | 953 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CWAKEUP_SOURCE_CLKM, |
954 | CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE); | | 954 | CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE); |
955 | bus_space_write_4(bst, bsh, CAR_CCLKG_BURST_POLICY_REG, bp); | | 955 | bus_space_write_4(bst, bsh, CAR_CCLKG_BURST_POLICY_REG, bp); |
956 | | | 956 | |
957 | base = bus_space_read_4(bst, bsh, CAR_PLLX_BASE_REG); | | 957 | base = bus_space_read_4(bst, bsh, CAR_PLLX_BASE_REG); |
958 | base &= ~CAR_PLLX_BASE_DIVM; | | 958 | base &= ~CAR_PLLX_BASE_DIVM; |
959 | base &= ~CAR_PLLX_BASE_DIVN; | | 959 | base &= ~CAR_PLLX_BASE_DIVN; |
960 | base &= ~CAR_PLLX_BASE_DIVP; | | 960 | base &= ~CAR_PLLX_BASE_DIVP; |
961 | base |= __SHIFTIN(divm, CAR_PLLX_BASE_DIVM); | | 961 | base |= __SHIFTIN(divm, CAR_PLLX_BASE_DIVM); |
962 | base |= __SHIFTIN(divn, CAR_PLLX_BASE_DIVN); | | 962 | base |= __SHIFTIN(divn, CAR_PLLX_BASE_DIVN); |
963 | base |= __SHIFTIN(divp, CAR_PLLX_BASE_DIVP); | | 963 | base |= __SHIFTIN(divp, CAR_PLLX_BASE_DIVP); |
964 | bus_space_write_4(bst, bsh, CAR_PLLX_BASE_REG, base); | | 964 | bus_space_write_4(bst, bsh, CAR_PLLX_BASE_REG, base); |
965 | | | 965 | |
966 | tegra_reg_set_clear(bst, bsh, CAR_PLLX_MISC_REG, | | 966 | tegra_reg_set_clear(bst, bsh, CAR_PLLX_MISC_REG, |
967 | CAR_PLLX_MISC_LOCK_ENABLE, 0); | | 967 | CAR_PLLX_MISC_LOCK_ENABLE, 0); |
968 | do { | | 968 | do { |
969 | delay(2); | | 969 | delay(2); |
970 | base = bus_space_read_4(bst, bsh, tpll->base_reg); | | 970 | base = bus_space_read_4(bst, bsh, tpll->base_reg); |
971 | } while ((base & CAR_PLLX_BASE_LOCK) == 0); | | 971 | } while ((base & CAR_PLLX_BASE_LOCK) == 0); |
972 | delay(100); | | 972 | delay(100); |
973 | | | 973 | |
974 | bp &= ~CAR_CCLKG_BURST_POLICY_CPU_STATE; | | 974 | bp &= ~CAR_CCLKG_BURST_POLICY_CPU_STATE; |
975 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CPU_STATE_RUN, | | 975 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CPU_STATE_RUN, |
976 | CAR_CCLKG_BURST_POLICY_CPU_STATE); | | 976 | CAR_CCLKG_BURST_POLICY_CPU_STATE); |
977 | bp &= ~CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE; | | 977 | bp &= ~CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE; |
978 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CWAKEUP_SOURCE_PLLX_OUT0_LJ, | | 978 | bp |= __SHIFTIN(CAR_CCLKG_BURST_POLICY_CWAKEUP_SOURCE_PLLX_OUT0_LJ, |
979 | CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE); | | 979 | CAR_CCLKG_BURST_POLICY_CWAKEUP_IDLE_SOURCE); |
980 | bus_space_write_4(bst, bsh, CAR_CCLKG_BURST_POLICY_REG, bp); | | 980 | bus_space_write_4(bst, bsh, CAR_CCLKG_BURST_POLICY_REG, bp); |
981 | | | 981 | |
982 | return 0; | | 982 | return 0; |
983 | } else if (tpll->base_reg == CAR_PLLD2_BASE_REG) { | | 983 | } else if (tpll->base_reg == CAR_PLLD2_BASE_REG) { |
984 | const u_int divm = 1; | | 984 | const u_int divm = 1; |
985 | const u_int pldiv = 1; | | 985 | const u_int pldiv = 1; |
986 | const u_int divn = (rate << pldiv) / rate_parent; | | 986 | const u_int divn = (rate << pldiv) / rate_parent; |
987 | | | 987 | |
988 | /* Set frequency */ | | 988 | /* Set frequency */ |
989 | tegra_reg_set_clear(bst, bsh, tpll->base_reg, | | 989 | tegra_reg_set_clear(bst, bsh, tpll->base_reg, |
990 | __SHIFTIN(divm, CAR_PLLD2_BASE_DIVM) | | | 990 | __SHIFTIN(divm, CAR_PLLD2_BASE_DIVM) | |
991 | __SHIFTIN(divn, CAR_PLLD2_BASE_DIVN) | | | 991 | __SHIFTIN(divn, CAR_PLLD2_BASE_DIVN) | |
992 | __SHIFTIN(pldiv, CAR_PLLD2_BASE_DIVP), | | 992 | __SHIFTIN(pldiv, CAR_PLLD2_BASE_DIVP), |
993 | CAR_PLLD2_BASE_REF_SRC_SEL | | | 993 | CAR_PLLD2_BASE_REF_SRC_SEL | |
994 | CAR_PLLD2_BASE_DIVM | | | 994 | CAR_PLLD2_BASE_DIVM | |
995 | CAR_PLLD2_BASE_DIVN | | | 995 | CAR_PLLD2_BASE_DIVN | |
996 | CAR_PLLD2_BASE_DIVP); | | 996 | CAR_PLLD2_BASE_DIVP); |
997 | | | 997 | |
998 | return 0; | | 998 | return 0; |
999 | } else { | | 999 | } else { |
1000 | /* TODO */ | | 1000 | /* TODO */ |
1001 | return EOPNOTSUPP; | | 1001 | return EOPNOTSUPP; |
1002 | } | | 1002 | } |
1003 | } | | 1003 | } |
1004 | | | 1004 | |
1005 | static int | | 1005 | static int |
1006 | tegra124_car_clock_set_parent_mux(struct tegra124_car_softc *sc, | | 1006 | tegra124_car_clock_set_parent_mux(struct tegra124_car_softc *sc, |
1007 | struct tegra_clk *tclk, struct tegra_clk *tclk_parent) | | 1007 | struct tegra_clk *tclk, struct tegra_clk *tclk_parent) |
1008 | { | | 1008 | { |
1009 | struct tegra_mux_clk *tmux = &tclk->u.mux; | | 1009 | struct tegra_mux_clk *tmux = &tclk->u.mux; |
1010 | bus_space_tag_t bst = sc->sc_bst; | | 1010 | bus_space_tag_t bst = sc->sc_bst; |
1011 | bus_space_handle_t bsh = sc->sc_bsh; | | 1011 | bus_space_handle_t bsh = sc->sc_bsh; |
1012 | uint32_t v; | | 1012 | uint32_t v; |
1013 | u_int src; | | 1013 | u_int src; |
1014 | | | 1014 | |
1015 | KASSERT(tclk->type == TEGRA_CLK_MUX); | | 1015 | KASSERT(tclk->type == TEGRA_CLK_MUX); |
1016 | | | 1016 | |
1017 | for (src = 0; src < tmux->nparents; src++) { | | 1017 | for (src = 0; src < tmux->nparents; src++) { |
1018 | if (tmux->parents[src] == NULL) { | | 1018 | if (tmux->parents[src] == NULL) { |
1019 | continue; | | 1019 | continue; |
1020 | } | | 1020 | } |
1021 | if (strcmp(tmux->parents[src], tclk_parent->base.name) == 0) { | | 1021 | if (strcmp(tmux->parents[src], tclk_parent->base.name) == 0) { |
1022 | break; | | 1022 | break; |
1023 | } | | 1023 | } |
1024 | } | | 1024 | } |
1025 | if (src == tmux->nparents) { | | 1025 | if (src == tmux->nparents) { |
1026 | return EINVAL; | | 1026 | return EINVAL; |
1027 | } | | 1027 | } |
1028 | | | 1028 | |
1029 | if (tmux->reg == CAR_CLKSRC_HDMI_REG && | | 1029 | if (tmux->reg == CAR_CLKSRC_HDMI_REG && |
1030 | src == CAR_CLKSRC_HDMI_SRC_PLLD2_OUT0) { | | 1030 | src == CAR_CLKSRC_HDMI_SRC_PLLD2_OUT0) { |
1031 | /* Change IDDQ from 1 to 0 */ | | 1031 | /* Change IDDQ from 1 to 0 */ |
1032 | tegra_reg_set_clear(bst, bsh, CAR_PLLD2_BASE_REG, | | 1032 | tegra_reg_set_clear(bst, bsh, CAR_PLLD2_BASE_REG, |
1033 | 0, CAR_PLLD2_BASE_IDDQ); | | 1033 | 0, CAR_PLLD2_BASE_IDDQ); |
1034 | delay(2); | | 1034 | delay(2); |
1035 | | | 1035 | |
1036 | /* Enable lock */ | | 1036 | /* Enable lock */ |
1037 | tegra_reg_set_clear(bst, bsh, CAR_PLLD2_MISC_REG, | | 1037 | tegra_reg_set_clear(bst, bsh, CAR_PLLD2_MISC_REG, |
1038 | CAR_PLLD2_MISC_LOCK_ENABLE, 0); | | 1038 | CAR_PLLD2_MISC_LOCK_ENABLE, 0); |
1039 | | | 1039 | |
1040 | /* Enable PLLD2 */ | | 1040 | /* Enable PLLD2 */ |
1041 | tegra_reg_set_clear(bst, bsh, CAR_PLLD2_BASE_REG, | | 1041 | tegra_reg_set_clear(bst, bsh, CAR_PLLD2_BASE_REG, |
1042 | CAR_PLLD2_BASE_ENABLE, 0); | | 1042 | CAR_PLLD2_BASE_ENABLE, 0); |
1043 | | | 1043 | |
1044 | /* Wait for lock */ | | 1044 | /* Wait for lock */ |
1045 | do { | | 1045 | do { |
1046 | delay(2); | | 1046 | delay(2); |
1047 | v = bus_space_read_4(bst, bsh, CAR_PLLD2_BASE_REG); | | 1047 | v = bus_space_read_4(bst, bsh, CAR_PLLD2_BASE_REG); |
1048 | } while ((v & CAR_PLLD2_BASE_LOCK) == 0); | | 1048 | } while ((v & CAR_PLLD2_BASE_LOCK) == 0); |
1049 | | | 1049 | |
1050 | delay(200); | | 1050 | delay(200); |
1051 | } | | 1051 | } |
1052 | | | 1052 | |
1053 | v = bus_space_read_4(bst, bsh, tmux->reg); | | 1053 | v = bus_space_read_4(bst, bsh, tmux->reg); |
1054 | v &= ~tmux->bits; | | 1054 | v &= ~tmux->bits; |
1055 | v |= __SHIFTIN(src, tmux->bits); | | 1055 | v |= __SHIFTIN(src, tmux->bits); |
1056 | bus_space_write_4(bst, bsh, tmux->reg, v); | | 1056 | bus_space_write_4(bst, bsh, tmux->reg, v); |
1057 | | | 1057 | |
1058 | return 0; | | 1058 | return 0; |
1059 | } | | 1059 | } |
1060 | | | 1060 | |
1061 | static struct tegra_clk * | | 1061 | static struct tegra_clk * |
1062 | tegra124_car_clock_get_parent_mux(struct tegra124_car_softc *sc, | | 1062 | tegra124_car_clock_get_parent_mux(struct tegra124_car_softc *sc, |
1063 | struct tegra_clk *tclk) | | 1063 | struct tegra_clk *tclk) |
1064 | { | | 1064 | { |
1065 | struct tegra_mux_clk *tmux = &tclk->u.mux; | | 1065 | struct tegra_mux_clk *tmux = &tclk->u.mux; |
1066 | bus_space_tag_t bst = sc->sc_bst; | | 1066 | bus_space_tag_t bst = sc->sc_bst; |
1067 | bus_space_handle_t bsh = sc->sc_bsh; | | 1067 | bus_space_handle_t bsh = sc->sc_bsh; |
1068 | | | 1068 | |
1069 | KASSERT(tclk->type == TEGRA_CLK_MUX); | | 1069 | KASSERT(tclk->type == TEGRA_CLK_MUX); |
1070 | | | 1070 | |
1071 | const uint32_t v = bus_space_read_4(bst, bsh, tmux->reg); | | 1071 | const uint32_t v = bus_space_read_4(bst, bsh, tmux->reg); |
1072 | const u_int src = __SHIFTOUT(v, tmux->bits); | | 1072 | const u_int src = __SHIFTOUT(v, tmux->bits); |
1073 | | | 1073 | |
1074 | KASSERT(src < tmux->nparents); | | 1074 | KASSERT(src < tmux->nparents); |
1075 | | | 1075 | |
1076 | if (tmux->parents[src] == NULL) { | | 1076 | if (tmux->parents[src] == NULL) { |
1077 | return NULL; | | 1077 | return NULL; |
1078 | } | | 1078 | } |
1079 | | | 1079 | |
1080 | return tegra124_car_clock_find(tmux->parents[src]); | | 1080 | return tegra124_car_clock_find(tmux->parents[src]); |
1081 | } | | 1081 | } |
1082 | | | 1082 | |
1083 | static u_int | | 1083 | static u_int |
1084 | tegra124_car_clock_get_rate_fixed_div(struct tegra124_car_softc *sc, | | 1084 | tegra124_car_clock_get_rate_fixed_div(struct tegra124_car_softc *sc, |
1085 | struct tegra_clk *tclk) | | 1085 | struct tegra_clk *tclk) |
1086 | { | | 1086 | { |
1087 | struct tegra_fixed_div_clk *tfixed_div = &tclk->u.fixed_div; | | 1087 | struct tegra_fixed_div_clk *tfixed_div = &tclk->u.fixed_div; |
1088 | struct clk *clk_parent; | | 1088 | struct clk *clk_parent; |
1089 | | | 1089 | |
1090 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); | | 1090 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); |
1091 | if (clk_parent == NULL) | | 1091 | if (clk_parent == NULL) |
1092 | return 0; | | 1092 | return 0; |
1093 | const u_int parent_rate = tegra124_car_clock_get_rate(sc, clk_parent); | | 1093 | const u_int parent_rate = tegra124_car_clock_get_rate(sc, clk_parent); |
1094 | | | 1094 | |
1095 | return parent_rate / tfixed_div->div; | | 1095 | return parent_rate / tfixed_div->div; |
1096 | } | | 1096 | } |
1097 | | | 1097 | |
1098 | static u_int | | 1098 | static u_int |
1099 | tegra124_car_clock_get_rate_div(struct tegra124_car_softc *sc, | | 1099 | tegra124_car_clock_get_rate_div(struct tegra124_car_softc *sc, |
1100 | struct tegra_clk *tclk) | | 1100 | struct tegra_clk *tclk) |
1101 | { | | 1101 | { |
1102 | struct tegra_div_clk *tdiv = &tclk->u.div; | | 1102 | struct tegra_div_clk *tdiv = &tclk->u.div; |
1103 | bus_space_tag_t bst = sc->sc_bst; | | 1103 | bus_space_tag_t bst = sc->sc_bst; |
1104 | bus_space_handle_t bsh = sc->sc_bsh; | | 1104 | bus_space_handle_t bsh = sc->sc_bsh; |
1105 | struct clk *clk_parent; | | 1105 | struct clk *clk_parent; |
1106 | u_int rate; | | 1106 | u_int rate; |
1107 | | | 1107 | |
1108 | KASSERT(tclk->type == TEGRA_CLK_DIV); | | 1108 | KASSERT(tclk->type == TEGRA_CLK_DIV); |
1109 | | | 1109 | |
1110 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); | | 1110 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); |
1111 | const u_int parent_rate = tegra124_car_clock_get_rate(sc, clk_parent); | | 1111 | const u_int parent_rate = tegra124_car_clock_get_rate(sc, clk_parent); |
1112 | | | 1112 | |
1113 | const uint32_t v = bus_space_read_4(bst, bsh, tdiv->reg); | | 1113 | const uint32_t v = bus_space_read_4(bst, bsh, tdiv->reg); |
1114 | const u_int raw_div = __SHIFTOUT(v, tdiv->bits); | | 1114 | const u_int raw_div = __SHIFTOUT(v, tdiv->bits); |
1115 | | | 1115 | |
1116 | switch (tdiv->reg) { | | 1116 | switch (tdiv->reg) { |
1117 | case CAR_CLKSRC_I2C1_REG: | | 1117 | case CAR_CLKSRC_I2C1_REG: |
1118 | case CAR_CLKSRC_I2C2_REG: | | 1118 | case CAR_CLKSRC_I2C2_REG: |
1119 | case CAR_CLKSRC_I2C3_REG: | | 1119 | case CAR_CLKSRC_I2C3_REG: |
1120 | case CAR_CLKSRC_I2C4_REG: | | 1120 | case CAR_CLKSRC_I2C4_REG: |
1121 | case CAR_CLKSRC_I2C5_REG: | | 1121 | case CAR_CLKSRC_I2C5_REG: |
1122 | case CAR_CLKSRC_I2C6_REG: | | 1122 | case CAR_CLKSRC_I2C6_REG: |
1123 | rate = parent_rate * 1 / (raw_div + 1); | | 1123 | rate = parent_rate * 1 / (raw_div + 1); |
1124 | break; | | 1124 | break; |
1125 | case CAR_CLKSRC_UARTA_REG: | | 1125 | case CAR_CLKSRC_UARTA_REG: |
1126 | case CAR_CLKSRC_UARTB_REG: | | 1126 | case CAR_CLKSRC_UARTB_REG: |
1127 | case CAR_CLKSRC_UARTC_REG: | | 1127 | case CAR_CLKSRC_UARTC_REG: |
1128 | case CAR_CLKSRC_UARTD_REG: | | 1128 | case CAR_CLKSRC_UARTD_REG: |
1129 | if (v & CAR_CLKSRC_UART_DIV_ENB) { | | 1129 | if (v & CAR_CLKSRC_UART_DIV_ENB) { |
1130 | rate = parent_rate * 2 / (raw_div + 2); | | 1130 | rate = parent_rate * 2 / (raw_div + 2); |
1131 | } else { | | 1131 | } else { |
1132 | rate = parent_rate; | | 1132 | rate = parent_rate; |
1133 | } | | 1133 | } |
1134 | break; | | 1134 | break; |
1135 | default: | | 1135 | default: |
1136 | rate = parent_rate * 2 / (raw_div + 2); | | 1136 | rate = parent_rate * 2 / (raw_div + 2); |
1137 | break; | | 1137 | break; |
1138 | } | | 1138 | } |
1139 | | | 1139 | |
1140 | return rate; | | 1140 | return rate; |
1141 | } | | 1141 | } |
1142 | | | 1142 | |
1143 | static int | | 1143 | static int |
1144 | tegra124_car_clock_set_rate_div(struct tegra124_car_softc *sc, | | 1144 | tegra124_car_clock_set_rate_div(struct tegra124_car_softc *sc, |
1145 | struct tegra_clk *tclk, u_int rate) | | 1145 | struct tegra_clk *tclk, u_int rate) |
1146 | { | | 1146 | { |
1147 | struct tegra_div_clk *tdiv = &tclk->u.div; | | 1147 | struct tegra_div_clk *tdiv = &tclk->u.div; |
1148 | bus_space_tag_t bst = sc->sc_bst; | | 1148 | bus_space_tag_t bst = sc->sc_bst; |
1149 | bus_space_handle_t bsh = sc->sc_bsh; | | 1149 | bus_space_handle_t bsh = sc->sc_bsh; |
1150 | struct clk *clk_parent; | | 1150 | struct clk *clk_parent; |
1151 | u_int raw_div; | | 1151 | u_int raw_div; |
1152 | uint32_t v; | | 1152 | uint32_t v; |
1153 | | | 1153 | |
1154 | KASSERT(tclk->type == TEGRA_CLK_DIV); | | 1154 | KASSERT(tclk->type == TEGRA_CLK_DIV); |
1155 | | | 1155 | |
1156 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); | | 1156 | clk_parent = tegra124_car_clock_get_parent(sc, TEGRA_CLK_BASE(tclk)); |
1157 | if (clk_parent == NULL) | | 1157 | if (clk_parent == NULL) |
1158 | return EINVAL; | | 1158 | return EINVAL; |
1159 | const u_int parent_rate = tegra124_car_clock_get_rate(sc, clk_parent); | | 1159 | const u_int parent_rate = tegra124_car_clock_get_rate(sc, clk_parent); |
1160 | | | 1160 | |
1161 | v = bus_space_read_4(bst, bsh, tdiv->reg); | | 1161 | v = bus_space_read_4(bst, bsh, tdiv->reg); |
1162 | | | 1162 | |
1163 | raw_div = __SHIFTOUT(tdiv->bits, tdiv->bits); | | 1163 | raw_div = __SHIFTOUT(tdiv->bits, tdiv->bits); |
1164 | | | 1164 | |
1165 | switch (tdiv->reg) { | | 1165 | switch (tdiv->reg) { |
1166 | case CAR_CLKSRC_UARTA_REG: | | 1166 | case CAR_CLKSRC_UARTA_REG: |
1167 | case CAR_CLKSRC_UARTB_REG: | | 1167 | case CAR_CLKSRC_UARTB_REG: |
1168 | case CAR_CLKSRC_UARTC_REG: | | 1168 | case CAR_CLKSRC_UARTC_REG: |
1169 | case CAR_CLKSRC_UARTD_REG: | | 1169 | case CAR_CLKSRC_UARTD_REG: |
1170 | if (rate == parent_rate) { | | 1170 | if (rate == parent_rate) { |
1171 | v &= ~CAR_CLKSRC_UART_DIV_ENB; | | 1171 | v &= ~CAR_CLKSRC_UART_DIV_ENB; |
1172 | } else { | | 1172 | } else { |
1173 | v |= CAR_CLKSRC_UART_DIV_ENB; | | 1173 | v |= CAR_CLKSRC_UART_DIV_ENB; |
1174 | raw_div = (parent_rate * 2) / rate - 2; | | 1174 | raw_div = (parent_rate * 2) / rate - 2; |
1175 | } | | 1175 | } |
1176 | break; | | 1176 | break; |
1177 | case CAR_CLKSRC_SATA_REG: | | 1177 | case CAR_CLKSRC_SATA_REG: |
1178 | if (rate) { | | 1178 | if (rate) { |
1179 | tegra_reg_set_clear(bst, bsh, CAR_SATA_PLL_CFG0_REG, | | 1179 | tegra_reg_set_clear(bst, bsh, CAR_SATA_PLL_CFG0_REG, |
1180 | 0, CAR_SATA_PLL_CFG0_PADPLL_RESET_SWCTL); | | 1180 | 0, CAR_SATA_PLL_CFG0_PADPLL_RESET_SWCTL); |
1181 | v |= CAR_CLKSRC_SATA_AUX_CLK_ENB; | | 1181 | v |= CAR_CLKSRC_SATA_AUX_CLK_ENB; |
1182 | raw_div = (parent_rate * 2) / rate - 2; | | 1182 | raw_div = (parent_rate * 2) / rate - 2; |
1183 | } else { | | 1183 | } else { |
1184 | v &= ~CAR_CLKSRC_SATA_AUX_CLK_ENB; | | 1184 | v &= ~CAR_CLKSRC_SATA_AUX_CLK_ENB; |
1185 | } | | 1185 | } |
1186 | break; | | 1186 | break; |
1187 | case CAR_CLKSRC_I2C1_REG: | | 1187 | case CAR_CLKSRC_I2C1_REG: |
1188 | case CAR_CLKSRC_I2C2_REG: | | 1188 | case CAR_CLKSRC_I2C2_REG: |
1189 | case CAR_CLKSRC_I2C3_REG: | | 1189 | case CAR_CLKSRC_I2C3_REG: |
1190 | case CAR_CLKSRC_I2C4_REG: | | 1190 | case CAR_CLKSRC_I2C4_REG: |
1191 | case CAR_CLKSRC_I2C5_REG: | | 1191 | case CAR_CLKSRC_I2C5_REG: |
1192 | case CAR_CLKSRC_I2C6_REG: | | 1192 | case CAR_CLKSRC_I2C6_REG: |
1193 | if (rate) | | 1193 | if (rate) |
1194 | raw_div = parent_rate / rate - 1; | | 1194 | raw_div = parent_rate / rate - 1; |
1195 | break; | | 1195 | break; |
1196 | default: | | 1196 | default: |
1197 | if (rate) | | 1197 | if (rate) |
1198 | raw_div = (parent_rate * 2) / rate - 2; | | 1198 | raw_div = (parent_rate * 2) / rate - 2; |
1199 | break; | | 1199 | break; |
1200 | } | | 1200 | } |
1201 | | | 1201 | |
1202 | v &= ~tdiv->bits; | | 1202 | v &= ~tdiv->bits; |
1203 | v |= __SHIFTIN(raw_div, tdiv->bits); | | 1203 | v |= __SHIFTIN(raw_div, tdiv->bits); |
1204 | | | 1204 | |
1205 | bus_space_write_4(bst, bsh, tdiv->reg, v); | | 1205 | bus_space_write_4(bst, bsh, tdiv->reg, v); |
1206 | | | 1206 | |
1207 | return 0; | | 1207 | return 0; |
1208 | } | | 1208 | } |
1209 | | | 1209 | |
1210 | static int | | 1210 | static int |
1211 | tegra124_car_clock_enable_gate(struct tegra124_car_softc *sc, | | 1211 | tegra124_car_clock_enable_gate(struct tegra124_car_softc *sc, |
1212 | struct tegra_clk *tclk, bool enable) | | 1212 | struct tegra_clk *tclk, bool enable) |
1213 | { | | 1213 | { |
1214 | struct tegra_gate_clk *tgate = &tclk->u.gate; | | 1214 | struct tegra_gate_clk *tgate = &tclk->u.gate; |
1215 | bus_space_tag_t bst = sc->sc_bst; | | 1215 | bus_space_tag_t bst = sc->sc_bst; |
1216 | bus_space_handle_t bsh = sc->sc_bsh; | | 1216 | bus_space_handle_t bsh = sc->sc_bsh; |
1217 | bus_size_t reg; | | 1217 | bus_size_t reg; |
1218 | | | 1218 | |
1219 | KASSERT(tclk->type == TEGRA_CLK_GATE); | | 1219 | KASSERT(tclk->type == TEGRA_CLK_GATE); |
1220 | | | 1220 | |
1221 | if (tgate->set_reg == tgate->clr_reg) { | | 1221 | if (tgate->set_reg == tgate->clr_reg) { |
1222 | uint32_t v = bus_space_read_4(bst, bsh, tgate->set_reg); | | 1222 | uint32_t v = bus_space_read_4(bst, bsh, tgate->set_reg); |
1223 | if (enable) { | | 1223 | if (enable) { |
1224 | v |= tgate->bits; | | 1224 | v |= tgate->bits; |
1225 | } else { | | 1225 | } else { |
1226 | v &= ~tgate->bits; | | 1226 | v &= ~tgate->bits; |
1227 | } | | 1227 | } |
1228 | bus_space_write_4(bst, bsh, tgate->set_reg, v); | | 1228 | bus_space_write_4(bst, bsh, tgate->set_reg, v); |
1229 | } else { | | 1229 | } else { |
1230 | if (enable) { | | 1230 | if (enable) { |
1231 | reg = tgate->set_reg; | | 1231 | reg = tgate->set_reg; |
1232 | } else { | | 1232 | } else { |
1233 | reg = tgate->clr_reg; | | 1233 | reg = tgate->clr_reg; |
1234 | } | | 1234 | } |
1235 | | | 1235 | |
1236 | if (reg == CAR_CLK_ENB_V_SET_REG && | | 1236 | if (reg == CAR_CLK_ENB_V_SET_REG && |
1237 | tgate->bits == CAR_DEV_V_SATA) { | | 1237 | tgate->bits == CAR_DEV_V_SATA) { |
1238 | /* De-assert reset to SATA PADPLL */ | | 1238 | /* De-assert reset to SATA PADPLL */ |
1239 | tegra_reg_set_clear(bst, bsh, CAR_SATA_PLL_CFG0_REG, | | 1239 | tegra_reg_set_clear(bst, bsh, CAR_SATA_PLL_CFG0_REG, |
1240 | 0, CAR_SATA_PLL_CFG0_PADPLL_RESET_OVERRIDE_VALUE); | | 1240 | 0, CAR_SATA_PLL_CFG0_PADPLL_RESET_OVERRIDE_VALUE); |
1241 | delay(15); | | 1241 | delay(15); |
1242 | } | | 1242 | } |
1243 | bus_space_write_4(bst, bsh, reg, tgate->bits); | | 1243 | bus_space_write_4(bst, bsh, reg, tgate->bits); |
1244 | } | | 1244 | } |
1245 | | | 1245 | |
1246 | return 0; | | 1246 | return 0; |
1247 | } | | 1247 | } |
1248 | | | 1248 | |
1249 | static u_int | | 1249 | static u_int |
1250 | tegra124_car_clock_get_rate(void *priv, struct clk *clk) | | 1250 | tegra124_car_clock_get_rate(void *priv, struct clk *clk) |
1251 | { | | 1251 | { |
1252 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); | | 1252 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); |
1253 | struct clk *clk_parent; | | 1253 | struct clk *clk_parent; |
1254 | | | 1254 | |
1255 | switch (tclk->type) { | | 1255 | switch (tclk->type) { |
1256 | case TEGRA_CLK_FIXED: | | 1256 | case TEGRA_CLK_FIXED: |
1257 | return tclk->u.fixed.rate; | | 1257 | return tclk->u.fixed.rate; |
1258 | case TEGRA_CLK_PLL: | | 1258 | case TEGRA_CLK_PLL: |
1259 | return tegra124_car_clock_get_rate_pll(priv, tclk); | | 1259 | return tegra124_car_clock_get_rate_pll(priv, tclk); |
1260 | case TEGRA_CLK_MUX: | | 1260 | case TEGRA_CLK_MUX: |
1261 | case TEGRA_CLK_GATE: | | 1261 | case TEGRA_CLK_GATE: |
1262 | clk_parent = tegra124_car_clock_get_parent(priv, clk); | | 1262 | clk_parent = tegra124_car_clock_get_parent(priv, clk); |
1263 | if (clk_parent == NULL) | | 1263 | if (clk_parent == NULL) |
1264 | return EINVAL; | | 1264 | return EINVAL; |
1265 | return tegra124_car_clock_get_rate(priv, clk_parent); | | 1265 | return tegra124_car_clock_get_rate(priv, clk_parent); |
1266 | case TEGRA_CLK_FIXED_DIV: | | 1266 | case TEGRA_CLK_FIXED_DIV: |
1267 | return tegra124_car_clock_get_rate_fixed_div(priv, tclk); | | 1267 | return tegra124_car_clock_get_rate_fixed_div(priv, tclk); |
1268 | case TEGRA_CLK_DIV: | | 1268 | case TEGRA_CLK_DIV: |
1269 | return tegra124_car_clock_get_rate_div(priv, tclk); | | 1269 | return tegra124_car_clock_get_rate_div(priv, tclk); |
1270 | default: | | 1270 | default: |
1271 | panic("tegra124: unknown tclk type %d", tclk->type); | | 1271 | panic("tegra124: unknown tclk type %d", tclk->type); |
1272 | } | | 1272 | } |
1273 | } | | 1273 | } |
1274 | | | 1274 | |
1275 | static int | | 1275 | static int |
1276 | tegra124_car_clock_set_rate(void *priv, struct clk *clk, u_int rate) | | 1276 | tegra124_car_clock_set_rate(void *priv, struct clk *clk, u_int rate) |
1277 | { | | 1277 | { |
1278 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); | | 1278 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); |
1279 | struct clk *clk_parent; | | 1279 | struct clk *clk_parent; |
1280 | | | 1280 | |
1281 | KASSERT((clk->flags & CLK_SET_RATE_PARENT) == 0); | | 1281 | KASSERT((clk->flags & CLK_SET_RATE_PARENT) == 0); |
1282 | | | 1282 | |
1283 | switch (tclk->type) { | | 1283 | switch (tclk->type) { |
1284 | case TEGRA_CLK_FIXED: | | 1284 | case TEGRA_CLK_FIXED: |
1285 | case TEGRA_CLK_MUX: | | 1285 | case TEGRA_CLK_MUX: |
1286 | return EIO; | | 1286 | return EIO; |
1287 | case TEGRA_CLK_FIXED_DIV: | | 1287 | case TEGRA_CLK_FIXED_DIV: |
1288 | clk_parent = tegra124_car_clock_get_parent(priv, clk); | | 1288 | clk_parent = tegra124_car_clock_get_parent(priv, clk); |
1289 | if (clk_parent == NULL) | | 1289 | if (clk_parent == NULL) |
1290 | return EIO; | | 1290 | return EIO; |
1291 | return tegra124_car_clock_set_rate(priv, clk_parent, | | 1291 | return tegra124_car_clock_set_rate(priv, clk_parent, |
1292 | rate * tclk->u.fixed_div.div); | | 1292 | rate * tclk->u.fixed_div.div); |
1293 | case TEGRA_CLK_GATE: | | 1293 | case TEGRA_CLK_GATE: |
1294 | return EINVAL; | | 1294 | return EINVAL; |
1295 | case TEGRA_CLK_PLL: | | 1295 | case TEGRA_CLK_PLL: |
1296 | return tegra124_car_clock_set_rate_pll(priv, tclk, rate); | | 1296 | return tegra124_car_clock_set_rate_pll(priv, tclk, rate); |
1297 | case TEGRA_CLK_DIV: | | 1297 | case TEGRA_CLK_DIV: |
1298 | return tegra124_car_clock_set_rate_div(priv, tclk, rate); | | 1298 | return tegra124_car_clock_set_rate_div(priv, tclk, rate); |
1299 | default: | | 1299 | default: |
1300 | panic("tegra124: unknown tclk type %d", tclk->type); | | 1300 | panic("tegra124: unknown tclk type %d", tclk->type); |
1301 | } | | 1301 | } |
1302 | } | | 1302 | } |
1303 | | | 1303 | |
1304 | static int | | 1304 | static int |
1305 | tegra124_car_clock_enable(void *priv, struct clk *clk) | | 1305 | tegra124_car_clock_enable(void *priv, struct clk *clk) |
1306 | { | | 1306 | { |
1307 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); | | 1307 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); |
1308 | struct clk *clk_parent; | | 1308 | struct clk *clk_parent; |
1309 | | | 1309 | |
1310 | if (tclk->type != TEGRA_CLK_GATE) { | | 1310 | if (tclk->type != TEGRA_CLK_GATE) { |
1311 | clk_parent = tegra124_car_clock_get_parent(priv, clk); | | 1311 | clk_parent = tegra124_car_clock_get_parent(priv, clk); |
1312 | if (clk_parent == NULL) | | 1312 | if (clk_parent == NULL) |
1313 | return 0; | | 1313 | return 0; |
1314 | return tegra124_car_clock_enable(priv, clk_parent); | | 1314 | return tegra124_car_clock_enable(priv, clk_parent); |
1315 | } | | 1315 | } |
1316 | | | 1316 | |
1317 | return tegra124_car_clock_enable_gate(priv, tclk, true); | | 1317 | return tegra124_car_clock_enable_gate(priv, tclk, true); |
1318 | } | | 1318 | } |
1319 | | | 1319 | |
1320 | static int | | 1320 | static int |
1321 | tegra124_car_clock_disable(void *priv, struct clk *clk) | | 1321 | tegra124_car_clock_disable(void *priv, struct clk *clk) |
1322 | { | | 1322 | { |
1323 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); | | 1323 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); |
1324 | | | 1324 | |
1325 | if (tclk->type != TEGRA_CLK_GATE) | | 1325 | if (tclk->type != TEGRA_CLK_GATE) |
1326 | return EINVAL; | | 1326 | return EINVAL; |
1327 | | | 1327 | |
1328 | return tegra124_car_clock_enable_gate(priv, tclk, false); | | 1328 | return tegra124_car_clock_enable_gate(priv, tclk, false); |
1329 | } | | 1329 | } |
1330 | | | 1330 | |
1331 | static int | | 1331 | static int |
1332 | tegra124_car_clock_set_parent(void *priv, struct clk *clk, | | 1332 | tegra124_car_clock_set_parent(void *priv, struct clk *clk, |
1333 | struct clk *clk_parent) | | 1333 | struct clk *clk_parent) |
1334 | { | | 1334 | { |
1335 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); | | 1335 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); |
1336 | struct tegra_clk *tclk_parent = TEGRA_CLK_PRIV(clk_parent); | | 1336 | struct tegra_clk *tclk_parent = TEGRA_CLK_PRIV(clk_parent); |
1337 | struct clk *nclk_parent; | | 1337 | struct clk *nclk_parent; |
1338 | | | 1338 | |
1339 | if (tclk->type != TEGRA_CLK_MUX) { | | 1339 | if (tclk->type != TEGRA_CLK_MUX) { |
1340 | nclk_parent = tegra124_car_clock_get_parent(priv, clk); | | 1340 | nclk_parent = tegra124_car_clock_get_parent(priv, clk); |
1341 | if (nclk_parent == clk_parent || nclk_parent == NULL) | | 1341 | if (nclk_parent == clk_parent || nclk_parent == NULL) |
1342 | return EINVAL; | | 1342 | return EINVAL; |
1343 | return tegra124_car_clock_set_parent(priv, nclk_parent, | | 1343 | return tegra124_car_clock_set_parent(priv, nclk_parent, |
1344 | clk_parent); | | 1344 | clk_parent); |
1345 | } | | 1345 | } |
1346 | | | 1346 | |
1347 | return tegra124_car_clock_set_parent_mux(priv, tclk, tclk_parent); | | 1347 | return tegra124_car_clock_set_parent_mux(priv, tclk, tclk_parent); |
1348 | } | | 1348 | } |
1349 | | | 1349 | |
1350 | static struct clk * | | 1350 | static struct clk * |
1351 | tegra124_car_clock_get_parent(void *priv, struct clk *clk) | | 1351 | tegra124_car_clock_get_parent(void *priv, struct clk *clk) |
1352 | { | | 1352 | { |
1353 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); | | 1353 | struct tegra_clk *tclk = TEGRA_CLK_PRIV(clk); |
1354 | struct tegra_clk *tclk_parent = NULL; | | 1354 | struct tegra_clk *tclk_parent = NULL; |
1355 | | | 1355 | |
1356 | switch (tclk->type) { | | 1356 | switch (tclk->type) { |
1357 | case TEGRA_CLK_FIXED: | | 1357 | case TEGRA_CLK_FIXED: |
1358 | case TEGRA_CLK_PLL: | | 1358 | case TEGRA_CLK_PLL: |
1359 | case TEGRA_CLK_FIXED_DIV: | | 1359 | case TEGRA_CLK_FIXED_DIV: |
1360 | case TEGRA_CLK_DIV: | | 1360 | case TEGRA_CLK_DIV: |
1361 | case TEGRA_CLK_GATE: | | 1361 | case TEGRA_CLK_GATE: |
1362 | if (tclk->parent) { | | 1362 | if (tclk->parent) { |
1363 | tclk_parent = tegra124_car_clock_find(tclk->parent); | | 1363 | tclk_parent = tegra124_car_clock_find(tclk->parent); |
1364 | } | | 1364 | } |
1365 | break; | | 1365 | break; |
1366 | case TEGRA_CLK_MUX: | | 1366 | case TEGRA_CLK_MUX: |
1367 | tclk_parent = tegra124_car_clock_get_parent_mux(priv, tclk); | | 1367 | tclk_parent = tegra124_car_clock_get_parent_mux(priv, tclk); |
1368 | break; | | 1368 | break; |
1369 | } | | 1369 | } |
1370 | | | 1370 | |
1371 | if (tclk_parent == NULL) | | 1371 | if (tclk_parent == NULL) |
1372 | return NULL; | | 1372 | return NULL; |
1373 | | | 1373 | |
1374 | return TEGRA_CLK_BASE(tclk_parent); | | 1374 | return TEGRA_CLK_BASE(tclk_parent); |
1375 | } | | 1375 | } |
1376 | | | 1376 | |
1377 | static void * | | 1377 | static void * |
1378 | tegra124_car_reset_acquire(device_t dev, const void *data, size_t len) | | 1378 | tegra124_car_reset_acquire(device_t dev, const void *data, size_t len) |
1379 | { | | 1379 | { |
1380 | struct tegra124_car_softc * const sc = device_private(dev); | | 1380 | struct tegra124_car_softc * const sc = device_private(dev); |
1381 | struct tegra124_car_rst *rst; | | 1381 | struct tegra124_car_rst *rst; |
1382 | | | 1382 | |
1383 | if (len != sc->sc_reset_cells * 4) | | 1383 | if (len != sc->sc_reset_cells * 4) |
1384 | return NULL; | | 1384 | return NULL; |
1385 | | | 1385 | |
1386 | const u_int reset_id = be32dec(data); | | 1386 | const u_int reset_id = be32dec(data); |
1387 | | | 1387 | |
1388 | if (reset_id > __arraycount(tegra124_car_reset_regs) * 32) | | 1388 | if (reset_id > __arraycount(tegra124_car_reset_regs) * 32) |
1389 | return NULL; | | 1389 | return NULL; |
1390 | | | 1390 | |
1391 | const u_int reg = reset_id / 32; | | 1391 | const u_int reg = reset_id / 32; |
1392 | | | 1392 | |
1393 | rst = kmem_alloc(sizeof(*rst), KM_SLEEP); | | 1393 | rst = kmem_alloc(sizeof(*rst), KM_SLEEP); |
1394 | rst->set_reg = tegra124_car_reset_regs[reg].set_reg; | | 1394 | rst->set_reg = tegra124_car_reset_regs[reg].set_reg; |
1395 | rst->clr_reg = tegra124_car_reset_regs[reg].clr_reg; | | 1395 | rst->clr_reg = tegra124_car_reset_regs[reg].clr_reg; |
1396 | rst->mask = __BIT(reset_id % 32); | | 1396 | rst->mask = __BIT(reset_id % 32); |
1397 | | | 1397 | |
1398 | return rst; | | 1398 | return rst; |
1399 | } | | 1399 | } |
1400 | | | 1400 | |
1401 | static void | | 1401 | static void |
1402 | tegra124_car_reset_release(device_t dev, void *priv) | | 1402 | tegra124_car_reset_release(device_t dev, void *priv) |
1403 | { | | 1403 | { |
1404 | struct tegra124_car_rst *rst = priv; | | 1404 | struct tegra124_car_rst *rst = priv; |
1405 | | | 1405 | |
1406 | kmem_free(rst, sizeof(*rst)); | | 1406 | kmem_free(rst, sizeof(*rst)); |
1407 | } | | 1407 | } |
1408 | | | 1408 | |
1409 | static int | | 1409 | static int |
1410 | tegra124_car_reset_assert(device_t dev, void *priv) | | 1410 | tegra124_car_reset_assert(device_t dev, void *priv) |
1411 | { | | 1411 | { |
1412 | struct tegra124_car_softc * const sc = device_private(dev); | | 1412 | struct tegra124_car_softc * const sc = device_private(dev); |
1413 | struct tegra124_car_rst *rst = priv; | | 1413 | struct tegra124_car_rst *rst = priv; |
1414 | | | 1414 | |
1415 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, rst->set_reg, rst->mask); | | 1415 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, rst->set_reg, rst->mask); |
1416 | | | 1416 | |
1417 | return 0; | | 1417 | return 0; |
1418 | } | | 1418 | } |
1419 | | | 1419 | |
1420 | static int | | 1420 | static int |
1421 | tegra124_car_reset_deassert(device_t dev, void *priv) | | 1421 | tegra124_car_reset_deassert(device_t dev, void *priv) |
1422 | { | | 1422 | { |
1423 | struct tegra124_car_softc * const sc = device_private(dev); | | 1423 | struct tegra124_car_softc * const sc = device_private(dev); |
1424 | struct tegra124_car_rst *rst = priv; | | 1424 | struct tegra124_car_rst *rst = priv; |
1425 | | | 1425 | |
1426 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, rst->clr_reg, rst->mask); | | 1426 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, rst->clr_reg, rst->mask); |
1427 | | | 1427 | |
1428 | return 0; | | 1428 | return 0; |
1429 | } | | 1429 | } |