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