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