Esempio n. 1
0
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);
}
Esempio n. 5
0
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);
}
Esempio n. 7
0
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);
}
Esempio n. 9
0
struct clk *pll_vote_clk_get_parent(struct clk *c)
{
	return to_pll_vote_clk(c)->parent;
}
Esempio n. 10
0
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);
}