The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm64/nvidia/tegra210/tegra210_pinmux.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 /*
   32  * Pin multiplexer driver for Tegra SoCs.
   33  */
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 #include <sys/kernel.h>
   38 #include <sys/module.h>
   39 #include <sys/malloc.h>
   40 #include <sys/rman.h>
   41 
   42 #include <machine/bus.h>
   43 
   44 #include <dev/fdt/fdt_common.h>
   45 #include <dev/fdt/fdt_pinctrl.h>
   46 #include <dev/ofw/openfirm.h>
   47 #include <dev/ofw/ofw_bus.h>
   48 #include <dev/ofw/ofw_bus_subr.h>
   49 
   50 /* Pin multipexor register. */
   51 #define TEGRA_MUX_FUNCTION_MASK  0x03
   52 #define TEGRA_MUX_FUNCTION_SHIFT 0
   53 #define TEGRA_MUX_PUPD_MASK  0x03
   54 #define TEGRA_MUX_PUPD_SHIFT 2
   55 #define TEGRA_MUX_TRISTATE_SHIFT 4
   56 #define TEGRA_MUX_ENABLE_INPUT_SHIFT 5
   57 #define TEGRA_MUX_OPEN_DRAIN_SHIFT 6
   58 #define TEGRA_MUX_LOCK_SHIFT 7
   59 #define TEGRA_MUX_IORESET_SHIFT 8
   60 #define TEGRA_MUX_RCV_SEL_SHIFT 9
   61 
   62 
   63 /* Pin goup register. */
   64 #define TEGRA_GRP_HSM_SHIFT 2
   65 #define TEGRA_GRP_SCHMT_SHIFT 3
   66 #define TEGRA_GRP_DRV_TYPE_SHIFT 6
   67 #define TEGRA_GRP_DRV_TYPE_MASK 0x03
   68 #define TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT 28
   69 #define TEGRA_GRP_DRV_DRVDN_SLWR_MASK 0x03
   70 #define TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT 30
   71 #define TEGRA_GRP_DRV_DRVUP_SLWF_MASK 0x03
   72 
   73 struct pinmux_softc {
   74         device_t        dev;
   75         struct resource *pad_mem_res;
   76         struct resource *mux_mem_res;
   77 };
   78 
   79 static struct ofw_compat_data compat_data[] = {
   80         {"nvidia,tegra210-pinmux",      1},
   81         {NULL,                          0},
   82 };
   83 
   84 enum prop_id {
   85         PROP_ID_PULL,
   86         PROP_ID_TRISTATE,
   87         PROP_ID_ENABLE_INPUT,
   88         PROP_ID_OPEN_DRAIN,
   89         PROP_ID_LOCK,
   90         PROP_ID_IORESET,
   91         PROP_ID_RCV_SEL,
   92         PROP_ID_HIGH_SPEED_MODE,
   93         PROP_ID_SCHMITT,
   94         PROP_ID_LOW_POWER_MODE,
   95         PROP_ID_DRIVE_DOWN_STRENGTH,
   96         PROP_ID_DRIVE_UP_STRENGTH,
   97         PROP_ID_SLEW_RATE_FALLING,
   98         PROP_ID_SLEW_RATE_RISING,
   99         PROP_ID_DRIVE_TYPE,
  100 
  101         PROP_ID_MAX_ID
  102 };
  103 
  104 /* Numeric based parameters. */
  105 static const struct prop_name {
  106         const char *name;
  107         enum prop_id id;
  108 } prop_names[] = {
  109         {"nvidia,pull",                 PROP_ID_PULL},
  110         {"nvidia,tristate",             PROP_ID_TRISTATE},
  111         {"nvidia,enable-input",         PROP_ID_ENABLE_INPUT},
  112         {"nvidia,open-drain",           PROP_ID_OPEN_DRAIN},
  113         {"nvidia,lock",                 PROP_ID_LOCK},
  114         {"nvidia,io-reset",             PROP_ID_IORESET},
  115         {"nvidia,rcv-sel",              PROP_ID_RCV_SEL},
  116         {"nvidia,io-hv",                PROP_ID_RCV_SEL},
  117         {"nvidia,high-speed-mode",      PROP_ID_HIGH_SPEED_MODE},
  118         {"nvidia,schmitt",              PROP_ID_SCHMITT},
  119         {"nvidia,low-power-mode",       PROP_ID_LOW_POWER_MODE},
  120         {"nvidia,pull-down-strength",   PROP_ID_DRIVE_DOWN_STRENGTH},
  121         {"nvidia,pull-up-strength",     PROP_ID_DRIVE_UP_STRENGTH},
  122         {"nvidia,slew-rate-falling",    PROP_ID_SLEW_RATE_FALLING},
  123         {"nvidia,slew-rate-rising",     PROP_ID_SLEW_RATE_RISING},
  124         {"nvidia,drive-type",           PROP_ID_DRIVE_TYPE},
  125 };
  126 
  127 /*
  128  * configuration for one pin group.
  129  */
  130 struct pincfg {
  131         char    *function;
  132         int     params[PROP_ID_MAX_ID];
  133 };
  134 #define GPIO_BANK_A      0
  135 #define GPIO_BANK_B      1
  136 #define GPIO_BANK_C      2
  137 #define GPIO_BANK_D      3
  138 #define GPIO_BANK_E      4
  139 #define GPIO_BANK_F      5
  140 #define GPIO_BANK_G      6
  141 #define GPIO_BANK_H      7
  142 #define GPIO_BANK_I      8
  143 #define GPIO_BANK_J      9
  144 #define GPIO_BANK_K     10
  145 #define GPIO_BANK_L     11
  146 #define GPIO_BANK_M     12
  147 #define GPIO_BANK_N     13
  148 #define GPIO_BANK_O     14
  149 #define GPIO_BANK_P     15
  150 #define GPIO_BANK_Q     16
  151 #define GPIO_BANK_R     17
  152 #define GPIO_BANK_S     18
  153 #define GPIO_BANK_T     19
  154 #define GPIO_BANK_U     20
  155 #define GPIO_BANK_V     21
  156 #define GPIO_BANK_W     22
  157 #define GPIO_BANK_X     23
  158 #define GPIO_BANK_Y     24
  159 #define GPIO_BANK_Z     25
  160 #define GPIO_BANK_AA    26
  161 #define GPIO_BANK_BB    27
  162 #define GPIO_BANK_CC    28
  163 #define GPIO_BANK_DD    29
  164 #define GPIO_BANK_EE    30
  165 #define GPIO_NUM(b, p) (8 * (b) + (p))
  166 
  167 struct tegra_grp {
  168         char *name;
  169         bus_size_t reg;
  170         int drvdn_shift;
  171         int drvdn_mask;
  172         int drvup_shift;
  173         int drvup_mask;
  174 };
  175 
  176 #define GRP(r, nm, dn_s, dn_w, up_s, up_w)                              \
  177 {                                                                       \
  178         .name = #nm,                                                    \
  179         .reg = r - 0x8D4,                                               \
  180         .drvdn_shift = dn_s,                                            \
  181         .drvdn_mask = (1 << dn_w) - 1,                                  \
  182         .drvup_shift = up_s,                                            \
  183         .drvup_mask = (1 << up_w) - 1,                                  \
  184 }
  185 
  186 /* Use register offsets from TRM */
  187 static const struct tegra_grp pin_grp_tbl[] = {
  188         GRP(0x9c0,    pa6, 12,  5, 20,  5),
  189         GRP(0x9c4,   pcc7, 12,  5, 20,  5),
  190         GRP(0x9c8,    pe6, 12,  5, 20,  5),
  191         GRP(0x9cc,    pe7, 12,  5, 20,  5),
  192         GRP(0x9d0,    ph6, 12,  5, 20,  5),
  193         GRP(0x9d4,    pk0,  0,  0,  0,  0),
  194         GRP(0x9d8,    pk1,  0,  0,  0,  0),
  195         GRP(0x9dc,    pk2,  0,  0,  0,  0),
  196         GRP(0x9e0,    pk3,  0,  0,  0,  0),
  197         GRP(0x9e4,    pk4,  0,  0,  0,  0),
  198         GRP(0x9e8,    pk5,  0,  0,  0,  0),
  199         GRP(0x9ec,    pk6,  0,  0,  0,  0),
  200         GRP(0x9f0,    pk7,  0,  0,  0,  0),
  201         GRP(0x9f4,    pl0,  0,  0,  0,  0),
  202         GRP(0x9f8,    pl1,  0,  0,  0,  0),
  203         GRP(0x9fc,    pz0, 12,  7, 20,  7),
  204         GRP(0xa00,    pz1, 12,  7, 20,  7),
  205         GRP(0xa04,    pz2, 12,  7, 20,  7),
  206         GRP(0xa08,    pz3, 12,  7, 20,  7),
  207         GRP(0xa0c,    pz4, 12,  7, 20,  7),
  208         GRP(0xa10,    pz5, 12,  7, 20,  7),
  209         GRP(0xa98, sdmmc1, 12,  7, 20,  7),
  210         GRP(0xa9c, sdmmc2,  2,  6,  8,  6),
  211         GRP(0xab0, sdmmc3, 12,  7, 20,  7),
  212         GRP(0xab4, sdmmc4,  2,  6,  8,  6),
  213 };
  214 
  215 struct tegra_mux {
  216         struct tegra_grp grp;
  217         char *name;
  218         bus_size_t reg;
  219         char *functions[4];
  220         int gpio_num;
  221 
  222 };
  223 
  224 #define GMUX(r, gb, gi, nm, f1, f2, f3, f4, gr, dn_s, dn_w, up_s, up_w) \
  225 {                                                                       \
  226         .name = #nm,                                                    \
  227         .reg = r,                                                       \
  228         .gpio_num = GPIO_NUM(GPIO_BANK_##gb, gi),                       \
  229         .functions = {#f1, #f2, #f3, #f4},                              \
  230         .grp.name = #nm,                                                \
  231         .grp.reg = gr - 0x8D4,                                          \
  232         .grp.drvdn_shift = dn_s,                                        \
  233         .grp.drvdn_mask = (1 << dn_w) - 1,                              \
  234         .grp.drvup_shift = up_s,                                        \
  235         .grp.drvup_mask = (1 << up_w) - 1,                              \
  236 }
  237 
  238 #define FMUX(r, nm, f1, f2, f3, f4, gr, dn_s, dn_w, up_s, up_w)         \
  239 {                                                                       \
  240         .name = #nm,                                                    \
  241         .reg = r,                                                       \
  242         .gpio_num = -1,                                                 \
  243         .functions = {#f1, #f2, #f3, #f4},                              \
  244         .grp.name = #nm,                                                \
  245         .grp.reg = gr - 0x8D4,                                          \
  246         .grp.drvdn_shift = dn_s,                                        \
  247         .grp.drvdn_mask = (1 << dn_w) - 1,                              \
  248         .grp.drvup_shift = up_s,                                        \
  249         .grp.drvup_mask = (1 << up_w) - 1,                              \
  250 }
  251 
  252 static const struct tegra_mux pin_mux_tbl[] = {
  253         GMUX(0x000,  M, 0, sdmmc1_clk_pm0,       sdmmc1,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  254         GMUX(0x004,  M, 1, sdmmc1_cmd_pm1,       sdmmc1,   spi3, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  255         GMUX(0x008,  M, 2, sdmmc1_dat3_pm2,      sdmmc1,   spi3, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  256         GMUX(0x00c,  M, 3, sdmmc1_dat2_pm3,      sdmmc1,   spi3, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  257         GMUX(0x010,  M, 4, sdmmc1_dat1_pm4,      sdmmc1,   spi3, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  258         GMUX(0x014,  M, 5, sdmmc1_dat0_pm5,      sdmmc1,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  259         GMUX(0x01c,  P, 0, sdmmc3_clk_pp0,       sdmmc3,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  260         GMUX(0x020,  P, 1, sdmmc3_cmd_pp1,       sdmmc3,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  261         GMUX(0x024,  P, 5, sdmmc3_dat0_pp5,      sdmmc3,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  262         GMUX(0x028,  P, 4, sdmmc3_dat1_pp4,      sdmmc3,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  263         GMUX(0x02c,  P, 3, sdmmc3_dat2_pp3,      sdmmc3,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  264         GMUX(0x030,  P, 2, sdmmc3_dat3_pp2,      sdmmc3,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  265         GMUX(0x038,  A, 0, pex_l0_rst_n_pa0,        pe0,  rsvd1, rsvd2, rsvd3,   0xa5c, 12,  5, 20,  5),
  266         GMUX(0x03c,  A, 1, pex_l0_clkreq_n_pa1,     pe0,  rsvd1, rsvd2, rsvd3,   0xa58, 12,  5, 20,  5),
  267         GMUX(0x040,  A, 2, pex_wake_n_pa2,           pe,  rsvd1, rsvd2, rsvd3,   0xa68, 12,  5, 20,  5),
  268         GMUX(0x044,  A, 3, pex_l1_rst_n_pa3,        pe1,  rsvd1, rsvd2, rsvd3,   0xa64, 12,  5, 20,  5),
  269         GMUX(0x048,  A, 4, pex_l1_clkreq_n_pa4,     pe1,  rsvd1, rsvd2, rsvd3,   0xa60, 12,  5, 20,  5),
  270         GMUX(0x04c,  A, 5, sata_led_active_pa5,    sata,  rsvd1, rsvd2, rsvd3,   0xa94, 12,  5, 20,  5),
  271         GMUX(0x050,  C, 0, spi1_mosi_pc0,          spi1,  rsvd1, rsvd2, rsvd3,   0xae0,  0,  0,  0,  0),
  272         GMUX(0x054,  C, 1, spi1_miso_pc1,          spi1,  rsvd1, rsvd2, rsvd3,   0xadc,  0,  0,  0,  0),
  273         GMUX(0x058,  C, 2, spi1_sck_pc2,           spi1,  rsvd1, rsvd2, rsvd3,   0xae4,  0,  0,  0,  0),
  274         GMUX(0x05c,  C, 3, spi1_cs0_pc3,           spi1,  rsvd1, rsvd2, rsvd3,   0xad4,  0,  0,  0,  0),
  275         GMUX(0x060,  C, 4, spi1_cs1_pc4,           spi1,  rsvd1, rsvd2, rsvd3,   0xad8,  0,  0,  0,  0),
  276         GMUX(0x064,  B, 4, spi2_mosi_pb4,          spi2,    dtv, rsvd2, rsvd3,   0xaf4,  0,  0,  0,  0),
  277         GMUX(0x068,  B, 5, spi2_miso_pb5,          spi2,    dtv, rsvd2, rsvd3,   0xaf0,  0,  0,  0,  0),
  278         GMUX(0x06c,  B, 6, spi2_sck_pb6,           spi2,    dtv, rsvd2, rsvd3,   0xaf8,  0,  0,  0,  0),
  279         GMUX(0x070,  B, 7, spi2_cs0_pb7,           spi2,    dtv, rsvd2, rsvd3,   0xae8,  0,  0,  0,  0),
  280         GMUX(0x074, DD, 0, spi2_cs1_pdd0,          spi2,  rsvd1, rsvd2, rsvd3,   0xaec,  0,  0,  0,  0),
  281         GMUX(0x078,  C, 7, spi4_mosi_pc7,          spi4,  rsvd1, rsvd2, rsvd3,   0xb04,  0,  0,  0,  0),
  282         GMUX(0x07c,  D, 0, spi4_miso_pd0,          spi4,  rsvd1, rsvd2, rsvd3,   0xb00,  0,  0,  0,  0),
  283         GMUX(0x080,  C, 5, spi4_sck_pc5,           spi4,  rsvd1, rsvd2, rsvd3,   0xb08,  0,  0,  0,  0),
  284         GMUX(0x084,  C, 6, spi4_cs0_pc6,           spi4,  rsvd1, rsvd2, rsvd3,   0xafc,  0,  0,  0,  0),
  285         GMUX(0x088, EE, 0, qspi_sck_pee0,          qspi,  rsvd1, rsvd2, rsvd3,   0xa90,  0,  0,  0,  0),
  286         GMUX(0x08c, EE, 1, qspi_cs_n_pee1,         qspi,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  287         GMUX(0x090, EE, 2, qspi_io0_pee2,          qspi,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  288         GMUX(0x094, EE, 3, qspi_io1_pee3,          qspi,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  289         GMUX(0x098, EE, 4, qspi_io2_pee4,          qspi,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  290         GMUX(0x09c, EE, 5, qspi_io3_pee5,          qspi,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  291         GMUX(0x0a4,  E, 0, dmic1_clk_pe0,         dmic1,   i2s3, rsvd2, rsvd3,   0x984, 12,  5, 20,  5),
  292         GMUX(0x0a8,  E, 1, dmic1_dat_pe1,         dmic1,   i2s3, rsvd2, rsvd3,   0x988, 12,  5, 20,  5),
  293         GMUX(0x0ac,  E, 2, dmic2_clk_pe2,         dmic2,   i2s3, rsvd2, rsvd3,   0x98c, 12,  5, 20,  5),
  294         GMUX(0x0b0,  E, 3, dmic2_dat_pe3,         dmic2,   i2s3, rsvd2, rsvd3,   0x990, 12,  5, 20,  5),
  295         GMUX(0x0b4,  E, 4, dmic3_clk_pe4,         dmic3,  i2s5a, rsvd2, rsvd3,   0x994, 12,  5, 20,  5),
  296         GMUX(0x0b8,  E, 5, dmic3_dat_pe5,         dmic3,  i2s5a, rsvd2, rsvd3,   0x998, 12,  5, 20,  5),
  297         GMUX(0x0bc,  J, 1, gen1_i2c_scl_pj1,       i2c1,  rsvd1, rsvd2, rsvd3,   0x9a8, 12,  5, 20,  5),
  298         GMUX(0x0c0,  J, 0, gen1_i2c_sda_pj0,       i2c1,  rsvd1, rsvd2, rsvd3,   0x9ac, 12,  5, 20,  5),
  299         GMUX(0x0c4,  J, 2, gen2_i2c_scl_pj2,       i2c2,  rsvd1, rsvd2, rsvd3,   0x9b0, 12,  5, 20,  5),
  300         GMUX(0x0c8,  J, 3, gen2_i2c_sda_pj3,       i2c2,  rsvd1, rsvd2, rsvd3,   0x9b4, 12,  5, 20,  5),
  301         GMUX(0x0cc,  F, 0, gen3_i2c_scl_pf0,       i2c3,  rsvd1, rsvd2, rsvd3,   0x9b8, 12,  5, 20,  5),
  302         GMUX(0x0d0,  F, 1, gen3_i2c_sda_pf1,       i2c3,  rsvd1, rsvd2, rsvd3,   0x9bc, 12,  5, 20,  5),
  303         GMUX(0x0d4,  S, 2, cam_i2c_scl_ps2,        i2c3,  i2cvi, rsvd2, rsvd3,   0x934, 12,  5, 20,  5),
  304         GMUX(0x0d8,  S, 3, cam_i2c_sda_ps3,        i2c3,  i2cvi, rsvd2, rsvd3,   0x938, 12,  5, 20,  5),
  305         GMUX(0x0dc,  Y, 3, pwr_i2c_scl_py3,      i2cpmu,  rsvd1, rsvd2, rsvd3,   0xa6c, 12,  5, 20,  5),
  306         GMUX(0x0e0,  Y, 4, pwr_i2c_sda_py4,      i2cpmu,  rsvd1, rsvd2, rsvd3,   0xa70, 12,  5, 20,  5),
  307         GMUX(0x0e4,  U, 0, uart1_tx_pu0,          uarta,  rsvd1, rsvd2, rsvd3,   0xb28, 12,  5, 20,  5),
  308         GMUX(0x0e8,  U, 1, uart1_rx_pu1,          uarta,  rsvd1, rsvd2, rsvd3,   0xb24, 12,  5, 20,  5),
  309         GMUX(0x0ec,  U, 2, uart1_rts_pu2,         uarta,  rsvd1, rsvd2, rsvd3,   0xb20, 12,  5, 20,  5),
  310         GMUX(0x0f0,  U, 3, uart1_cts_pu3,         uarta,  rsvd1, rsvd2, rsvd3,   0xb1c, 12,  5, 20,  5),
  311         GMUX(0x0f4,  G, 0, uart2_tx_pg0,          uartb,  i2s4a, spdif,  uart,   0xb38, 12,  5, 20,  5),
  312         GMUX(0x0f8,  G, 1, uart2_rx_pg1,          uartb,  i2s4a, spdif,  uart,   0xb34, 12,  5, 20,  5),
  313         GMUX(0x0fc,  G, 2, uart2_rts_pg2,         uartb,  i2s4a, rsvd2,  uart,   0xb30, 12,  5, 20,  5),
  314         GMUX(0x100,  G, 3, uart2_cts_pg3,         uartb,  i2s4a, rsvd2,  uart,   0xb2c, 12,  5, 20,  5),
  315         GMUX(0x104,  D, 1, uart3_tx_pd1,          uartc,   spi4, rsvd2, rsvd3,   0xb48, 12,  5, 20,  5),
  316         GMUX(0x108,  D, 2, uart3_rx_pd2,          uartc,   spi4, rsvd2, rsvd3,   0xb44, 12,  5, 20,  5),
  317         GMUX(0x10c,  D, 3, uart3_rts_pd3,         uartc,   spi4, rsvd2, rsvd3,   0xb40, 12,  5, 20,  5),
  318         GMUX(0x110,  D, 4, uart3_cts_pd4,         uartc,   spi4, rsvd2, rsvd3,   0xb3c, 12,  5, 20,  5),
  319         GMUX(0x114,  I, 4, uart4_tx_pi4,          uartd,   uart, rsvd2, rsvd3,   0xb58, 12,  5, 20,  5),
  320         GMUX(0x118,  I, 5, uart4_rx_pi5,          uartd,   uart, rsvd2, rsvd3,   0xb54, 12,  5, 20,  5),
  321         GMUX(0x11c,  I, 6, uart4_rts_pi6,         uartd,   uart, rsvd2, rsvd3,   0xb50, 12,  5, 20,  5),
  322         GMUX(0x120,  I, 7, uart4_cts_pi7,         uartd,   uart, rsvd2, rsvd3,   0xb4c, 12,  5, 20,  5),
  323         GMUX(0x124,  B, 0, dap1_fs_pb0,            i2s1,  rsvd1, rsvd2, rsvd3,   0x95c,  0,  0,  0,  0),
  324         GMUX(0x128,  B, 1, dap1_din_pb1,           i2s1,  rsvd1, rsvd2, rsvd3,   0x954,  0,  0,  0,  0),
  325         GMUX(0x12c,  B, 2, dap1_dout_pb2,          i2s1,  rsvd1, rsvd2, rsvd3,   0x958,  0,  0,  0,  0),
  326         GMUX(0x130,  B, 3, dap1_sclk_pb3,          i2s1,  rsvd1, rsvd2, rsvd3,   0x960,  0,  0,  0,  0),
  327         GMUX(0x134, AA, 0, dap2_fs_paa0,           i2s2,  rsvd1, rsvd2, rsvd3,   0x96c,  0,  0,  0,  0),
  328         GMUX(0x138, AA, 2, dap2_din_paa2,          i2s2,  rsvd1, rsvd2, rsvd3,   0x964,  0,  0,  0,  0),
  329         GMUX(0x13c, AA, 3, dap2_dout_paa3,         i2s2,  rsvd1, rsvd2, rsvd3,   0x968,  0,  0,  0,  0),
  330         GMUX(0x140, AA, 1, dap2_sclk_paa1,         i2s2,  rsvd1, rsvd2, rsvd3,   0x970,  0,  0,  0,  0),
  331         GMUX(0x144,  J, 4, dap4_fs_pj4,           i2s4b,  rsvd1, rsvd2, rsvd3,   0x97c, 12,  5, 20,  5),
  332         GMUX(0x148,  J, 5, dap4_din_pj5,          i2s4b,  rsvd1, rsvd2, rsvd3,   0x974, 12,  5, 20,  5),
  333         GMUX(0x14c,  J, 6, dap4_dout_pj6,         i2s4b,  rsvd1, rsvd2, rsvd3,   0x978, 12,  5, 20,  5),
  334         GMUX(0x150,  J, 7, dap4_sclk_pj7,         i2s4b,  rsvd1, rsvd2, rsvd3,   0x980, 12,  5, 20,  5),
  335         GMUX(0x154,  S, 0, cam1_mclk_ps0,    extperiph3,  rsvd1, rsvd2, rsvd3,   0x918, 12,  5, 20,  5),
  336         GMUX(0x158,  S, 1, cam2_mclk_ps1,    extperiph3,  rsvd1, rsvd2, rsvd3,   0x924, 12,  5, 20,  5),
  337         FMUX(0x15c,        jtag_rtck,              jtag,  rsvd1, rsvd2, rsvd3,   0xa2c, 12,  5, 20,  5),
  338         FMUX(0x160,        clk_32k_in,              clk,  rsvd1, rsvd2, rsvd3,   0x940, 12,  5, 20,  5),
  339         GMUX(0x164,  Y, 5, clk_32k_out_py5,         soc,  blink, rsvd2, rsvd3,   0x944, 12,  5, 20,  5),
  340         FMUX(0x168,        batt_bcl,                bcl,  rsvd1, rsvd2, rsvd3,   0x8f8, 12,  5, 20,  5),
  341         FMUX(0x16c,        clk_req,                 sys,  rsvd1, rsvd2, rsvd3,   0x948, 12,  5, 20,  5),
  342         FMUX(0x170,        cpu_pwr_req,             cpu,  rsvd1, rsvd2, rsvd3,   0x950, 12,  5, 20,  5),
  343         FMUX(0x174,        pwr_int_n,               pmi,  rsvd1, rsvd2, rsvd3,   0xa74, 12,  5, 20,  5),
  344         FMUX(0x178,        shutdown,           shutdown,  rsvd1, rsvd2, rsvd3,   0xac8, 12,  5, 20,  5),
  345         FMUX(0x17c,        core_pwr_req,           core,  rsvd1, rsvd2, rsvd3,   0x94c, 12,  5, 20,  5),
  346         GMUX(0x180, BB, 0, aud_mclk_pbb0,           aud,  rsvd1, rsvd2, rsvd3,   0x8f4, 12,  5, 20,  5),
  347         GMUX(0x184, BB, 1, dvfs_pwm_pbb1,         rsvd0, cldvfs,  spi3, rsvd3,   0x9a4, 12,  5, 20,  5),
  348         GMUX(0x188, BB, 2, dvfs_clk_pbb2,         rsvd0, cldvfs,  spi3, rsvd3,   0x9a0, 12,  5, 20,  5),
  349         GMUX(0x18c, BB, 3, gpio_x1_aud_pbb3,      rsvd0,  rsvd1,  spi3, rsvd3,   0xa14, 12,  5, 20,  5),
  350         GMUX(0x190, BB, 4, gpio_x3_aud_pbb4,      rsvd0,  rsvd1,  spi3, rsvd3,   0xa18, 12,  5, 20,  5),
  351         GMUX(0x194, CC, 7, pcc7,                  rsvd0,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  352         GMUX(0x198, CC, 0, hdmi_cec_pcc0,           cec,  rsvd1, rsvd2, rsvd3,   0xa24, 12,  5, 20,  5),
  353         GMUX(0x19c, CC, 1, hdmi_int_dp_hpd_pcc1,     dp,  rsvd1, rsvd2, rsvd3,   0xa28, 12,  5, 20,  5),
  354         GMUX(0x1a0, CC, 2, spdif_out_pcc2,        spdif,  rsvd1, rsvd2, rsvd3,   0xad0, 12,  5, 20,  5),
  355         GMUX(0x1a4, CC, 3, spdif_in_pcc3,         spdif,  rsvd1, rsvd2, rsvd3,   0xacc, 12,  5, 20,  5),
  356         GMUX(0x1a8, CC, 4, usb_vbus_en0_pcc4,       usb,  rsvd1, rsvd2, rsvd3,   0xb5c, 12,  5, 20,  5),
  357         GMUX(0x1ac, CC, 5, usb_vbus_en1_pcc5,       usb,  rsvd1, rsvd2, rsvd3,   0xb60, 12,  5, 20,  5),
  358         GMUX(0x1b0, CC, 6, dp_hpd0_pcc6,             dp,  rsvd1, rsvd2, rsvd3,   0x99c, 12,  5, 20,  5),
  359         GMUX(0x1b4,  H, 0, wifi_en_ph0,           rsvd0,  rsvd1, rsvd2, rsvd3,   0xb64, 12,  5, 20,  5),
  360         GMUX(0x1b8,  H, 1, wifi_rst_ph1,          rsvd0,  rsvd1, rsvd2, rsvd3,   0xb68, 12,  5, 20,  5),
  361         GMUX(0x1bc,  H, 2, wifi_wake_ap_ph2,      rsvd0,  rsvd1, rsvd2, rsvd3,   0xb6c, 12,  5, 20,  5),
  362         GMUX(0x1c0,  H, 3, ap_wake_bt_ph3,        rsvd0,  uartb, spdif, rsvd3,   0x8ec, 12,  5, 20,  5),
  363         GMUX(0x1c4,  H, 4, bt_rst_ph4,            rsvd0,  uartb, spdif, rsvd3,   0x8fc, 12,  5, 20,  5),
  364         GMUX(0x1c8,  H, 5, bt_wake_ap_ph5,        rsvd0,  rsvd1, rsvd2, rsvd3,   0x900, 12,  5, 20,  5),
  365         GMUX(0x1cc,  H, 7, ap_wake_nfc_ph7,       rsvd0,  rsvd1, rsvd2, rsvd3,   0x8f0, 12,  5, 20,  5),
  366         GMUX(0x1d0,  I, 0, nfc_en_pi0,            rsvd0,  rsvd1, rsvd2, rsvd3,   0xa50, 12,  5, 20,  5),
  367         GMUX(0x1d4,  I, 1, nfc_int_pi1,           rsvd0,  rsvd1, rsvd2, rsvd3,   0xa54, 12,  5, 20,  5),
  368         GMUX(0x1d8,  I, 2, gps_en_pi2,            rsvd0,  rsvd1, rsvd2, rsvd3,   0xa1c, 12,  5, 20,  5),
  369         GMUX(0x1dc,  I, 3, gps_rst_pi3,           rsvd0,  rsvd1, rsvd2, rsvd3,   0xa20, 12,  5, 20,  5),
  370         GMUX(0x1e0,  S, 4, cam_rst_ps4,            vgp1,  rsvd1, rsvd2, rsvd3,   0x93c, 12,  5, 20,  5),
  371         GMUX(0x1e4,  S, 5, cam_af_en_ps5,        vimclk,   vgp2, rsvd2, rsvd3,   0x92c, 12,  5, 20,  5),
  372         GMUX(0x1e8,  S, 6, cam_flash_en_ps6,     vimclk,   vgp3, rsvd2, rsvd3,   0x930, 12,  5, 20,  5),
  373         GMUX(0x1ec,  S, 7, cam1_pwdn_ps7,          vgp4,  rsvd1, rsvd2, rsvd3,   0x91c, 12,  5, 20,  5),
  374         GMUX(0x1f0,  T, 0, cam2_pwdn_pt0,          vgp5,  rsvd1, rsvd2, rsvd3,   0x928, 12,  5, 20,  5),
  375         GMUX(0x1f4,  T, 1, cam1_strobe_pt1,        vgp6,  rsvd1, rsvd2, rsvd3,   0x920, 12,  5, 20,  5),
  376         GMUX(0x1f8,  Y, 2, lcd_te_py2,         displaya,  rsvd1, rsvd2, rsvd3,   0xa44, 12,  5, 20,  5),
  377         GMUX(0x1fc,  V, 0, lcd_bl_pwm_pv0,     displaya,   pwm0,  sor0, rsvd3,   0xa34, 12,  5, 20,  5),
  378         GMUX(0x200,  V, 1, lcd_bl_en_pv1,         rsvd0,  rsvd1, rsvd2, rsvd3,   0xa30, 12,  5, 20,  5),
  379         GMUX(0x204,  V, 2, lcd_rst_pv2,           rsvd0,  rsvd1, rsvd2, rsvd3,   0xa40, 12,  5, 20,  5),
  380         GMUX(0x208,  V, 3, lcd_gpio1_pv3,      displayb,  rsvd1, rsvd2, rsvd3,   0xa38, 12,  5, 20,  5),
  381         GMUX(0x20c,  V, 4, lcd_gpio2_pv4,      displayb,   pwm1, rsvd2,  sor1,   0xa3c, 12,  5, 20,  5),
  382         GMUX(0x210,  V, 5, ap_ready_pv5,          rsvd0,  rsvd1, rsvd2, rsvd3,   0x8e8, 12,  5, 20,  5),
  383         GMUX(0x214,  V, 6, touch_rst_pv6,         rsvd0,  rsvd1, rsvd2, rsvd3,   0xb18, 12,  5, 20,  5),
  384         GMUX(0x218,  V, 7, touch_clk_pv7,         touch,  rsvd1, rsvd2, rsvd3,   0xb10, 12,  5, 20,  5),
  385         GMUX(0x21c,  X, 0, modem_wake_ap_px0,     rsvd0,  rsvd1, rsvd2, rsvd3,   0xa48, 12,  5, 20,  5),
  386         GMUX(0x220,  X, 1, touch_int_px1,         rsvd0,  rsvd1, rsvd2, rsvd3,   0xb14, 12,  5, 20,  5),
  387         GMUX(0x224,  X, 2, motion_int_px2,        rsvd0,  rsvd1, rsvd2, rsvd3,   0xa4c, 12,  5, 20,  5),
  388         GMUX(0x228,  X, 3, als_prox_int_px3,      rsvd0,  rsvd1, rsvd2, rsvd3,   0x8e4, 12,  5, 20,  5),
  389         GMUX(0x22c,  X, 4, temp_alert_px4,        rsvd0,  rsvd1, rsvd2, rsvd3,   0xb0c, 12,  5, 20,  5),
  390         GMUX(0x230,  X, 5, button_power_on_px5,   rsvd0,  rsvd1, rsvd2, rsvd3,   0x908, 12,  5, 20,  5),
  391         GMUX(0x234,  X, 6, button_vol_up_px6,     rsvd0,  rsvd1, rsvd2, rsvd3,   0x914, 12,  5, 20,  5),
  392         GMUX(0x238,  X, 7, button_vol_down_px7,   rsvd0,  rsvd1, rsvd2, rsvd3,   0x910, 12,  5, 20,  5),
  393         GMUX(0x23c,  Y, 0, button_slide_sw_py0,   rsvd0,  rsvd1, rsvd2, rsvd3,   0x90c, 12,  5, 20,  5),
  394         GMUX(0x240,  Y, 1, button_home_py1,       rsvd0,  rsvd1, rsvd2, rsvd3,   0x904, 12,  5, 20,  5),
  395         GMUX(0x244,  A, 6, pa6,                   sata,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  396         GMUX(0x248,  E, 6, pe6,                   rsvd0,  i2s5a,  pwm2, rsvd3,      -1,  0,  0,  0,  0),
  397         GMUX(0x24c,  E, 7, pe7,                   rsvd0,  i2s5a,  pwm3, rsvd3,      -1,  0,  0,  0,  0),
  398         GMUX(0x250,  H, 6, ph6,                   rsvd0,  rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  399         GMUX(0x254,  K, 0, pk0,                   iqc0,   i2s5b, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  400         GMUX(0x258,  K, 1, pk1,                   iqc0,   i2s5b, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  401         GMUX(0x25c,  K, 2, pk2,                   iqc0,   i2s5b, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  402         GMUX(0x260,  K, 3, pk3,                   iqc0,   i2s5b, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  403         GMUX(0x264,  K, 4, pk4,                   iqc1,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  404         GMUX(0x268,  K, 5, pk5,                   iqc1,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  405         GMUX(0x26c,  K, 6, pk6,                   iqc1,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  406         GMUX(0x270,  K, 7, pk7,                   iqc1,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  407         GMUX(0x274,  L, 0, pl0,                  rsvd0,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  408         GMUX(0x278,  L, 1, pl1,                    soc,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  409         GMUX(0x27c,  Z, 0, pz0,                vimclk2,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  410         GMUX(0x280,  Z, 1, pz1,                vimclk2,  sdmmc1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  411         GMUX(0x284,  Z, 2, pz2,                 sdmmc3,    ccla, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  412         GMUX(0x288,  Z, 3, pz3,                 sdmmc3,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  413         GMUX(0x28c,  Z, 4, pz4,                 sdmmc1,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  414         GMUX(0x290,  Z, 5, pz5,                    soc,   rsvd1, rsvd2, rsvd3,      -1,  0,  0,  0,  0),
  415 };
  416 
  417 
  418 static const struct tegra_grp *
  419 pinmux_search_grp(char *grp_name)
  420 {
  421         int i;
  422 
  423         for (i = 0; i < nitems(pin_grp_tbl); i++) {
  424                 if (strcmp(grp_name, pin_grp_tbl[i].name) == 0)
  425                         return  (&pin_grp_tbl[i]);
  426         }
  427         return (NULL);
  428 }
  429 
  430 static const struct tegra_mux *
  431 pinmux_search_mux(char *pin_name)
  432 {
  433         int i;
  434 
  435         for (i = 0; i < nitems(pin_mux_tbl); i++) {
  436                 if (strcmp(pin_name, pin_mux_tbl[i].name) == 0)
  437                         return  (&pin_mux_tbl[i]);
  438         }
  439         return (NULL);
  440 }
  441 
  442 static int
  443 pinmux_mux_function(const struct tegra_mux *mux, char *fnc_name)
  444 {
  445         int i;
  446 
  447         for (i = 0; i < 4; i++) {
  448                 if (strcmp(fnc_name, mux->functions[i]) == 0)
  449                         return  (i);
  450         }
  451         return (-1);
  452 }
  453 
  454 static int
  455 pinmux_config_mux(struct pinmux_softc *sc, char *pin_name,
  456     const struct tegra_mux *mux, struct pincfg *cfg)
  457 {
  458         int tmp;
  459         uint32_t reg;
  460 
  461         reg = bus_read_4(sc->mux_mem_res, mux->reg);
  462 
  463         if (cfg->function != NULL) {
  464                 tmp = pinmux_mux_function(mux, cfg->function);
  465                 if (tmp == -1) {
  466                         device_printf(sc->dev,
  467                             "Unknown function %s for pin %s\n", cfg->function,
  468                             pin_name);
  469                         return (ENXIO);
  470                 }
  471                 reg &= ~(TEGRA_MUX_FUNCTION_MASK << TEGRA_MUX_FUNCTION_SHIFT);
  472                 reg |=  (tmp & TEGRA_MUX_FUNCTION_MASK) <<
  473                     TEGRA_MUX_FUNCTION_SHIFT;
  474         }
  475         if (cfg->params[PROP_ID_PULL] != -1) {
  476                 reg &= ~(TEGRA_MUX_PUPD_MASK << TEGRA_MUX_PUPD_SHIFT);
  477                 reg |=  (cfg->params[PROP_ID_PULL] & TEGRA_MUX_PUPD_MASK) <<
  478                     TEGRA_MUX_PUPD_SHIFT;
  479         }
  480         if (cfg->params[PROP_ID_TRISTATE] != -1) {
  481                 reg &= ~(1 << TEGRA_MUX_TRISTATE_SHIFT);
  482                 reg |=  (cfg->params[PROP_ID_TRISTATE] & 1) <<
  483                     TEGRA_MUX_TRISTATE_SHIFT;
  484         }
  485         if (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] != -1) {
  486                 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
  487                 reg |=  (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] & 1) <<
  488                     TEGRA_MUX_ENABLE_INPUT_SHIFT;
  489         }
  490         if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
  491                 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
  492                 reg |=  (cfg->params[PROP_ID_ENABLE_INPUT] & 1) <<
  493                     TEGRA_MUX_ENABLE_INPUT_SHIFT;
  494         }
  495         if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
  496                 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
  497                 reg |=  (cfg->params[PROP_ID_OPEN_DRAIN] & 1) <<
  498                     TEGRA_MUX_ENABLE_INPUT_SHIFT;
  499         }
  500         if (cfg->params[PROP_ID_LOCK] != -1) {
  501                 reg &= ~(1 << TEGRA_MUX_LOCK_SHIFT);
  502                 reg |=  (cfg->params[PROP_ID_LOCK] & 1) <<
  503                     TEGRA_MUX_LOCK_SHIFT;
  504         }
  505         if (cfg->params[PROP_ID_IORESET] != -1) {
  506                 reg &= ~(1 << TEGRA_MUX_IORESET_SHIFT);
  507                 reg |=  (cfg->params[PROP_ID_IORESET] & 1) <<
  508                     TEGRA_MUX_IORESET_SHIFT;
  509         }
  510         if (cfg->params[PROP_ID_RCV_SEL] != -1) {
  511                 reg &= ~(1 << TEGRA_MUX_RCV_SEL_SHIFT);
  512                 reg |=  (cfg->params[PROP_ID_RCV_SEL] & 1) <<
  513                     TEGRA_MUX_RCV_SEL_SHIFT;
  514         }
  515         bus_write_4(sc->mux_mem_res, mux->reg, reg);
  516         return (0);
  517 }
  518 
  519 static int
  520 pinmux_config_grp(struct pinmux_softc *sc, char *grp_name,
  521     const struct tegra_grp *grp, struct pincfg *cfg)
  522 {
  523         uint32_t reg;
  524 
  525         reg = bus_read_4(sc->pad_mem_res, grp->reg);
  526 
  527         if (cfg->params[PROP_ID_HIGH_SPEED_MODE] != -1) {
  528                 reg &= ~(1 << TEGRA_GRP_HSM_SHIFT);
  529                 reg |=  (cfg->params[PROP_ID_HIGH_SPEED_MODE] & 1) <<
  530                     TEGRA_GRP_HSM_SHIFT;
  531         }
  532         if (cfg->params[PROP_ID_SCHMITT] != -1) {
  533                 reg &= ~(1 << TEGRA_GRP_SCHMT_SHIFT);
  534                 reg |=  (cfg->params[PROP_ID_SCHMITT] & 1) <<
  535                     TEGRA_GRP_SCHMT_SHIFT;
  536         }
  537         if (cfg->params[PROP_ID_DRIVE_TYPE] != -1) {
  538                 reg &= ~(TEGRA_GRP_DRV_TYPE_MASK << TEGRA_GRP_DRV_TYPE_SHIFT);
  539                 reg |=  (cfg->params[PROP_ID_DRIVE_TYPE] &
  540                     TEGRA_GRP_DRV_TYPE_MASK) << TEGRA_GRP_DRV_TYPE_SHIFT;
  541         }
  542         if (cfg->params[PROP_ID_SLEW_RATE_RISING] != -1) {
  543                 reg &= ~(TEGRA_GRP_DRV_DRVDN_SLWR_MASK <<
  544                     TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT);
  545                 reg |=  (cfg->params[PROP_ID_SLEW_RATE_RISING] &
  546                     TEGRA_GRP_DRV_DRVDN_SLWR_MASK) <<
  547                     TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT;
  548         }
  549         if (cfg->params[PROP_ID_SLEW_RATE_FALLING] != -1) {
  550                 reg &= ~(TEGRA_GRP_DRV_DRVUP_SLWF_MASK <<
  551                     TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT);
  552                 reg |=  (cfg->params[PROP_ID_SLEW_RATE_FALLING] &
  553                     TEGRA_GRP_DRV_DRVUP_SLWF_MASK) <<
  554                     TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT;
  555         }
  556         if ((cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] != -1) &&
  557                  (grp->drvdn_mask != 0)) {
  558                 reg &= ~(grp->drvdn_shift << grp->drvdn_mask);
  559                 reg |=  (cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] &
  560                     grp->drvdn_mask) << grp->drvdn_shift;
  561         }
  562         if ((cfg->params[PROP_ID_DRIVE_UP_STRENGTH] != -1) &&
  563                  (grp->drvup_mask != 0)) {
  564                 reg &= ~(grp->drvup_shift << grp->drvup_mask);
  565                 reg |=  (cfg->params[PROP_ID_DRIVE_UP_STRENGTH] &
  566                     grp->drvup_mask) << grp->drvup_shift;
  567         }
  568         bus_write_4(sc->pad_mem_res, grp->reg, reg);
  569         return (0);
  570 }
  571 
  572 static int
  573 pinmux_config_node(struct pinmux_softc *sc, char *pin_name, struct pincfg *cfg)
  574 {
  575         const struct tegra_mux *mux;
  576         const struct tegra_grp *grp;
  577         bool handled;
  578         int rv;
  579 
  580         /* Handle pin muxes */
  581         mux = pinmux_search_mux(pin_name);
  582         handled = false;
  583         if (mux != NULL) {
  584                 if (mux->gpio_num != -1) {
  585                         /* XXXX TODO: Reserve gpio here */
  586                 }
  587                 rv = pinmux_config_mux(sc, pin_name, mux, cfg);
  588                 if (rv != 0)
  589                         return (rv);
  590                 if (mux->grp.reg <= 0) {
  591                         rv = pinmux_config_grp(sc, pin_name, &mux->grp, cfg);
  592                         return (rv);
  593                 }
  594                 handled = true;
  595         }
  596 
  597         /* And/or handle pin groups */
  598         grp = pinmux_search_grp(pin_name);
  599         if (grp != NULL) {
  600                 rv = pinmux_config_grp(sc, pin_name, grp, cfg);
  601                 if (rv != 0)
  602                         return (rv);
  603                 handled = true;
  604         }
  605 
  606         if (!handled) {
  607                 device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
  608                 return (ENXIO);
  609         }
  610         return (0);
  611 }
  612 
  613 static int
  614 pinmux_read_node(struct pinmux_softc *sc, phandle_t node, struct pincfg *cfg,
  615     char **pins, int *lpins)
  616 {
  617         int rv, i;
  618 
  619         *lpins = OF_getprop_alloc(node, "nvidia,pins", (void **)pins);
  620         if (*lpins <= 0)
  621                 return (ENOENT);
  622 
  623         /* Read function (mux) settings. */
  624         rv = OF_getprop_alloc(node, "nvidia,function", (void **)&cfg->function);
  625         if (rv <= 0)
  626                 cfg->function = NULL;
  627 
  628         /* Read numeric properties. */
  629         for (i = 0; i < PROP_ID_MAX_ID; i++) {
  630                 rv = OF_getencprop(node, prop_names[i].name, &cfg->params[i],
  631                     sizeof(cfg->params[i]));
  632                 if (rv <= 0)
  633                         cfg->params[i] = -1;
  634         }
  635         return (0);
  636 }
  637 
  638 static int
  639 pinmux_process_node(struct pinmux_softc *sc, phandle_t node)
  640 {
  641         struct pincfg cfg;
  642         char *pins, *pname;
  643         int i, len, lpins, rv;
  644 
  645         rv = pinmux_read_node(sc, node, &cfg, &pins, &lpins);
  646         if (rv != 0)
  647                 return (rv);
  648 
  649         len = 0;
  650         pname = pins;
  651         do {
  652                 i = strlen(pname) + 1;
  653                 rv = pinmux_config_node(sc, pname, &cfg);
  654                 if (rv != 0)
  655                         device_printf(sc->dev, "Cannot configure pin: %s: %d\n",
  656                             pname, rv);
  657                 len += i;
  658                 pname += i;
  659         } while (len < lpins);
  660 
  661         if (pins != NULL)
  662                 OF_prop_free(pins);
  663         if (cfg.function != NULL)
  664                 OF_prop_free(cfg.function);
  665         return (rv);
  666 }
  667 
  668 static int pinmux_configure(device_t dev, phandle_t cfgxref)
  669 {
  670         struct pinmux_softc *sc;
  671         phandle_t node, cfgnode;
  672 
  673         sc = device_get_softc(dev);
  674         cfgnode = OF_node_from_xref(cfgxref);
  675 
  676 
  677         for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
  678                 if (!ofw_bus_node_status_okay(node))
  679                         continue;
  680                 pinmux_process_node(sc, node);
  681         }
  682         return (0);
  683 }
  684 
  685 static int
  686 pinmux_probe(device_t dev)
  687 {
  688 
  689         if (!ofw_bus_status_okay(dev))
  690                 return (ENXIO);
  691 
  692         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
  693                 return (ENXIO);
  694 
  695         device_set_desc(dev, "Tegra pin configuration");
  696         return (BUS_PROBE_DEFAULT);
  697 }
  698 
  699 static int
  700 pinmux_detach(device_t dev)
  701 {
  702 
  703         /* This device is always present. */
  704         return (EBUSY);
  705 }
  706 
  707 static int
  708 pinmux_attach(device_t dev)
  709 {
  710         struct pinmux_softc * sc;
  711         int rid;
  712 
  713         sc = device_get_softc(dev);
  714         sc->dev = dev;
  715 
  716         rid = 0;
  717         sc->pad_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  718             RF_ACTIVE);
  719         if (sc->pad_mem_res == NULL) {
  720                 device_printf(dev, "Cannot allocate memory resources\n");
  721                 return (ENXIO);
  722         }
  723 
  724         rid = 1;
  725         sc->mux_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  726             RF_ACTIVE);
  727         if (sc->mux_mem_res == NULL) {
  728                 device_printf(dev, "Cannot allocate memory resources\n");
  729                 return (ENXIO);
  730         }
  731 
  732 
  733         /* Register as a pinctrl device and process default configuration */
  734         fdt_pinctrl_register(dev, NULL);
  735         fdt_pinctrl_configure_by_name(dev, "boot");
  736 
  737         return (0);
  738 }
  739 
  740 
  741 static device_method_t tegra210_pinmux_methods[] = {
  742         /* Device interface */
  743         DEVMETHOD(device_probe,         pinmux_probe),
  744         DEVMETHOD(device_attach,        pinmux_attach),
  745         DEVMETHOD(device_detach,        pinmux_detach),
  746 
  747         /* fdt_pinctrl interface */
  748         DEVMETHOD(fdt_pinctrl_configure,pinmux_configure),
  749 
  750         DEVMETHOD_END
  751 };
  752 
  753 static DEFINE_CLASS_0(pinmux, tegra210_pinmux_driver, tegra210_pinmux_methods,
  754     sizeof(struct pinmux_softc));
  755 EARLY_DRIVER_MODULE(tegra210_pinmux, simplebus, tegra210_pinmux_driver,
  756     NULL, NULL, 71);

Cache object: 56afa9e25852b95fde985562cfaf865c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.