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/arm/nvidia/tegra_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  * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 /*
   31  * Pin multiplexer driver for Tegra SoCs.
   32  */
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/bus.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/malloc.h>
   39 #include <sys/rman.h>
   40 
   41 #include <machine/bus.h>
   42 #include <machine/fdt.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 /* Pin goup register. */
   63 #define TEGRA_GRP_HSM_SHIFT 2
   64 #define TEGRA_GRP_SCHMT_SHIFT 3
   65 #define TEGRA_GRP_DRV_TYPE_SHIFT 6
   66 #define TEGRA_GRP_DRV_TYPE_MASK 0x03
   67 #define TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT 28
   68 #define TEGRA_GRP_DRV_DRVDN_SLWR_MASK 0x03
   69 #define TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT 30
   70 #define TEGRA_GRP_DRV_DRVUP_SLWF_MASK 0x03
   71 
   72 struct pinmux_softc {
   73         device_t        dev;
   74         struct resource *pad_mem_res;
   75         struct resource *mux_mem_res;
   76         struct resource *mipi_mem_res;
   77 };
   78 
   79 static struct ofw_compat_data compat_data[] = {
   80         {"nvidia,tegra124-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,high-speed-mode",      PROP_ID_HIGH_SPEED_MODE},
  117         {"nvidia,schmitt",              PROP_ID_SCHMITT},
  118         {"nvidia,low-power-mode",       PROP_ID_LOW_POWER_MODE},
  119         {"nvidia,pull-down-strength",   PROP_ID_DRIVE_DOWN_STRENGTH},
  120         {"nvidia,pull-up-strength",     PROP_ID_DRIVE_UP_STRENGTH},
  121         {"nvidia,slew-rate-falling",    PROP_ID_SLEW_RATE_FALLING},
  122         {"nvidia,slew-rate-rising",     PROP_ID_SLEW_RATE_RISING},
  123         {"nvidia,drive-type",           PROP_ID_DRIVE_TYPE},
  124 };
  125 
  126 /*
  127  * configuration for one pin group.
  128  */
  129 struct pincfg {
  130         char    *function;
  131         int     params[PROP_ID_MAX_ID];
  132 };
  133 #define GPIO_BANK_A      0
  134 #define GPIO_BANK_B      1
  135 #define GPIO_BANK_C      2
  136 #define GPIO_BANK_D      3
  137 #define GPIO_BANK_E      4
  138 #define GPIO_BANK_F      5
  139 #define GPIO_BANK_G      6
  140 #define GPIO_BANK_H      7
  141 #define GPIO_BANK_I      8
  142 #define GPIO_BANK_J      9
  143 #define GPIO_BANK_K     10
  144 #define GPIO_BANK_L     11
  145 #define GPIO_BANK_M     12
  146 #define GPIO_BANK_N     13
  147 #define GPIO_BANK_O     14
  148 #define GPIO_BANK_P     15
  149 #define GPIO_BANK_Q     16
  150 #define GPIO_BANK_R     17
  151 #define GPIO_BANK_S     18
  152 #define GPIO_BANK_T     19
  153 #define GPIO_BANK_U     20
  154 #define GPIO_BANK_V     21
  155 #define GPIO_BANK_W     22
  156 #define GPIO_BANK_X     23
  157 #define GPIO_BANK_Y     24
  158 #define GPIO_BANK_Z     25
  159 #define GPIO_BANK_AA    26
  160 #define GPIO_BANK_BB    27
  161 #define GPIO_BANK_CC    28
  162 #define GPIO_BANK_DD    29
  163 #define GPIO_BANK_EE    30
  164 #define GPIO_BANK_FF    31
  165 #define GPIO_NUM(b, p) (8 * (b) + (p))
  166 
  167 struct tegra_mux {
  168         char *name;
  169         bus_size_t reg;
  170         char *functions[4];
  171         int gpio_num;
  172 };
  173 
  174 #define GMUX(r, gb, gi, nm, f1, f2, f3, f4)                             \
  175 {                                                                       \
  176         .name = #nm,                                                    \
  177         .reg = r,                                                       \
  178         .gpio_num = GPIO_NUM(GPIO_BANK_##gb, gi),                       \
  179         .functions = {#f1, #f2, #f3, #f4},                              \
  180 }
  181 
  182 #define FMUX(r, nm, f1, f2, f3, f4)                                     \
  183 {                                                                       \
  184         .name = #nm,                                                    \
  185         .reg = r,                                                       \
  186         .gpio_num = -1,                                                 \
  187         .functions = {#f1, #f2, #f3, #f4},                              \
  188 }
  189 
  190 static const struct tegra_mux pin_mux_tbl[] = {
  191         GMUX(0x000,  O, 1, ulpi_data0_po1,         spi3,       hsi,        uarta,        ulpi),
  192         GMUX(0x004,  O, 2, ulpi_data1_po2,         spi3,       hsi,        uarta,        ulpi),
  193         GMUX(0x008,  O, 3, ulpi_data2_po3,         spi3,       hsi,        uarta,        ulpi),
  194         GMUX(0x00C,  O, 4, ulpi_data3_po4,         spi3,       hsi,        uarta,        ulpi),
  195         GMUX(0x010,  O, 5, ulpi_data4_po5,         spi2,       hsi,        uarta,        ulpi),
  196         GMUX(0x014,  O, 6, ulpi_data5_po6,         spi2,       hsi,        uarta,        ulpi),
  197         GMUX(0x018,  O, 7, ulpi_data6_po7,         spi2,       hsi,        uarta,        ulpi),
  198         GMUX(0x01C,  O, 0, ulpi_data7_po0,         spi2,       hsi,        uarta,        ulpi),
  199         GMUX(0x020,  P, 9, ulpi_clk_py0,           spi1,       spi5,       uartd,        ulpi),
  200         GMUX(0x024,  P, 1, ulpi_dir_py1,           spi1,       spi5,       uartd,        ulpi),
  201         GMUX(0x028,  P, 2, ulpi_nxt_py2,           spi1,       spi5,       uartd,        ulpi),
  202         GMUX(0x02C,  P, 3, ulpi_stp_py3,           spi1,       spi5,       uartd,        ulpi),
  203         GMUX(0x030,  P, 0, dap3_fs_pp0,            i2s2,       spi5,       displaya,     displayb),
  204         GMUX(0x034,  P, 1, dap3_din_pp1,           i2s2,       spi5,       displaya,     displayb),
  205         GMUX(0x038,  P, 2, dap3_dout_pp2,          i2s2,       spi5,       displaya,     rsvd4),
  206         GMUX(0x03C,  P, 3, dap3_sclk_pp3,          i2s2,       spi5,       rsvd3,        displayb),
  207         GMUX(0x040,  V, 0, pv0,                    rsvd1,      rsvd2,      rsvd3,        rsvd4),
  208         GMUX(0x044,  V, 1, pv1,                    rsvd1,      rsvd2,      rsvd3,        rsvd4),
  209         GMUX(0x048,  Z, 0, sdmmc1_clk_pz0,         sdmmc1,     clk12,      rsvd3,        rsvd4),
  210         GMUX(0x04C,  Z, 1, sdmmc1_cmd_pz1,         sdmmc1,     spdif,      spi4,         uarta),
  211         GMUX(0x050,  Y, 4, sdmmc1_dat3_py4,        sdmmc1,     spdif,      spi4,         uarta),
  212         GMUX(0x054,  Y, 5, sdmmc1_dat2_py5,        sdmmc1,     pwm0,       spi4,         uarta),
  213         GMUX(0x058,  Y, 6, sdmmc1_dat1_py6,        sdmmc1,     pwm1,       spi4,         uarta),
  214         GMUX(0x05C,  Y, 7, sdmmc1_dat0_py7,        sdmmc1,     rsvd2,      spi4,         uarta),
  215         GMUX(0x068,  W, 5, clk2_out_pw5,           extperiph2, rsvd2,      rsvd3,        rsvd4),
  216         GMUX(0x06C, CC, 5, clk2_req_pcc5,          dap,        rsvd2,      rsvd3,        rsvd4),
  217         GMUX(0x110,  N, 7, hdmi_int_pn7,           rsvd1,      rsvd2,      rsvd3,        rsvd4),
  218         GMUX(0x114,  V, 4, ddc_scl_pv4,            i2c4,       rsvd2,      rsvd3,        rsvd4),
  219         GMUX(0x118,  V, 5, ddc_sda_pv5,            i2c4,       rsvd2,      rsvd3,        rsvd4),
  220         GMUX(0x164,  V, 3, uart2_rxd_pc3,          irda,       spdif,      uarta,        spi4),
  221         GMUX(0x168,  C, 2, uart2_txd_pc2,          irda,       spdif,      uarta,        spi4),
  222         GMUX(0x16C,  J, 6, uart2_rts_n_pj6,        uarta,      uartb,      gmi,          spi4),
  223         GMUX(0x170,  J, 5, uart2_cts_n_pj5,        uarta,      uartb,      gmi,          spi4),
  224         GMUX(0x174,  W, 6, uart3_txd_pw6,          uartc,      rsvd2,      gmi,          spi4),
  225         GMUX(0x178,  W, 7, uart3_rxd_pw7,          uartc,      rsvd2,      gmi,          spi4),
  226         GMUX(0x17C,  S, 1, uart3_cts_n_pa1,        uartc,      sdmmc1,     dtv,          gmi),
  227         GMUX(0x180,  C, 0, uart3_rts_n_pc0,        uartc,      pwm0,       dtv,          gmi),
  228         GMUX(0x184,  U, 0, pu0,                    owr,        uarta,      gmi,          rsvd4),
  229         GMUX(0x188,  U, 1, pu1,                    rsvd1,      uarta,      gmi,          rsvd4),
  230         GMUX(0x18C,  U, 2, pu2,                    rsvd1,      uarta,      gmi,          rsvd4),
  231         GMUX(0x190,  U, 3, pu3,                    pwm0,       uarta,      gmi,          displayb),
  232         GMUX(0x194,  U, 4, pu4,                    pwm1,       uarta,      gmi,          displayb),
  233         GMUX(0x198,  U, 5, pu5,                    pwm2,       uarta,      gmi,          displayb),
  234         GMUX(0x19C,  U, 6, pu6,                    pwm3,       uarta,      rsvd3,        gmi),
  235         GMUX(0x1A0,  C, 5, gen1_i2c_sda_pc5,       i2c1,       rsvd2,      rsvd3,        rsvd4),
  236         GMUX(0x1A4,  C, 4, gen1_i2c_scl_pc4,       i2c1,       rsvd2,      rsvd3,        rsvd4),
  237         GMUX(0x1A8,  P, 3, dap4_fs_pp4,            i2s3,       gmi,        dtv,          rsvd4),
  238         GMUX(0x1AC,  P, 4, dap4_din_pp5,           i2s3,       gmi,        rsvd3,        rsvd4),
  239         GMUX(0x1B0,  P, 5, dap4_dout_pp6,          i2s3,       gmi,        dtv,          rsvd4),
  240         GMUX(0x1B4,  P, 7, dap4_sclk_pp7,          i2s3,       gmi,        rsvd3,        rsvd4),
  241         GMUX(0x1B8,  P, 0, clk3_out_pee0,          extperiph3, rsvd2,      rsvd3,        rsvd4),
  242         GMUX(0x1BC, EE, 1, clk3_req_pee1,          dev3,       rsvd2,      rsvd3,        rsvd4),
  243         GMUX(0x1C0,  C, 7, pc7,                    rsvd1,      rsvd2,      gmi,          gmi_alt),
  244         GMUX(0x1C4,  I, 5, pi5,                    sdmmc2,     rsvd2,      gmi,          rsvd4),
  245         GMUX(0x1C8,  I, 7, pi7,                    rsvd1,      trace,      gmi,          dtv),
  246         GMUX(0x1CC,  K, 0, pk0,                    rsvd1,      sdmmc3,     gmi,          soc),
  247         GMUX(0x1D0,  K, 1, pk1,                    sdmmc2,     trace,      gmi,          rsvd4),
  248         GMUX(0x1D4,  J, 0, pj0,                    rsvd1,      rsvd2,      gmi,          usb),
  249         GMUX(0x1D8,  J, 2, pj2,                    rsvd1,      rsvd2,      gmi,          soc),
  250         GMUX(0x1DC,  K, 3, pk3,                    sdmmc2,     trace,      gmi,          ccla),
  251         GMUX(0x1E0,  K, 4, pk4,                    sdmmc2,     rsvd2,      gmi,          gmi_alt),
  252         GMUX(0x1E4,  K, 2, pk2,                    rsvd1,      rsvd2,      gmi,          rsvd4),
  253         GMUX(0x1E8,  I, 3, pi3,                    rsvd1,      rsvd2,      gmi,          spi4),
  254         GMUX(0x1EC,  I, 6, pi6,                    rsvd1,      rsvd2,      gmi,          sdmmc2),
  255         GMUX(0x1F0,  G, 0, pg0,                    rsvd1,      rsvd2,      gmi,          rsvd4),
  256         GMUX(0x1F4,  G, 1, pg1,                    rsvd1,      rsvd2,      gmi,          rsvd4),
  257         GMUX(0x1F8,  G, 2, pg2,                    rsvd1,      trace,      gmi,          rsvd4),
  258         GMUX(0x1FC,  G, 3, pg3,                    rsvd1,      trace,      gmi,          rsvd4),
  259         GMUX(0x200,  G, 4, pg4,                    rsvd1,      tmds,       gmi,          spi4),
  260         GMUX(0x204,  G, 5, pg5,                    rsvd1,      rsvd2,      gmi,          spi4),
  261         GMUX(0x208,  G, 6, pg6,                    rsvd1,      rsvd2,      gmi,          spi4),
  262         GMUX(0x20C,  G, 7, pg7,                    rsvd1,      rsvd2,      gmi,          spi4),
  263         GMUX(0x210,  H, 0, ph0,                    pwm0,       trace,      gmi,          dtv),
  264         GMUX(0x214,  H, 1, ph1,                    pwm1,       tmds,       gmi,          displaya),
  265         GMUX(0x218,  H, 2, ph2,                    pwm2,       tmds,       gmi,          cldvfs),
  266         GMUX(0x21C,  H, 3, ph3,                    pwm3,       spi4,       gmi,          cldvfs),
  267         GMUX(0x220,  H, 4, ph4,                    sdmmc2,     rsvd2,      gmi,          rsvd4),
  268         GMUX(0x224,  H, 5, ph5,                    sdmmc2,     rsvd2,      gmi,          rsvd4),
  269         GMUX(0x228,  H, 6, ph6,                    sdmmc2,     trace,      gmi,          dtv),
  270         GMUX(0x22C,  H, 7, ph7,                    sdmmc2,     trace,      gmi,          dtv),
  271         GMUX(0x230,  J, 7, pj7,                    uartd,      rsvd2,      gmi,          gmi_alt),
  272         GMUX(0x234,  B, 0, pb0,                    uartd,      rsvd2,      gmi,          rsvd4),
  273         GMUX(0x238,  B, 1, pb1,                    uartd,      rsvd2,      gmi,          rsvd4),
  274         GMUX(0x23C,  K, 7, pk7,                    uartd,      rsvd2,      gmi,          rsvd4),
  275         GMUX(0x240,  I, 0, pi0,                    rsvd1,      rsvd2,      gmi,          rsvd4),
  276         GMUX(0x244,  I, 1, pi1,                    rsvd1,      rsvd2,      gmi,          rsvd4),
  277         GMUX(0x248,  I, 2, pi2,                    sdmmc2,     trace,      gmi,          rsvd4),
  278         GMUX(0x24C,  I, 4, pi4,                    spi4,       trace,      gmi,          displaya),
  279         GMUX(0x250,  T, 5, gen2_i2c_scl_pt5,       i2c2,       rsvd2,      gmi,          rsvd4),
  280         GMUX(0x254,  T, 6, gen2_i2c_sda_pt6,       i2c2,       rsvd2,      gmi,          rsvd4),
  281         GMUX(0x258, CC, 4, sdmmc4_clk_pcc4,        sdmmc4,     rsvd2,      gmi,          rsvd4),
  282         GMUX(0x25C,  T, 7, sdmmc4_cmd_pt7,         sdmmc4,     rsvd2,      gmi,          rsvd4),
  283         GMUX(0x260, AA, 0, sdmmc4_dat0_paa0,       sdmmc4,     spi3,       gmi,          rsvd4),
  284         GMUX(0x264, AA, 1, sdmmc4_dat1_paa1,       sdmmc4,     spi3,       gmi,          rsvd4),
  285         GMUX(0x268, AA, 2, sdmmc4_dat2_paa2,       sdmmc4,     spi3,       gmi,          rsvd4),
  286         GMUX(0x26C, AA, 3, sdmmc4_dat3_paa3,       sdmmc4,     spi3,       gmi,          rsvd4),
  287         GMUX(0x270, AA, 4, sdmmc4_dat4_paa4,       sdmmc4,     spi3,       gmi,          rsvd4),
  288         GMUX(0x274, AA, 5, sdmmc4_dat5_paa5,       sdmmc4,     spi3,       rsvd3,        rsvd4),
  289         GMUX(0x278, AA, 6, sdmmc4_dat6_paa6,       sdmmc4,     spi3,       gmi,          rsvd4),
  290         GMUX(0x27C, AA, 7, sdmmc4_dat7_paa7,       sdmmc4,     rsvd2,      gmi,          rsvd4),
  291         GMUX(0x284, CC, 0, cam_mclk_pcc0,          vi,         vi_alt1,    vi_alt3,      sdmmc2),
  292         GMUX(0x288, CC, 1, pcc1,                   i2s4,       rsvd2,      rsvd3,        sdmmc2),
  293         GMUX(0x28C, BB, 0, pbb0,                   vgp6,       vimclk2,    sdmmc2,       vimclk2_alt),
  294         GMUX(0x290, BB, 1, cam_i2c_scl_pbb1,       vgp1,       i2c3,       rsvd3,        sdmmc2),
  295         GMUX(0x294, BB, 2, cam_i2c_sda_pbb2,       vgp2,       i2c3,       rsvd3,        sdmmc2),
  296         GMUX(0x298, BB, 3, pbb3,                   vgp3,       displaya,   displayb,     sdmmc2),
  297         GMUX(0x29C, BB, 4, pbb4,                   vgp4,       displaya,   displayb,     sdmmc2),
  298         GMUX(0x2A0, BB, 5, pbb5,                   vgp5,       displaya,   rsvd3,        sdmmc2),
  299         GMUX(0x2A4, BB, 6, pbb6,                   i2s4,       rsvd2,      displayb,     sdmmc2),
  300         GMUX(0x2A8, BB, 7, pbb7,                   i2s4,       rsvd2,      rsvd3,        sdmmc2),
  301         GMUX(0x2AC, CC, 2, pcc2,                   i2s4,       rsvd2,      sdmmc3,       sdmmc2),
  302         FMUX(0x2B0,        jtag_rtck,              rtck,       rsvd2,      rsvd3,        rsvd4),
  303         GMUX(0x2B4,  Z, 6, pwr_i2c_scl_pz6,        i2cpwr,     rsvd2,      rsvd3,        rsvd4),
  304         GMUX(0x2B8,  Z, 7, pwr_i2c_sda_pz7,        i2cpwr,     rsvd2,      rsvd3,        rsvd4),
  305         GMUX(0x2BC,  R, 0, kb_row0_pr0,            kbc,        rsvd2,      rsvd3,        rsvd4),
  306         GMUX(0x2C0,  R, 1, kb_row1_pr1,            kbc,        rsvd2,      rsvd3,        rsvd4),
  307         GMUX(0x2C4,  R, 2, kb_row2_pr2,            kbc,        rsvd2,      rsvd3,        rsvd4),
  308         GMUX(0x2C8,  R, 3, kb_row3_pr3,            kbc,        displaya,   sys,          displayb),
  309         GMUX(0x2CC,  R, 4, kb_row4_pr4,            kbc,        displaya,   rsvd3,        displayb),
  310         GMUX(0x2D0,  R, 5, kb_row5_pr5,            kbc,        displaya,   rsvd3,        displayb),
  311         GMUX(0x2D4,  R, 6, kb_row6_pr6,            kbc,        displaya,   displaya_alt, displayb),
  312         GMUX(0x2D8,  R, 7, kb_row7_pr7,            kbc,        rsvd2,      cldvfs,       uarta),
  313         GMUX(0x2DC,  S, 0, kb_row8_ps0,            kbc,        rsvd2,      cldvfs,       uarta),
  314         GMUX(0x2E0,  S, 1, kb_row9_ps1,            kbc,        rsvd2,      rsvd3,        uarta),
  315         GMUX(0x2E4,  S, 2, kb_row10_ps2,           kbc,        rsvd2,      rsvd3,        uarta),
  316         GMUX(0x2E8,  S, 3, kb_row11_ps3,           kbc,        rsvd2,      rsvd3,        irda),
  317         GMUX(0x2EC,  S, 4, kb_row12_ps4,           kbc,        rsvd2,      rsvd3,        irda),
  318         GMUX(0x2F0,  S, 5, kb_row13_ps5,           kbc,        rsvd2,      spi2,         rsvd4),
  319         GMUX(0x2F4,  S, 6, kb_row14_ps6,           kbc,        rsvd2,      spi2,         rsvd4),
  320         GMUX(0x2F8,  S, 7, kb_row15_ps7,           kbc,        soc,        rsvd3,        rsvd4),
  321         GMUX(0x2FC,  Q, 0, kb_col0_pq0,            kbc,        rsvd2,      spi2,         rsvd4),
  322         GMUX(0x300,  Q, 1, kb_col1_pq1,            kbc,        rsvd2,      spi2,         rsvd4),
  323         GMUX(0x304,  Q, 2, kb_col2_pq2,            kbc,        rsvd2,      spi2,         rsvd4),
  324         GMUX(0x308,  Q, 3, kb_col3_pq3,            kbc,        displaya,   pwm2,         uarta),
  325         GMUX(0x30C,  Q, 4, kb_col4_pq4,            kbc,        owr,        sdmmc3,       uarta),
  326         GMUX(0x310,  Q, 5, kb_col5_pq5,            kbc,        rsvd2,      sdmmc3,       rsvd4),
  327         GMUX(0x314,  Q, 6, kb_col6_pq6,            kbc,        rsvd2,      spi2,         uartd),
  328         GMUX(0x318,  Q, 7, kb_col7_pq7,            kbc,        rsvd2,      spi2,         uartd),
  329         GMUX(0x31C,  A, 0, clk_32k_out_pa0,        blink,      soc,        rsvd3,        rsvd4),
  330         FMUX(0x324,        core_pwr_req,           pwron,      rsvd2,      rsvd3,        rsvd4),
  331         FMUX(0x328,        cpu_pwr_req,            cpu,        rsvd2,      rsvd3,        rsvd4),
  332         FMUX(0x32C,        pwr_int_n,              pmi,        rsvd2,      rsvd3,        rsvd4),
  333         FMUX(0x330,        clk_32k_in,             clk,        rsvd2,      rsvd3,        rsvd4),
  334         FMUX(0x334,        owr,                    owr,        rsvd2,      rsvd3,        rsvd4),
  335         GMUX(0x338,  N, 0, dap1_fs_pn0,            i2s0,       hda,        gmi,          rsvd4),
  336         GMUX(0x33C,  N, 1, dap1_din_pn1,           i2s0,       hda,        gmi,          rsvd4),
  337         GMUX(0x340,  N, 2, dap1_dout_pn2,          i2s0,       hda,        gmi,          sata),
  338         GMUX(0x344,  N, 3, dap1_sclk_pn3,          i2s0,       hda,        gmi,          rsvd4),
  339         GMUX(0x348, EE, 2, dap_mclk1_req_pee2,     dap,        dap1,       sata,         rsvd4),
  340         GMUX(0x34C,  W, 4, dap_mclk1_pw4,          extperiph1, dap2,       rsvd3,        rsvd4),
  341         GMUX(0x350,  K, 6, spdif_in_pk6,           spdif,      rsvd2,      rsvd3,        i2c3),
  342         GMUX(0x354,  K, 5, spdif_out_pk5,          spdif,      rsvd2,      rsvd3,        i2c3),
  343         GMUX(0x358,  A, 2, dap2_fs_pa2,            i2s1,       hda,        gmi,          rsvd4),
  344         GMUX(0x35C,  A, 4, dap2_din_pa4,           i2s1,       hda,        gmi,          rsvd4),
  345         GMUX(0x360,  A, 5, dap2_dout_pa5,          i2s1,       hda,        gmi,          rsvd4),
  346         GMUX(0x364,  A, 3, dap2_sclk_pa3,          i2s1,       hda,        gmi,          rsvd4),
  347         GMUX(0x368,  X, 0, dvfs_pwm_px0,           spi6,       cldvfs,     gmi,          rsvd4),
  348         GMUX(0x36C,  X, 1, gpio_x1_aud_px1,        spi6,       rsvd2,      gmi,          rsvd4),
  349         GMUX(0x370,  X, 3, gpio_x3_aud_px3,        spi6,       spi1,       gmi,          rsvd4),
  350         GMUX(0x374,  X, 2, dvfs_clk_px2,           spi6,       cldvfs,     gmi,          rsvd4),
  351         GMUX(0x378,  X, 4, gpio_x4_aud_px4,        gmi,        spi1,       spi2,         dap2),
  352         GMUX(0x37C,  X, 5, gpio_x5_aud_px5,        gmi,        spi1,       spi2,         rsvd4),
  353         GMUX(0x380,  X, 6, gpio_x6_aud_px6,        spi6,       spi1,       spi2,         gmi),
  354         GMUX(0x384,  X, 7, gpio_x7_aud_px7,        rsvd1,      spi1,       spi2,         rsvd4),
  355         GMUX(0x390,  A, 6, sdmmc3_clk_pa6,         sdmmc3,     rsvd2,      rsvd3,        spi3),
  356         GMUX(0x394,  A, 7, sdmmc3_cmd_pa7,         sdmmc3,     pwm3,       uarta,        spi3),
  357         GMUX(0x398,  B, 7, sdmmc3_dat0_pb7,        sdmmc3,     rsvd2,      rsvd3,        spi3),
  358         GMUX(0x39C,  B, 6, sdmmc3_dat1_pb6,        sdmmc3,     pwm2,       uarta,        spi3),
  359         GMUX(0x3A0,  B, 5, sdmmc3_dat2_pb5,        sdmmc3,     pwm1,       displaya,     spi3),
  360         GMUX(0x3A4,  B, 4, sdmmc3_dat3_pb4,        sdmmc3,     pwm0,       displayb,     spi3),
  361         GMUX(0x3BC, DD, 1, pex_l0_rst_n_pdd1,      pe0,        rsvd2,      rsvd3,        rsvd4),
  362         GMUX(0x3C0, DD, 2, pex_l0_clkreq_n_pdd2,   pe0,        rsvd2,      rsvd3,        rsvd4),
  363         GMUX(0x3C4, DD, 3, pex_wake_n_pdd3,        pe,         rsvd2,      rsvd3,        rsvd4),
  364         GMUX(0x3CC, DD, 5, pex_l1_rst_n_pdd5,      pe1,        rsvd2,      rsvd3,        rsvd4),
  365         GMUX(0x3D0, DD, 6, pex_l1_clkreq_n_pdd6,   pe1,        rsvd2,      rsvd3,        rsvd4),
  366         GMUX(0x3E0, EE, 3, hdmi_cec_pee3,          cec,        rsvd2,      rsvd3,        rsvd4),
  367         GMUX(0x3E4,  V, 3, sdmmc1_wp_n_pv3,        sdmmc1,     clk12,      spi4,         uarta),
  368         GMUX(0x3E8,  V, 2, sdmmc3_cd_n_pv2,        sdmmc3,     owr,        rsvd3,        rsvd4),
  369         GMUX(0x3EC,  W, 2, gpio_w2_aud_pw2,        spi6,       rsvd2,      spi2,         i2c1),
  370         GMUX(0x3F0,  W, 3, gpio_w3_aud_pw3,        spi6,       spi1,       spi2,         i2c1),
  371         GMUX(0x3F4,  N, 4, usb_vbus_en0_pn4,       usb,        rsvd2,      rsvd3,        rsvd4),
  372         GMUX(0x3F8,  N, 5, usb_vbus_en1_pn5,       usb,        rsvd2,      rsvd3,        rsvd4),
  373         GMUX(0x3FC, EE, 5, sdmmc3_clk_lb_in_pee5,  sdmmc3,     rsvd2,      rsvd3,        rsvd4),
  374         GMUX(0x400, EE, 4, sdmmc3_clk_lb_out_pee4, sdmmc3,     rsvd2,      rsvd3,        rsvd4),
  375         FMUX(0x404,        gmi_clk_lb,             sdmmc2,     rsvd2,      gmi,          rsvd4),
  376         FMUX(0x408,        reset_out_n,            rsvd1,      rsvd2,      rsvd3,        reset_out_n),
  377         GMUX(0x40C,  T, 0, kb_row16_pt0,           kbc,        rsvd2,      rsvd3,        uartc),
  378         GMUX(0x410,  T, 1, kb_row17_pt1,           kbc,        rsvd2,      rsvd3,        uartc),
  379         GMUX(0x414, FF, 1, usb_vbus_en2_pff1,      usb,        rsvd2,      rsvd3,        rsvd4),
  380         GMUX(0x418, FF, 2, pff2,                   sata,       rsvd2,      rsvd3,        rsvd4),
  381         GMUX(0x430, FF, 0, dp_hpd_pff0,            dp,         rsvd2,      rsvd3,        rsvd4),
  382 };
  383 
  384 struct tegra_grp {
  385         char *name;
  386         bus_size_t reg;
  387         int drvdn_shift;
  388         int drvdn_mask;
  389         int drvup_shift;
  390         int drvup_mask;
  391 };
  392 
  393 #define GRP(r, nm, dn_s, dn_w, up_s, up_w)                              \
  394 {                                                                       \
  395         .name = #nm,                                                    \
  396         .reg = r - 0x868,                                               \
  397         .drvdn_shift = dn_s,                                            \
  398         .drvdn_mask = (1 << dn_w) - 1,                                  \
  399         .drvup_shift = up_s,                                            \
  400         .drvup_mask = (1 << dn_w) - 1,                                  \
  401 }
  402 
  403 /* Use register offsets from TRM */
  404 static const struct tegra_grp pin_grp_tbl[] = {
  405         GRP(0x868, ao1,          12,  5,  20,  5),
  406         GRP(0x86C, ao2,          12,  5,  20,  5),
  407         GRP(0x870, at1,          12,  7,  20,  7),
  408         GRP(0x874, at2,          12,  7,  20,  7),
  409         GRP(0x878, at3,          12,  7,  20,  7),
  410         GRP(0x87C, at4,          12,  7,  20,  7),
  411         GRP(0x880, at5,          14,  5,  19,  5),
  412         GRP(0x884, cdev1,        12,  5,  20,  5),
  413         GRP(0x888, cdev2,        12,  5,  20,  5),
  414         GRP(0x890, dap1,         12,  5,  20,  5),
  415         GRP(0x894, dap2,         12,  5,  20,  5),
  416         GRP(0x898, dap3,         12,  5,  20,  5),
  417         GRP(0x89C, dap4,         12,  5,  20,  5),
  418         GRP(0x8A0, dbg,          12,  5,  20,  5),
  419         GRP(0x8B0, sdio3,        12,  7,  20,  7),
  420         GRP(0x8B4, spi,          12,  5,  20,  5),
  421         GRP(0x8B8, uaa,          12,  5,  20,  5),
  422         GRP(0x8BC, uab,          12,  5,  20,  5),
  423         GRP(0x8C0, uart2,        12,  5,  20,  5),
  424         GRP(0x8C4, uart3,        12,  5,  20,  5),
  425         GRP(0x8EC, sdio1,        12,  7,  20,  7),
  426         GRP(0x8FC, ddc,          12,  5,  20,  5),
  427         GRP(0x900, gma,          14,  5,  20,  5),
  428         GRP(0x910, gme,          14,  5,  19,  5),
  429         GRP(0x914, gmf,          14,  5,  19,  5),
  430         GRP(0x918, gmg,          14,  5,  19,  5),
  431         GRP(0x91C, gmh,          14,  5,  19,  5),
  432         GRP(0x920, owr,          12,  5,  20,  5),
  433         GRP(0x924, uda,          12,  5,  20,  5),
  434         GRP(0x928, gpv,          12,  5,  20,  5),
  435         GRP(0x92C, dev3,         12,  5,  20,  5),
  436         GRP(0x938, cec,          12,  5,  20,  5),
  437         GRP(0x994, at6,          12,  7,  20,  7),
  438         GRP(0x998, dap5,         12,  5,  20,  5),
  439         GRP(0x99C, usb_vbus_en,  12,  5,  20,  5),
  440         GRP(0x9A8, ao3,          12,  5,  -1,  0),
  441         GRP(0x9B0, ao0,          12,  5,  20,  5),
  442         GRP(0x9B4, hv0,          12,  5,  -1,  0),
  443         GRP(0x9C4, sdio4,        12,  5,  20,  5),
  444         GRP(0x9C8, ao4,          12,  7,  20,  7),
  445 };
  446 
  447 static const struct tegra_grp *
  448 pinmux_search_grp(char *grp_name)
  449 {
  450         int i;
  451 
  452         for (i = 0; i < nitems(pin_grp_tbl); i++) {
  453                 if (strcmp(grp_name, pin_grp_tbl[i].name) == 0)
  454                         return  (&pin_grp_tbl[i]);
  455         }
  456         return (NULL);
  457 }
  458 
  459 static const struct tegra_mux *
  460 pinmux_search_mux(char *pin_name)
  461 {
  462         int i;
  463 
  464         for (i = 0; i < nitems(pin_mux_tbl); i++) {
  465                 if (strcmp(pin_name, pin_mux_tbl[i].name) == 0)
  466                         return  (&pin_mux_tbl[i]);
  467         }
  468         return (NULL);
  469 }
  470 
  471 static int
  472 pinmux_mux_function(const struct tegra_mux *mux, char *fnc_name)
  473 {
  474         int i;
  475 
  476         for (i = 0; i < 4; i++) {
  477                 if (strcmp(fnc_name, mux->functions[i]) == 0)
  478                         return  (i);
  479         }
  480         return (-1);
  481 }
  482 
  483 static int
  484 pinmux_config_mux(struct pinmux_softc *sc, char *pin_name,
  485     const struct tegra_mux *mux, struct pincfg *cfg)
  486 {
  487         int tmp;
  488         uint32_t reg;
  489 
  490         reg = bus_read_4(sc->mux_mem_res, mux->reg);
  491 
  492         if (cfg->function != NULL) {
  493                 tmp = pinmux_mux_function(mux, cfg->function);
  494                 if (tmp == -1) {
  495                         device_printf(sc->dev,
  496                             "Unknown function %s for pin %s\n", cfg->function,
  497                             pin_name);
  498                         return (ENXIO);
  499                 }
  500                 reg &= ~(TEGRA_MUX_FUNCTION_MASK << TEGRA_MUX_FUNCTION_SHIFT);
  501                 reg |=  (tmp & TEGRA_MUX_FUNCTION_MASK) <<
  502                     TEGRA_MUX_FUNCTION_SHIFT;
  503         }
  504         if (cfg->params[PROP_ID_PULL] != -1) {
  505                 reg &= ~(TEGRA_MUX_PUPD_MASK << TEGRA_MUX_PUPD_SHIFT);
  506                 reg |=  (cfg->params[PROP_ID_PULL] & TEGRA_MUX_PUPD_MASK) <<
  507                     TEGRA_MUX_PUPD_SHIFT;
  508         }
  509         if (cfg->params[PROP_ID_TRISTATE] != -1) {
  510                 reg &= ~(1 << TEGRA_MUX_TRISTATE_SHIFT);
  511                 reg |=  (cfg->params[PROP_ID_TRISTATE] & 1) <<
  512                     TEGRA_MUX_TRISTATE_SHIFT;
  513         }
  514         if (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] != -1) {
  515                 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
  516                 reg |=  (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] & 1) <<
  517                     TEGRA_MUX_ENABLE_INPUT_SHIFT;
  518         }
  519         if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
  520                 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
  521                 reg |=  (cfg->params[PROP_ID_ENABLE_INPUT] & 1) <<
  522                     TEGRA_MUX_ENABLE_INPUT_SHIFT;
  523         }
  524         if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
  525                 reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
  526                 reg |=  (cfg->params[PROP_ID_OPEN_DRAIN] & 1) <<
  527                     TEGRA_MUX_ENABLE_INPUT_SHIFT;
  528         }
  529         if (cfg->params[PROP_ID_LOCK] != -1) {
  530                 reg &= ~(1 << TEGRA_MUX_LOCK_SHIFT);
  531                 reg |=  (cfg->params[PROP_ID_LOCK] & 1) <<
  532                     TEGRA_MUX_LOCK_SHIFT;
  533         }
  534         if (cfg->params[PROP_ID_IORESET] != -1) {
  535                 reg &= ~(1 << TEGRA_MUX_IORESET_SHIFT);
  536                 reg |=  (cfg->params[PROP_ID_IORESET] & 1) <<
  537                     TEGRA_MUX_IORESET_SHIFT;
  538         }
  539         if (cfg->params[PROP_ID_RCV_SEL] != -1) {
  540                 reg &= ~(1 << TEGRA_MUX_RCV_SEL_SHIFT);
  541                 reg |=  (cfg->params[PROP_ID_RCV_SEL] & 1) <<
  542                     TEGRA_MUX_RCV_SEL_SHIFT;
  543         }
  544         bus_write_4(sc->mux_mem_res, mux->reg, reg);
  545         return (0);
  546 }
  547 
  548 static int
  549 pinmux_config_grp(struct pinmux_softc *sc, char *grp_name,
  550     const struct tegra_grp *grp, struct pincfg *cfg)
  551 {
  552         uint32_t reg;
  553 
  554         reg = bus_read_4(sc->pad_mem_res, grp->reg);
  555 
  556         if (cfg->params[PROP_ID_HIGH_SPEED_MODE] != -1) {
  557                 reg &= ~(1 << TEGRA_GRP_HSM_SHIFT);
  558                 reg |=  (cfg->params[PROP_ID_HIGH_SPEED_MODE] & 1) <<
  559                     TEGRA_GRP_HSM_SHIFT;
  560         }
  561         if (cfg->params[PROP_ID_SCHMITT] != -1) {
  562                 reg &= ~(1 << TEGRA_GRP_SCHMT_SHIFT);
  563                 reg |=  (cfg->params[PROP_ID_SCHMITT] & 1) <<
  564                     TEGRA_GRP_SCHMT_SHIFT;
  565         }
  566         if (cfg->params[PROP_ID_DRIVE_TYPE] != -1) {
  567                 reg &= ~(TEGRA_GRP_DRV_TYPE_MASK << TEGRA_GRP_DRV_TYPE_SHIFT);
  568                 reg |=  (cfg->params[PROP_ID_DRIVE_TYPE] &
  569                     TEGRA_GRP_DRV_TYPE_MASK) << TEGRA_GRP_DRV_TYPE_SHIFT;
  570         }
  571         if (cfg->params[PROP_ID_SLEW_RATE_RISING] != -1) {
  572                 reg &= ~(TEGRA_GRP_DRV_DRVDN_SLWR_MASK <<
  573                     TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT);
  574                 reg |=  (cfg->params[PROP_ID_SLEW_RATE_RISING] &
  575                     TEGRA_GRP_DRV_DRVDN_SLWR_MASK) <<
  576                     TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT;
  577         }
  578         if (cfg->params[PROP_ID_SLEW_RATE_FALLING] != -1) {
  579                 reg &= ~(TEGRA_GRP_DRV_DRVUP_SLWF_MASK <<
  580                     TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT);
  581                 reg |=  (cfg->params[PROP_ID_SLEW_RATE_FALLING] &
  582                     TEGRA_GRP_DRV_DRVUP_SLWF_MASK) <<
  583                     TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT;
  584         }
  585         if ((cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] != -1) &&
  586                  (grp->drvdn_mask != -1)) {
  587                 reg &= ~(grp->drvdn_shift << grp->drvdn_mask);
  588                 reg |=  (cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] &
  589                     grp->drvdn_mask) << grp->drvdn_shift;
  590         }
  591         if ((cfg->params[PROP_ID_DRIVE_UP_STRENGTH] != -1) &&
  592                  (grp->drvup_mask != -1)) {
  593                 reg &= ~(grp->drvup_shift << grp->drvup_mask);
  594                 reg |=  (cfg->params[PROP_ID_DRIVE_UP_STRENGTH] &
  595                     grp->drvup_mask) << grp->drvup_shift;
  596         }
  597         bus_write_4(sc->pad_mem_res, grp->reg, reg);
  598         return (0);
  599 }
  600 
  601 static int
  602 pinmux_config_node(struct pinmux_softc *sc, char *pin_name, struct pincfg *cfg)
  603 {
  604         const struct tegra_mux *mux;
  605         const struct tegra_grp *grp;
  606         uint32_t reg;
  607         int rv;
  608 
  609         /* Handle MIPI special case first */
  610         if (strcmp(pin_name, "dsi_b") == 0) {
  611                 if (cfg->function == NULL) {
  612                         /* nothing to set */
  613                         return (0);
  614                 }
  615                 reg = bus_read_4(sc->mipi_mem_res, 0); /* register 0x820 */
  616                 if (strcmp(cfg->function, "csi") == 0)
  617                         reg &= ~(1 << 1);
  618                 else if (strcmp(cfg->function, "dsi_b") == 0)
  619                         reg |= (1 << 1);
  620                 bus_write_4(sc->mipi_mem_res, 0, reg); /* register 0x820 */
  621         }
  622 
  623         /* Handle pin muxes */
  624         mux = pinmux_search_mux(pin_name);
  625         if (mux != NULL) {
  626                 if (mux->gpio_num != -1) {
  627                         /* XXXX TODO: Reserve gpio here */
  628                 }
  629                 rv = pinmux_config_mux(sc, pin_name, mux, cfg);
  630                 return (rv);
  631         }
  632 
  633         /* Handle pin groups */
  634         grp = pinmux_search_grp(pin_name);
  635         if (grp != NULL) {
  636                 rv = pinmux_config_grp(sc, pin_name, grp, cfg);
  637                 return (rv);
  638         }
  639 
  640         device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
  641         return (ENXIO);
  642 }
  643 
  644 static int
  645 pinmux_read_node(struct pinmux_softc *sc, phandle_t node, struct pincfg *cfg,
  646     char **pins, int *lpins)
  647 {
  648         int rv, i;
  649 
  650         *lpins = OF_getprop_alloc(node, "nvidia,pins", (void **)pins);
  651         if (*lpins <= 0)
  652                 return (ENOENT);
  653 
  654         /* Read function (mux) settings. */
  655         rv = OF_getprop_alloc(node, "nvidia,function",
  656             (void **)&cfg->function);
  657         if (rv <= 0)
  658                 cfg->function = NULL;
  659 
  660         /* Read numeric properties. */
  661         for (i = 0; i < PROP_ID_MAX_ID; i++) {
  662                 rv = OF_getencprop(node, prop_names[i].name, &cfg->params[i],
  663                     sizeof(cfg->params[i]));
  664                 if (rv <= 0)
  665                         cfg->params[i] = -1;
  666         }
  667         return (0);
  668 }
  669 
  670 static int
  671 pinmux_process_node(struct pinmux_softc *sc, phandle_t node)
  672 {
  673         struct pincfg cfg;
  674         char *pins, *pname;
  675         int i, len, lpins, rv;
  676 
  677         rv = pinmux_read_node(sc, node, &cfg, &pins, &lpins);
  678         if (rv != 0)
  679                 return (rv);
  680 
  681         len = 0;
  682         pname = pins;
  683         do {
  684                 i = strlen(pname) + 1;
  685                 rv = pinmux_config_node(sc, pname, &cfg);
  686                 if (rv != 0)
  687                         device_printf(sc->dev,
  688                             "Cannot configure pin: %s: %d\n", pname, rv);
  689 
  690                 len += i;
  691                 pname += i;
  692         } while (len < lpins);
  693 
  694         if (pins != NULL)
  695                 OF_prop_free(pins);
  696         if (cfg.function != NULL)
  697                 OF_prop_free(cfg.function);
  698         return (rv);
  699 }
  700 
  701 static int pinmux_configure(device_t dev, phandle_t cfgxref)
  702 {
  703         struct pinmux_softc *sc;
  704         phandle_t node, cfgnode;
  705         int rv;
  706 
  707         sc = device_get_softc(dev);
  708         cfgnode = OF_node_from_xref(cfgxref);
  709 
  710         for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
  711                 if (!ofw_bus_node_status_okay(node))
  712                         continue;
  713                 rv = pinmux_process_node(sc, node);
  714         }
  715         return (0);
  716 }
  717 
  718 static int
  719 pinmux_probe(device_t dev)
  720 {
  721 
  722         if (!ofw_bus_status_okay(dev))
  723                 return (ENXIO);
  724 
  725         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
  726                 return (ENXIO);
  727 
  728         device_set_desc(dev, "Tegra pin configuration");
  729         return (BUS_PROBE_DEFAULT);
  730 }
  731 
  732 static int
  733 pinmux_detach(device_t dev)
  734 {
  735 
  736         /* This device is always present. */
  737         return (EBUSY);
  738 }
  739 
  740 static int
  741 pinmux_attach(device_t dev)
  742 {
  743         struct pinmux_softc * sc;
  744         int rid;
  745 
  746         sc = device_get_softc(dev);
  747         sc->dev = dev;
  748 
  749         rid = 0;
  750         sc->pad_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  751             RF_ACTIVE);
  752         if (sc->pad_mem_res == NULL) {
  753                 device_printf(dev, "Cannot allocate memory resources\n");
  754                 return (ENXIO);
  755         }
  756 
  757         rid = 1;
  758         sc->mux_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  759             RF_ACTIVE);
  760         if (sc->mux_mem_res == NULL) {
  761                 device_printf(dev, "Cannot allocate memory resources\n");
  762                 return (ENXIO);
  763         }
  764 
  765         rid = 2;
  766         sc->mipi_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  767             RF_ACTIVE);
  768         if (sc->mipi_mem_res == NULL) {
  769                 device_printf(dev, "Cannot allocate memory resources\n");
  770                 return (ENXIO);
  771         }
  772 
  773         /* Register as a pinctrl device and process default configuration */
  774         fdt_pinctrl_register(dev, NULL);
  775         fdt_pinctrl_configure_by_name(dev, "boot");
  776 
  777         return (0);
  778 }
  779 
  780 static device_method_t tegra_pinmux_methods[] = {
  781         /* Device interface */
  782         DEVMETHOD(device_probe,         pinmux_probe),
  783         DEVMETHOD(device_attach,        pinmux_attach),
  784         DEVMETHOD(device_detach,        pinmux_detach),
  785 
  786         /* fdt_pinctrl interface */
  787         DEVMETHOD(fdt_pinctrl_configure,pinmux_configure),
  788 
  789         DEVMETHOD_END
  790 };
  791 
  792 static devclass_t tegra_pinmux_devclass;
  793 static DEFINE_CLASS_0(pinmux, tegra_pinmux_driver, tegra_pinmux_methods,
  794     sizeof(struct pinmux_softc));
  795 EARLY_DRIVER_MODULE(tegra_pinmux, simplebus, tegra_pinmux_driver,
  796     tegra_pinmux_devclass, NULL, NULL, 71);

Cache object: a4e62a88ca30184d026dac9d01b9dbfd


[ 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.