Exemple #1
0
static void sysclk_init_disable(struct work_struct *not_used)
{
	int i;

	mutex_lock(&sysclk_mutex);

	/* Enable SWAT  */
	if (ab8500_sysctrl_set(AB8500_SWATCTRL, AB8500_SWATCTRL_SWATENABLE))
		goto err_swat;

	for (i = 0; i < ARRAY_SIZE(u8500_v2_sysclks); i++) {
		struct clk *clk = u8500_v2_sysclks[i].clk;

		/* Disable sysclks */
		if (!clk->enabled && clk->cg_sel) {
			if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
				(u8)clk->cg_sel))
				goto err_sysclk;
		}
	}
	goto unlock_and_exit;

err_sysclk:
	pr_err("clock: Disable %s failed", u8500_v2_sysclks[i].clk->name);
	ab8500_sysctrl_clear(AB8500_SWATCTRL, AB8500_SWATCTRL_SWATENABLE);
	goto unlock_and_exit;

err_swat:
	pr_err("clock: Enable SWAT failed");

unlock_and_exit:
	mutex_unlock(&sysclk_mutex);
}
static int ab_intclk_set_parent(struct clk *clk, struct clk *parent)
{
	int err;

	if (!clk->enabled)
		return 0;

	err = __clk_enable(parent, clk->mutex);

	if (unlikely(err))
		goto parent_enable_error;

	if (parent == clk->parents[AB_INTCLK_PARENT_ULPCLK]) {
		err = ab8500_sysctrl_write(AB8500_SYSULPCLKCTRL1,
			AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK,
			(1 << AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT));
	} else {
		err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
			AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK);
	}
	if (unlikely(err))
		goto config_error;

	__clk_disable(clk->parent, clk->mutex);

	return 0;

config_error:
	__clk_disable(parent, clk->mutex);
parent_enable_error:
	return err;
}
static int ab_ulpclk_enable(struct clk *clk)
{
	int err;

	if (clk->regulator == NULL) {
		struct regulator *reg;

		reg = regulator_get(NULL, "v-intcore");
		if (IS_ERR(reg))
			return PTR_ERR(reg);
		clk->regulator = reg;
	}
	err = regulator_set_optimum_mode(clk->regulator, 1500);
	if (unlikely(err < 0))
		goto regulator_enable_error;
	err = regulator_enable(clk->regulator);
	if (unlikely(err))
		goto regulator_enable_error;
	err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCONF,
		AB8500_SYSULPCLKCONF_ULPCLKCONF_MASK);
	if (unlikely(err))
		goto enable_error;
	err = ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1,
		AB8500_SYSULPCLKCTRL1_ULPCLKREQ);
	if (unlikely(err))
		goto enable_error;
	/* Unknown/undocumented PLL locking time => wait 1 ms. */
	msleep(1);
	return 0;

enable_error:
	(void)regulator_disable(clk->regulator);
regulator_enable_error:
	return err;
}
static int clk_sysctrl_set_parent(struct clk_hw *hw, u8 index)
{
	struct clk_sysctrl *clk = to_clk_sysctrl(hw);
	u8 old_index = clk->parent_index;
	int ret = 0;

	if (clk->reg_sel[old_index]) {
		ret = ab8500_sysctrl_clear(clk->reg_sel[old_index],
					clk->reg_mask[old_index]);
		if (ret)
			return ret;
	}

	if (clk->reg_sel[index]) {
		ret = ab8500_sysctrl_write(clk->reg_sel[index],
					clk->reg_mask[index],
					clk->reg_bits[index]);
		if (ret) {
			if (clk->reg_sel[old_index])
				ab8500_sysctrl_write(clk->reg_sel[old_index],
						clk->reg_mask[old_index],
						clk->reg_bits[old_index]);
			return ret;
		}
	}
	clk->parent_index = index;

	return ret;
}
static void clk_sysctrl_unprepare(struct clk_hw *hw)
{
	struct clk_sysctrl *clk = to_clk_sysctrl(hw);
	if (ab8500_sysctrl_clear(clk->reg_sel[0], clk->reg_mask[0]))
		dev_err(clk->dev, "clk_sysctrl: %s fail to clear %s.\n",
			__func__, clk_hw_get_name(hw));
}
static void audioclk_disable(struct clk *clk)
{
	if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
		AB8500_SYSULPCLKCTRL1_AUDIOCLKENA)) {
		pr_err("clock: %s failed to disable %s.\n", __func__,
			clk->name);
	}
}
static void ab_intclk_disable(struct clk *clk)
{
	if (clk->parent == clk->parents[AB_INTCLK_PARENT_SYSCLK])
		return;

	if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
		AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK)) {
		pr_err("clock: %s failed to disable %s.\n", __func__,
			clk->name);
	}
}
static void ab_ulpclk_disable(struct clk *clk)
{
	int err;

	err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
		AB8500_SYSULPCLKCTRL1_ULPCLKREQ);
	if (unlikely(regulator_disable(clk->regulator) || err))
		goto out_err;

	regulator_set_optimum_mode(clk->regulator, 0);

	return;

out_err:
	pr_err("clock: %s failed to disable %s.\n", __func__, clk->name);
}
static void sysclk_disable(struct clk *clk)
{
	int r;

	if (clk->cg_sel) {
		r = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
			(u8)clk->cg_sel);
		if (r)
			goto disable_failed;
	}
	r = request_sysclk(false);
	if (r)
		goto disable_failed;
	return;

disable_failed:
	pr_err("clock: failed to disable %s.\n", clk->name);
}