diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2016-01-23 16:30:08 +0100 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2016-02-05 15:16:43 +0100 |
commit | 25cbac7716be6a8d5c57534645ca472d2e4be1fd (patch) | |
tree | 28f1c9501475847f0bcd7ac215e0eb01ac1c6202 /drivers/pinctrl/pinctrl-tegra-xusb.c | |
parent | pinctrl: sunxi: guard sub-directory with CONFIG_PINCTRL_SUNXI (diff) | |
download | linux-25cbac7716be6a8d5c57534645ca472d2e4be1fd.tar.xz linux-25cbac7716be6a8d5c57534645ca472d2e4be1fd.zip |
pinctrl: tegra: move Tegra pinctrl drivers to sub-directory
Tegra has several pinctrl drivers. Now it is reasonable enough to
move them into drivers/pinctrl/tegra/.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-tegra-xusb.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-tegra-xusb.c | 985 |
1 files changed, 0 insertions, 985 deletions
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c deleted file mode 100644 index bd3aa5a4fd6d..000000000000 --- a/drivers/pinctrl/pinctrl-tegra-xusb.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/phy/phy.h> -#include <linux/pinctrl/pinctrl.h> -#include <linux/pinctrl/pinmux.h> -#include <linux/platform_device.h> -#include <linux/reset.h> -#include <linux/slab.h> - -#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> - -#include "core.h" -#include "pinctrl-utils.h" - -#define XUSB_PADCTL_ELPG_PROGRAM 0x01c -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) - -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) - -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) - -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) - -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) - -struct tegra_xusb_padctl_function { - const char *name; - const char * const *groups; - unsigned int num_groups; -}; - -struct tegra_xusb_padctl_soc { - const struct pinctrl_pin_desc *pins; - unsigned int num_pins; - - const struct tegra_xusb_padctl_function *functions; - unsigned int num_functions; - - const struct tegra_xusb_padctl_lane *lanes; - unsigned int num_lanes; -}; - -struct tegra_xusb_padctl_lane { - const char *name; - - unsigned int offset; - unsigned int shift; - unsigned int mask; - unsigned int iddq; - - const unsigned int *funcs; - unsigned int num_funcs; -}; - -struct tegra_xusb_padctl { - struct device *dev; - void __iomem *regs; - struct mutex lock; - struct reset_control *rst; - - const struct tegra_xusb_padctl_soc *soc; - struct pinctrl_dev *pinctrl; - struct pinctrl_desc desc; - - struct phy_provider *provider; - struct phy *phys[2]; - - unsigned int enable; -}; - -static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, - unsigned long offset) -{ - writel(value, padctl->regs + offset); -} - -static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, - unsigned long offset) -{ - return readl(padctl->regs + offset); -} - -static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->num_pins; -} - -static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl, - unsigned int group) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->pins[group].name; -} - -static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl, - unsigned group, - const unsigned **pins, - unsigned *num_pins) -{ - /* - * For the tegra-xusb pad controller groups are synonomous - * with lanes/pins and there is always one lane/pin per group. - */ - *pins = &pinctrl->desc->pins[group].number; - *num_pins = 1; - - return 0; -} - -enum tegra_xusb_padctl_param { - TEGRA_XUSB_PADCTL_IDDQ, -}; - -static const struct tegra_xusb_padctl_property { - const char *name; - enum tegra_xusb_padctl_param param; -} properties[] = { - { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ }, -}; - -#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value)) -#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16) -#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff) - -static int 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) -{ - unsigned int i, reserve = 0, num_configs = 0; - unsigned long config, *configs = NULL; - const char *function, *group; - struct property *prop; - int err = 0; - u32 value; - - err = of_property_read_string(np, "nvidia,function", &function); - if (err < 0) { - if (err != -EINVAL) - return err; - - function = NULL; - } - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - err = of_property_read_u32(np, properties[i].name, &value); - if (err < 0) { - if (err == -EINVAL) - continue; - - goto out; - } - - config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value); - - err = pinctrl_utils_add_config(padctl->pinctrl, &configs, - &num_configs, config); - if (err < 0) - goto out; - } - - if (function) - reserve++; - - if (num_configs) - reserve++; - - err = of_property_count_strings(np, "nvidia,lanes"); - if (err < 0) - goto out; - - reserve *= err; - - err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps, - num_maps, reserve); - if (err < 0) - goto out; - - of_property_for_each_string(np, "nvidia,lanes", prop, group) { - if (function) { - err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps, - reserved_maps, num_maps, group, - function); - if (err < 0) - goto out; - } - - if (num_configs) { - err = pinctrl_utils_add_map_configs(padctl->pinctrl, - maps, reserved_maps, num_maps, group, - configs, num_configs, - PIN_MAP_TYPE_CONFIGS_GROUP); - if (err < 0) - goto out; - } - } - - err = 0; - -out: - kfree(configs); - return err; -} - -static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl, - struct device_node *parent, - struct pinctrl_map **maps, - unsigned int *num_maps) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - unsigned int reserved_maps = 0; - struct device_node *np; - int err; - - *num_maps = 0; - *maps = NULL; - - for_each_child_of_node(parent, np) { - err = tegra_xusb_padctl_parse_subnode(padctl, np, maps, - &reserved_maps, - num_maps); - if (err < 0) { - of_node_put(np); - return err; - } - } - - return 0; -} - -static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = { - .get_groups_count = tegra_xusb_padctl_get_groups_count, - .get_group_name = tegra_xusb_padctl_get_group_name, - .get_group_pins = tegra_xusb_padctl_get_group_pins, - .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, -}; - -static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->num_functions; -} - -static const char * -tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl, - unsigned int function) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->functions[function].name; -} - -static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl, - unsigned int function, - const char * const **groups, - unsigned * const num_groups) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - *num_groups = padctl->soc->functions[function].num_groups; - *groups = padctl->soc->functions[function].groups; - - return 0; -} - -static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl, - unsigned int function, - unsigned int group) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - unsigned int i; - u32 value; - - lane = &padctl->soc->lanes[group]; - - for (i = 0; i < lane->num_funcs; i++) - if (lane->funcs[i] == function) - break; - - if (i >= lane->num_funcs) - return -EINVAL; - - value = padctl_readl(padctl, lane->offset); - value &= ~(lane->mask << lane->shift); - value |= i << lane->shift; - padctl_writel(padctl, value, lane->offset); - - return 0; -} - -static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = { - .get_functions_count = tegra_xusb_padctl_get_functions_count, - .get_function_name = tegra_xusb_padctl_get_function_name, - .get_function_groups = tegra_xusb_padctl_get_function_groups, - .set_mux = tegra_xusb_padctl_pinmux_set, -}; - -static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl, - unsigned int group, - unsigned long *config) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - enum tegra_xusb_padctl_param param; - u32 value; - - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config); - lane = &padctl->soc->lanes[group]; - - switch (param) { - case TEGRA_XUSB_PADCTL_IDDQ: - /* lanes with iddq == 0 don't support this parameter */ - if (lane->iddq == 0) - return -EINVAL; - - value = padctl_readl(padctl, lane->offset); - - if (value & BIT(lane->iddq)) - value = 0; - else - value = 1; - - *config = TEGRA_XUSB_PADCTL_PACK(param, value); - break; - - default: - dev_err(padctl->dev, "invalid configuration parameter: %04x\n", - param); - return -ENOTSUPP; - } - - return 0; -} - -static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl, - unsigned int group, - unsigned long *configs, - unsigned int num_configs) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - enum tegra_xusb_padctl_param param; - unsigned long value; - unsigned int i; - u32 regval; - - lane = &padctl->soc->lanes[group]; - - for (i = 0; i < num_configs; i++) { - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]); - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]); - - switch (param) { - case TEGRA_XUSB_PADCTL_IDDQ: - /* lanes with iddq == 0 don't support this parameter */ - if (lane->iddq == 0) - return -EINVAL; - - regval = padctl_readl(padctl, lane->offset); - - if (value) - regval &= ~BIT(lane->iddq); - else - regval |= BIT(lane->iddq); - - padctl_writel(padctl, regval, lane->offset); - break; - - default: - dev_err(padctl->dev, - "invalid configuration parameter: %04x\n", - param); - return -ENOTSUPP; - } - } - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static const char *strip_prefix(const char *s) -{ - const char *comma = strchr(s, ','); - if (!comma) - return s; - - return comma + 1; -} - -static void -tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl, - struct seq_file *s, - unsigned int group) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - unsigned long config, value; - int err; - - config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0); - - err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group, - &config); - if (err < 0) - continue; - - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); - - seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name), - value); - } -} - -static void -tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl, - struct seq_file *s, - unsigned long config) -{ - enum tegra_xusb_padctl_param param; - const char *name = "unknown"; - unsigned long value; - unsigned int i; - - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config); - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - if (properties[i].param == param) { - name = properties[i].name; - break; - } - } - - seq_printf(s, "%s=%lu", strip_prefix(name), value); -} -#endif - -static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = { - .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get, - .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set, -#ifdef CONFIG_DEBUG_FS - .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show, - .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show, -#endif -}; - -static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) -{ - u32 value; - - mutex_lock(&padctl->lock); - - if (padctl->enable++ > 0) - goto out; - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; -} - -static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) -{ - u32 value; - - mutex_lock(&padctl->lock); - - if (WARN_ON(padctl->enable == 0)) - goto out; - - if (--padctl->enable > 0) - goto out; - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; -} - -static int tegra_xusb_phy_init(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - - return tegra_xusb_padctl_enable(padctl); -} - -static int tegra_xusb_phy_exit(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - - return tegra_xusb_padctl_disable(padctl); -} - -static int pcie_phy_power_on(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - unsigned long timeout; - int err = -ETIMEDOUT; - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); - value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | - XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | - XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - timeout = jiffies + msecs_to_jiffies(50); - - while (time_before(jiffies, timeout)) { - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { - err = 0; - break; - } - - usleep_range(100, 200); - } - - return err; -} - -static int pcie_phy_power_off(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - return 0; -} - -static const struct phy_ops pcie_phy_ops = { - .init = tegra_xusb_phy_init, - .exit = tegra_xusb_phy_exit, - .power_on = pcie_phy_power_on, - .power_off = pcie_phy_power_off, - .owner = THIS_MODULE, -}; - -static int sata_phy_power_on(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - unsigned long timeout; - int err = -ETIMEDOUT; - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; - value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - timeout = jiffies + msecs_to_jiffies(50); - - while (time_before(jiffies, timeout)) { - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { - err = 0; - break; - } - - usleep_range(100, 200); - } - - return err; -} - -static int sata_phy_power_off(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; - value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - - return 0; -} - -static const struct phy_ops sata_phy_ops = { - .init = tegra_xusb_phy_init, - .exit = tegra_xusb_phy_exit, - .power_on = sata_phy_power_on, - .power_off = sata_phy_power_off, - .owner = THIS_MODULE, -}; - -static struct phy *tegra_xusb_padctl_xlate(struct device *dev, - struct of_phandle_args *args) -{ - struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); - unsigned int index = args->args[0]; - - if (args->args_count <= 0) - return ERR_PTR(-EINVAL); - - if (index >= ARRAY_SIZE(padctl->phys)) - return ERR_PTR(-EINVAL); - - return padctl->phys[index]; -} - -#define PIN_OTG_0 0 -#define PIN_OTG_1 1 -#define PIN_OTG_2 2 -#define PIN_ULPI_0 3 -#define PIN_HSIC_0 4 -#define PIN_HSIC_1 5 -#define PIN_PCIE_0 6 -#define PIN_PCIE_1 7 -#define PIN_PCIE_2 8 -#define PIN_PCIE_3 9 -#define PIN_PCIE_4 10 -#define PIN_SATA_0 11 - -static const struct pinctrl_pin_desc tegra124_pins[] = { - PINCTRL_PIN(PIN_OTG_0, "otg-0"), - PINCTRL_PIN(PIN_OTG_1, "otg-1"), - PINCTRL_PIN(PIN_OTG_2, "otg-2"), - PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"), - PINCTRL_PIN(PIN_HSIC_0, "hsic-0"), - PINCTRL_PIN(PIN_HSIC_1, "hsic-1"), - PINCTRL_PIN(PIN_PCIE_0, "pcie-0"), - PINCTRL_PIN(PIN_PCIE_1, "pcie-1"), - PINCTRL_PIN(PIN_PCIE_2, "pcie-2"), - PINCTRL_PIN(PIN_PCIE_3, "pcie-3"), - PINCTRL_PIN(PIN_PCIE_4, "pcie-4"), - PINCTRL_PIN(PIN_SATA_0, "sata-0"), -}; - -static const char * const tegra124_snps_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "ulpi-0", - "hsic-0", - "hsic-1", -}; - -static const char * const tegra124_xusb_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "ulpi-0", - "hsic-0", - "hsic-1", -}; - -static const char * const tegra124_uart_groups[] = { - "otg-0", - "otg-1", - "otg-2", -}; - -static const char * const tegra124_pcie_groups[] = { - "pcie-0", - "pcie-1", - "pcie-2", - "pcie-3", - "pcie-4", -}; - -static const char * const tegra124_usb3_groups[] = { - "pcie-0", - "pcie-1", - "sata-0", -}; - -static const char * const tegra124_sata_groups[] = { - "sata-0", -}; - -static const char * const tegra124_rsvd_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "pcie-0", - "pcie-1", - "pcie-2", - "pcie-3", - "pcie-4", - "sata-0", -}; - -#define TEGRA124_FUNCTION(_name) \ - { \ - .name = #_name, \ - .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \ - .groups = tegra124_##_name##_groups, \ - } - -static struct tegra_xusb_padctl_function tegra124_functions[] = { - TEGRA124_FUNCTION(snps), - TEGRA124_FUNCTION(xusb), - TEGRA124_FUNCTION(uart), - TEGRA124_FUNCTION(pcie), - TEGRA124_FUNCTION(usb3), - TEGRA124_FUNCTION(sata), - TEGRA124_FUNCTION(rsvd), -}; - -enum tegra124_function { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, - TEGRA124_FUNC_UART, - TEGRA124_FUNC_PCIE, - TEGRA124_FUNC_USB3, - TEGRA124_FUNC_SATA, - TEGRA124_FUNC_RSVD, -}; - -static const unsigned int tegra124_otg_functions[] = { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, - TEGRA124_FUNC_UART, - TEGRA124_FUNC_RSVD, -}; - -static const unsigned int tegra124_usb_functions[] = { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, -}; - -static const unsigned int tegra124_pci_functions[] = { - TEGRA124_FUNC_PCIE, - TEGRA124_FUNC_USB3, - TEGRA124_FUNC_SATA, - TEGRA124_FUNC_RSVD, -}; - -#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \ - { \ - .name = _name, \ - .offset = _offset, \ - .shift = _shift, \ - .mask = _mask, \ - .iddq = _iddq, \ - .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \ - .funcs = tegra124_##_funcs##_functions, \ - } - -static const struct tegra_xusb_padctl_lane tegra124_lanes[] = { - TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg), - TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg), - TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg), - TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb), - TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb), - TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb), - TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci), - TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci), - TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci), - TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci), - TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci), - TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci), -}; - -static const struct tegra_xusb_padctl_soc tegra124_soc = { - .num_pins = ARRAY_SIZE(tegra124_pins), - .pins = tegra124_pins, - .num_functions = ARRAY_SIZE(tegra124_functions), - .functions = tegra124_functions, - .num_lanes = ARRAY_SIZE(tegra124_lanes), - .lanes = tegra124_lanes, -}; - -static const struct of_device_id tegra_xusb_padctl_of_match[] = { - { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc }, - { } -}; -MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); - -static int tegra_xusb_padctl_probe(struct platform_device *pdev) -{ - struct tegra_xusb_padctl *padctl; - const struct of_device_id *match; - struct resource *res; - struct phy *phy; - int err; - - padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL); - if (!padctl) - return -ENOMEM; - - platform_set_drvdata(pdev, padctl); - mutex_init(&padctl->lock); - padctl->dev = &pdev->dev; - - match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node); - padctl->soc = match->data; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - padctl->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(padctl->regs)) - return PTR_ERR(padctl->regs); - - padctl->rst = devm_reset_control_get(&pdev->dev, NULL); - if (IS_ERR(padctl->rst)) - return PTR_ERR(padctl->rst); - - err = reset_control_deassert(padctl->rst); - if (err < 0) - return err; - - memset(&padctl->desc, 0, sizeof(padctl->desc)); - padctl->desc.name = dev_name(padctl->dev); - padctl->desc.pins = tegra124_pins; - padctl->desc.npins = ARRAY_SIZE(tegra124_pins); - padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops; - padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops; - padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops; - padctl->desc.owner = THIS_MODULE; - - padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl); - if (IS_ERR(padctl->pinctrl)) { - dev_err(&pdev->dev, "failed to register pincontrol\n"); - err = PTR_ERR(padctl->pinctrl); - goto reset; - } - - phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops); - if (IS_ERR(phy)) { - err = PTR_ERR(phy); - goto unregister; - } - - padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy; - phy_set_drvdata(phy, padctl); - - phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops); - if (IS_ERR(phy)) { - err = PTR_ERR(phy); - goto unregister; - } - - padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy; - phy_set_drvdata(phy, padctl); - - padctl->provider = devm_of_phy_provider_register(&pdev->dev, - tegra_xusb_padctl_xlate); - if (IS_ERR(padctl->provider)) { - err = PTR_ERR(padctl->provider); - dev_err(&pdev->dev, "failed to register PHYs: %d\n", err); - goto unregister; - } - - return 0; - -unregister: - pinctrl_unregister(padctl->pinctrl); -reset: - reset_control_assert(padctl->rst); - return err; -} - -static int tegra_xusb_padctl_remove(struct platform_device *pdev) -{ - struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); - int err; - - pinctrl_unregister(padctl->pinctrl); - - err = reset_control_assert(padctl->rst); - if (err < 0) - dev_err(&pdev->dev, "failed to assert reset: %d\n", err); - - return err; -} - -static struct platform_driver tegra_xusb_padctl_driver = { - .driver = { - .name = "tegra-xusb-padctl", - .of_match_table = tegra_xusb_padctl_of_match, - }, - .probe = tegra_xusb_padctl_probe, - .remove = tegra_xusb_padctl_remove, -}; -module_platform_driver(tegra_xusb_padctl_driver); - -MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); -MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver"); -MODULE_LICENSE("GPL v2"); |