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 int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) { u32 value; if (padctl->enable == 0) { error("tegra-xusb-padctl: 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 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 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 sata_phy_power_on(struct phy *phy) { struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); int err; 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); err = wait_on_timeout(50 * MSECOND, padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1) & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET); return err; }
static int pcie_phy_power_on(struct phy *phy) { struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); int err; 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); err = wait_on_timeout(50 * MSECOND, padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1) & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET); 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 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 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 tegra_xusb_padctl_group_apply(struct tegra_xusb_padctl *padctl, const struct tegra_xusb_padctl_group *group) { unsigned int i; for (i = 0; i < group->num_pins; i++) { const struct tegra_xusb_padctl_lane *lane; unsigned int func; u32 value; lane = tegra_xusb_padctl_find_lane(padctl, group->pins[i]); if (!lane) { error("tegra-xusb-padctl: no lane for pin %s", group->pins[i]); continue; } func = tegra_xusb_padctl_lane_find_function(padctl, lane, group->func); if (func < 0) { error("tegra-xusb-padctl: function %s invalid for lane %s: %d", group->func, lane->name, func); continue; } value = padctl_readl(padctl, lane->offset); /* set pin function */ value &= ~(lane->mask << lane->shift); value |= func << lane->shift; /* * Set IDDQ if supported on the lane and specified in the * configuration. */ if (lane->iddq > 0 && group->iddq >= 0) { if (group->iddq != 0) value &= ~(1 << lane->iddq); else value |= 1 << lane->iddq; } padctl_writel(padctl, value, lane->offset); } return 0; }
static int pinctrl_tegra_xusb_set_state(struct pinctrl_device *pdev, struct device_node *np) { struct tegra_xusb_padctl *padctl = container_of(pdev, struct tegra_xusb_padctl, pinctrl); struct device_node *childnode; int iddq = -1, i, j, k; const char *lanes, *func = NULL; const struct tegra_xusb_padctl_lane *lane = NULL; u32 val; /* * At first look if the node we are pointed at has children, * which we may want to visit. */ list_for_each_entry(childnode, &np->children, parent_list) pinctrl_tegra_xusb_set_state(pdev, childnode); /* read relevant state from devicetree */ of_property_read_string(np, "nvidia,function", &func); of_property_read_u32_array(np, "nvidia,iddq", &iddq, 1); /* iterate over all lanes referenced in the dt node */ for (i = 0; ; i++) { if (of_property_read_string_index(np, "nvidia,lanes", i, &lanes)) break; for (j = 0; j < padctl->soc->num_lanes; j++) { if (!strcmp(lanes, padctl->soc->lanes[j].name)) { lane = &padctl->soc->lanes[j]; break; } } /* if no matching lane is found */ if (j == padctl->soc->num_lanes) { /* nothing matching found, warn and bail out */ dev_warn(padctl->pinctrl.dev, "invalid lane %s referenced in node %s\n", lanes, np->name); continue; } if (func) { for (k = 0; k < lane->num_funcs; k++) { if (!strcmp(func, lane->funcs[k])) break; } if (k < lane->num_funcs) { val = padctl_readl(padctl, lane->offset); val &= ~(lane->mask << lane->shift); val |= k << lane->shift; padctl_writel(padctl, val, lane->offset); } else { dev_warn(padctl->pinctrl.dev, "invalid function %s for lane %s in node %s\n", func, lane->name, np->name); } } if (iddq >= 0) { if (lane->iddq) { val = padctl_readl(padctl, lane->offset); if (iddq) val &= ~BIT(lane->iddq); else val |= BIT(lane->iddq); padctl_writel(padctl, val, lane->offset); } else { dev_warn(padctl->pinctrl.dev, "invalid iddq setting for lane %s in node %s\n", lane->name, np->name); } } } return 0; }