1296936Smmel/*- 2296936Smmel * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org> 3296936Smmel * All rights reserved. 4296936Smmel * 5296936Smmel * Redistribution and use in source and binary forms, with or without 6296936Smmel * modification, are permitted provided that the following conditions 7296936Smmel * are met: 8296936Smmel * 1. Redistributions of source code must retain the above copyright 9296936Smmel * notice, this list of conditions and the following disclaimer. 10296936Smmel * 2. Redistributions in binary form must reproduce the above copyright 11296936Smmel * notice, this list of conditions and the following disclaimer in the 12296936Smmel * documentation and/or other materials provided with the distribution. 13296936Smmel * 14296936Smmel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15296936Smmel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16296936Smmel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17296936Smmel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18296936Smmel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19296936Smmel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20296936Smmel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21296936Smmel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22296936Smmel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23296936Smmel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24296936Smmel * SUCH DAMAGE. 25296936Smmel */ 26296936Smmel 27296936Smmel#include <sys/cdefs.h> 28296936Smmel__FBSDID("$FreeBSD: stable/11/sys/arm/nvidia/tegra_pinmux.c 308335 2016-11-05 10:56:32Z mmel $"); 29296936Smmel 30296936Smmel/* 31296936Smmel * Pin multiplexer driver for Tegra SoCs. 32296936Smmel */ 33296936Smmel#include <sys/param.h> 34296936Smmel#include <sys/systm.h> 35296936Smmel#include <sys/bus.h> 36296936Smmel#include <sys/kernel.h> 37296936Smmel#include <sys/module.h> 38296936Smmel#include <sys/malloc.h> 39296936Smmel#include <sys/rman.h> 40296936Smmel 41296936Smmel#include <machine/bus.h> 42296936Smmel#include <machine/fdt.h> 43296936Smmel 44296936Smmel#include <dev/fdt/fdt_common.h> 45296936Smmel#include <dev/fdt/fdt_pinctrl.h> 46296936Smmel#include <dev/ofw/openfirm.h> 47296936Smmel#include <dev/ofw/ofw_bus.h> 48296936Smmel#include <dev/ofw/ofw_bus_subr.h> 49296936Smmel 50296936Smmel/* Pin multipexor register. */ 51296936Smmel#define TEGRA_MUX_FUNCTION_MASK 0x03 52296936Smmel#define TEGRA_MUX_FUNCTION_SHIFT 0 53296936Smmel#define TEGRA_MUX_PUPD_MASK 0x03 54296936Smmel#define TEGRA_MUX_PUPD_SHIFT 2 55296936Smmel#define TEGRA_MUX_TRISTATE_SHIFT 4 56296936Smmel#define TEGRA_MUX_ENABLE_INPUT_SHIFT 5 57296936Smmel#define TEGRA_MUX_OPEN_DRAIN_SHIFT 6 58296936Smmel#define TEGRA_MUX_LOCK_SHIFT 7 59296936Smmel#define TEGRA_MUX_IORESET_SHIFT 8 60296936Smmel#define TEGRA_MUX_RCV_SEL_SHIFT 9 61296936Smmel 62296936Smmel 63296936Smmel/* Pin goup register. */ 64296936Smmel#define TEGRA_GRP_HSM_SHIFT 2 65296936Smmel#define TEGRA_GRP_SCHMT_SHIFT 3 66296936Smmel#define TEGRA_GRP_DRV_TYPE_SHIFT 6 67296936Smmel#define TEGRA_GRP_DRV_TYPE_MASK 0x03 68296936Smmel#define TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT 28 69296936Smmel#define TEGRA_GRP_DRV_DRVDN_SLWR_MASK 0x03 70296936Smmel#define TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT 30 71296936Smmel#define TEGRA_GRP_DRV_DRVUP_SLWF_MASK 0x03 72296936Smmel 73296936Smmelstruct pinmux_softc { 74296936Smmel device_t dev; 75296936Smmel struct resource *pad_mem_res; 76296936Smmel struct resource *mux_mem_res; 77296936Smmel struct resource *mipi_mem_res; 78296936Smmel}; 79296936Smmel 80296936Smmelstatic struct ofw_compat_data compat_data[] = { 81296936Smmel {"nvidia,tegra124-pinmux", 1}, 82296936Smmel {NULL, 0}, 83296936Smmel}; 84296936Smmel 85296936Smmelenum prop_id { 86296936Smmel PROP_ID_PULL, 87296936Smmel PROP_ID_TRISTATE, 88296936Smmel PROP_ID_ENABLE_INPUT, 89296936Smmel PROP_ID_OPEN_DRAIN, 90296936Smmel PROP_ID_LOCK, 91296936Smmel PROP_ID_IORESET, 92296936Smmel PROP_ID_RCV_SEL, 93296936Smmel PROP_ID_HIGH_SPEED_MODE, 94296936Smmel PROP_ID_SCHMITT, 95296936Smmel PROP_ID_LOW_POWER_MODE, 96296936Smmel PROP_ID_DRIVE_DOWN_STRENGTH, 97296936Smmel PROP_ID_DRIVE_UP_STRENGTH, 98296936Smmel PROP_ID_SLEW_RATE_FALLING, 99296936Smmel PROP_ID_SLEW_RATE_RISING, 100296936Smmel PROP_ID_DRIVE_TYPE, 101296936Smmel 102296936Smmel PROP_ID_MAX_ID 103296936Smmel}; 104296936Smmel 105296936Smmel/* Numeric based parameters. */ 106296936Smmelstatic const struct prop_name { 107296936Smmel const char *name; 108296936Smmel enum prop_id id; 109296936Smmel} prop_names[] = { 110296936Smmel {"nvidia,pull", PROP_ID_PULL}, 111296936Smmel {"nvidia,tristate", PROP_ID_TRISTATE}, 112296936Smmel {"nvidia,enable-input", PROP_ID_ENABLE_INPUT}, 113296936Smmel {"nvidia,open-drain", PROP_ID_OPEN_DRAIN}, 114296936Smmel {"nvidia,lock", PROP_ID_LOCK}, 115296936Smmel {"nvidia,io-reset", PROP_ID_IORESET}, 116296936Smmel {"nvidia,rcv-sel", PROP_ID_RCV_SEL}, 117296936Smmel {"nvidia,high-speed-mode", PROP_ID_HIGH_SPEED_MODE}, 118296936Smmel {"nvidia,schmitt", PROP_ID_SCHMITT}, 119296936Smmel {"nvidia,low-power-mode", PROP_ID_LOW_POWER_MODE}, 120296936Smmel {"nvidia,pull-down-strength", PROP_ID_DRIVE_DOWN_STRENGTH}, 121296936Smmel {"nvidia,pull-up-strength", PROP_ID_DRIVE_UP_STRENGTH}, 122296936Smmel {"nvidia,slew-rate-falling", PROP_ID_SLEW_RATE_FALLING}, 123296936Smmel {"nvidia,slew-rate-rising", PROP_ID_SLEW_RATE_RISING}, 124296936Smmel {"nvidia,drive-type", PROP_ID_DRIVE_TYPE}, 125296936Smmel}; 126296936Smmel 127296936Smmel/* 128296936Smmel * configuration for one pin group. 129296936Smmel */ 130296936Smmelstruct pincfg { 131296936Smmel char *function; 132296936Smmel int params[PROP_ID_MAX_ID]; 133296936Smmel}; 134296936Smmel#define GPIO_BANK_A 0 135296936Smmel#define GPIO_BANK_B 1 136296936Smmel#define GPIO_BANK_C 2 137296936Smmel#define GPIO_BANK_D 3 138296936Smmel#define GPIO_BANK_E 4 139296936Smmel#define GPIO_BANK_F 5 140296936Smmel#define GPIO_BANK_G 6 141296936Smmel#define GPIO_BANK_H 7 142296936Smmel#define GPIO_BANK_I 8 143296936Smmel#define GPIO_BANK_J 9 144296936Smmel#define GPIO_BANK_K 10 145296936Smmel#define GPIO_BANK_L 11 146296936Smmel#define GPIO_BANK_M 12 147296936Smmel#define GPIO_BANK_N 13 148296936Smmel#define GPIO_BANK_O 14 149296936Smmel#define GPIO_BANK_P 15 150296936Smmel#define GPIO_BANK_Q 16 151296936Smmel#define GPIO_BANK_R 17 152296936Smmel#define GPIO_BANK_S 18 153296936Smmel#define GPIO_BANK_T 19 154296936Smmel#define GPIO_BANK_U 20 155296936Smmel#define GPIO_BANK_V 21 156296936Smmel#define GPIO_BANK_W 22 157296936Smmel#define GPIO_BANK_X 23 158296936Smmel#define GPIO_BANK_Y 24 159296936Smmel#define GPIO_BANK_Z 25 160296936Smmel#define GPIO_BANK_AA 26 161296936Smmel#define GPIO_BANK_BB 27 162296936Smmel#define GPIO_BANK_CC 28 163296936Smmel#define GPIO_BANK_DD 29 164296936Smmel#define GPIO_BANK_EE 30 165296936Smmel#define GPIO_BANK_FF 31 166296936Smmel#define GPIO_NUM(b, p) (8 * (b) + (p)) 167296936Smmel 168296936Smmelstruct tegra_mux { 169296936Smmel char *name; 170296936Smmel bus_size_t reg; 171296936Smmel char *functions[4]; 172296936Smmel int gpio_num; 173296936Smmel}; 174296936Smmel 175296936Smmel#define GMUX(r, gb, gi, nm, f1, f2, f3, f4) \ 176296936Smmel{ \ 177296936Smmel .name = #nm, \ 178296936Smmel .reg = r, \ 179296936Smmel .gpio_num = GPIO_NUM(GPIO_BANK_##gb, gi), \ 180296936Smmel .functions = {#f1, #f2, #f3, #f4}, \ 181296936Smmel} 182296936Smmel 183296936Smmel#define FMUX(r, nm, f1, f2, f3, f4) \ 184296936Smmel{ \ 185296936Smmel .name = #nm, \ 186296936Smmel .reg = r, \ 187296936Smmel .gpio_num = -1, \ 188296936Smmel .functions = {#f1, #f2, #f3, #f4}, \ 189296936Smmel} 190296936Smmel 191296936Smmelstatic const struct tegra_mux pin_mux_tbl[] = { 192296936Smmel GMUX(0x000, O, 1, ulpi_data0_po1, spi3, hsi, uarta, ulpi), 193296936Smmel GMUX(0x004, O, 2, ulpi_data1_po2, spi3, hsi, uarta, ulpi), 194296936Smmel GMUX(0x008, O, 3, ulpi_data2_po3, spi3, hsi, uarta, ulpi), 195296936Smmel GMUX(0x00C, O, 4, ulpi_data3_po4, spi3, hsi, uarta, ulpi), 196296936Smmel GMUX(0x010, O, 5, ulpi_data4_po5, spi2, hsi, uarta, ulpi), 197296936Smmel GMUX(0x014, O, 6, ulpi_data5_po6, spi2, hsi, uarta, ulpi), 198296936Smmel GMUX(0x018, O, 7, ulpi_data6_po7, spi2, hsi, uarta, ulpi), 199296936Smmel GMUX(0x01C, O, 0, ulpi_data7_po0, spi2, hsi, uarta, ulpi), 200296936Smmel GMUX(0x020, P, 9, ulpi_clk_py0, spi1, spi5, uartd, ulpi), 201296936Smmel GMUX(0x024, P, 1, ulpi_dir_py1, spi1, spi5, uartd, ulpi), 202296936Smmel GMUX(0x028, P, 2, ulpi_nxt_py2, spi1, spi5, uartd, ulpi), 203296936Smmel GMUX(0x02C, P, 3, ulpi_stp_py3, spi1, spi5, uartd, ulpi), 204296936Smmel GMUX(0x030, P, 0, dap3_fs_pp0, i2s2, spi5, displaya, displayb), 205296936Smmel GMUX(0x034, P, 1, dap3_din_pp1, i2s2, spi5, displaya, displayb), 206296936Smmel GMUX(0x038, P, 2, dap3_dout_pp2, i2s2, spi5, displaya, rsvd4), 207296936Smmel GMUX(0x03C, P, 3, dap3_sclk_pp3, i2s2, spi5, rsvd3, displayb), 208296936Smmel GMUX(0x040, V, 0, pv0, rsvd1, rsvd2, rsvd3, rsvd4), 209296936Smmel GMUX(0x044, V, 1, pv1, rsvd1, rsvd2, rsvd3, rsvd4), 210296936Smmel GMUX(0x048, Z, 0, sdmmc1_clk_pz0, sdmmc1, clk12, rsvd3, rsvd4), 211296936Smmel GMUX(0x04C, Z, 1, sdmmc1_cmd_pz1, sdmmc1, spdif, spi4, uarta), 212296936Smmel GMUX(0x050, Y, 4, sdmmc1_dat3_py4, sdmmc1, spdif, spi4, uarta), 213296936Smmel GMUX(0x054, Y, 5, sdmmc1_dat2_py5, sdmmc1, pwm0, spi4, uarta), 214296936Smmel GMUX(0x058, Y, 6, sdmmc1_dat1_py6, sdmmc1, pwm1, spi4, uarta), 215296936Smmel GMUX(0x05C, Y, 7, sdmmc1_dat0_py7, sdmmc1, rsvd2, spi4, uarta), 216296936Smmel GMUX(0x068, W, 5, clk2_out_pw5, extperiph2, rsvd2, rsvd3, rsvd4), 217296936Smmel GMUX(0x06C, CC, 5, clk2_req_pcc5, dap, rsvd2, rsvd3, rsvd4), 218296936Smmel GMUX(0x110, N, 7, hdmi_int_pn7, rsvd1, rsvd2, rsvd3, rsvd4), 219296936Smmel GMUX(0x114, V, 4, ddc_scl_pv4, i2c4, rsvd2, rsvd3, rsvd4), 220296936Smmel GMUX(0x118, V, 5, ddc_sda_pv5, i2c4, rsvd2, rsvd3, rsvd4), 221296936Smmel GMUX(0x164, V, 3, uart2_rxd_pc3, irda, spdif, uarta, spi4), 222296936Smmel GMUX(0x168, C, 2, uart2_txd_pc2, irda, spdif, uarta, spi4), 223296936Smmel GMUX(0x16C, J, 6, uart2_rts_n_pj6, uarta, uartb, gmi, spi4), 224296936Smmel GMUX(0x170, J, 5, uart2_cts_n_pj5, uarta, uartb, gmi, spi4), 225296936Smmel GMUX(0x174, W, 6, uart3_txd_pw6, uartc, rsvd2, gmi, spi4), 226296936Smmel GMUX(0x178, W, 7, uart3_rxd_pw7, uartc, rsvd2, gmi, spi4), 227296936Smmel GMUX(0x17C, S, 1, uart3_cts_n_pa1, uartc, sdmmc1, dtv, gmi), 228296936Smmel GMUX(0x180, C, 0, uart3_rts_n_pc0, uartc, pwm0, dtv, gmi), 229296936Smmel GMUX(0x184, U, 0, pu0, owr, uarta, gmi, rsvd4), 230296936Smmel GMUX(0x188, U, 1, pu1, rsvd1, uarta, gmi, rsvd4), 231296936Smmel GMUX(0x18C, U, 2, pu2, rsvd1, uarta, gmi, rsvd4), 232296936Smmel GMUX(0x190, U, 3, pu3, pwm0, uarta, gmi, displayb), 233296936Smmel GMUX(0x194, U, 4, pu4, pwm1, uarta, gmi, displayb), 234296936Smmel GMUX(0x198, U, 5, pu5, pwm2, uarta, gmi, displayb), 235296936Smmel GMUX(0x19C, U, 6, pu6, pwm3, uarta, rsvd3, gmi), 236296936Smmel GMUX(0x1A0, C, 5, gen1_i2c_sda_pc5, i2c1, rsvd2, rsvd3, rsvd4), 237296936Smmel GMUX(0x1A4, C, 4, gen1_i2c_scl_pc4, i2c1, rsvd2, rsvd3, rsvd4), 238296936Smmel GMUX(0x1A8, P, 3, dap4_fs_pp4, i2s3, gmi, dtv, rsvd4), 239296936Smmel GMUX(0x1AC, P, 4, dap4_din_pp5, i2s3, gmi, rsvd3, rsvd4), 240296936Smmel GMUX(0x1B0, P, 5, dap4_dout_pp6, i2s3, gmi, dtv, rsvd4), 241296936Smmel GMUX(0x1B4, P, 7, dap4_sclk_pp7, i2s3, gmi, rsvd3, rsvd4), 242296936Smmel GMUX(0x1B8, P, 0, clk3_out_pee0, extperiph3, rsvd2, rsvd3, rsvd4), 243296936Smmel GMUX(0x1BC, EE, 1, clk3_req_pee1, dev3, rsvd2, rsvd3, rsvd4), 244296936Smmel GMUX(0x1C0, C, 7, pc7, rsvd1, rsvd2, gmi, gmi_alt), 245296936Smmel GMUX(0x1C4, I, 5, pi5, sdmmc2, rsvd2, gmi, rsvd4), 246296936Smmel GMUX(0x1C8, I, 7, pi7, rsvd1, trace, gmi, dtv), 247296936Smmel GMUX(0x1CC, K, 0, pk0, rsvd1, sdmmc3, gmi, soc), 248296936Smmel GMUX(0x1D0, K, 1, pk1, sdmmc2, trace, gmi, rsvd4), 249296936Smmel GMUX(0x1D4, J, 0, pj0, rsvd1, rsvd2, gmi, usb), 250296936Smmel GMUX(0x1D8, J, 2, pj2, rsvd1, rsvd2, gmi, soc), 251296936Smmel GMUX(0x1DC, K, 3, pk3, sdmmc2, trace, gmi, ccla), 252296936Smmel GMUX(0x1E0, K, 4, pk4, sdmmc2, rsvd2, gmi, gmi_alt), 253296936Smmel GMUX(0x1E4, K, 2, pk2, rsvd1, rsvd2, gmi, rsvd4), 254296936Smmel GMUX(0x1E8, I, 3, pi3, rsvd1, rsvd2, gmi, spi4), 255296936Smmel GMUX(0x1EC, I, 6, pi6, rsvd1, rsvd2, gmi, sdmmc2), 256296936Smmel GMUX(0x1F0, G, 0, pg0, rsvd1, rsvd2, gmi, rsvd4), 257296936Smmel GMUX(0x1F4, G, 1, pg1, rsvd1, rsvd2, gmi, rsvd4), 258296936Smmel GMUX(0x1F8, G, 2, pg2, rsvd1, trace, gmi, rsvd4), 259296936Smmel GMUX(0x1FC, G, 3, pg3, rsvd1, trace, gmi, rsvd4), 260296936Smmel GMUX(0x200, G, 4, pg4, rsvd1, tmds, gmi, spi4), 261296936Smmel GMUX(0x204, G, 5, pg5, rsvd1, rsvd2, gmi, spi4), 262296936Smmel GMUX(0x208, G, 6, pg6, rsvd1, rsvd2, gmi, spi4), 263296936Smmel GMUX(0x20C, G, 7, pg7, rsvd1, rsvd2, gmi, spi4), 264296936Smmel GMUX(0x210, H, 0, ph0, pwm0, trace, gmi, dtv), 265296936Smmel GMUX(0x214, H, 1, ph1, pwm1, tmds, gmi, displaya), 266296936Smmel GMUX(0x218, H, 2, ph2, pwm2, tmds, gmi, cldvfs), 267296936Smmel GMUX(0x21C, H, 3, ph3, pwm3, spi4, gmi, cldvfs), 268296936Smmel GMUX(0x220, H, 4, ph4, sdmmc2, rsvd2, gmi, rsvd4), 269296936Smmel GMUX(0x224, H, 5, ph5, sdmmc2, rsvd2, gmi, rsvd4), 270296936Smmel GMUX(0x228, H, 6, ph6, sdmmc2, trace, gmi, dtv), 271296936Smmel GMUX(0x22C, H, 7, ph7, sdmmc2, trace, gmi, dtv), 272296936Smmel GMUX(0x230, J, 7, pj7, uartd, rsvd2, gmi, gmi_alt), 273296936Smmel GMUX(0x234, B, 0, pb0, uartd, rsvd2, gmi, rsvd4), 274296936Smmel GMUX(0x238, B, 1, pb1, uartd, rsvd2, gmi, rsvd4), 275296936Smmel GMUX(0x23C, K, 7, pk7, uartd, rsvd2, gmi, rsvd4), 276296936Smmel GMUX(0x240, I, 0, pi0, rsvd1, rsvd2, gmi, rsvd4), 277296936Smmel GMUX(0x244, I, 1, pi1, rsvd1, rsvd2, gmi, rsvd4), 278296936Smmel GMUX(0x248, I, 2, pi2, sdmmc2, trace, gmi, rsvd4), 279296936Smmel GMUX(0x24C, I, 4, pi4, spi4, trace, gmi, displaya), 280296936Smmel GMUX(0x250, T, 5, gen2_i2c_scl_pt5, i2c2, rsvd2, gmi, rsvd4), 281296936Smmel GMUX(0x254, T, 6, gen2_i2c_sda_pt6, i2c2, rsvd2, gmi, rsvd4), 282296936Smmel GMUX(0x258, CC, 4, sdmmc4_clk_pcc4, sdmmc4, rsvd2, gmi, rsvd4), 283296936Smmel GMUX(0x25C, T, 7, sdmmc4_cmd_pt7, sdmmc4, rsvd2, gmi, rsvd4), 284296936Smmel GMUX(0x260, AA, 0, sdmmc4_dat0_paa0, sdmmc4, spi3, gmi, rsvd4), 285296936Smmel GMUX(0x264, AA, 1, sdmmc4_dat1_paa1, sdmmc4, spi3, gmi, rsvd4), 286296936Smmel GMUX(0x268, AA, 2, sdmmc4_dat2_paa2, sdmmc4, spi3, gmi, rsvd4), 287296936Smmel GMUX(0x26C, AA, 3, sdmmc4_dat3_paa3, sdmmc4, spi3, gmi, rsvd4), 288296936Smmel GMUX(0x270, AA, 4, sdmmc4_dat4_paa4, sdmmc4, spi3, gmi, rsvd4), 289296936Smmel GMUX(0x274, AA, 5, sdmmc4_dat5_paa5, sdmmc4, spi3, rsvd3, rsvd4), 290296936Smmel GMUX(0x278, AA, 6, sdmmc4_dat6_paa6, sdmmc4, spi3, gmi, rsvd4), 291296936Smmel GMUX(0x27C, AA, 7, sdmmc4_dat7_paa7, sdmmc4, rsvd2, gmi, rsvd4), 292296936Smmel GMUX(0x284, CC, 0, cam_mclk_pcc0, vi, vi_alt1, vi_alt3, sdmmc2), 293296936Smmel GMUX(0x288, CC, 1, pcc1, i2s4, rsvd2, rsvd3, sdmmc2), 294296936Smmel GMUX(0x28C, BB, 0, pbb0, vgp6, vimclk2, sdmmc2, vimclk2_alt), 295296936Smmel GMUX(0x290, BB, 1, cam_i2c_scl_pbb1, vgp1, i2c3, rsvd3, sdmmc2), 296296936Smmel GMUX(0x294, BB, 2, cam_i2c_sda_pbb2, vgp2, i2c3, rsvd3, sdmmc2), 297296936Smmel GMUX(0x298, BB, 3, pbb3, vgp3, displaya, displayb, sdmmc2), 298296936Smmel GMUX(0x29C, BB, 4, pbb4, vgp4, displaya, displayb, sdmmc2), 299296936Smmel GMUX(0x2A0, BB, 5, pbb5, vgp5, displaya, rsvd3, sdmmc2), 300296936Smmel GMUX(0x2A4, BB, 6, pbb6, i2s4, rsvd2, displayb, sdmmc2), 301296936Smmel GMUX(0x2A8, BB, 7, pbb7, i2s4, rsvd2, rsvd3, sdmmc2), 302296936Smmel GMUX(0x2AC, CC, 2, pcc2, i2s4, rsvd2, sdmmc3, sdmmc2), 303296936Smmel FMUX(0x2B0, jtag_rtck, rtck, rsvd2, rsvd3, rsvd4), 304296936Smmel GMUX(0x2B4, Z, 6, pwr_i2c_scl_pz6, i2cpwr, rsvd2, rsvd3, rsvd4), 305296936Smmel GMUX(0x2B8, Z, 7, pwr_i2c_sda_pz7, i2cpwr, rsvd2, rsvd3, rsvd4), 306296936Smmel GMUX(0x2BC, R, 0, kb_row0_pr0, kbc, rsvd2, rsvd3, rsvd4), 307296936Smmel GMUX(0x2C0, R, 1, kb_row1_pr1, kbc, rsvd2, rsvd3, rsvd4), 308296936Smmel GMUX(0x2C4, R, 2, kb_row2_pr2, kbc, rsvd2, rsvd3, rsvd4), 309296936Smmel GMUX(0x2C8, R, 3, kb_row3_pr3, kbc, displaya, sys, displayb), 310296936Smmel GMUX(0x2CC, R, 4, kb_row4_pr4, kbc, displaya, rsvd3, displayb), 311296936Smmel GMUX(0x2D0, R, 5, kb_row5_pr5, kbc, displaya, rsvd3, displayb), 312296936Smmel GMUX(0x2D4, R, 6, kb_row6_pr6, kbc, displaya, displaya_alt, displayb), 313296936Smmel GMUX(0x2D8, R, 7, kb_row7_pr7, kbc, rsvd2, cldvfs, uarta), 314296936Smmel GMUX(0x2DC, S, 0, kb_row8_ps0, kbc, rsvd2, cldvfs, uarta), 315296936Smmel GMUX(0x2E0, S, 1, kb_row9_ps1, kbc, rsvd2, rsvd3, uarta), 316296936Smmel GMUX(0x2E4, S, 2, kb_row10_ps2, kbc, rsvd2, rsvd3, uarta), 317296936Smmel GMUX(0x2E8, S, 3, kb_row11_ps3, kbc, rsvd2, rsvd3, irda), 318296936Smmel GMUX(0x2EC, S, 4, kb_row12_ps4, kbc, rsvd2, rsvd3, irda), 319296936Smmel GMUX(0x2F0, S, 5, kb_row13_ps5, kbc, rsvd2, spi2, rsvd4), 320296936Smmel GMUX(0x2F4, S, 6, kb_row14_ps6, kbc, rsvd2, spi2, rsvd4), 321296936Smmel GMUX(0x2F8, S, 7, kb_row15_ps7, kbc, soc, rsvd3, rsvd4), 322296936Smmel GMUX(0x2FC, Q, 0, kb_col0_pq0, kbc, rsvd2, spi2, rsvd4), 323296936Smmel GMUX(0x300, Q, 1, kb_col1_pq1, kbc, rsvd2, spi2, rsvd4), 324296936Smmel GMUX(0x304, Q, 2, kb_col2_pq2, kbc, rsvd2, spi2, rsvd4), 325296936Smmel GMUX(0x308, Q, 3, kb_col3_pq3, kbc, displaya, pwm2, uarta), 326296936Smmel GMUX(0x30C, Q, 4, kb_col4_pq4, kbc, owr, sdmmc3, uarta), 327296936Smmel GMUX(0x310, Q, 5, kb_col5_pq5, kbc, rsvd2, sdmmc3, rsvd4), 328296936Smmel GMUX(0x314, Q, 6, kb_col6_pq6, kbc, rsvd2, spi2, uartd), 329296936Smmel GMUX(0x318, Q, 7, kb_col7_pq7, kbc, rsvd2, spi2, uartd), 330296936Smmel GMUX(0x31C, A, 0, clk_32k_out_pa0, blink, soc, rsvd3, rsvd4), 331296936Smmel FMUX(0x324, core_pwr_req, pwron, rsvd2, rsvd3, rsvd4), 332296936Smmel FMUX(0x328, cpu_pwr_req, cpu, rsvd2, rsvd3, rsvd4), 333296936Smmel FMUX(0x32C, pwr_int_n, pmi, rsvd2, rsvd3, rsvd4), 334296936Smmel FMUX(0x330, clk_32k_in, clk, rsvd2, rsvd3, rsvd4), 335296936Smmel FMUX(0x334, owr, owr, rsvd2, rsvd3, rsvd4), 336296936Smmel GMUX(0x338, N, 0, dap1_fs_pn0, i2s0, hda, gmi, rsvd4), 337296936Smmel GMUX(0x33C, N, 1, dap1_din_pn1, i2s0, hda, gmi, rsvd4), 338296936Smmel GMUX(0x340, N, 2, dap1_dout_pn2, i2s0, hda, gmi, sata), 339296936Smmel GMUX(0x344, N, 3, dap1_sclk_pn3, i2s0, hda, gmi, rsvd4), 340296936Smmel GMUX(0x348, EE, 2, dap_mclk1_req_pee2, dap, dap1, sata, rsvd4), 341296936Smmel GMUX(0x34C, W, 4, dap_mclk1_pw4, extperiph1, dap2, rsvd3, rsvd4), 342296936Smmel GMUX(0x350, K, 6, spdif_in_pk6, spdif, rsvd2, rsvd3, i2c3), 343296936Smmel GMUX(0x354, K, 5, spdif_out_pk5, spdif, rsvd2, rsvd3, i2c3), 344296936Smmel GMUX(0x358, A, 2, dap2_fs_pa2, i2s1, hda, gmi, rsvd4), 345296936Smmel GMUX(0x35C, A, 4, dap2_din_pa4, i2s1, hda, gmi, rsvd4), 346296936Smmel GMUX(0x360, A, 5, dap2_dout_pa5, i2s1, hda, gmi, rsvd4), 347296936Smmel GMUX(0x364, A, 3, dap2_sclk_pa3, i2s1, hda, gmi, rsvd4), 348296936Smmel GMUX(0x368, X, 0, dvfs_pwm_px0, spi6, cldvfs, gmi, rsvd4), 349296936Smmel GMUX(0x36C, X, 1, gpio_x1_aud_px1, spi6, rsvd2, gmi, rsvd4), 350296936Smmel GMUX(0x370, X, 3, gpio_x3_aud_px3, spi6, spi1, gmi, rsvd4), 351296936Smmel GMUX(0x374, X, 2, dvfs_clk_px2, spi6, cldvfs, gmi, rsvd4), 352296936Smmel GMUX(0x378, X, 4, gpio_x4_aud_px4, gmi, spi1, spi2, dap2), 353296936Smmel GMUX(0x37C, X, 5, gpio_x5_aud_px5, gmi, spi1, spi2, rsvd4), 354296936Smmel GMUX(0x380, X, 6, gpio_x6_aud_px6, spi6, spi1, spi2, gmi), 355296936Smmel GMUX(0x384, X, 7, gpio_x7_aud_px7, rsvd1, spi1, spi2, rsvd4), 356296936Smmel GMUX(0x390, A, 6, sdmmc3_clk_pa6, sdmmc3, rsvd2, rsvd3, spi3), 357296936Smmel GMUX(0x394, A, 7, sdmmc3_cmd_pa7, sdmmc3, pwm3, uarta, spi3), 358296936Smmel GMUX(0x398, B, 7, sdmmc3_dat0_pb7, sdmmc3, rsvd2, rsvd3, spi3), 359296936Smmel GMUX(0x39C, B, 6, sdmmc3_dat1_pb6, sdmmc3, pwm2, uarta, spi3), 360296936Smmel GMUX(0x3A0, B, 5, sdmmc3_dat2_pb5, sdmmc3, pwm1, displaya, spi3), 361296936Smmel GMUX(0x3A4, B, 4, sdmmc3_dat3_pb4, sdmmc3, pwm0, displayb, spi3), 362296936Smmel GMUX(0x3BC, DD, 1, pex_l0_rst_n_pdd1, pe0, rsvd2, rsvd3, rsvd4), 363296936Smmel GMUX(0x3C0, DD, 2, pex_l0_clkreq_n_pdd2, pe0, rsvd2, rsvd3, rsvd4), 364296936Smmel GMUX(0x3C4, DD, 3, pex_wake_n_pdd3, pe, rsvd2, rsvd3, rsvd4), 365296936Smmel GMUX(0x3CC, DD, 5, pex_l1_rst_n_pdd5, pe1, rsvd2, rsvd3, rsvd4), 366296936Smmel GMUX(0x3D0, DD, 6, pex_l1_clkreq_n_pdd6, pe1, rsvd2, rsvd3, rsvd4), 367296936Smmel GMUX(0x3E0, EE, 3, hdmi_cec_pee3, cec, rsvd2, rsvd3, rsvd4), 368296936Smmel GMUX(0x3E4, V, 3, sdmmc1_wp_n_pv3, sdmmc1, clk12, spi4, uarta), 369296936Smmel GMUX(0x3E8, V, 2, sdmmc3_cd_n_pv2, sdmmc3, owr, rsvd3, rsvd4), 370296936Smmel GMUX(0x3EC, W, 2, gpio_w2_aud_pw2, spi6, rsvd2, spi2, i2c1), 371296936Smmel GMUX(0x3F0, W, 3, gpio_w3_aud_pw3, spi6, spi1, spi2, i2c1), 372296936Smmel GMUX(0x3F4, N, 4, usb_vbus_en0_pn4, usb, rsvd2, rsvd3, rsvd4), 373296936Smmel GMUX(0x3F8, N, 5, usb_vbus_en1_pn5, usb, rsvd2, rsvd3, rsvd4), 374296936Smmel GMUX(0x3FC, EE, 5, sdmmc3_clk_lb_in_pee5, sdmmc3, rsvd2, rsvd3, rsvd4), 375296936Smmel GMUX(0x400, EE, 4, sdmmc3_clk_lb_out_pee4, sdmmc3, rsvd2, rsvd3, rsvd4), 376296936Smmel FMUX(0x404, gmi_clk_lb, sdmmc2, rsvd2, gmi, rsvd4), 377296936Smmel FMUX(0x408, reset_out_n, rsvd1, rsvd2, rsvd3, reset_out_n), 378296936Smmel GMUX(0x40C, T, 0, kb_row16_pt0, kbc, rsvd2, rsvd3, uartc), 379296936Smmel GMUX(0x410, T, 1, kb_row17_pt1, kbc, rsvd2, rsvd3, uartc), 380296936Smmel GMUX(0x414, FF, 1, usb_vbus_en2_pff1, usb, rsvd2, rsvd3, rsvd4), 381296936Smmel GMUX(0x418, FF, 2, pff2, sata, rsvd2, rsvd3, rsvd4), 382296936Smmel GMUX(0x430, FF, 0, dp_hpd_pff0, dp, rsvd2, rsvd3, rsvd4), 383296936Smmel}; 384296936Smmel 385296936Smmelstruct tegra_grp { 386296936Smmel char *name; 387296936Smmel bus_size_t reg; 388296936Smmel int drvdn_shift; 389296936Smmel int drvdn_mask; 390296936Smmel int drvup_shift; 391296936Smmel int drvup_mask; 392296936Smmel}; 393296936Smmel 394296936Smmel#define GRP(r, nm, dn_s, dn_w, up_s, up_w) \ 395296936Smmel{ \ 396296936Smmel .name = #nm, \ 397296936Smmel .reg = r - 0x868, \ 398296936Smmel .drvdn_shift = dn_s, \ 399296936Smmel .drvdn_mask = (1 << dn_w) - 1, \ 400296936Smmel .drvup_shift = up_s, \ 401296936Smmel .drvup_mask = (1 << dn_w) - 1, \ 402296936Smmel} 403296936Smmel 404296936Smmel/* Use register offsets from TRM */ 405296936Smmelstatic const struct tegra_grp pin_grp_tbl[] = { 406296936Smmel GRP(0x868, ao1, 12, 5, 20, 5), 407296936Smmel GRP(0x86C, ao2, 12, 5, 20, 5), 408296936Smmel GRP(0x870, at1, 12, 7, 20, 7), 409296936Smmel GRP(0x874, at2, 12, 7, 20, 7), 410296936Smmel GRP(0x878, at3, 12, 7, 20, 7), 411296936Smmel GRP(0x87C, at4, 12, 7, 20, 7), 412296936Smmel GRP(0x880, at5, 14, 5, 19, 5), 413296936Smmel GRP(0x884, cdev1, 12, 5, 20, 5), 414296936Smmel GRP(0x888, cdev2, 12, 5, 20, 5), 415296936Smmel GRP(0x890, dap1, 12, 5, 20, 5), 416296936Smmel GRP(0x894, dap2, 12, 5, 20, 5), 417296936Smmel GRP(0x898, dap3, 12, 5, 20, 5), 418296936Smmel GRP(0x89C, dap4, 12, 5, 20, 5), 419296936Smmel GRP(0x8A0, dbg, 12, 5, 20, 5), 420296936Smmel GRP(0x8B0, sdio3, 12, 7, 20, 7), 421296936Smmel GRP(0x8B4, spi, 12, 5, 20, 5), 422296936Smmel GRP(0x8B8, uaa, 12, 5, 20, 5), 423296936Smmel GRP(0x8BC, uab, 12, 5, 20, 5), 424296936Smmel GRP(0x8C0, uart2, 12, 5, 20, 5), 425296936Smmel GRP(0x8C4, uart3, 12, 5, 20, 5), 426296936Smmel GRP(0x8EC, sdio1, 12, 7, 20, 7), 427296936Smmel GRP(0x8FC, ddc, 12, 5, 20, 5), 428296936Smmel GRP(0x900, gma, 14, 5, 20, 5), 429296936Smmel GRP(0x910, gme, 14, 5, 19, 5), 430296936Smmel GRP(0x914, gmf, 14, 5, 19, 5), 431296936Smmel GRP(0x918, gmg, 14, 5, 19, 5), 432296936Smmel GRP(0x91C, gmh, 14, 5, 19, 5), 433296936Smmel GRP(0x920, owr, 12, 5, 20, 5), 434296936Smmel GRP(0x924, uda, 12, 5, 20, 5), 435296936Smmel GRP(0x928, gpv, 12, 5, 20, 5), 436296936Smmel GRP(0x92C, dev3, 12, 5, 20, 5), 437296936Smmel GRP(0x938, cec, 12, 5, 20, 5), 438296936Smmel GRP(0x994, at6, 12, 7, 20, 7), 439296936Smmel GRP(0x998, dap5, 12, 5, 20, 5), 440296936Smmel GRP(0x99C, usb_vbus_en, 12, 5, 20, 5), 441296936Smmel GRP(0x9A8, ao3, 12, 5, -1, 0), 442296936Smmel GRP(0x9B0, ao0, 12, 5, 20, 5), 443296936Smmel GRP(0x9B4, hv0, 12, 5, -1, 0), 444296936Smmel GRP(0x9C4, sdio4, 12, 5, 20, 5), 445296936Smmel GRP(0x9C8, ao4, 12, 7, 20, 7), 446296936Smmel}; 447296936Smmel 448296936Smmelstatic const struct tegra_grp * 449296936Smmelpinmux_search_grp(char *grp_name) 450296936Smmel{ 451296936Smmel int i; 452296936Smmel 453296936Smmel for (i = 0; i < nitems(pin_grp_tbl); i++) { 454296936Smmel if (strcmp(grp_name, pin_grp_tbl[i].name) == 0) 455296936Smmel return (&pin_grp_tbl[i]); 456296936Smmel } 457296936Smmel return (NULL); 458296936Smmel} 459296936Smmel 460296936Smmelstatic const struct tegra_mux * 461296936Smmelpinmux_search_mux(char *pin_name) 462296936Smmel{ 463296936Smmel int i; 464296936Smmel 465296936Smmel for (i = 0; i < nitems(pin_mux_tbl); i++) { 466296936Smmel if (strcmp(pin_name, pin_mux_tbl[i].name) == 0) 467296936Smmel return (&pin_mux_tbl[i]); 468296936Smmel } 469296936Smmel return (NULL); 470296936Smmel} 471296936Smmel 472296936Smmelstatic int 473296936Smmelpinmux_mux_function(const struct tegra_mux *mux, char *fnc_name) 474296936Smmel{ 475296936Smmel int i; 476296936Smmel 477296936Smmel for (i = 0; i < 4; i++) { 478296936Smmel if (strcmp(fnc_name, mux->functions[i]) == 0) 479296936Smmel return (i); 480296936Smmel } 481296936Smmel return (-1); 482296936Smmel} 483296936Smmel 484296936Smmelstatic int 485296936Smmelpinmux_config_mux(struct pinmux_softc *sc, char *pin_name, 486296936Smmel const struct tegra_mux *mux, struct pincfg *cfg) 487296936Smmel{ 488296936Smmel int tmp; 489296936Smmel uint32_t reg; 490296936Smmel 491296936Smmel reg = bus_read_4(sc->mux_mem_res, mux->reg); 492296936Smmel 493296936Smmel if (cfg->function != NULL) { 494296936Smmel tmp = pinmux_mux_function(mux, cfg->function); 495296936Smmel if (tmp == -1) { 496296936Smmel device_printf(sc->dev, 497296936Smmel "Unknown function %s for pin %s\n", cfg->function, 498296936Smmel pin_name); 499296936Smmel return (ENXIO); 500296936Smmel } 501296936Smmel reg &= ~(TEGRA_MUX_FUNCTION_MASK << TEGRA_MUX_FUNCTION_SHIFT); 502296936Smmel reg |= (tmp & TEGRA_MUX_FUNCTION_MASK) << 503296936Smmel TEGRA_MUX_FUNCTION_SHIFT; 504296936Smmel } 505296936Smmel if (cfg->params[PROP_ID_PULL] != -1) { 506296936Smmel reg &= ~(TEGRA_MUX_PUPD_MASK << TEGRA_MUX_PUPD_SHIFT); 507296936Smmel reg |= (cfg->params[PROP_ID_PULL] & TEGRA_MUX_PUPD_MASK) << 508296936Smmel TEGRA_MUX_PUPD_SHIFT; 509296936Smmel } 510296936Smmel if (cfg->params[PROP_ID_TRISTATE] != -1) { 511296936Smmel reg &= ~(1 << TEGRA_MUX_TRISTATE_SHIFT); 512296936Smmel reg |= (cfg->params[PROP_ID_TRISTATE] & 1) << 513296936Smmel TEGRA_MUX_TRISTATE_SHIFT; 514296936Smmel } 515296936Smmel if (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] != -1) { 516296936Smmel reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT); 517296936Smmel reg |= (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] & 1) << 518296936Smmel TEGRA_MUX_ENABLE_INPUT_SHIFT; 519296936Smmel } 520296936Smmel if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) { 521296936Smmel reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT); 522296936Smmel reg |= (cfg->params[PROP_ID_ENABLE_INPUT] & 1) << 523296936Smmel TEGRA_MUX_ENABLE_INPUT_SHIFT; 524296936Smmel } 525296936Smmel if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) { 526296936Smmel reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT); 527296936Smmel reg |= (cfg->params[PROP_ID_OPEN_DRAIN] & 1) << 528296936Smmel TEGRA_MUX_ENABLE_INPUT_SHIFT; 529296936Smmel } 530296936Smmel if (cfg->params[PROP_ID_LOCK] != -1) { 531296936Smmel reg &= ~(1 << TEGRA_MUX_LOCK_SHIFT); 532296936Smmel reg |= (cfg->params[PROP_ID_LOCK] & 1) << 533296936Smmel TEGRA_MUX_LOCK_SHIFT; 534296936Smmel } 535296936Smmel if (cfg->params[PROP_ID_IORESET] != -1) { 536296936Smmel reg &= ~(1 << TEGRA_MUX_IORESET_SHIFT); 537296936Smmel reg |= (cfg->params[PROP_ID_IORESET] & 1) << 538296936Smmel TEGRA_MUX_IORESET_SHIFT; 539296936Smmel } 540296936Smmel if (cfg->params[PROP_ID_RCV_SEL] != -1) { 541296936Smmel reg &= ~(1 << TEGRA_MUX_RCV_SEL_SHIFT); 542296936Smmel reg |= (cfg->params[PROP_ID_RCV_SEL] & 1) << 543296936Smmel TEGRA_MUX_RCV_SEL_SHIFT; 544296936Smmel } 545296936Smmel bus_write_4(sc->mux_mem_res, mux->reg, reg); 546296936Smmel return (0); 547296936Smmel} 548296936Smmel 549296936Smmelstatic int 550296936Smmelpinmux_config_grp(struct pinmux_softc *sc, char *grp_name, 551296936Smmel const struct tegra_grp *grp, struct pincfg *cfg) 552296936Smmel{ 553296936Smmel uint32_t reg; 554296936Smmel 555296936Smmel reg = bus_read_4(sc->pad_mem_res, grp->reg); 556296936Smmel 557296936Smmel if (cfg->params[PROP_ID_HIGH_SPEED_MODE] != -1) { 558296936Smmel reg &= ~(1 << TEGRA_GRP_HSM_SHIFT); 559296936Smmel reg |= (cfg->params[PROP_ID_HIGH_SPEED_MODE] & 1) << 560296936Smmel TEGRA_GRP_HSM_SHIFT; 561296936Smmel } 562296936Smmel if (cfg->params[PROP_ID_SCHMITT] != -1) { 563296936Smmel reg &= ~(1 << TEGRA_GRP_SCHMT_SHIFT); 564296936Smmel reg |= (cfg->params[PROP_ID_SCHMITT] & 1) << 565296936Smmel TEGRA_GRP_SCHMT_SHIFT; 566296936Smmel } 567296936Smmel if (cfg->params[PROP_ID_DRIVE_TYPE] != -1) { 568296936Smmel reg &= ~(TEGRA_GRP_DRV_TYPE_MASK << TEGRA_GRP_DRV_TYPE_SHIFT); 569296936Smmel reg |= (cfg->params[PROP_ID_DRIVE_TYPE] & 570296936Smmel TEGRA_GRP_DRV_TYPE_MASK) << TEGRA_GRP_DRV_TYPE_SHIFT; 571296936Smmel } 572296936Smmel if (cfg->params[PROP_ID_SLEW_RATE_RISING] != -1) { 573296936Smmel reg &= ~(TEGRA_GRP_DRV_DRVDN_SLWR_MASK << 574296936Smmel TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT); 575296936Smmel reg |= (cfg->params[PROP_ID_SLEW_RATE_RISING] & 576296936Smmel TEGRA_GRP_DRV_DRVDN_SLWR_MASK) << 577296936Smmel TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT; 578296936Smmel } 579296936Smmel if (cfg->params[PROP_ID_SLEW_RATE_FALLING] != -1) { 580296936Smmel reg &= ~(TEGRA_GRP_DRV_DRVUP_SLWF_MASK << 581296936Smmel TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT); 582296936Smmel reg |= (cfg->params[PROP_ID_SLEW_RATE_FALLING] & 583296936Smmel TEGRA_GRP_DRV_DRVUP_SLWF_MASK) << 584296936Smmel TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT; 585296936Smmel } 586296936Smmel if ((cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] != -1) && 587296936Smmel (grp->drvdn_mask != -1)) { 588296936Smmel reg &= ~(grp->drvdn_shift << grp->drvdn_mask); 589296936Smmel reg |= (cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] & 590296936Smmel grp->drvdn_mask) << grp->drvdn_shift; 591296936Smmel } 592296936Smmel if ((cfg->params[PROP_ID_DRIVE_UP_STRENGTH] != -1) && 593296936Smmel (grp->drvup_mask != -1)) { 594296936Smmel reg &= ~(grp->drvup_shift << grp->drvup_mask); 595296936Smmel reg |= (cfg->params[PROP_ID_DRIVE_UP_STRENGTH] & 596296936Smmel grp->drvup_mask) << grp->drvup_shift; 597296936Smmel } 598296936Smmel bus_write_4(sc->pad_mem_res, grp->reg, reg); 599296936Smmel return (0); 600296936Smmel} 601296936Smmel 602296936Smmelstatic int 603296936Smmelpinmux_config_node(struct pinmux_softc *sc, char *pin_name, struct pincfg *cfg) 604296936Smmel{ 605296936Smmel const struct tegra_mux *mux; 606296936Smmel const struct tegra_grp *grp; 607296936Smmel uint32_t reg; 608296936Smmel int rv; 609296936Smmel 610296936Smmel /* Handle MIPI special case first */ 611296936Smmel if (strcmp(pin_name, "dsi_b") == 0) { 612296936Smmel if (cfg->function == NULL) { 613296936Smmel /* nothing to set */ 614296936Smmel return (0); 615296936Smmel } 616296936Smmel reg = bus_read_4(sc->mipi_mem_res, 0); /* register 0x820 */ 617296936Smmel if (strcmp(cfg->function, "csi") == 0) 618296936Smmel reg &= ~(1 << 1); 619296936Smmel else if (strcmp(cfg->function, "dsi_b") == 0) 620296936Smmel reg |= (1 << 1); 621296936Smmel bus_write_4(sc->mipi_mem_res, 0, reg); /* register 0x820 */ 622296936Smmel } 623296936Smmel 624296936Smmel /* Handle pin muxes */ 625296936Smmel mux = pinmux_search_mux(pin_name); 626296936Smmel if (mux != NULL) { 627296936Smmel if (mux->gpio_num != -1) { 628296936Smmel /* XXXX TODO: Reserve gpio here */ 629296936Smmel } 630296936Smmel rv = pinmux_config_mux(sc, pin_name, mux, cfg); 631296936Smmel return (rv); 632296936Smmel } 633296936Smmel 634296936Smmel /* Handle pin groups */ 635296936Smmel grp = pinmux_search_grp(pin_name); 636296936Smmel if (grp != NULL) { 637296936Smmel rv = pinmux_config_grp(sc, pin_name, grp, cfg); 638296936Smmel return (rv); 639296936Smmel } 640296936Smmel 641296936Smmel device_printf(sc->dev, "Unknown pin: %s\n", pin_name); 642296936Smmel return (ENXIO); 643296936Smmel} 644296936Smmel 645296936Smmelstatic int 646296936Smmelpinmux_read_node(struct pinmux_softc *sc, phandle_t node, struct pincfg *cfg, 647296936Smmel char **pins, int *lpins) 648296936Smmel{ 649296936Smmel int rv, i; 650296936Smmel 651296936Smmel *lpins = OF_getprop_alloc(node, "nvidia,pins", 1, (void **)pins); 652296936Smmel if (*lpins <= 0) 653296936Smmel return (ENOENT); 654296936Smmel 655296936Smmel /* Read function (mux) settings. */ 656296936Smmel rv = OF_getprop_alloc(node, "nvidia,function", 1, 657296936Smmel (void **)&cfg->function); 658296936Smmel if (rv <= 0) 659296936Smmel cfg->function = NULL; 660296936Smmel 661296936Smmel /* Read numeric properties. */ 662296936Smmel for (i = 0; i < PROP_ID_MAX_ID; i++) { 663296936Smmel rv = OF_getencprop(node, prop_names[i].name, &cfg->params[i], 664296936Smmel sizeof(cfg->params[i])); 665296936Smmel if (rv <= 0) 666296936Smmel cfg->params[i] = -1; 667296936Smmel } 668296936Smmel return (0); 669296936Smmel} 670296936Smmel 671296936Smmelstatic int 672296936Smmelpinmux_process_node(struct pinmux_softc *sc, phandle_t node) 673296936Smmel{ 674296936Smmel struct pincfg cfg; 675296936Smmel char *pins, *pname; 676296936Smmel int i, len, lpins, rv; 677296936Smmel 678296936Smmel rv = pinmux_read_node(sc, node, &cfg, &pins, &lpins); 679296936Smmel if (rv != 0) 680296936Smmel return (rv); 681296936Smmel 682296936Smmel len = 0; 683296936Smmel pname = pins; 684296936Smmel do { 685296936Smmel i = strlen(pname) + 1; 686296936Smmel rv = pinmux_config_node(sc, pname, &cfg); 687296936Smmel if (rv != 0) 688296936Smmel device_printf(sc->dev, 689296936Smmel "Cannot configure pin: %s: %d\n", pname, rv); 690296936Smmel 691296936Smmel len += i; 692296936Smmel pname += i; 693296936Smmel } while (len < lpins); 694296936Smmel 695296936Smmel if (pins != NULL) 696299715Sgonzo OF_prop_free(pins); 697296936Smmel if (cfg.function != NULL) 698299715Sgonzo OF_prop_free(cfg.function); 699296936Smmel return (rv); 700296936Smmel} 701296936Smmel 702296936Smmelstatic int pinmux_configure(device_t dev, phandle_t cfgxref) 703296936Smmel{ 704296936Smmel struct pinmux_softc *sc; 705296936Smmel phandle_t node, cfgnode; 706296936Smmel int rv; 707296936Smmel 708296936Smmel sc = device_get_softc(dev); 709296936Smmel cfgnode = OF_node_from_xref(cfgxref); 710296936Smmel 711296936Smmel 712296936Smmel for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) { 713296936Smmel if (!fdt_is_enabled(node)) 714296936Smmel continue; 715296936Smmel rv = pinmux_process_node(sc, node); 716296936Smmel } 717296936Smmel return (0); 718296936Smmel} 719296936Smmel 720296936Smmelstatic int 721296936Smmelpinmux_probe(device_t dev) 722296936Smmel{ 723296936Smmel 724296936Smmel if (!ofw_bus_status_okay(dev)) 725296936Smmel return (ENXIO); 726296936Smmel 727296936Smmel if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 728296936Smmel return (ENXIO); 729296936Smmel 730296936Smmel device_set_desc(dev, "Tegra pin configuration"); 731296936Smmel return (BUS_PROBE_DEFAULT); 732296936Smmel} 733296936Smmel 734296936Smmelstatic int 735296936Smmelpinmux_detach(device_t dev) 736296936Smmel{ 737296936Smmel 738296936Smmel /* This device is always present. */ 739296936Smmel return (EBUSY); 740296936Smmel} 741296936Smmel 742296936Smmelstatic int 743296936Smmelpinmux_attach(device_t dev) 744296936Smmel{ 745296936Smmel struct pinmux_softc * sc; 746296936Smmel int rid; 747296936Smmel 748296936Smmel sc = device_get_softc(dev); 749296936Smmel sc->dev = dev; 750296936Smmel 751296936Smmel rid = 0; 752296936Smmel sc->pad_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 753296936Smmel RF_ACTIVE); 754296936Smmel if (sc->pad_mem_res == NULL) { 755296936Smmel device_printf(dev, "Cannot allocate memory resources\n"); 756296936Smmel return (ENXIO); 757296936Smmel } 758296936Smmel 759296936Smmel rid = 1; 760296936Smmel sc->mux_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 761296936Smmel RF_ACTIVE); 762296936Smmel if (sc->mux_mem_res == NULL) { 763296936Smmel device_printf(dev, "Cannot allocate memory resources\n"); 764296936Smmel return (ENXIO); 765296936Smmel } 766296936Smmel 767296936Smmel rid = 2; 768296936Smmel sc->mipi_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 769296936Smmel RF_ACTIVE); 770296936Smmel if (sc->mipi_mem_res == NULL) { 771296936Smmel device_printf(dev, "Cannot allocate memory resources\n"); 772296936Smmel return (ENXIO); 773296936Smmel } 774296936Smmel 775296936Smmel /* Register as a pinctrl device and process default configuration */ 776296936Smmel fdt_pinctrl_register(dev, NULL); 777296936Smmel fdt_pinctrl_configure_by_name(dev, "boot"); 778296936Smmel 779296936Smmel return (0); 780296936Smmel} 781296936Smmel 782296936Smmel 783296936Smmelstatic device_method_t tegra_pinmux_methods[] = { 784296936Smmel /* Device interface */ 785296936Smmel DEVMETHOD(device_probe, pinmux_probe), 786296936Smmel DEVMETHOD(device_attach, pinmux_attach), 787296936Smmel DEVMETHOD(device_detach, pinmux_detach), 788296936Smmel 789296936Smmel /* fdt_pinctrl interface */ 790296936Smmel DEVMETHOD(fdt_pinctrl_configure,pinmux_configure), 791296936Smmel 792296936Smmel DEVMETHOD_END 793296936Smmel}; 794296936Smmel 795296936Smmelstatic devclass_t tegra_pinmux_devclass; 796308335Smmelstatic DEFINE_CLASS_0(pinmux, tegra_pinmux_driver, tegra_pinmux_methods, 797308335Smmel sizeof(struct pinmux_softc)); 798296936SmmelEARLY_DRIVER_MODULE(tegra_pinmux, simplebus, tegra_pinmux_driver, 799308335Smmel tegra_pinmux_devclass, NULL, NULL, 71); 800