diff options
Diffstat (limited to 'arch/arm/mach-tegra/tegra210/xusb-padctl.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra210/xusb-padctl.c | 248 |
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__); |