xref: /rk3399_rockchip-uboot/arch/arm/mach-tegra/tegra124/xusb-padctl.c (revision 1680d7b6de2c63333d3a67c2f5f852a127e412cd)
109f455dcSMasahiro Yamada /*
2*1680d7b6SStephen Warren  * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
309f455dcSMasahiro Yamada  *
409f455dcSMasahiro Yamada  * SPDX-License-Identifier: GPL-2.0
509f455dcSMasahiro Yamada  */
609f455dcSMasahiro Yamada 
709f455dcSMasahiro Yamada #define pr_fmt(fmt) "tegra-xusb-padctl: " fmt
809f455dcSMasahiro Yamada 
909f455dcSMasahiro Yamada #include <common.h>
1009f455dcSMasahiro Yamada #include <errno.h>
1109f455dcSMasahiro Yamada #include <fdtdec.h>
1209f455dcSMasahiro Yamada #include <malloc.h>
1309f455dcSMasahiro Yamada 
14*1680d7b6SStephen Warren #include "../xusb-padctl-common.h"
15*1680d7b6SStephen Warren 
1609f455dcSMasahiro Yamada #include <asm/io.h>
1709f455dcSMasahiro Yamada 
1809f455dcSMasahiro Yamada #include <asm/arch/clock.h>
1909f455dcSMasahiro Yamada #include <asm/arch-tegra/xusb-padctl.h>
2009f455dcSMasahiro Yamada 
2109f455dcSMasahiro Yamada #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
2209f455dcSMasahiro Yamada 
2309f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM 0x01c
2409f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
2509f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
2609f455dcSMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
2709f455dcSMasahiro Yamada 
2809f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
2909f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
3009f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
3109f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
3209f455dcSMasahiro Yamada 
3309f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
3409f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
3509f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
3609f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
3709f455dcSMasahiro Yamada 
3809f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
3909f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
4009f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
4109f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
4209f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
4309f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
4409f455dcSMasahiro Yamada 
4509f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
4609f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
4709f455dcSMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
4809f455dcSMasahiro Yamada 
4909f455dcSMasahiro Yamada enum tegra124_function {
5009f455dcSMasahiro Yamada 	TEGRA124_FUNC_SNPS,
5109f455dcSMasahiro Yamada 	TEGRA124_FUNC_XUSB,
5209f455dcSMasahiro Yamada 	TEGRA124_FUNC_UART,
5309f455dcSMasahiro Yamada 	TEGRA124_FUNC_PCIE,
5409f455dcSMasahiro Yamada 	TEGRA124_FUNC_USB3,
5509f455dcSMasahiro Yamada 	TEGRA124_FUNC_SATA,
5609f455dcSMasahiro Yamada 	TEGRA124_FUNC_RSVD,
5709f455dcSMasahiro Yamada };
5809f455dcSMasahiro Yamada 
5909f455dcSMasahiro Yamada static const char *const tegra124_functions[] = {
6009f455dcSMasahiro Yamada 	"snps",
6109f455dcSMasahiro Yamada 	"xusb",
6209f455dcSMasahiro Yamada 	"uart",
6309f455dcSMasahiro Yamada 	"pcie",
6409f455dcSMasahiro Yamada 	"usb3",
6509f455dcSMasahiro Yamada 	"sata",
6609f455dcSMasahiro Yamada 	"rsvd",
6709f455dcSMasahiro Yamada };
6809f455dcSMasahiro Yamada 
6909f455dcSMasahiro Yamada static const unsigned int tegra124_otg_functions[] = {
7009f455dcSMasahiro Yamada 	TEGRA124_FUNC_SNPS,
7109f455dcSMasahiro Yamada 	TEGRA124_FUNC_XUSB,
7209f455dcSMasahiro Yamada 	TEGRA124_FUNC_UART,
7309f455dcSMasahiro Yamada 	TEGRA124_FUNC_RSVD,
7409f455dcSMasahiro Yamada };
7509f455dcSMasahiro Yamada 
7609f455dcSMasahiro Yamada static const unsigned int tegra124_usb_functions[] = {
7709f455dcSMasahiro Yamada 	TEGRA124_FUNC_SNPS,
7809f455dcSMasahiro Yamada 	TEGRA124_FUNC_XUSB,
7909f455dcSMasahiro Yamada };
8009f455dcSMasahiro Yamada 
8109f455dcSMasahiro Yamada static const unsigned int tegra124_pci_functions[] = {
8209f455dcSMasahiro Yamada 	TEGRA124_FUNC_PCIE,
8309f455dcSMasahiro Yamada 	TEGRA124_FUNC_USB3,
8409f455dcSMasahiro Yamada 	TEGRA124_FUNC_SATA,
8509f455dcSMasahiro Yamada 	TEGRA124_FUNC_RSVD,
8609f455dcSMasahiro Yamada };
8709f455dcSMasahiro Yamada 
8809f455dcSMasahiro Yamada #define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)	\
8909f455dcSMasahiro Yamada 	{								\
9009f455dcSMasahiro Yamada 		.name = _name,						\
9109f455dcSMasahiro Yamada 		.offset = _offset,					\
9209f455dcSMasahiro Yamada 		.shift = _shift,					\
9309f455dcSMasahiro Yamada 		.mask = _mask,						\
9409f455dcSMasahiro Yamada 		.iddq = _iddq,						\
9509f455dcSMasahiro Yamada 		.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions),	\
9609f455dcSMasahiro Yamada 		.funcs = tegra124_##_funcs##_functions,			\
9709f455dcSMasahiro Yamada 	}
9809f455dcSMasahiro Yamada 
9909f455dcSMasahiro Yamada static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
10009f455dcSMasahiro Yamada 	TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
10109f455dcSMasahiro Yamada 	TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
10209f455dcSMasahiro Yamada 	TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
10309f455dcSMasahiro Yamada 	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
10409f455dcSMasahiro Yamada 	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
10509f455dcSMasahiro Yamada 	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
10609f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
10709f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
10809f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
10909f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
11009f455dcSMasahiro Yamada 	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
11109f455dcSMasahiro Yamada 	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
11209f455dcSMasahiro Yamada };
11309f455dcSMasahiro Yamada 
11409f455dcSMasahiro Yamada static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
11509f455dcSMasahiro Yamada {
11609f455dcSMasahiro Yamada 	u32 value;
11709f455dcSMasahiro Yamada 
11809f455dcSMasahiro Yamada 	if (padctl->enable++ > 0)
11909f455dcSMasahiro Yamada 		return 0;
12009f455dcSMasahiro Yamada 
12109f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
12209f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
12309f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
12409f455dcSMasahiro Yamada 
12509f455dcSMasahiro Yamada 	udelay(100);
12609f455dcSMasahiro Yamada 
12709f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
12809f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
12909f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
13009f455dcSMasahiro Yamada 
13109f455dcSMasahiro Yamada 	udelay(100);
13209f455dcSMasahiro Yamada 
13309f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
13409f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
13509f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
13609f455dcSMasahiro Yamada 
13709f455dcSMasahiro Yamada 	return 0;
13809f455dcSMasahiro Yamada }
13909f455dcSMasahiro Yamada 
14009f455dcSMasahiro Yamada static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
14109f455dcSMasahiro Yamada {
14209f455dcSMasahiro Yamada 	u32 value;
14309f455dcSMasahiro Yamada 
14409f455dcSMasahiro Yamada 	if (padctl->enable == 0) {
145057fd32fSStephen Warren 		error("unbalanced enable/disable");
14609f455dcSMasahiro Yamada 		return 0;
14709f455dcSMasahiro Yamada 	}
14809f455dcSMasahiro Yamada 
14909f455dcSMasahiro Yamada 	if (--padctl->enable > 0)
15009f455dcSMasahiro Yamada 		return 0;
15109f455dcSMasahiro Yamada 
15209f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
15309f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
15409f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
15509f455dcSMasahiro Yamada 
15609f455dcSMasahiro Yamada 	udelay(100);
15709f455dcSMasahiro Yamada 
15809f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
15909f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
16009f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
16109f455dcSMasahiro Yamada 
16209f455dcSMasahiro Yamada 	udelay(100);
16309f455dcSMasahiro Yamada 
16409f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
16509f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
16609f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
16709f455dcSMasahiro Yamada 
16809f455dcSMasahiro Yamada 	return 0;
16909f455dcSMasahiro Yamada }
17009f455dcSMasahiro Yamada 
17109f455dcSMasahiro Yamada static int phy_prepare(struct tegra_xusb_phy *phy)
17209f455dcSMasahiro Yamada {
17309f455dcSMasahiro Yamada 	return tegra_xusb_padctl_enable(phy->padctl);
17409f455dcSMasahiro Yamada }
17509f455dcSMasahiro Yamada 
17609f455dcSMasahiro Yamada static int phy_unprepare(struct tegra_xusb_phy *phy)
17709f455dcSMasahiro Yamada {
17809f455dcSMasahiro Yamada 	return tegra_xusb_padctl_disable(phy->padctl);
17909f455dcSMasahiro Yamada }
18009f455dcSMasahiro Yamada 
18109f455dcSMasahiro Yamada static int pcie_phy_enable(struct tegra_xusb_phy *phy)
18209f455dcSMasahiro Yamada {
18309f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
18409f455dcSMasahiro Yamada 	int err = -ETIMEDOUT;
18509f455dcSMasahiro Yamada 	unsigned long start;
18609f455dcSMasahiro Yamada 	u32 value;
18709f455dcSMasahiro Yamada 
18809f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
18909f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
19009f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
19109f455dcSMasahiro Yamada 
19209f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
19309f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
19409f455dcSMasahiro Yamada 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
19509f455dcSMasahiro Yamada 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
19609f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
19709f455dcSMasahiro Yamada 
19809f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
19909f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
20009f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
20109f455dcSMasahiro Yamada 
20209f455dcSMasahiro Yamada 	start = get_timer(0);
20309f455dcSMasahiro Yamada 
20409f455dcSMasahiro Yamada 	while (get_timer(start) < 50) {
20509f455dcSMasahiro Yamada 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
20609f455dcSMasahiro Yamada 		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
20709f455dcSMasahiro Yamada 			err = 0;
20809f455dcSMasahiro Yamada 			break;
20909f455dcSMasahiro Yamada 		}
21009f455dcSMasahiro Yamada 	}
21109f455dcSMasahiro Yamada 
21209f455dcSMasahiro Yamada 	return err;
21309f455dcSMasahiro Yamada }
21409f455dcSMasahiro Yamada 
21509f455dcSMasahiro Yamada static int pcie_phy_disable(struct tegra_xusb_phy *phy)
21609f455dcSMasahiro Yamada {
21709f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
21809f455dcSMasahiro Yamada 	u32 value;
21909f455dcSMasahiro Yamada 
22009f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
22109f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
22209f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
22309f455dcSMasahiro Yamada 
22409f455dcSMasahiro Yamada 	return 0;
22509f455dcSMasahiro Yamada }
22609f455dcSMasahiro Yamada 
22709f455dcSMasahiro Yamada static int sata_phy_enable(struct tegra_xusb_phy *phy)
22809f455dcSMasahiro Yamada {
22909f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
23009f455dcSMasahiro Yamada 	int err = -ETIMEDOUT;
23109f455dcSMasahiro Yamada 	unsigned long start;
23209f455dcSMasahiro Yamada 	u32 value;
23309f455dcSMasahiro Yamada 
23409f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
23509f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
23609f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
23709f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
23809f455dcSMasahiro Yamada 
23909f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
24009f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
24109f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
24209f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
24309f455dcSMasahiro Yamada 
24409f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
24509f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
24609f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
24709f455dcSMasahiro Yamada 
24809f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
24909f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
25009f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
25109f455dcSMasahiro Yamada 
25209f455dcSMasahiro Yamada 	start = get_timer(0);
25309f455dcSMasahiro Yamada 
25409f455dcSMasahiro Yamada 	while (get_timer(start) < 50) {
25509f455dcSMasahiro Yamada 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
25609f455dcSMasahiro Yamada 		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
25709f455dcSMasahiro Yamada 			err = 0;
25809f455dcSMasahiro Yamada 			break;
25909f455dcSMasahiro Yamada 		}
26009f455dcSMasahiro Yamada 	}
26109f455dcSMasahiro Yamada 
26209f455dcSMasahiro Yamada 	return err;
26309f455dcSMasahiro Yamada }
26409f455dcSMasahiro Yamada 
26509f455dcSMasahiro Yamada static int sata_phy_disable(struct tegra_xusb_phy *phy)
26609f455dcSMasahiro Yamada {
26709f455dcSMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy->padctl;
26809f455dcSMasahiro Yamada 	u32 value;
26909f455dcSMasahiro Yamada 
27009f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
27109f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
27209f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
27309f455dcSMasahiro Yamada 
27409f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
27509f455dcSMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
27609f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
27709f455dcSMasahiro Yamada 
27809f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
27909f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
28009f455dcSMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
28109f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
28209f455dcSMasahiro Yamada 
28309f455dcSMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
28409f455dcSMasahiro Yamada 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
28509f455dcSMasahiro Yamada 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
28609f455dcSMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
28709f455dcSMasahiro Yamada 
28809f455dcSMasahiro Yamada 	return 0;
28909f455dcSMasahiro Yamada }
29009f455dcSMasahiro Yamada 
29109f455dcSMasahiro Yamada static const struct tegra_xusb_phy_ops pcie_phy_ops = {
29209f455dcSMasahiro Yamada 	.prepare = phy_prepare,
29309f455dcSMasahiro Yamada 	.enable = pcie_phy_enable,
29409f455dcSMasahiro Yamada 	.disable = pcie_phy_disable,
29509f455dcSMasahiro Yamada 	.unprepare = phy_unprepare,
29609f455dcSMasahiro Yamada };
29709f455dcSMasahiro Yamada 
29809f455dcSMasahiro Yamada static const struct tegra_xusb_phy_ops sata_phy_ops = {
29909f455dcSMasahiro Yamada 	.prepare = phy_prepare,
30009f455dcSMasahiro Yamada 	.enable = sata_phy_enable,
30109f455dcSMasahiro Yamada 	.disable = sata_phy_disable,
30209f455dcSMasahiro Yamada 	.unprepare = phy_unprepare,
30309f455dcSMasahiro Yamada };
30409f455dcSMasahiro Yamada 
305*1680d7b6SStephen Warren struct tegra_xusb_padctl *padctl = &(struct tegra_xusb_padctl) {
30609f455dcSMasahiro Yamada 	.phys = {
30709f455dcSMasahiro Yamada 		[0] = {
30809f455dcSMasahiro Yamada 			.ops = &pcie_phy_ops,
30909f455dcSMasahiro Yamada 		},
31009f455dcSMasahiro Yamada 		[1] = {
31109f455dcSMasahiro Yamada 			.ops = &sata_phy_ops,
31209f455dcSMasahiro Yamada 		},
31309f455dcSMasahiro Yamada 	},
31409f455dcSMasahiro Yamada };
31509f455dcSMasahiro Yamada 
316*1680d7b6SStephen Warren int process_nodes(const void *fdt, int nodes[], unsigned int count)
31709f455dcSMasahiro Yamada {
31809f455dcSMasahiro Yamada 	unsigned int i;
31909f455dcSMasahiro Yamada 
32009f455dcSMasahiro Yamada 	for (i = 0; i < count; i++) {
32109f455dcSMasahiro Yamada 		enum fdt_compat_id id;
32209f455dcSMasahiro Yamada 		int err;
32309f455dcSMasahiro Yamada 
32409f455dcSMasahiro Yamada 		if (!fdtdec_get_is_enabled(fdt, nodes[i]))
32509f455dcSMasahiro Yamada 			continue;
32609f455dcSMasahiro Yamada 
32709f455dcSMasahiro Yamada 		id = fdtdec_lookup(fdt, nodes[i]);
32809f455dcSMasahiro Yamada 		switch (id) {
32909f455dcSMasahiro Yamada 		case COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL:
33009f455dcSMasahiro Yamada 			break;
33109f455dcSMasahiro Yamada 
33209f455dcSMasahiro Yamada 		default:
333057fd32fSStephen Warren 			error("unsupported compatible: %s",
33409f455dcSMasahiro Yamada 			      fdtdec_get_compatible(id));
33509f455dcSMasahiro Yamada 			continue;
33609f455dcSMasahiro Yamada 		}
33709f455dcSMasahiro Yamada 
33809f455dcSMasahiro Yamada 		padctl->num_lanes = ARRAY_SIZE(tegra124_lanes);
33909f455dcSMasahiro Yamada 		padctl->lanes = tegra124_lanes;
34009f455dcSMasahiro Yamada 
34109f455dcSMasahiro Yamada 		padctl->num_functions = ARRAY_SIZE(tegra124_functions);
34209f455dcSMasahiro Yamada 		padctl->functions = tegra124_functions;
34309f455dcSMasahiro Yamada 
34409f455dcSMasahiro Yamada 		err = tegra_xusb_padctl_parse_dt(padctl, fdt, nodes[i]);
34509f455dcSMasahiro Yamada 		if (err < 0) {
346057fd32fSStephen Warren 			error("failed to parse DT: %d", err);
34709f455dcSMasahiro Yamada 			continue;
34809f455dcSMasahiro Yamada 		}
34909f455dcSMasahiro Yamada 
35009f455dcSMasahiro Yamada 		/* deassert XUSB padctl reset */
35109f455dcSMasahiro Yamada 		reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0);
35209f455dcSMasahiro Yamada 
35309f455dcSMasahiro Yamada 		err = tegra_xusb_padctl_config_apply(padctl, &padctl->config);
35409f455dcSMasahiro Yamada 		if (err < 0) {
355057fd32fSStephen Warren 			error("failed to apply pinmux: %d", err);
35609f455dcSMasahiro Yamada 			continue;
35709f455dcSMasahiro Yamada 		}
35809f455dcSMasahiro Yamada 
35909f455dcSMasahiro Yamada 		/* only a single instance is supported */
36009f455dcSMasahiro Yamada 		break;
36109f455dcSMasahiro Yamada 	}
36209f455dcSMasahiro Yamada 
36309f455dcSMasahiro Yamada 	return 0;
36409f455dcSMasahiro Yamada }
36509f455dcSMasahiro Yamada 
36609f455dcSMasahiro Yamada void tegra_xusb_padctl_init(const void *fdt)
36709f455dcSMasahiro Yamada {
36809f455dcSMasahiro Yamada 	int count, nodes[1];
36909f455dcSMasahiro Yamada 
37009f455dcSMasahiro Yamada 	count = fdtdec_find_aliases_for_id(fdt, "padctl",
37109f455dcSMasahiro Yamada 					   COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
37209f455dcSMasahiro Yamada 					   nodes, ARRAY_SIZE(nodes));
37309f455dcSMasahiro Yamada 	if (process_nodes(fdt, nodes, count))
37409f455dcSMasahiro Yamada 		return;
37509f455dcSMasahiro Yamada }
376