int pll_vote_clk_enable(struct clk *c) { u32 ena, count; unsigned long flags; struct pll_vote_clk *pllv = to_pll_vote_clk(c); spin_lock_irqsave(&pll_reg_lock, flags); ena = readl_relaxed(PLL_EN_REG(pllv)); ena |= pllv->en_mask; writel_relaxed(ena, PLL_EN_REG(pllv)); spin_unlock_irqrestore(&pll_reg_lock, flags); mb(); for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) { if (readl_relaxed(PLL_STATUS_REG(pllv)) & pllv->status_mask) return 0; udelay(1); } WARN("PLL %s didn't enable after voting for it!\n", c->dbg_name); return -ETIMEDOUT; }
int pll_vote_clk_enable(struct clk *c) { u32 ena, count; unsigned long flags; struct pll_vote_clk *pllv = to_pll_vote_clk(c); spin_lock_irqsave(&pll_reg_lock, flags); ena = readl_relaxed(PLL_EN_REG(pllv)); ena |= pllv->en_mask; writel_relaxed(ena, PLL_EN_REG(pllv)); spin_unlock_irqrestore(&pll_reg_lock, flags); /* * Use a memory barrier since some PLL status registers are * not within the same 1K segment as the voting registers. */ mb(); /* Wait for pll to enable. */ for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) { if (readl_relaxed(PLL_STATUS_REG(pllv)) & pllv->status_mask) return 0; udelay(1); } WARN("PLL %s didn't enable after voting for it!\n", c->dbg_name); return -ETIMEDOUT; }
static enum handoff pll_vote_clk_handoff(struct clk *c) { struct pll_vote_clk *pllv = to_pll_vote_clk(c); if (readl_relaxed(PLL_EN_REG(pllv)) & pllv->en_mask) return HANDOFF_ENABLED_CLK; return HANDOFF_DISABLED_CLK; }
void pll_vote_clk_disable(struct clk *c) { u32 ena; unsigned long flags; struct pll_vote_clk *pllv = to_pll_vote_clk(c); spin_lock_irqsave(&pll_reg_lock, flags); ena = readl_relaxed(PLL_EN_REG(pllv)); ena &= ~(pllv->en_mask); writel_relaxed(ena, PLL_EN_REG(pllv)); spin_unlock_irqrestore(&pll_reg_lock, flags); }
static void pll_acpu_vote_clk_disable(struct clk *c) { unsigned long flags; struct pll_vote_clk *pllv = to_pll_vote_clk(c); spin_lock_irqsave(&soft_vote_lock, flags); *pllv->soft_vote &= ~(pllv->soft_vote_mask); if (!*pllv->soft_vote) pll_vote_clk_disable(c); spin_unlock_irqrestore(&soft_vote_lock, flags); }
static void __iomem *pll_vote_clk_list_registers(struct clk *c, int n, struct clk_register_data **regs, u32 *size) { struct pll_vote_clk *pllv = to_pll_vote_clk(c); static struct clk_register_data data1[] = { {"APPS_VOTE", 0x0}, }; if (n) return ERR_PTR(-EINVAL); *regs = data1; *size = ARRAY_SIZE(data1); return PLL_EN_REG(pllv); }
static int pll_acpu_vote_clk_enable(struct clk *c) { int ret = 0; unsigned long flags; struct pll_vote_clk *pllv = to_pll_vote_clk(c); spin_lock_irqsave(&soft_vote_lock, flags); if (!*pllv->soft_vote) ret = pll_vote_clk_enable(c); if (ret == 0) *pllv->soft_vote |= (pllv->soft_vote_mask); spin_unlock_irqrestore(&soft_vote_lock, flags); return ret; }
int pll_vote_clk_is_enabled(struct clk *c) { struct pll_vote_clk *pllv = to_pll_vote_clk(c); return !!(readl_relaxed(PLL_STATUS_REG(pllv)) & pllv->status_mask); }
struct clk *pll_vote_clk_get_parent(struct clk *c) { return to_pll_vote_clk(c)->parent; }
struct clk *pll_vote_clk_get_parent(struct clk *clk) { struct pll_vote_clk *pll = to_pll_vote_clk(clk); return pll->parent; }
static void *votable_pll_clk_dt_parser(struct device *dev, struct device_node *np) { struct pll_vote_clk *v, *peer; struct clk *c; u32 val, rc; phandle p; struct msmclk_data *drv; v = devm_kzalloc(dev, sizeof(*v), GFP_KERNEL); if (!v) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } drv = msmclk_parse_phandle(dev, np->parent->phandle); if (IS_ERR_OR_NULL(drv)) return ERR_CAST(drv); v->base = &drv->base; rc = of_property_read_u32(np, "qcom,en-offset", (u32 *)&v->en_reg); if (rc) { dt_err(np, "missing qcom,en-offset dt property\n"); return ERR_PTR(-EINVAL); } rc = of_property_read_u32(np, "qcom,en-bit", &val); if (rc) { dt_err(np, "missing qcom,en-bit dt property\n"); return ERR_PTR(-EINVAL); } v->en_mask = BIT(val); rc = of_property_read_u32(np, "qcom,status-offset", (u32 *)&v->status_reg); if (rc) { dt_err(np, "missing qcom,status-offset dt property\n"); return ERR_PTR(-EINVAL); } rc = of_property_read_u32(np, "qcom,status-bit", &val); if (rc) { dt_err(np, "missing qcom,status-bit dt property\n"); return ERR_PTR(-EINVAL); } v->status_mask = BIT(val); rc = of_property_read_u32(np, "qcom,pll-config-rate", &val); if (rc) { dt_err(np, "missing qcom,pll-config-rate dt property\n"); return ERR_PTR(-EINVAL); } v->c.rate = val; if (of_device_is_compatible(np, "qcom,active-only-pll")) v->soft_vote_mask = PLL_SOFT_VOTE_ACPU; else if (of_device_is_compatible(np, "qcom,sleep-active-pll")) v->soft_vote_mask = PLL_SOFT_VOTE_PRIMARY; if (of_device_is_compatible(np, "qcom,votable-pll")) { v->c.ops = &clk_ops_pll_vote; return msmclk_generic_clk_init(dev, np, &v->c); } rc = of_property_read_phandle_index(np, "qcom,peer", 0, &p); if (rc) { dt_err(np, "missing qcom,peer dt property\n"); return ERR_PTR(-EINVAL); } c = msmclk_lookup_phandle(dev, p); if (!IS_ERR_OR_NULL(c)) { v->soft_vote = devm_kzalloc(dev, sizeof(*v->soft_vote), GFP_KERNEL); if (!v->soft_vote) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } peer = to_pll_vote_clk(c); peer->soft_vote = v->soft_vote; } v->c.ops = &clk_ops_pll_acpu_vote; return msmclk_generic_clk_init(dev, np, &v->c); }