xref: /openbmc/linux/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
225cbac77SMasahiro Yamada /*
325cbac77SMasahiro Yamada  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
425cbac77SMasahiro Yamada  */
525cbac77SMasahiro Yamada 
625cbac77SMasahiro Yamada #include <linux/delay.h>
725cbac77SMasahiro Yamada #include <linux/io.h>
825cbac77SMasahiro Yamada #include <linux/module.h>
925cbac77SMasahiro Yamada #include <linux/of.h>
1025cbac77SMasahiro Yamada #include <linux/phy/phy.h>
1125cbac77SMasahiro Yamada #include <linux/platform_device.h>
1225cbac77SMasahiro Yamada #include <linux/reset.h>
13*eebeeb53SAndy Shevchenko #include <linux/seq_file.h>
1425cbac77SMasahiro Yamada #include <linux/slab.h>
1525cbac77SMasahiro Yamada 
16*eebeeb53SAndy Shevchenko #include <linux/pinctrl/pinconf.h>
17*eebeeb53SAndy Shevchenko #include <linux/pinctrl/pinctrl.h>
18*eebeeb53SAndy Shevchenko #include <linux/pinctrl/pinmux.h>
19*eebeeb53SAndy Shevchenko 
2025cbac77SMasahiro Yamada #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
2125cbac77SMasahiro Yamada 
2225cbac77SMasahiro Yamada #include "../core.h"
2325cbac77SMasahiro Yamada #include "../pinctrl-utils.h"
2425cbac77SMasahiro Yamada 
2525cbac77SMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM 0x01c
2625cbac77SMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
2725cbac77SMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
2825cbac77SMasahiro Yamada #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
2925cbac77SMasahiro Yamada 
3025cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
3125cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
3225cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
3325cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
3425cbac77SMasahiro Yamada 
3525cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
3625cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
3725cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
3825cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
3925cbac77SMasahiro Yamada 
4025cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
4125cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
4225cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
4325cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
4425cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
4525cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
4625cbac77SMasahiro Yamada 
4725cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
4825cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
4925cbac77SMasahiro Yamada #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
5025cbac77SMasahiro Yamada 
5125cbac77SMasahiro Yamada struct tegra_xusb_padctl_function {
5225cbac77SMasahiro Yamada 	const char *name;
5325cbac77SMasahiro Yamada 	const char * const *groups;
5425cbac77SMasahiro Yamada 	unsigned int num_groups;
5525cbac77SMasahiro Yamada };
5625cbac77SMasahiro Yamada 
5725cbac77SMasahiro Yamada struct tegra_xusb_padctl_soc {
5825cbac77SMasahiro Yamada 	const struct pinctrl_pin_desc *pins;
5925cbac77SMasahiro Yamada 	unsigned int num_pins;
6025cbac77SMasahiro Yamada 
6125cbac77SMasahiro Yamada 	const struct tegra_xusb_padctl_function *functions;
6225cbac77SMasahiro Yamada 	unsigned int num_functions;
6325cbac77SMasahiro Yamada 
6425cbac77SMasahiro Yamada 	const struct tegra_xusb_padctl_lane *lanes;
6525cbac77SMasahiro Yamada 	unsigned int num_lanes;
6625cbac77SMasahiro Yamada };
6725cbac77SMasahiro Yamada 
6825cbac77SMasahiro Yamada struct tegra_xusb_padctl_lane {
6925cbac77SMasahiro Yamada 	const char *name;
7025cbac77SMasahiro Yamada 
7125cbac77SMasahiro Yamada 	unsigned int offset;
7225cbac77SMasahiro Yamada 	unsigned int shift;
7325cbac77SMasahiro Yamada 	unsigned int mask;
7425cbac77SMasahiro Yamada 	unsigned int iddq;
7525cbac77SMasahiro Yamada 
7625cbac77SMasahiro Yamada 	const unsigned int *funcs;
7725cbac77SMasahiro Yamada 	unsigned int num_funcs;
7825cbac77SMasahiro Yamada };
7925cbac77SMasahiro Yamada 
8025cbac77SMasahiro Yamada struct tegra_xusb_padctl {
8125cbac77SMasahiro Yamada 	struct device *dev;
8225cbac77SMasahiro Yamada 	void __iomem *regs;
8325cbac77SMasahiro Yamada 	struct mutex lock;
8425cbac77SMasahiro Yamada 	struct reset_control *rst;
8525cbac77SMasahiro Yamada 
8625cbac77SMasahiro Yamada 	const struct tegra_xusb_padctl_soc *soc;
8725cbac77SMasahiro Yamada 	struct pinctrl_dev *pinctrl;
8825cbac77SMasahiro Yamada 	struct pinctrl_desc desc;
8925cbac77SMasahiro Yamada 
9025cbac77SMasahiro Yamada 	struct phy_provider *provider;
9125cbac77SMasahiro Yamada 	struct phy *phys[2];
9225cbac77SMasahiro Yamada 
9325cbac77SMasahiro Yamada 	unsigned int enable;
9425cbac77SMasahiro Yamada };
9525cbac77SMasahiro Yamada 
padctl_writel(struct tegra_xusb_padctl * padctl,u32 value,unsigned long offset)9625cbac77SMasahiro Yamada static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
9725cbac77SMasahiro Yamada 				 unsigned long offset)
9825cbac77SMasahiro Yamada {
9925cbac77SMasahiro Yamada 	writel(value, padctl->regs + offset);
10025cbac77SMasahiro Yamada }
10125cbac77SMasahiro Yamada 
padctl_readl(struct tegra_xusb_padctl * padctl,unsigned long offset)10225cbac77SMasahiro Yamada static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
10325cbac77SMasahiro Yamada 			       unsigned long offset)
10425cbac77SMasahiro Yamada {
10525cbac77SMasahiro Yamada 	return readl(padctl->regs + offset);
10625cbac77SMasahiro Yamada }
10725cbac77SMasahiro Yamada 
tegra_xusb_padctl_get_groups_count(struct pinctrl_dev * pinctrl)10825cbac77SMasahiro Yamada static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
10925cbac77SMasahiro Yamada {
11025cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
11125cbac77SMasahiro Yamada 
11225cbac77SMasahiro Yamada 	return padctl->soc->num_pins;
11325cbac77SMasahiro Yamada }
11425cbac77SMasahiro Yamada 
tegra_xusb_padctl_get_group_name(struct pinctrl_dev * pinctrl,unsigned int group)11525cbac77SMasahiro Yamada static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
11625cbac77SMasahiro Yamada 						    unsigned int group)
11725cbac77SMasahiro Yamada {
11825cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
11925cbac77SMasahiro Yamada 
12025cbac77SMasahiro Yamada 	return padctl->soc->pins[group].name;
12125cbac77SMasahiro Yamada }
12225cbac77SMasahiro Yamada 
tegra_xusb_padctl_get_group_pins(struct pinctrl_dev * pinctrl,unsigned group,const unsigned ** pins,unsigned * num_pins)12325cbac77SMasahiro Yamada static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl,
12425cbac77SMasahiro Yamada 					    unsigned group,
12525cbac77SMasahiro Yamada 					    const unsigned **pins,
12625cbac77SMasahiro Yamada 					    unsigned *num_pins)
12725cbac77SMasahiro Yamada {
12825cbac77SMasahiro Yamada 	/*
129d71ffeb9SDejin Zheng 	 * For the tegra-xusb pad controller groups are synonymous
13025cbac77SMasahiro Yamada 	 * with lanes/pins and there is always one lane/pin per group.
13125cbac77SMasahiro Yamada 	 */
13225cbac77SMasahiro Yamada 	*pins = &pinctrl->desc->pins[group].number;
13325cbac77SMasahiro Yamada 	*num_pins = 1;
13425cbac77SMasahiro Yamada 
13525cbac77SMasahiro Yamada 	return 0;
13625cbac77SMasahiro Yamada }
13725cbac77SMasahiro Yamada 
13825cbac77SMasahiro Yamada enum tegra_xusb_padctl_param {
13925cbac77SMasahiro Yamada 	TEGRA_XUSB_PADCTL_IDDQ,
14025cbac77SMasahiro Yamada };
14125cbac77SMasahiro Yamada 
14225cbac77SMasahiro Yamada static const struct tegra_xusb_padctl_property {
14325cbac77SMasahiro Yamada 	const char *name;
14425cbac77SMasahiro Yamada 	enum tegra_xusb_padctl_param param;
14525cbac77SMasahiro Yamada } properties[] = {
14625cbac77SMasahiro Yamada 	{ "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
14725cbac77SMasahiro Yamada };
14825cbac77SMasahiro Yamada 
14925cbac77SMasahiro Yamada #define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
15025cbac77SMasahiro Yamada #define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
15125cbac77SMasahiro Yamada #define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
15225cbac77SMasahiro Yamada 
tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl * padctl,struct device_node * np,struct pinctrl_map ** maps,unsigned int * reserved_maps,unsigned int * num_maps)15325cbac77SMasahiro Yamada static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
15425cbac77SMasahiro Yamada 					   struct device_node *np,
15525cbac77SMasahiro Yamada 					   struct pinctrl_map **maps,
15625cbac77SMasahiro Yamada 					   unsigned int *reserved_maps,
15725cbac77SMasahiro Yamada 					   unsigned int *num_maps)
15825cbac77SMasahiro Yamada {
15925cbac77SMasahiro Yamada 	unsigned int i, reserve = 0, num_configs = 0;
16025cbac77SMasahiro Yamada 	unsigned long config, *configs = NULL;
16125cbac77SMasahiro Yamada 	const char *function, *group;
16225cbac77SMasahiro Yamada 	struct property *prop;
16325cbac77SMasahiro Yamada 	int err = 0;
16425cbac77SMasahiro Yamada 	u32 value;
16525cbac77SMasahiro Yamada 
16625cbac77SMasahiro Yamada 	err = of_property_read_string(np, "nvidia,function", &function);
16725cbac77SMasahiro Yamada 	if (err < 0) {
16825cbac77SMasahiro Yamada 		if (err != -EINVAL)
16925cbac77SMasahiro Yamada 			return err;
17025cbac77SMasahiro Yamada 
17125cbac77SMasahiro Yamada 		function = NULL;
17225cbac77SMasahiro Yamada 	}
17325cbac77SMasahiro Yamada 
17425cbac77SMasahiro Yamada 	for (i = 0; i < ARRAY_SIZE(properties); i++) {
17525cbac77SMasahiro Yamada 		err = of_property_read_u32(np, properties[i].name, &value);
17625cbac77SMasahiro Yamada 		if (err < 0) {
17725cbac77SMasahiro Yamada 			if (err == -EINVAL)
17825cbac77SMasahiro Yamada 				continue;
17925cbac77SMasahiro Yamada 
18025cbac77SMasahiro Yamada 			goto out;
18125cbac77SMasahiro Yamada 		}
18225cbac77SMasahiro Yamada 
18325cbac77SMasahiro Yamada 		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
18425cbac77SMasahiro Yamada 
18525cbac77SMasahiro Yamada 		err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
18625cbac77SMasahiro Yamada 					       &num_configs, config);
18725cbac77SMasahiro Yamada 		if (err < 0)
18825cbac77SMasahiro Yamada 			goto out;
18925cbac77SMasahiro Yamada 	}
19025cbac77SMasahiro Yamada 
19125cbac77SMasahiro Yamada 	if (function)
19225cbac77SMasahiro Yamada 		reserve++;
19325cbac77SMasahiro Yamada 
19425cbac77SMasahiro Yamada 	if (num_configs)
19525cbac77SMasahiro Yamada 		reserve++;
19625cbac77SMasahiro Yamada 
19725cbac77SMasahiro Yamada 	err = of_property_count_strings(np, "nvidia,lanes");
19825cbac77SMasahiro Yamada 	if (err < 0)
19925cbac77SMasahiro Yamada 		goto out;
20025cbac77SMasahiro Yamada 
20125cbac77SMasahiro Yamada 	reserve *= err;
20225cbac77SMasahiro Yamada 
20325cbac77SMasahiro Yamada 	err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
20425cbac77SMasahiro Yamada 					num_maps, reserve);
20525cbac77SMasahiro Yamada 	if (err < 0)
20625cbac77SMasahiro Yamada 		goto out;
20725cbac77SMasahiro Yamada 
20825cbac77SMasahiro Yamada 	of_property_for_each_string(np, "nvidia,lanes", prop, group) {
20925cbac77SMasahiro Yamada 		if (function) {
21025cbac77SMasahiro Yamada 			err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
21125cbac77SMasahiro Yamada 					reserved_maps, num_maps, group,
21225cbac77SMasahiro Yamada 					function);
21325cbac77SMasahiro Yamada 			if (err < 0)
21425cbac77SMasahiro Yamada 				goto out;
21525cbac77SMasahiro Yamada 		}
21625cbac77SMasahiro Yamada 
21725cbac77SMasahiro Yamada 		if (num_configs) {
21825cbac77SMasahiro Yamada 			err = pinctrl_utils_add_map_configs(padctl->pinctrl,
21925cbac77SMasahiro Yamada 					maps, reserved_maps, num_maps, group,
22025cbac77SMasahiro Yamada 					configs, num_configs,
22125cbac77SMasahiro Yamada 					PIN_MAP_TYPE_CONFIGS_GROUP);
22225cbac77SMasahiro Yamada 			if (err < 0)
22325cbac77SMasahiro Yamada 				goto out;
22425cbac77SMasahiro Yamada 		}
22525cbac77SMasahiro Yamada 	}
22625cbac77SMasahiro Yamada 
22725cbac77SMasahiro Yamada 	err = 0;
22825cbac77SMasahiro Yamada 
22925cbac77SMasahiro Yamada out:
23025cbac77SMasahiro Yamada 	kfree(configs);
23125cbac77SMasahiro Yamada 	return err;
23225cbac77SMasahiro Yamada }
23325cbac77SMasahiro Yamada 
tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev * pinctrl,struct device_node * parent,struct pinctrl_map ** maps,unsigned int * num_maps)23425cbac77SMasahiro Yamada static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
23525cbac77SMasahiro Yamada 					    struct device_node *parent,
23625cbac77SMasahiro Yamada 					    struct pinctrl_map **maps,
23725cbac77SMasahiro Yamada 					    unsigned int *num_maps)
23825cbac77SMasahiro Yamada {
23925cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
24025cbac77SMasahiro Yamada 	unsigned int reserved_maps = 0;
24125cbac77SMasahiro Yamada 	struct device_node *np;
24225cbac77SMasahiro Yamada 	int err;
24325cbac77SMasahiro Yamada 
24425cbac77SMasahiro Yamada 	*num_maps = 0;
24525cbac77SMasahiro Yamada 	*maps = NULL;
24625cbac77SMasahiro Yamada 
24725cbac77SMasahiro Yamada 	for_each_child_of_node(parent, np) {
24825cbac77SMasahiro Yamada 		err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
24925cbac77SMasahiro Yamada 						      &reserved_maps,
25025cbac77SMasahiro Yamada 						      num_maps);
25125cbac77SMasahiro Yamada 		if (err < 0) {
25225cbac77SMasahiro Yamada 			of_node_put(np);
25325cbac77SMasahiro Yamada 			return err;
25425cbac77SMasahiro Yamada 		}
25525cbac77SMasahiro Yamada 	}
25625cbac77SMasahiro Yamada 
25725cbac77SMasahiro Yamada 	return 0;
25825cbac77SMasahiro Yamada }
25925cbac77SMasahiro Yamada 
26025cbac77SMasahiro Yamada static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
26125cbac77SMasahiro Yamada 	.get_groups_count = tegra_xusb_padctl_get_groups_count,
26225cbac77SMasahiro Yamada 	.get_group_name = tegra_xusb_padctl_get_group_name,
26325cbac77SMasahiro Yamada 	.get_group_pins = tegra_xusb_padctl_get_group_pins,
26425cbac77SMasahiro Yamada 	.dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
265d32f7fd3SIrina Tirdea 	.dt_free_map = pinctrl_utils_free_map,
26625cbac77SMasahiro Yamada };
26725cbac77SMasahiro Yamada 
tegra_xusb_padctl_get_functions_count(struct pinctrl_dev * pinctrl)26825cbac77SMasahiro Yamada static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
26925cbac77SMasahiro Yamada {
27025cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
27125cbac77SMasahiro Yamada 
27225cbac77SMasahiro Yamada 	return padctl->soc->num_functions;
27325cbac77SMasahiro Yamada }
27425cbac77SMasahiro Yamada 
27525cbac77SMasahiro Yamada static const char *
tegra_xusb_padctl_get_function_name(struct pinctrl_dev * pinctrl,unsigned int function)27625cbac77SMasahiro Yamada tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
27725cbac77SMasahiro Yamada 				    unsigned int function)
27825cbac77SMasahiro Yamada {
27925cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
28025cbac77SMasahiro Yamada 
28125cbac77SMasahiro Yamada 	return padctl->soc->functions[function].name;
28225cbac77SMasahiro Yamada }
28325cbac77SMasahiro Yamada 
tegra_xusb_padctl_get_function_groups(struct pinctrl_dev * pinctrl,unsigned int function,const char * const ** groups,unsigned * const num_groups)28425cbac77SMasahiro Yamada static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
28525cbac77SMasahiro Yamada 						 unsigned int function,
28625cbac77SMasahiro Yamada 						 const char * const **groups,
28725cbac77SMasahiro Yamada 						 unsigned * const num_groups)
28825cbac77SMasahiro Yamada {
28925cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
29025cbac77SMasahiro Yamada 
29125cbac77SMasahiro Yamada 	*num_groups = padctl->soc->functions[function].num_groups;
29225cbac77SMasahiro Yamada 	*groups = padctl->soc->functions[function].groups;
29325cbac77SMasahiro Yamada 
29425cbac77SMasahiro Yamada 	return 0;
29525cbac77SMasahiro Yamada }
29625cbac77SMasahiro Yamada 
tegra_xusb_padctl_pinmux_set(struct pinctrl_dev * pinctrl,unsigned int function,unsigned int group)29725cbac77SMasahiro Yamada static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl,
29825cbac77SMasahiro Yamada 					unsigned int function,
29925cbac77SMasahiro Yamada 					unsigned int group)
30025cbac77SMasahiro Yamada {
30125cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
30225cbac77SMasahiro Yamada 	const struct tegra_xusb_padctl_lane *lane;
30325cbac77SMasahiro Yamada 	unsigned int i;
30425cbac77SMasahiro Yamada 	u32 value;
30525cbac77SMasahiro Yamada 
30625cbac77SMasahiro Yamada 	lane = &padctl->soc->lanes[group];
30725cbac77SMasahiro Yamada 
30825cbac77SMasahiro Yamada 	for (i = 0; i < lane->num_funcs; i++)
30925cbac77SMasahiro Yamada 		if (lane->funcs[i] == function)
31025cbac77SMasahiro Yamada 			break;
31125cbac77SMasahiro Yamada 
31225cbac77SMasahiro Yamada 	if (i >= lane->num_funcs)
31325cbac77SMasahiro Yamada 		return -EINVAL;
31425cbac77SMasahiro Yamada 
31525cbac77SMasahiro Yamada 	value = padctl_readl(padctl, lane->offset);
31625cbac77SMasahiro Yamada 	value &= ~(lane->mask << lane->shift);
31725cbac77SMasahiro Yamada 	value |= i << lane->shift;
31825cbac77SMasahiro Yamada 	padctl_writel(padctl, value, lane->offset);
31925cbac77SMasahiro Yamada 
32025cbac77SMasahiro Yamada 	return 0;
32125cbac77SMasahiro Yamada }
32225cbac77SMasahiro Yamada 
32325cbac77SMasahiro Yamada static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
32425cbac77SMasahiro Yamada 	.get_functions_count = tegra_xusb_padctl_get_functions_count,
32525cbac77SMasahiro Yamada 	.get_function_name = tegra_xusb_padctl_get_function_name,
32625cbac77SMasahiro Yamada 	.get_function_groups = tegra_xusb_padctl_get_function_groups,
32725cbac77SMasahiro Yamada 	.set_mux = tegra_xusb_padctl_pinmux_set,
32825cbac77SMasahiro Yamada };
32925cbac77SMasahiro Yamada 
tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev * pinctrl,unsigned int group,unsigned long * config)33025cbac77SMasahiro Yamada static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
33125cbac77SMasahiro Yamada 					       unsigned int group,
33225cbac77SMasahiro Yamada 					       unsigned long *config)
33325cbac77SMasahiro Yamada {
33425cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
33525cbac77SMasahiro Yamada 	const struct tegra_xusb_padctl_lane *lane;
33625cbac77SMasahiro Yamada 	enum tegra_xusb_padctl_param param;
33725cbac77SMasahiro Yamada 	u32 value;
33825cbac77SMasahiro Yamada 
33925cbac77SMasahiro Yamada 	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
34025cbac77SMasahiro Yamada 	lane = &padctl->soc->lanes[group];
34125cbac77SMasahiro Yamada 
34225cbac77SMasahiro Yamada 	switch (param) {
34325cbac77SMasahiro Yamada 	case TEGRA_XUSB_PADCTL_IDDQ:
34425cbac77SMasahiro Yamada 		/* lanes with iddq == 0 don't support this parameter */
34525cbac77SMasahiro Yamada 		if (lane->iddq == 0)
34625cbac77SMasahiro Yamada 			return -EINVAL;
34725cbac77SMasahiro Yamada 
34825cbac77SMasahiro Yamada 		value = padctl_readl(padctl, lane->offset);
34925cbac77SMasahiro Yamada 
35025cbac77SMasahiro Yamada 		if (value & BIT(lane->iddq))
35125cbac77SMasahiro Yamada 			value = 0;
35225cbac77SMasahiro Yamada 		else
35325cbac77SMasahiro Yamada 			value = 1;
35425cbac77SMasahiro Yamada 
35525cbac77SMasahiro Yamada 		*config = TEGRA_XUSB_PADCTL_PACK(param, value);
35625cbac77SMasahiro Yamada 		break;
35725cbac77SMasahiro Yamada 
35825cbac77SMasahiro Yamada 	default:
35925cbac77SMasahiro Yamada 		dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
36025cbac77SMasahiro Yamada 			param);
36125cbac77SMasahiro Yamada 		return -ENOTSUPP;
36225cbac77SMasahiro Yamada 	}
36325cbac77SMasahiro Yamada 
36425cbac77SMasahiro Yamada 	return 0;
36525cbac77SMasahiro Yamada }
36625cbac77SMasahiro Yamada 
tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev * pinctrl,unsigned int group,unsigned long * configs,unsigned int num_configs)36725cbac77SMasahiro Yamada static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
36825cbac77SMasahiro Yamada 					       unsigned int group,
36925cbac77SMasahiro Yamada 					       unsigned long *configs,
37025cbac77SMasahiro Yamada 					       unsigned int num_configs)
37125cbac77SMasahiro Yamada {
37225cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
37325cbac77SMasahiro Yamada 	const struct tegra_xusb_padctl_lane *lane;
37425cbac77SMasahiro Yamada 	enum tegra_xusb_padctl_param param;
37525cbac77SMasahiro Yamada 	unsigned long value;
37625cbac77SMasahiro Yamada 	unsigned int i;
37725cbac77SMasahiro Yamada 	u32 regval;
37825cbac77SMasahiro Yamada 
37925cbac77SMasahiro Yamada 	lane = &padctl->soc->lanes[group];
38025cbac77SMasahiro Yamada 
38125cbac77SMasahiro Yamada 	for (i = 0; i < num_configs; i++) {
38225cbac77SMasahiro Yamada 		param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
38325cbac77SMasahiro Yamada 		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
38425cbac77SMasahiro Yamada 
38525cbac77SMasahiro Yamada 		switch (param) {
38625cbac77SMasahiro Yamada 		case TEGRA_XUSB_PADCTL_IDDQ:
38725cbac77SMasahiro Yamada 			/* lanes with iddq == 0 don't support this parameter */
38825cbac77SMasahiro Yamada 			if (lane->iddq == 0)
38925cbac77SMasahiro Yamada 				return -EINVAL;
39025cbac77SMasahiro Yamada 
39125cbac77SMasahiro Yamada 			regval = padctl_readl(padctl, lane->offset);
39225cbac77SMasahiro Yamada 
39325cbac77SMasahiro Yamada 			if (value)
39425cbac77SMasahiro Yamada 				regval &= ~BIT(lane->iddq);
39525cbac77SMasahiro Yamada 			else
39625cbac77SMasahiro Yamada 				regval |= BIT(lane->iddq);
39725cbac77SMasahiro Yamada 
39825cbac77SMasahiro Yamada 			padctl_writel(padctl, regval, lane->offset);
39925cbac77SMasahiro Yamada 			break;
40025cbac77SMasahiro Yamada 
40125cbac77SMasahiro Yamada 		default:
40225cbac77SMasahiro Yamada 			dev_err(padctl->dev,
40325cbac77SMasahiro Yamada 				"invalid configuration parameter: %04x\n",
40425cbac77SMasahiro Yamada 				param);
40525cbac77SMasahiro Yamada 			return -ENOTSUPP;
40625cbac77SMasahiro Yamada 		}
40725cbac77SMasahiro Yamada 	}
40825cbac77SMasahiro Yamada 
40925cbac77SMasahiro Yamada 	return 0;
41025cbac77SMasahiro Yamada }
41125cbac77SMasahiro Yamada 
41225cbac77SMasahiro Yamada #ifdef CONFIG_DEBUG_FS
strip_prefix(const char * s)41325cbac77SMasahiro Yamada static const char *strip_prefix(const char *s)
41425cbac77SMasahiro Yamada {
41525cbac77SMasahiro Yamada 	const char *comma = strchr(s, ',');
41625cbac77SMasahiro Yamada 	if (!comma)
41725cbac77SMasahiro Yamada 		return s;
41825cbac77SMasahiro Yamada 
41925cbac77SMasahiro Yamada 	return comma + 1;
42025cbac77SMasahiro Yamada }
42125cbac77SMasahiro Yamada 
42225cbac77SMasahiro Yamada static void
tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev * pinctrl,struct seq_file * s,unsigned int group)42325cbac77SMasahiro Yamada tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
42425cbac77SMasahiro Yamada 					 struct seq_file *s,
42525cbac77SMasahiro Yamada 					 unsigned int group)
42625cbac77SMasahiro Yamada {
42725cbac77SMasahiro Yamada 	unsigned int i;
42825cbac77SMasahiro Yamada 
42925cbac77SMasahiro Yamada 	for (i = 0; i < ARRAY_SIZE(properties); i++) {
43025cbac77SMasahiro Yamada 		unsigned long config, value;
43125cbac77SMasahiro Yamada 		int err;
43225cbac77SMasahiro Yamada 
43325cbac77SMasahiro Yamada 		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
43425cbac77SMasahiro Yamada 
43525cbac77SMasahiro Yamada 		err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
43625cbac77SMasahiro Yamada 							  &config);
43725cbac77SMasahiro Yamada 		if (err < 0)
43825cbac77SMasahiro Yamada 			continue;
43925cbac77SMasahiro Yamada 
44025cbac77SMasahiro Yamada 		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
44125cbac77SMasahiro Yamada 
44225cbac77SMasahiro Yamada 		seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
44325cbac77SMasahiro Yamada 			   value);
44425cbac77SMasahiro Yamada 	}
44525cbac77SMasahiro Yamada }
44625cbac77SMasahiro Yamada 
44725cbac77SMasahiro Yamada static void
tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev * pinctrl,struct seq_file * s,unsigned long config)44825cbac77SMasahiro Yamada tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
44925cbac77SMasahiro Yamada 					  struct seq_file *s,
45025cbac77SMasahiro Yamada 					  unsigned long config)
45125cbac77SMasahiro Yamada {
45225cbac77SMasahiro Yamada 	enum tegra_xusb_padctl_param param;
45325cbac77SMasahiro Yamada 	const char *name = "unknown";
45425cbac77SMasahiro Yamada 	unsigned long value;
45525cbac77SMasahiro Yamada 	unsigned int i;
45625cbac77SMasahiro Yamada 
45725cbac77SMasahiro Yamada 	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
45825cbac77SMasahiro Yamada 	value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
45925cbac77SMasahiro Yamada 
46025cbac77SMasahiro Yamada 	for (i = 0; i < ARRAY_SIZE(properties); i++) {
46125cbac77SMasahiro Yamada 		if (properties[i].param == param) {
46225cbac77SMasahiro Yamada 			name = properties[i].name;
46325cbac77SMasahiro Yamada 			break;
46425cbac77SMasahiro Yamada 		}
46525cbac77SMasahiro Yamada 	}
46625cbac77SMasahiro Yamada 
46725cbac77SMasahiro Yamada 	seq_printf(s, "%s=%lu", strip_prefix(name), value);
46825cbac77SMasahiro Yamada }
46925cbac77SMasahiro Yamada #endif
47025cbac77SMasahiro Yamada 
47125cbac77SMasahiro Yamada static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
47225cbac77SMasahiro Yamada 	.pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
47325cbac77SMasahiro Yamada 	.pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
47425cbac77SMasahiro Yamada #ifdef CONFIG_DEBUG_FS
47525cbac77SMasahiro Yamada 	.pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
47625cbac77SMasahiro Yamada 	.pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
47725cbac77SMasahiro Yamada #endif
47825cbac77SMasahiro Yamada };
47925cbac77SMasahiro Yamada 
tegra_xusb_padctl_enable(struct tegra_xusb_padctl * padctl)48025cbac77SMasahiro Yamada static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
48125cbac77SMasahiro Yamada {
48225cbac77SMasahiro Yamada 	u32 value;
48325cbac77SMasahiro Yamada 
48425cbac77SMasahiro Yamada 	mutex_lock(&padctl->lock);
48525cbac77SMasahiro Yamada 
48625cbac77SMasahiro Yamada 	if (padctl->enable++ > 0)
48725cbac77SMasahiro Yamada 		goto out;
48825cbac77SMasahiro Yamada 
48925cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
49025cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
49125cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
49225cbac77SMasahiro Yamada 
49325cbac77SMasahiro Yamada 	usleep_range(100, 200);
49425cbac77SMasahiro Yamada 
49525cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
49625cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
49725cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
49825cbac77SMasahiro Yamada 
49925cbac77SMasahiro Yamada 	usleep_range(100, 200);
50025cbac77SMasahiro Yamada 
50125cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
50225cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
50325cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
50425cbac77SMasahiro Yamada 
50525cbac77SMasahiro Yamada out:
50625cbac77SMasahiro Yamada 	mutex_unlock(&padctl->lock);
50725cbac77SMasahiro Yamada 	return 0;
50825cbac77SMasahiro Yamada }
50925cbac77SMasahiro Yamada 
tegra_xusb_padctl_disable(struct tegra_xusb_padctl * padctl)51025cbac77SMasahiro Yamada static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
51125cbac77SMasahiro Yamada {
51225cbac77SMasahiro Yamada 	u32 value;
51325cbac77SMasahiro Yamada 
51425cbac77SMasahiro Yamada 	mutex_lock(&padctl->lock);
51525cbac77SMasahiro Yamada 
51625cbac77SMasahiro Yamada 	if (WARN_ON(padctl->enable == 0))
51725cbac77SMasahiro Yamada 		goto out;
51825cbac77SMasahiro Yamada 
51925cbac77SMasahiro Yamada 	if (--padctl->enable > 0)
52025cbac77SMasahiro Yamada 		goto out;
52125cbac77SMasahiro Yamada 
52225cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
52325cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
52425cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
52525cbac77SMasahiro Yamada 
52625cbac77SMasahiro Yamada 	usleep_range(100, 200);
52725cbac77SMasahiro Yamada 
52825cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
52925cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
53025cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
53125cbac77SMasahiro Yamada 
53225cbac77SMasahiro Yamada 	usleep_range(100, 200);
53325cbac77SMasahiro Yamada 
53425cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
53525cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
53625cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
53725cbac77SMasahiro Yamada 
53825cbac77SMasahiro Yamada out:
53925cbac77SMasahiro Yamada 	mutex_unlock(&padctl->lock);
54025cbac77SMasahiro Yamada 	return 0;
54125cbac77SMasahiro Yamada }
54225cbac77SMasahiro Yamada 
tegra_xusb_phy_init(struct phy * phy)54325cbac77SMasahiro Yamada static int tegra_xusb_phy_init(struct phy *phy)
54425cbac77SMasahiro Yamada {
54525cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
54625cbac77SMasahiro Yamada 
54725cbac77SMasahiro Yamada 	return tegra_xusb_padctl_enable(padctl);
54825cbac77SMasahiro Yamada }
54925cbac77SMasahiro Yamada 
tegra_xusb_phy_exit(struct phy * phy)55025cbac77SMasahiro Yamada static int tegra_xusb_phy_exit(struct phy *phy)
55125cbac77SMasahiro Yamada {
55225cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
55325cbac77SMasahiro Yamada 
55425cbac77SMasahiro Yamada 	return tegra_xusb_padctl_disable(padctl);
55525cbac77SMasahiro Yamada }
55625cbac77SMasahiro Yamada 
pcie_phy_power_on(struct phy * phy)55725cbac77SMasahiro Yamada static int pcie_phy_power_on(struct phy *phy)
55825cbac77SMasahiro Yamada {
55925cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
56025cbac77SMasahiro Yamada 	unsigned long timeout;
56125cbac77SMasahiro Yamada 	int err = -ETIMEDOUT;
56225cbac77SMasahiro Yamada 	u32 value;
56325cbac77SMasahiro Yamada 
56425cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
56525cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
56625cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
56725cbac77SMasahiro Yamada 
56825cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
56925cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
57025cbac77SMasahiro Yamada 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
57125cbac77SMasahiro Yamada 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
57225cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
57325cbac77SMasahiro Yamada 
57425cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
57525cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
57625cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
57725cbac77SMasahiro Yamada 
57825cbac77SMasahiro Yamada 	timeout = jiffies + msecs_to_jiffies(50);
57925cbac77SMasahiro Yamada 
58025cbac77SMasahiro Yamada 	while (time_before(jiffies, timeout)) {
58125cbac77SMasahiro Yamada 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
58225cbac77SMasahiro Yamada 		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
58325cbac77SMasahiro Yamada 			err = 0;
58425cbac77SMasahiro Yamada 			break;
58525cbac77SMasahiro Yamada 		}
58625cbac77SMasahiro Yamada 
58725cbac77SMasahiro Yamada 		usleep_range(100, 200);
58825cbac77SMasahiro Yamada 	}
58925cbac77SMasahiro Yamada 
59025cbac77SMasahiro Yamada 	return err;
59125cbac77SMasahiro Yamada }
59225cbac77SMasahiro Yamada 
pcie_phy_power_off(struct phy * phy)59325cbac77SMasahiro Yamada static int pcie_phy_power_off(struct phy *phy)
59425cbac77SMasahiro Yamada {
59525cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
59625cbac77SMasahiro Yamada 	u32 value;
59725cbac77SMasahiro Yamada 
59825cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
59925cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
60025cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
60125cbac77SMasahiro Yamada 
60225cbac77SMasahiro Yamada 	return 0;
60325cbac77SMasahiro Yamada }
60425cbac77SMasahiro Yamada 
60525cbac77SMasahiro Yamada static const struct phy_ops pcie_phy_ops = {
60625cbac77SMasahiro Yamada 	.init = tegra_xusb_phy_init,
60725cbac77SMasahiro Yamada 	.exit = tegra_xusb_phy_exit,
60825cbac77SMasahiro Yamada 	.power_on = pcie_phy_power_on,
60925cbac77SMasahiro Yamada 	.power_off = pcie_phy_power_off,
61025cbac77SMasahiro Yamada 	.owner = THIS_MODULE,
61125cbac77SMasahiro Yamada };
61225cbac77SMasahiro Yamada 
sata_phy_power_on(struct phy * phy)61325cbac77SMasahiro Yamada static int sata_phy_power_on(struct phy *phy)
61425cbac77SMasahiro Yamada {
61525cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
61625cbac77SMasahiro Yamada 	unsigned long timeout;
61725cbac77SMasahiro Yamada 	int err = -ETIMEDOUT;
61825cbac77SMasahiro Yamada 	u32 value;
61925cbac77SMasahiro Yamada 
62025cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
62125cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
62225cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
62325cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
62425cbac77SMasahiro Yamada 
62525cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
62625cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
62725cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
62825cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
62925cbac77SMasahiro Yamada 
63025cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
63125cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
63225cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
63325cbac77SMasahiro Yamada 
63425cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
63525cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
63625cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
63725cbac77SMasahiro Yamada 
63825cbac77SMasahiro Yamada 	timeout = jiffies + msecs_to_jiffies(50);
63925cbac77SMasahiro Yamada 
64025cbac77SMasahiro Yamada 	while (time_before(jiffies, timeout)) {
64125cbac77SMasahiro Yamada 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
64225cbac77SMasahiro Yamada 		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
64325cbac77SMasahiro Yamada 			err = 0;
64425cbac77SMasahiro Yamada 			break;
64525cbac77SMasahiro Yamada 		}
64625cbac77SMasahiro Yamada 
64725cbac77SMasahiro Yamada 		usleep_range(100, 200);
64825cbac77SMasahiro Yamada 	}
64925cbac77SMasahiro Yamada 
65025cbac77SMasahiro Yamada 	return err;
65125cbac77SMasahiro Yamada }
65225cbac77SMasahiro Yamada 
sata_phy_power_off(struct phy * phy)65325cbac77SMasahiro Yamada static int sata_phy_power_off(struct phy *phy)
65425cbac77SMasahiro Yamada {
65525cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
65625cbac77SMasahiro Yamada 	u32 value;
65725cbac77SMasahiro Yamada 
65825cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
65925cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
66025cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
66125cbac77SMasahiro Yamada 
66225cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
66325cbac77SMasahiro Yamada 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
66425cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
66525cbac77SMasahiro Yamada 
66625cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
66725cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
66825cbac77SMasahiro Yamada 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
66925cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
67025cbac77SMasahiro Yamada 
67125cbac77SMasahiro Yamada 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
67225cbac77SMasahiro Yamada 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
67325cbac77SMasahiro Yamada 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
67425cbac77SMasahiro Yamada 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
67525cbac77SMasahiro Yamada 
67625cbac77SMasahiro Yamada 	return 0;
67725cbac77SMasahiro Yamada }
67825cbac77SMasahiro Yamada 
67925cbac77SMasahiro Yamada static const struct phy_ops sata_phy_ops = {
68025cbac77SMasahiro Yamada 	.init = tegra_xusb_phy_init,
68125cbac77SMasahiro Yamada 	.exit = tegra_xusb_phy_exit,
68225cbac77SMasahiro Yamada 	.power_on = sata_phy_power_on,
68325cbac77SMasahiro Yamada 	.power_off = sata_phy_power_off,
68425cbac77SMasahiro Yamada 	.owner = THIS_MODULE,
68525cbac77SMasahiro Yamada };
68625cbac77SMasahiro Yamada 
tegra_xusb_padctl_xlate(struct device * dev,struct of_phandle_args * args)68725cbac77SMasahiro Yamada static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
68825cbac77SMasahiro Yamada 					   struct of_phandle_args *args)
68925cbac77SMasahiro Yamada {
69025cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
69125cbac77SMasahiro Yamada 	unsigned int index = args->args[0];
69225cbac77SMasahiro Yamada 
69325cbac77SMasahiro Yamada 	if (args->args_count <= 0)
69425cbac77SMasahiro Yamada 		return ERR_PTR(-EINVAL);
69525cbac77SMasahiro Yamada 
69625cbac77SMasahiro Yamada 	if (index >= ARRAY_SIZE(padctl->phys))
69725cbac77SMasahiro Yamada 		return ERR_PTR(-EINVAL);
69825cbac77SMasahiro Yamada 
69925cbac77SMasahiro Yamada 	return padctl->phys[index];
70025cbac77SMasahiro Yamada }
70125cbac77SMasahiro Yamada 
70225cbac77SMasahiro Yamada #define PIN_OTG_0   0
70325cbac77SMasahiro Yamada #define PIN_OTG_1   1
70425cbac77SMasahiro Yamada #define PIN_OTG_2   2
70525cbac77SMasahiro Yamada #define PIN_ULPI_0  3
70625cbac77SMasahiro Yamada #define PIN_HSIC_0  4
70725cbac77SMasahiro Yamada #define PIN_HSIC_1  5
70825cbac77SMasahiro Yamada #define PIN_PCIE_0  6
70925cbac77SMasahiro Yamada #define PIN_PCIE_1  7
71025cbac77SMasahiro Yamada #define PIN_PCIE_2  8
71125cbac77SMasahiro Yamada #define PIN_PCIE_3  9
71225cbac77SMasahiro Yamada #define PIN_PCIE_4 10
71325cbac77SMasahiro Yamada #define PIN_SATA_0 11
71425cbac77SMasahiro Yamada 
71525cbac77SMasahiro Yamada static const struct pinctrl_pin_desc tegra124_pins[] = {
71625cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
71725cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
71825cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
71925cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
72025cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
72125cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
72225cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
72325cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
72425cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
72525cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
72625cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
72725cbac77SMasahiro Yamada 	PINCTRL_PIN(PIN_SATA_0, "sata-0"),
72825cbac77SMasahiro Yamada };
72925cbac77SMasahiro Yamada 
73025cbac77SMasahiro Yamada static const char * const tegra124_snps_groups[] = {
73125cbac77SMasahiro Yamada 	"otg-0",
73225cbac77SMasahiro Yamada 	"otg-1",
73325cbac77SMasahiro Yamada 	"otg-2",
73425cbac77SMasahiro Yamada 	"ulpi-0",
73525cbac77SMasahiro Yamada 	"hsic-0",
73625cbac77SMasahiro Yamada 	"hsic-1",
73725cbac77SMasahiro Yamada };
73825cbac77SMasahiro Yamada 
73925cbac77SMasahiro Yamada static const char * const tegra124_xusb_groups[] = {
74025cbac77SMasahiro Yamada 	"otg-0",
74125cbac77SMasahiro Yamada 	"otg-1",
74225cbac77SMasahiro Yamada 	"otg-2",
74325cbac77SMasahiro Yamada 	"ulpi-0",
74425cbac77SMasahiro Yamada 	"hsic-0",
74525cbac77SMasahiro Yamada 	"hsic-1",
74625cbac77SMasahiro Yamada };
74725cbac77SMasahiro Yamada 
74825cbac77SMasahiro Yamada static const char * const tegra124_uart_groups[] = {
74925cbac77SMasahiro Yamada 	"otg-0",
75025cbac77SMasahiro Yamada 	"otg-1",
75125cbac77SMasahiro Yamada 	"otg-2",
75225cbac77SMasahiro Yamada };
75325cbac77SMasahiro Yamada 
75425cbac77SMasahiro Yamada static const char * const tegra124_pcie_groups[] = {
75525cbac77SMasahiro Yamada 	"pcie-0",
75625cbac77SMasahiro Yamada 	"pcie-1",
75725cbac77SMasahiro Yamada 	"pcie-2",
75825cbac77SMasahiro Yamada 	"pcie-3",
75925cbac77SMasahiro Yamada 	"pcie-4",
76025cbac77SMasahiro Yamada };
76125cbac77SMasahiro Yamada 
76225cbac77SMasahiro Yamada static const char * const tegra124_usb3_groups[] = {
76325cbac77SMasahiro Yamada 	"pcie-0",
76425cbac77SMasahiro Yamada 	"pcie-1",
76525cbac77SMasahiro Yamada 	"sata-0",
76625cbac77SMasahiro Yamada };
76725cbac77SMasahiro Yamada 
76825cbac77SMasahiro Yamada static const char * const tegra124_sata_groups[] = {
76925cbac77SMasahiro Yamada 	"sata-0",
77025cbac77SMasahiro Yamada };
77125cbac77SMasahiro Yamada 
77225cbac77SMasahiro Yamada static const char * const tegra124_rsvd_groups[] = {
77325cbac77SMasahiro Yamada 	"otg-0",
77425cbac77SMasahiro Yamada 	"otg-1",
77525cbac77SMasahiro Yamada 	"otg-2",
77625cbac77SMasahiro Yamada 	"pcie-0",
77725cbac77SMasahiro Yamada 	"pcie-1",
77825cbac77SMasahiro Yamada 	"pcie-2",
77925cbac77SMasahiro Yamada 	"pcie-3",
78025cbac77SMasahiro Yamada 	"pcie-4",
78125cbac77SMasahiro Yamada 	"sata-0",
78225cbac77SMasahiro Yamada };
78325cbac77SMasahiro Yamada 
78425cbac77SMasahiro Yamada #define TEGRA124_FUNCTION(_name)					\
78525cbac77SMasahiro Yamada 	{								\
78625cbac77SMasahiro Yamada 		.name = #_name,						\
78725cbac77SMasahiro Yamada 		.num_groups = ARRAY_SIZE(tegra124_##_name##_groups),	\
78825cbac77SMasahiro Yamada 		.groups = tegra124_##_name##_groups,			\
78925cbac77SMasahiro Yamada 	}
79025cbac77SMasahiro Yamada 
79125cbac77SMasahiro Yamada static struct tegra_xusb_padctl_function tegra124_functions[] = {
79225cbac77SMasahiro Yamada 	TEGRA124_FUNCTION(snps),
79325cbac77SMasahiro Yamada 	TEGRA124_FUNCTION(xusb),
79425cbac77SMasahiro Yamada 	TEGRA124_FUNCTION(uart),
79525cbac77SMasahiro Yamada 	TEGRA124_FUNCTION(pcie),
79625cbac77SMasahiro Yamada 	TEGRA124_FUNCTION(usb3),
79725cbac77SMasahiro Yamada 	TEGRA124_FUNCTION(sata),
79825cbac77SMasahiro Yamada 	TEGRA124_FUNCTION(rsvd),
79925cbac77SMasahiro Yamada };
80025cbac77SMasahiro Yamada 
80125cbac77SMasahiro Yamada enum tegra124_function {
80225cbac77SMasahiro Yamada 	TEGRA124_FUNC_SNPS,
80325cbac77SMasahiro Yamada 	TEGRA124_FUNC_XUSB,
80425cbac77SMasahiro Yamada 	TEGRA124_FUNC_UART,
80525cbac77SMasahiro Yamada 	TEGRA124_FUNC_PCIE,
80625cbac77SMasahiro Yamada 	TEGRA124_FUNC_USB3,
80725cbac77SMasahiro Yamada 	TEGRA124_FUNC_SATA,
80825cbac77SMasahiro Yamada 	TEGRA124_FUNC_RSVD,
80925cbac77SMasahiro Yamada };
81025cbac77SMasahiro Yamada 
81125cbac77SMasahiro Yamada static const unsigned int tegra124_otg_functions[] = {
81225cbac77SMasahiro Yamada 	TEGRA124_FUNC_SNPS,
81325cbac77SMasahiro Yamada 	TEGRA124_FUNC_XUSB,
81425cbac77SMasahiro Yamada 	TEGRA124_FUNC_UART,
81525cbac77SMasahiro Yamada 	TEGRA124_FUNC_RSVD,
81625cbac77SMasahiro Yamada };
81725cbac77SMasahiro Yamada 
81825cbac77SMasahiro Yamada static const unsigned int tegra124_usb_functions[] = {
81925cbac77SMasahiro Yamada 	TEGRA124_FUNC_SNPS,
82025cbac77SMasahiro Yamada 	TEGRA124_FUNC_XUSB,
82125cbac77SMasahiro Yamada };
82225cbac77SMasahiro Yamada 
82325cbac77SMasahiro Yamada static const unsigned int tegra124_pci_functions[] = {
82425cbac77SMasahiro Yamada 	TEGRA124_FUNC_PCIE,
82525cbac77SMasahiro Yamada 	TEGRA124_FUNC_USB3,
82625cbac77SMasahiro Yamada 	TEGRA124_FUNC_SATA,
82725cbac77SMasahiro Yamada 	TEGRA124_FUNC_RSVD,
82825cbac77SMasahiro Yamada };
82925cbac77SMasahiro Yamada 
83025cbac77SMasahiro Yamada #define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)	\
83125cbac77SMasahiro Yamada 	{								\
83225cbac77SMasahiro Yamada 		.name = _name,						\
83325cbac77SMasahiro Yamada 		.offset = _offset,					\
83425cbac77SMasahiro Yamada 		.shift = _shift,					\
83525cbac77SMasahiro Yamada 		.mask = _mask,						\
83625cbac77SMasahiro Yamada 		.iddq = _iddq,						\
83725cbac77SMasahiro Yamada 		.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions),	\
83825cbac77SMasahiro Yamada 		.funcs = tegra124_##_funcs##_functions,			\
83925cbac77SMasahiro Yamada 	}
84025cbac77SMasahiro Yamada 
84125cbac77SMasahiro Yamada static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
84225cbac77SMasahiro Yamada 	TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
84325cbac77SMasahiro Yamada 	TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
84425cbac77SMasahiro Yamada 	TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
84525cbac77SMasahiro Yamada 	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
84625cbac77SMasahiro Yamada 	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
84725cbac77SMasahiro Yamada 	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
84825cbac77SMasahiro Yamada 	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
84925cbac77SMasahiro Yamada 	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
85025cbac77SMasahiro Yamada 	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
85125cbac77SMasahiro Yamada 	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
85225cbac77SMasahiro Yamada 	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
85325cbac77SMasahiro Yamada 	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
85425cbac77SMasahiro Yamada };
85525cbac77SMasahiro Yamada 
85625cbac77SMasahiro Yamada static const struct tegra_xusb_padctl_soc tegra124_soc = {
85725cbac77SMasahiro Yamada 	.num_pins = ARRAY_SIZE(tegra124_pins),
85825cbac77SMasahiro Yamada 	.pins = tegra124_pins,
85925cbac77SMasahiro Yamada 	.num_functions = ARRAY_SIZE(tegra124_functions),
86025cbac77SMasahiro Yamada 	.functions = tegra124_functions,
86125cbac77SMasahiro Yamada 	.num_lanes = ARRAY_SIZE(tegra124_lanes),
86225cbac77SMasahiro Yamada 	.lanes = tegra124_lanes,
86325cbac77SMasahiro Yamada };
86425cbac77SMasahiro Yamada 
86525cbac77SMasahiro Yamada static const struct of_device_id tegra_xusb_padctl_of_match[] = {
86625cbac77SMasahiro Yamada 	{ .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
86725cbac77SMasahiro Yamada 	{ }
86825cbac77SMasahiro Yamada };
86925cbac77SMasahiro Yamada MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
87025cbac77SMasahiro Yamada 
87102101cb3SThierry Reding /* predeclare these in order to silence sparse */
87202101cb3SThierry Reding int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev);
87302101cb3SThierry Reding int tegra_xusb_padctl_legacy_remove(struct platform_device *pdev);
87402101cb3SThierry Reding 
tegra_xusb_padctl_legacy_probe(struct platform_device * pdev)87553d2a715SThierry Reding int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev)
87625cbac77SMasahiro Yamada {
87725cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl;
87825cbac77SMasahiro Yamada 	const struct of_device_id *match;
87925cbac77SMasahiro Yamada 	struct phy *phy;
88025cbac77SMasahiro Yamada 	int err;
88125cbac77SMasahiro Yamada 
88225cbac77SMasahiro Yamada 	padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
88325cbac77SMasahiro Yamada 	if (!padctl)
88425cbac77SMasahiro Yamada 		return -ENOMEM;
88525cbac77SMasahiro Yamada 
88625cbac77SMasahiro Yamada 	platform_set_drvdata(pdev, padctl);
88725cbac77SMasahiro Yamada 	mutex_init(&padctl->lock);
88825cbac77SMasahiro Yamada 	padctl->dev = &pdev->dev;
88925cbac77SMasahiro Yamada 
8909978339aSThierry Reding 	/*
8919978339aSThierry Reding 	 * Note that we can't replace this by of_device_get_match_data()
8929978339aSThierry Reding 	 * because we need the separate matching table for this legacy code on
8939978339aSThierry Reding 	 * Tegra124. of_device_get_match_data() would attempt to use the table
8949978339aSThierry Reding 	 * from the updated driver and fail.
8959978339aSThierry Reding 	 */
89625cbac77SMasahiro Yamada 	match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
89725cbac77SMasahiro Yamada 	padctl->soc = match->data;
89825cbac77SMasahiro Yamada 
8994b024225SYueHaibing 	padctl->regs = devm_platform_ioremap_resource(pdev, 0);
90025cbac77SMasahiro Yamada 	if (IS_ERR(padctl->regs))
90125cbac77SMasahiro Yamada 		return PTR_ERR(padctl->regs);
90225cbac77SMasahiro Yamada 
903725e2221SPhilipp Zabel 	padctl->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
90425cbac77SMasahiro Yamada 	if (IS_ERR(padctl->rst))
90525cbac77SMasahiro Yamada 		return PTR_ERR(padctl->rst);
90625cbac77SMasahiro Yamada 
90725cbac77SMasahiro Yamada 	err = reset_control_deassert(padctl->rst);
90825cbac77SMasahiro Yamada 	if (err < 0)
90925cbac77SMasahiro Yamada 		return err;
91025cbac77SMasahiro Yamada 
91125cbac77SMasahiro Yamada 	memset(&padctl->desc, 0, sizeof(padctl->desc));
91225cbac77SMasahiro Yamada 	padctl->desc.name = dev_name(padctl->dev);
91325cbac77SMasahiro Yamada 	padctl->desc.pins = tegra124_pins;
91425cbac77SMasahiro Yamada 	padctl->desc.npins = ARRAY_SIZE(tegra124_pins);
91525cbac77SMasahiro Yamada 	padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
91625cbac77SMasahiro Yamada 	padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
91725cbac77SMasahiro Yamada 	padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
91825cbac77SMasahiro Yamada 	padctl->desc.owner = THIS_MODULE;
91925cbac77SMasahiro Yamada 
920e46e3ef3SLaxman Dewangan 	padctl->pinctrl = devm_pinctrl_register(&pdev->dev, &padctl->desc,
921e46e3ef3SLaxman Dewangan 						padctl);
92225cbac77SMasahiro Yamada 	if (IS_ERR(padctl->pinctrl)) {
92325cbac77SMasahiro Yamada 		dev_err(&pdev->dev, "failed to register pincontrol\n");
92425cbac77SMasahiro Yamada 		err = PTR_ERR(padctl->pinctrl);
92525cbac77SMasahiro Yamada 		goto reset;
92625cbac77SMasahiro Yamada 	}
92725cbac77SMasahiro Yamada 
92825cbac77SMasahiro Yamada 	phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops);
92925cbac77SMasahiro Yamada 	if (IS_ERR(phy)) {
93025cbac77SMasahiro Yamada 		err = PTR_ERR(phy);
931e46e3ef3SLaxman Dewangan 		goto reset;
93225cbac77SMasahiro Yamada 	}
93325cbac77SMasahiro Yamada 
93425cbac77SMasahiro Yamada 	padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
93525cbac77SMasahiro Yamada 	phy_set_drvdata(phy, padctl);
93625cbac77SMasahiro Yamada 
93725cbac77SMasahiro Yamada 	phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops);
93825cbac77SMasahiro Yamada 	if (IS_ERR(phy)) {
93925cbac77SMasahiro Yamada 		err = PTR_ERR(phy);
940e46e3ef3SLaxman Dewangan 		goto reset;
94125cbac77SMasahiro Yamada 	}
94225cbac77SMasahiro Yamada 
94325cbac77SMasahiro Yamada 	padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
94425cbac77SMasahiro Yamada 	phy_set_drvdata(phy, padctl);
94525cbac77SMasahiro Yamada 
94625cbac77SMasahiro Yamada 	padctl->provider = devm_of_phy_provider_register(&pdev->dev,
94725cbac77SMasahiro Yamada 							 tegra_xusb_padctl_xlate);
94825cbac77SMasahiro Yamada 	if (IS_ERR(padctl->provider)) {
94925cbac77SMasahiro Yamada 		err = PTR_ERR(padctl->provider);
95025cbac77SMasahiro Yamada 		dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
951e46e3ef3SLaxman Dewangan 		goto reset;
95225cbac77SMasahiro Yamada 	}
95325cbac77SMasahiro Yamada 
95425cbac77SMasahiro Yamada 	return 0;
95525cbac77SMasahiro Yamada 
95625cbac77SMasahiro Yamada reset:
95725cbac77SMasahiro Yamada 	reset_control_assert(padctl->rst);
95825cbac77SMasahiro Yamada 	return err;
95925cbac77SMasahiro Yamada }
96053d2a715SThierry Reding EXPORT_SYMBOL_GPL(tegra_xusb_padctl_legacy_probe);
96125cbac77SMasahiro Yamada 
tegra_xusb_padctl_legacy_remove(struct platform_device * pdev)96253d2a715SThierry Reding int tegra_xusb_padctl_legacy_remove(struct platform_device *pdev)
96325cbac77SMasahiro Yamada {
96425cbac77SMasahiro Yamada 	struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
96525cbac77SMasahiro Yamada 	int err;
96625cbac77SMasahiro Yamada 
96725cbac77SMasahiro Yamada 	err = reset_control_assert(padctl->rst);
96825cbac77SMasahiro Yamada 	if (err < 0)
96925cbac77SMasahiro Yamada 		dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
97025cbac77SMasahiro Yamada 
97125cbac77SMasahiro Yamada 	return err;
97225cbac77SMasahiro Yamada }
97353d2a715SThierry Reding EXPORT_SYMBOL_GPL(tegra_xusb_padctl_legacy_remove);
974