[go: nahoru, domu]

1dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding/*
2dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
3dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding *
4dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * This program is free software; you can redistribute it and/or modify it
5dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * under the terms and conditions of the GNU General Public License,
6dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * version 2, as published by the Free Software Foundation.
7dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding *
8dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * This program is distributed in the hope it will be useful, but WITHOUT
9dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding * more details.
12dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding */
13dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
14dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/delay.h>
15dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/io.h>
16dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/module.h>
17dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/of.h>
18dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/phy/phy.h>
19dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/pinctrl/pinctrl.h>
20dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/pinctrl/pinmux.h>
21dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/platform_device.h>
22dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <linux/reset.h>
23dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
24dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
25dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
26dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include "core.h"
27dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#include "pinctrl-utils.h"
28dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
29dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
30dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
31dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
32dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
33dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
34dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
35dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
36dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
37dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
38dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
39dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
40dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
41dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
42dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
43dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
44dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
45dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
46dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
47dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
48dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
49dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
50dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
51dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
52dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
53dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
54dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
55dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstruct tegra_xusb_padctl_function {
56dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const char *name;
57dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const char * const *groups;
58dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int num_groups;
59dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
60dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
61dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstruct tegra_xusb_padctl_group {
62dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const unsigned int *funcs;
63dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int num_funcs;
64dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
65dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
66dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstruct tegra_xusb_padctl_soc {
67dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct pinctrl_pin_desc *pins;
68dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int num_pins;
69dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
70dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct tegra_xusb_padctl_function *functions;
71dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int num_functions;
72dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
73dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct tegra_xusb_padctl_lane *lanes;
74dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int num_lanes;
75dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
76dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
77dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstruct tegra_xusb_padctl_lane {
78dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const char *name;
79dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
80dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int offset;
81dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int shift;
82dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int mask;
83dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int iddq;
84dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
85dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const unsigned int *funcs;
86dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int num_funcs;
87dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
88dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
89dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstruct tegra_xusb_padctl {
90dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct device *dev;
91dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	void __iomem *regs;
92dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct mutex lock;
93dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct reset_control *rst;
94dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
95dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct tegra_xusb_padctl_soc *soc;
96dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct pinctrl_dev *pinctrl;
97dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct pinctrl_desc desc;
98dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
99dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct phy_provider *provider;
100dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct phy *phys[2];
101dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
102dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int enable;
103dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
104dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
105dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
106dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				 unsigned long offset)
107dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
108dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	writel(value, padctl->regs + offset);
109dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
110dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
111dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
112dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			       unsigned long offset)
113dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
114dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return readl(padctl->regs + offset);
115dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
116dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
117dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
118dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
119dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
120dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
121dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return padctl->soc->num_pins;
122dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
123dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
124dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
125dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding						    unsigned int group)
126dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
127dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
128dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
129dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return padctl->soc->pins[group].name;
130dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
131dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
132dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingenum tegra_xusb_padctl_param {
133dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA_XUSB_PADCTL_IDDQ,
134dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
135dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
136dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct tegra_xusb_padctl_property {
137dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const char *name;
138dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	enum tegra_xusb_padctl_param param;
139dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding} properties[] = {
140dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	{ "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
141dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
142dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
143dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
144dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
145dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
146dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
147dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
148dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					   struct device_node *np,
149dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					   struct pinctrl_map **maps,
150dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					   unsigned int *reserved_maps,
151dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					   unsigned int *num_maps)
152dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
153dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int i, reserve = 0, num_configs = 0;
154dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned long config, *configs = NULL;
155dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const char *function, *group;
156dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct property *prop;
157dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	int err = 0;
158dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
159dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
160dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	err = of_property_read_string(np, "nvidia,function", &function);
161dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (err < 0) {
162dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (err != -EINVAL)
163dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			return err;
164dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
165dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		function = NULL;
166dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
167dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
168dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	for (i = 0; i < ARRAY_SIZE(properties); i++) {
169dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		err = of_property_read_u32(np, properties[i].name, &value);
170dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (err < 0) {
171dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			if (err == -EINVAL)
172dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				continue;
173dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
174dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			return err;
175dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		}
176dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
177dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
178dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
179dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
180dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					       &num_configs, config);
181dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (err < 0)
182dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			return err;
183dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
184dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
185dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (function)
186dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		reserve++;
187dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
188dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (num_configs)
189dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		reserve++;
190dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
191dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	err = of_property_count_strings(np, "nvidia,lanes");
192dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (err < 0)
193dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return err;
194dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
195dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	reserve *= err;
196dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
197dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
198dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					num_maps, reserve);
199dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (err < 0)
200dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return err;
201dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
202dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	of_property_for_each_string(np, "nvidia,lanes", prop, group) {
203dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (function) {
204dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
205dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					reserved_maps, num_maps, group,
206dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					function);
207dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			if (err < 0)
208dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				return err;
209dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		}
210dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
211dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (num_configs) {
212dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			err = pinctrl_utils_add_map_configs(padctl->pinctrl,
213dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					maps, reserved_maps, num_maps, group,
214dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					configs, num_configs,
215dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					PIN_MAP_TYPE_CONFIGS_GROUP);
216dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			if (err < 0)
217dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				return err;
218dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		}
219dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
220dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
221dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
222dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
223dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
224dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
225dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					    struct device_node *parent,
226dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					    struct pinctrl_map **maps,
227dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					    unsigned int *num_maps)
228dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
229dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
230dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int reserved_maps = 0;
231dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct device_node *np;
232dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	int err;
233dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
234dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	*num_maps = 0;
235dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	*maps = NULL;
236dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
237dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	for_each_child_of_node(parent, np) {
238dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
239dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding						      &reserved_maps,
240dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding						      num_maps);
241dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (err < 0)
242dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			return err;
243dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
244dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
245dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
246dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
247dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
248dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
249dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.get_groups_count = tegra_xusb_padctl_get_groups_count,
250dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.get_group_name = tegra_xusb_padctl_get_group_name,
251dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
252dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.dt_free_map = pinctrl_utils_dt_free_map,
253dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
254dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
255dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
256dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
257dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
258dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
259dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return padctl->soc->num_functions;
260dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
261dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
262dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char *
263dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingtegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
264dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				    unsigned int function)
265dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
266dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
267dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
268dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return padctl->soc->functions[function].name;
269dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
270dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
271dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
272dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding						 unsigned int function,
273dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding						 const char * const **groups,
274dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding						 unsigned * const num_groups)
275dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
276dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
277dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
278dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	*num_groups = padctl->soc->functions[function].num_groups;
279dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	*groups = padctl->soc->functions[function].groups;
280dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
281dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
282dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
283dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
28403e9f0cac5da6af85758276cb4624caf5911f2b9Linus Walleijstatic int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl,
28503e9f0cac5da6af85758276cb4624caf5911f2b9Linus Walleij					unsigned int function,
28603e9f0cac5da6af85758276cb4624caf5911f2b9Linus Walleij					unsigned int group)
287dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
288dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
289dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct tegra_xusb_padctl_lane *lane;
290dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int i;
291dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
292dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
293dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	lane = &padctl->soc->lanes[group];
294dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
295dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	for (i = 0; i < lane->num_funcs; i++)
296dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (lane->funcs[i] == function)
297dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			break;
298dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
299dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (i >= lane->num_funcs)
300dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return -EINVAL;
301dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
302dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, lane->offset);
303dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~(lane->mask << lane->shift);
304dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= i << lane->shift;
305dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, lane->offset);
306dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
307dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
308dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
309dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
310dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
311dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.get_functions_count = tegra_xusb_padctl_get_functions_count,
312dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.get_function_name = tegra_xusb_padctl_get_function_name,
313dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.get_function_groups = tegra_xusb_padctl_get_function_groups,
31403e9f0cac5da6af85758276cb4624caf5911f2b9Linus Walleij	.set_mux = tegra_xusb_padctl_pinmux_set,
315dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
316dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
317dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
318dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					       unsigned int group,
319dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					       unsigned long *config)
320dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
321dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
322dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct tegra_xusb_padctl_lane *lane;
323dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	enum tegra_xusb_padctl_param param;
324dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
325dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
326dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
327dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	lane = &padctl->soc->lanes[group];
328dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
329dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	switch (param) {
330dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	case TEGRA_XUSB_PADCTL_IDDQ:
331dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		/* lanes with iddq == 0 don't support this parameter */
332dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (lane->iddq == 0)
333dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			return -EINVAL;
334dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
335dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		value = padctl_readl(padctl, lane->offset);
336dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
337dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (value & BIT(lane->iddq))
338dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			value = 0;
339dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		else
340dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			value = 1;
341dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
342dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		*config = TEGRA_XUSB_PADCTL_PACK(param, value);
343dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		break;
344dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
345dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	default:
346dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
347dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			param);
348dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return -ENOTSUPP;
349dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
350dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
351dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
352dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
353dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
354dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
355dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					       unsigned int group,
356dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					       unsigned long *configs,
357dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					       unsigned int num_configs)
358dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
359dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
360dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct tegra_xusb_padctl_lane *lane;
361dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	enum tegra_xusb_padctl_param param;
362dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned long value;
363dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int i;
364dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 regval;
365dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
366dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	lane = &padctl->soc->lanes[group];
367dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
368dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	for (i = 0; i < num_configs; i++) {
369dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
370dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
371dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
372dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		switch (param) {
373dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		case TEGRA_XUSB_PADCTL_IDDQ:
374dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			/* lanes with iddq == 0 don't support this parameter */
375dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			if (lane->iddq == 0)
376dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				return -EINVAL;
377dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
378dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			regval = padctl_readl(padctl, lane->offset);
379dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
380dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			if (value)
381dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				regval &= ~BIT(lane->iddq);
382dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			else
383dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				regval |= BIT(lane->iddq);
384dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
385dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			padctl_writel(padctl, regval, lane->offset);
386dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			break;
387dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
388dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		default:
389dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			dev_err(padctl->dev,
390dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				"invalid configuration parameter: %04x\n",
391dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding				param);
392dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			return -ENOTSUPP;
393dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		}
394dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
395dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
396dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
397dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
398dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
399dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#ifdef CONFIG_DEBUG_FS
400dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char *strip_prefix(const char *s)
401dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
402dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const char *comma = strchr(s, ',');
403dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (!comma)
404dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return s;
405dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
406dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return comma + 1;
407dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
408dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
409dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic void
410dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingtegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
411dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					 struct seq_file *s,
412dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					 unsigned int group)
413dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
414dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int i;
415dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
416dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	for (i = 0; i < ARRAY_SIZE(properties); i++) {
417dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		unsigned long config, value;
418dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		int err;
419dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
420dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
421dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
422dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
423dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding							  &config);
424dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (err < 0)
425dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			continue;
426dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
427dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
428dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
429dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
430dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			   value);
431dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
432dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
433dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
434dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic void
435dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingtegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
436dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					  struct seq_file *s,
437dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					  unsigned long config)
438dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
439dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	enum tegra_xusb_padctl_param param;
440dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const char *name = "unknown";
441dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned long value;
442dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int i;
443dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
444dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
445dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
446dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
447dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	for (i = 0; i < ARRAY_SIZE(properties); i++) {
448dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (properties[i].param == param) {
449dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			name = properties[i].name;
450dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			break;
451dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		}
452dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
453dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
454dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	seq_printf(s, "%s=%lu", strip_prefix(name), value);
455dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
456dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#endif
457dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
458dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
459dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
460dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
461dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#ifdef CONFIG_DEBUG_FS
462dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
463dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
464dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#endif
465dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
466dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
467dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
468dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
469dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
470dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
471dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	mutex_lock(&padctl->lock);
472dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
473dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (padctl->enable++ > 0)
474dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		goto out;
475dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
476dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
477dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
478dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
479dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
480dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	usleep_range(100, 200);
481dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
482dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
483dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
484dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
485dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
486dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	usleep_range(100, 200);
487dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
488dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
489dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
490dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
491dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
492dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingout:
493dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	mutex_unlock(&padctl->lock);
494dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
495dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
496dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
497dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
498dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
499dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
500dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
501dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	mutex_lock(&padctl->lock);
502dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
503dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (WARN_ON(padctl->enable == 0))
504dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		goto out;
505dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
506dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (--padctl->enable > 0)
507dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		goto out;
508dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
509dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
510dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
511dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
512dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
513dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	usleep_range(100, 200);
514dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
515dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
516dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
517dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
518dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
519dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	usleep_range(100, 200);
520dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
521dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
522dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
523dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
524dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
525dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingout:
526dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	mutex_unlock(&padctl->lock);
527dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
528dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
529dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
530dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_phy_init(struct phy *phy)
531dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
532dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
533dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
534dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return tegra_xusb_padctl_enable(padctl);
535dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
536dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
537dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_phy_exit(struct phy *phy)
538dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
539dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
540dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
541dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return tegra_xusb_padctl_disable(padctl);
542dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
543dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
544dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int pcie_phy_power_on(struct phy *phy)
545dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
546dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
547dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned long timeout;
548dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	int err = -ETIMEDOUT;
549dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
550dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
551dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
552dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
553dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
554dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
555dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
556dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
557dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
558dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
559dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
560dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
561dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
562dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
563dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
564dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
565dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	timeout = jiffies + msecs_to_jiffies(50);
566dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
567dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	while (time_before(jiffies, timeout)) {
568dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
569dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
570dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			err = 0;
571dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			break;
572dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		}
573dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
574dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		usleep_range(100, 200);
575dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
576dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
577dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return err;
578dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
579dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
580dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int pcie_phy_power_off(struct phy *phy)
581dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
582dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
583dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
584dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
585dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
586dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
587dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
588dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
589dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
590dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
591dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
592dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct phy_ops pcie_phy_ops = {
593dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.init = tegra_xusb_phy_init,
594dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.exit = tegra_xusb_phy_exit,
595dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.power_on = pcie_phy_power_on,
596dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.power_off = pcie_phy_power_off,
597dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.owner = THIS_MODULE,
598dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
599dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
600dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int sata_phy_power_on(struct phy *phy)
601dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
602dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
603dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned long timeout;
604dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	int err = -ETIMEDOUT;
605dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
606dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
607dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
608dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
609dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
610dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
611dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
612dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
613dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
614dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
615dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
616dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
617dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
618dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
619dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
620dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
621dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
622dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
623dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
624dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
625dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	timeout = jiffies + msecs_to_jiffies(50);
626dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
627dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	while (time_before(jiffies, timeout)) {
628dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
629dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
630dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			err = 0;
631dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding			break;
632dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		}
633dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
634dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		usleep_range(100, 200);
635dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
636dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
637dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return err;
638dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
639dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
640dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int sata_phy_power_off(struct phy *phy)
641dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
642dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
643dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	u32 value;
644dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
645dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
646dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
647dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
648dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
649dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
650dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
651dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
652dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
653dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
654dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
655dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
656dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
657dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
658dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
659dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
660dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
661dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
662dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
663dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
664dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
665dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
666dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct phy_ops sata_phy_ops = {
667dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.init = tegra_xusb_phy_init,
668dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.exit = tegra_xusb_phy_exit,
669dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.power_on = sata_phy_power_on,
670dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.power_off = sata_phy_power_off,
671dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.owner = THIS_MODULE,
672dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
673dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
674dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic struct phy *tegra_xusb_padctl_xlate(struct device *dev,
675dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding					   struct of_phandle_args *args)
676dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
677dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
678dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	unsigned int index = args->args[0];
679dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
680dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (args->args_count <= 0)
681dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return ERR_PTR(-EINVAL);
682dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
6838e1594db7e43eaf4ea88b870e97fa3ab9f8f98e0Dan Carpenter	if (index >= ARRAY_SIZE(padctl->phys))
684dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return ERR_PTR(-EINVAL);
685dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
686dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return padctl->phys[index];
687dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
688dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
689dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_OTG_0   0
690dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_OTG_1   1
691dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_OTG_2   2
692dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_ULPI_0  3
693dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_HSIC_0  4
694dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_HSIC_1  5
695dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_PCIE_0  6
696dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_PCIE_1  7
697dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_PCIE_2  8
698dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_PCIE_3  9
699dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_PCIE_4 10
700dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define PIN_SATA_0 11
701dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
702dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct pinctrl_pin_desc tegra124_pins[] = {
703dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
704dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
705dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
706dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
707dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
708dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
709dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
710dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
711dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
712dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
713dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
714dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	PINCTRL_PIN(PIN_SATA_0, "sata-0"),
715dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
716dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
717dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char * const tegra124_snps_groups[] = {
718dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-0",
719dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-1",
720dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-2",
721dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"ulpi-0",
722dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"hsic-0",
723dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"hsic-1",
724dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
725dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
726dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char * const tegra124_xusb_groups[] = {
727dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-0",
728dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-1",
729dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-2",
730dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"ulpi-0",
731dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"hsic-0",
732dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"hsic-1",
733dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
734dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
735dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char * const tegra124_uart_groups[] = {
736dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-0",
737dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-1",
738dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-2",
739dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
740dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
741dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char * const tegra124_pcie_groups[] = {
742dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-0",
743dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-1",
744dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-2",
745dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-3",
746dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-4",
747dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"sata-0",
748dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
749dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
750dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char * const tegra124_usb3_groups[] = {
751dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-0",
752dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-1",
753dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-2",
754dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-3",
755dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-4",
756dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"sata-0",
757dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
758dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
759dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char * const tegra124_sata_groups[] = {
760dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-0",
761dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-1",
762dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-2",
763dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-3",
764dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-4",
765dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"sata-0",
766dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
767dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
768dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const char * const tegra124_rsvd_groups[] = {
769dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-0",
770dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-1",
771dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"otg-2",
772dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-0",
773dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-1",
774dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-2",
775dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-3",
776dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"pcie-4",
777dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	"sata-0",
778dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
779dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
780dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define TEGRA124_FUNCTION(_name)					\
781dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	{								\
782dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.name = #_name,						\
783dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.num_groups = ARRAY_SIZE(tegra124_##_name##_groups),	\
784dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.groups = tegra124_##_name##_groups,			\
785dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
786dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
787dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic struct tegra_xusb_padctl_function tegra124_functions[] = {
788dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNCTION(snps),
789dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNCTION(xusb),
790dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNCTION(uart),
791dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNCTION(pcie),
792dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNCTION(usb3),
793dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNCTION(sata),
794dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNCTION(rsvd),
795dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
796dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
797dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingenum tegra124_function {
798dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_SNPS,
799dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_XUSB,
800dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_UART,
801dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_PCIE,
802dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_USB3,
803dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_SATA,
804dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_RSVD,
805dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
806dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
807dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const unsigned int tegra124_otg_functions[] = {
808dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_SNPS,
809dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_XUSB,
810dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_UART,
811dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_RSVD,
812dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
813dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
814dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const unsigned int tegra124_usb_functions[] = {
815dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_SNPS,
816dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_XUSB,
817dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
818dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
819dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const unsigned int tegra124_pci_functions[] = {
820dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_PCIE,
821dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_USB3,
822dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_SATA,
823dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_FUNC_RSVD,
824dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
825dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
826dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)	\
827dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	{								\
828dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.name = _name,						\
829dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.offset = _offset,					\
830dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.shift = _shift,					\
831dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.mask = _mask,						\
832dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.iddq = _iddq,						\
833dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions),	\
834dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.funcs = tegra124_##_funcs##_functions,			\
835dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
836dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
837dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
838dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
839dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
840dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
841dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
842dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
843dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
844dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
845dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
846dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
847dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
848dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
849dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
850dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
851dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
852dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct tegra_xusb_padctl_soc tegra124_soc = {
853dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.num_pins = ARRAY_SIZE(tegra124_pins),
854dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.pins = tegra124_pins,
855dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.num_functions = ARRAY_SIZE(tegra124_functions),
856dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.functions = tegra124_functions,
857dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.num_lanes = ARRAY_SIZE(tegra124_lanes),
858dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.lanes = tegra124_lanes,
859dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
860dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
861dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic const struct of_device_id tegra_xusb_padctl_of_match[] = {
862dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	{ .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
863dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	{ }
864dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
865dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry RedingMODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
866dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
867dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_probe(struct platform_device *pdev)
868dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
869dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl;
870dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	const struct of_device_id *match;
871dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct resource *res;
872dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct phy *phy;
873dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	int err;
874dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
875dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
876dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (!padctl)
877dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return -ENOMEM;
878dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
879dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	platform_set_drvdata(pdev, padctl);
880dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	mutex_init(&padctl->lock);
881dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->dev = &pdev->dev;
882dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
883dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
884dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->soc = match->data;
885dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
886dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
887dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->regs = devm_ioremap_resource(&pdev->dev, res);
888dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (IS_ERR(padctl->regs))
889dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return PTR_ERR(padctl->regs);
890dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
891dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
892dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (IS_ERR(padctl->rst))
893dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return PTR_ERR(padctl->rst);
894dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
895dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	err = reset_control_deassert(padctl->rst);
896dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (err < 0)
897dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		return err;
898dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
899dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	memset(&padctl->desc, 0, sizeof(padctl->desc));
900dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->desc.name = dev_name(padctl->dev);
901dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
902dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
903dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
904dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->desc.owner = THIS_MODULE;
905dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
906dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
907dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (!padctl->pinctrl) {
908dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		dev_err(&pdev->dev, "failed to register pincontrol\n");
909dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		err = -ENODEV;
910dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		goto reset;
911dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
912dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
91310c8e0562057b5d64ea170feab148e1550420030Linus Torvalds	phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops, NULL);
914dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (IS_ERR(phy)) {
915dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		err = PTR_ERR(phy);
916dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		goto unregister;
917dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
918dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
919dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
920dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	phy_set_drvdata(phy, padctl);
921dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
92210c8e0562057b5d64ea170feab148e1550420030Linus Torvalds	phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops, NULL);
923dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (IS_ERR(phy)) {
924dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		err = PTR_ERR(phy);
925dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		goto unregister;
926dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
927dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
928dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
929dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	phy_set_drvdata(phy, padctl);
930dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
931dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	padctl->provider = devm_of_phy_provider_register(&pdev->dev,
932dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding							 tegra_xusb_padctl_xlate);
9338a3cfb7c1700732df9fc13439b313bf8db39fefdDan Carpenter	if (IS_ERR(padctl->provider)) {
9348a3cfb7c1700732df9fc13439b313bf8db39fefdDan Carpenter		err = PTR_ERR(padctl->provider);
935dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
936dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		goto unregister;
937dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	}
938dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
939dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return 0;
940dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
941dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingunregister:
942dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	pinctrl_unregister(padctl->pinctrl);
943dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingreset:
944dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	reset_control_assert(padctl->rst);
945dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return err;
946dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
947dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
948dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic int tegra_xusb_padctl_remove(struct platform_device *pdev)
949dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding{
950dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
951dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	int err;
952dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
953dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	pinctrl_unregister(padctl->pinctrl);
954dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
955dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	err = reset_control_assert(padctl->rst);
956dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	if (err < 0)
957dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
958dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
959dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	return err;
960dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding}
961dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
962dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingstatic struct platform_driver tegra_xusb_padctl_driver = {
963dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.driver = {
964dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.name = "tegra-xusb-padctl",
965dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding		.of_match_table = tegra_xusb_padctl_of_match,
966dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	},
967dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.probe = tegra_xusb_padctl_probe,
968dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding	.remove = tegra_xusb_padctl_remove,
969dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding};
970dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Redingmodule_platform_driver(tegra_xusb_padctl_driver);
971dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry Reding
972dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry RedingMODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
973dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry RedingMODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
974dc0a3938668706f3a63cde4ceb431e9189fb2a0aThierry RedingMODULE_LICENSE("GPL v2");
975