mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-17 00:33:06 +00:00
83d290c56f
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
350 lines
9.7 KiB
C
350 lines
9.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "tegra-xusb-padctl: " fmt
|
|
|
|
#include <common.h>
|
|
#include <errno.h>
|
|
#include <dm/of_access.h>
|
|
#include <dm/ofnode.h>
|
|
|
|
#include "../xusb-padctl-common.h"
|
|
|
|
#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.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)
|
|
|
|
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 char *const tegra124_functions[] = {
|
|
"snps",
|
|
"xusb",
|
|
"uart",
|
|
"pcie",
|
|
"usb3",
|
|
"sata",
|
|
"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 int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
|
|
{
|
|
u32 value;
|
|
|
|
if (padctl->enable++ > 0)
|
|
return 0;
|
|
|
|
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);
|
|
|
|
udelay(100);
|
|
|
|
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);
|
|
|
|
udelay(100);
|
|
|
|
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);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
|
|
{
|
|
u32 value;
|
|
|
|
if (padctl->enable == 0) {
|
|
pr_err("unbalanced enable/disable");
|
|
return 0;
|
|
}
|
|
|
|
if (--padctl->enable > 0)
|
|
return 0;
|
|
|
|
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);
|
|
|
|
udelay(100);
|
|
|
|
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);
|
|
|
|
udelay(100);
|
|
|
|
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);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int phy_prepare(struct tegra_xusb_phy *phy)
|
|
{
|
|
return tegra_xusb_padctl_enable(phy->padctl);
|
|
}
|
|
|
|
static int phy_unprepare(struct tegra_xusb_phy *phy)
|
|
{
|
|
return tegra_xusb_padctl_disable(phy->padctl);
|
|
}
|
|
|
|
static int pcie_phy_enable(struct tegra_xusb_phy *phy)
|
|
{
|
|
struct tegra_xusb_padctl *padctl = phy->padctl;
|
|
int err = -ETIMEDOUT;
|
|
unsigned long start;
|
|
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);
|
|
|
|
start = get_timer(0);
|
|
|
|
while (get_timer(start) < 50) {
|
|
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
|
|
if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
|
|
err = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int pcie_phy_disable(struct tegra_xusb_phy *phy)
|
|
{
|
|
struct tegra_xusb_padctl *padctl = phy->padctl;
|
|
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 int sata_phy_enable(struct tegra_xusb_phy *phy)
|
|
{
|
|
struct tegra_xusb_padctl *padctl = phy->padctl;
|
|
int err = -ETIMEDOUT;
|
|
unsigned long start;
|
|
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);
|
|
|
|
start = get_timer(0);
|
|
|
|
while (get_timer(start) < 50) {
|
|
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
|
if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
|
|
err = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int sata_phy_disable(struct tegra_xusb_phy *phy)
|
|
{
|
|
struct tegra_xusb_padctl *padctl = phy->padctl;
|
|
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 tegra_xusb_phy_ops pcie_phy_ops = {
|
|
.prepare = phy_prepare,
|
|
.enable = pcie_phy_enable,
|
|
.disable = pcie_phy_disable,
|
|
.unprepare = phy_unprepare,
|
|
};
|
|
|
|
static const struct tegra_xusb_phy_ops sata_phy_ops = {
|
|
.prepare = phy_prepare,
|
|
.enable = sata_phy_enable,
|
|
.disable = sata_phy_disable,
|
|
.unprepare = phy_unprepare,
|
|
};
|
|
|
|
static struct tegra_xusb_phy tegra124_phys[] = {
|
|
{
|
|
.type = TEGRA_XUSB_PADCTL_PCIE,
|
|
.ops = &pcie_phy_ops,
|
|
.padctl = &padctl,
|
|
},
|
|
{
|
|
.type = TEGRA_XUSB_PADCTL_SATA,
|
|
.ops = &sata_phy_ops,
|
|
.padctl = &padctl,
|
|
},
|
|
};
|
|
|
|
static const struct tegra_xusb_padctl_soc tegra124_socdata = {
|
|
.lanes = tegra124_lanes,
|
|
.num_lanes = ARRAY_SIZE(tegra124_lanes),
|
|
.functions = tegra124_functions,
|
|
.num_functions = ARRAY_SIZE(tegra124_functions),
|
|
.phys = tegra124_phys,
|
|
.num_phys = ARRAY_SIZE(tegra124_phys),
|
|
};
|
|
|
|
void tegra_xusb_padctl_init(void)
|
|
{
|
|
ofnode nodes[1];
|
|
int count = 0;
|
|
int ret;
|
|
|
|
debug("%s: start\n", __func__);
|
|
if (of_live_active()) {
|
|
struct device_node *np = of_find_compatible_node(NULL, NULL,
|
|
"nvidia,tegra124-xusb-padctl");
|
|
|
|
debug("np=%p\n", np);
|
|
if (np) {
|
|
nodes[0] = np_to_ofnode(np);
|
|
count = 1;
|
|
}
|
|
} else {
|
|
int node_offsets[1];
|
|
int i;
|
|
|
|
count = fdtdec_find_aliases_for_id(gd->fdt_blob, "padctl",
|
|
COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
|
|
node_offsets, ARRAY_SIZE(node_offsets));
|
|
for (i = 0; i < count; i++)
|
|
nodes[i] = offset_to_ofnode(node_offsets[i]);
|
|
}
|
|
|
|
ret = tegra_xusb_process_nodes(nodes, count, &tegra124_socdata);
|
|
debug("%s: done, ret=%d\n", __func__, ret);
|
|
}
|