summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra210/xusb-padctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/tegra210/xusb-padctl.c')
-rw-r--r--arch/arm/mach-tegra/tegra210/xusb-padctl.c248
1 files changed, 95 insertions, 153 deletions
diff --git a/arch/arm/mach-tegra/tegra210/xusb-padctl.c b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
index 3c10a96aa3..9ec93e7c4c 100644
--- a/arch/arm/mach-tegra/tegra210/xusb-padctl.c
+++ b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
@@ -8,51 +8,82 @@
#include <common.h>
#include <errno.h>
-#include <fdtdec.h>
-#include <malloc.h>
-#include <asm/io.h>
+#include "../xusb-padctl-common.h"
#include <asm/arch/clock.h>
-#include <asm/arch-tegra/xusb-padctl.h>
#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
-struct tegra_xusb_phy_ops {
- int (*prepare)(struct tegra_xusb_phy *phy);
- int (*enable)(struct tegra_xusb_phy *phy);
- int (*disable)(struct tegra_xusb_phy *phy);
- int (*unprepare)(struct tegra_xusb_phy *phy);
+enum tegra210_function {
+ TEGRA210_FUNC_SNPS,
+ TEGRA210_FUNC_XUSB,
+ TEGRA210_FUNC_UART,
+ TEGRA210_FUNC_PCIE_X1,
+ TEGRA210_FUNC_PCIE_X4,
+ TEGRA210_FUNC_USB3,
+ TEGRA210_FUNC_SATA,
+ TEGRA210_FUNC_RSVD,
};
-struct tegra_xusb_phy {
- const struct tegra_xusb_phy_ops *ops;
-
- struct tegra_xusb_padctl *padctl;
+static const char *const tegra210_functions[] = {
+ "snps",
+ "xusb",
+ "uart",
+ "pcie-x1",
+ "pcie-x4",
+ "usb3",
+ "sata",
+ "rsvd",
};
-struct tegra_xusb_padctl {
- struct fdt_resource regs;
+static const unsigned int tegra210_otg_functions[] = {
+ TEGRA210_FUNC_SNPS,
+ TEGRA210_FUNC_XUSB,
+ TEGRA210_FUNC_UART,
+ TEGRA210_FUNC_RSVD,
+};
- unsigned int enable;
+static const unsigned int tegra210_usb_functions[] = {
+ TEGRA210_FUNC_SNPS,
+ TEGRA210_FUNC_XUSB,
+};
- struct tegra_xusb_phy phys[2];
+static const unsigned int tegra210_pci_functions[] = {
+ TEGRA210_FUNC_PCIE_X1,
+ TEGRA210_FUNC_USB3,
+ TEGRA210_FUNC_SATA,
+ TEGRA210_FUNC_PCIE_X4,
};
-static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
- unsigned long offset)
-{
- u32 value = readl(padctl->regs.start + offset);
- debug("padctl: %08lx > %08x\n", offset, value);
- return value;
-}
+#define TEGRA210_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \
+ { \
+ .name = _name, \
+ .offset = _offset, \
+ .shift = _shift, \
+ .mask = _mask, \
+ .iddq = _iddq, \
+ .num_funcs = ARRAY_SIZE(tegra210_##_funcs##_functions), \
+ .funcs = tegra210_##_funcs##_functions, \
+ }
-static inline void padctl_writel(struct tegra_xusb_padctl *padctl,
- u32 value, unsigned long offset)
-{
- debug("padctl: %08lx < %08x\n", offset, value);
- writel(value, padctl->regs.start + offset);
-}
+static const struct tegra_xusb_padctl_lane tegra210_lanes[] = {
+ TEGRA210_LANE("otg-0", 0x004, 0, 0x3, 0, otg),
+ TEGRA210_LANE("otg-1", 0x004, 2, 0x3, 0, otg),
+ TEGRA210_LANE("otg-2", 0x004, 4, 0x3, 0, otg),
+ TEGRA210_LANE("otg-3", 0x004, 6, 0x3, 0, otg),
+ TEGRA210_LANE("usb2-bias", 0x004, 18, 0x3, 0, otg),
+ TEGRA210_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
+ TEGRA210_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
+ TEGRA210_LANE("pcie-0", 0x028, 12, 0x3, 1, pci),
+ TEGRA210_LANE("pcie-1", 0x028, 14, 0x3, 2, pci),
+ TEGRA210_LANE("pcie-2", 0x028, 16, 0x3, 3, pci),
+ TEGRA210_LANE("pcie-3", 0x028, 18, 0x3, 4, pci),
+ TEGRA210_LANE("pcie-4", 0x028, 20, 0x3, 5, pci),
+ TEGRA210_LANE("pcie-5", 0x028, 22, 0x3, 6, pci),
+ TEGRA210_LANE("pcie-6", 0x028, 24, 0x3, 7, pci),
+ TEGRA210_LANE("sata-0", 0x028, 30, 0x3, 8, pci),
+};
#define XUSB_PADCTL_ELPG_PROGRAM 0x024
#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 31)
@@ -248,7 +279,10 @@ static int pcie_phy_enable(struct tegra_xusb_phy *phy)
if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_DONE)
break;
}
-
+ if (!(value & XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_DONE)) {
+ debug(" timeout\n");
+ return -ETIMEDOUT;
+ }
debug(" done\n");
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
@@ -264,7 +298,10 @@ static int pcie_phy_enable(struct tegra_xusb_phy *phy)
if ((value & XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_DONE) == 0)
break;
}
-
+ if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_DONE) {
+ debug(" timeout\n");
+ return -ETIMEDOUT;
+ }
debug(" done\n");
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
@@ -279,7 +316,10 @@ static int pcie_phy_enable(struct tegra_xusb_phy *phy)
if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL1_LOCKDET_STATUS)
break;
}
-
+ if (!(value & XUSB_PADCTL_UPHY_PLL_P0_CTL1_LOCKDET_STATUS)) {
+ debug(" timeout\n");
+ return -ETIMEDOUT;
+ }
debug(" done\n");
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
@@ -295,7 +335,10 @@ static int pcie_phy_enable(struct tegra_xusb_phy *phy)
if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_DONE)
break;
}
-
+ if (!(value & XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_DONE)) {
+ debug(" timeout\n");
+ return -ETIMEDOUT;
+ }
debug(" done\n");
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
@@ -310,7 +353,10 @@ static int pcie_phy_enable(struct tegra_xusb_phy *phy)
if ((value & XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_DONE) == 0)
break;
}
-
+ if (value & XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_DONE) {
+ debug(" timeout\n");
+ return -ETIMEDOUT;
+ }
debug(" done\n");
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
@@ -358,120 +404,22 @@ static const struct tegra_xusb_phy_ops pcie_phy_ops = {
.unprepare = phy_unprepare,
};
-static struct tegra_xusb_padctl *padctl = &(struct tegra_xusb_padctl) {
- .phys = {
- [0] = {
- .ops = &pcie_phy_ops,
- },
+static struct tegra_xusb_phy tegra210_phys[] = {
+ {
+ .type = TEGRA_XUSB_PADCTL_PCIE,
+ .ops = &pcie_phy_ops,
+ .padctl = &padctl,
},
};
-static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl,
- const void *fdt, int node)
-{
- int err;
-
- err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs);
- if (err < 0) {
- error("registers not found");
- return err;
- }
-
- debug("regs: %pa-%pa\n", &padctl->regs.start,
- &padctl->regs.end);
-
- return 0;
-}
-
-static int process_nodes(const void *fdt, int nodes[], unsigned int count)
-{
- unsigned int i;
- int err;
-
- debug("> %s(fdt=%p, nodes=%p, count=%u)\n", __func__, fdt, nodes,
- count);
-
- for (i = 0; i < count; i++) {
- enum fdt_compat_id id;
-
- if (!fdtdec_get_is_enabled(fdt, nodes[i]))
- continue;
-
- id = fdtdec_lookup(fdt, nodes[i]);
- switch (id) {
- case COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL:
- case COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL:
- break;
-
- default:
- error("unsupported compatible: %s",
- fdtdec_get_compatible(id));
- continue;
- }
-
- err = tegra_xusb_padctl_parse_dt(padctl, fdt, nodes[i]);
- if (err < 0) {
- error("failed to parse DT: %d",
- err);
- continue;
- }
-
- /* deassert XUSB padctl reset */
- reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0);
-
- /* only a single instance is supported */
- break;
- }
-
- debug("< %s()\n", __func__);
- return 0;
-}
-
-struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type)
-{
- struct tegra_xusb_phy *phy = NULL;
-
- switch (type) {
- case TEGRA_XUSB_PADCTL_PCIE:
- phy = &padctl->phys[0];
- phy->padctl = padctl;
- break;
- }
-
- return phy;
-}
-
-int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy)
-{
- if (phy && phy->ops && phy->ops->prepare)
- return phy->ops->prepare(phy);
-
- return phy ? -ENOSYS : -EINVAL;
-}
-
-int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy)
-{
- if (phy && phy->ops && phy->ops->enable)
- return phy->ops->enable(phy);
-
- return phy ? -ENOSYS : -EINVAL;
-}
-
-int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy)
-{
- if (phy && phy->ops && phy->ops->disable)
- return phy->ops->disable(phy);
-
- return phy ? -ENOSYS : -EINVAL;
-}
-
-int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy)
-{
- if (phy && phy->ops && phy->ops->unprepare)
- return phy->ops->unprepare(phy);
-
- return phy ? -ENOSYS : -EINVAL;
-}
+static const struct tegra_xusb_padctl_soc tegra210_socdata = {
+ .lanes = tegra210_lanes,
+ .num_lanes = ARRAY_SIZE(tegra210_lanes),
+ .functions = tegra210_functions,
+ .num_functions = ARRAY_SIZE(tegra210_functions),
+ .phys = tegra210_phys,
+ .num_phys = ARRAY_SIZE(tegra210_phys),
+};
void tegra_xusb_padctl_init(const void *fdt)
{
@@ -482,13 +430,7 @@ void tegra_xusb_padctl_init(const void *fdt)
count = fdtdec_find_aliases_for_id(fdt, "padctl",
COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL,
nodes, ARRAY_SIZE(nodes));
- if (process_nodes(fdt, nodes, count))
- return;
-
- count = fdtdec_find_aliases_for_id(fdt, "padctl",
- COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
- nodes, ARRAY_SIZE(nodes));
- if (process_nodes(fdt, nodes, count))
+ if (tegra_xusb_process_nodes(fdt, nodes, count, &tegra210_socdata))
return;
debug("< %s()\n", __func__);