// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*/
#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 synonymous
* 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 (