Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d82cf7d authored by Patrick Daly's avatar Patrick Daly Committed by Deepak Katragadda
Browse files

clk: clock-pll: Support parsing votable plls from dt



Add functionality to load votable and active-sleep PLLs
from device tree. Active/sleep PLLs, like RPM clocks,
support "active" and "sleep" modes of operation.

Change-Id: I997dfb5b51afeade7e1dde0e183b47f870f22bdd
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
parent 0f1bd39f
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -310,3 +310,84 @@ mmss_gpll0_clk_src: mmss_gpll0_clk_src {
	qcom,parent = <&gpll0>;
	qcom,delay = <1>;
};

*****************************************************************************

"qcom,votable-pll"

A software construct defining a PLL (Phase-locked Loop) which can be voted for.

Required Properties:
- compatible:		Must be "qcom,votable-pll"
- qcom,en-offset:	Register offset from the region described in parent
			clock controller.
- qcom,en-bit:		Bit used to enable the clock
- qcom,status-offset:	Register offset from the region described in parent
			clock controller.
- qcom,status-bit:	Status bit indicating the clock is on
- qcom,pll-config-rate:	The rate this clock runs at. This rate is not changeable.

Recommended Properties:
- qcom,parent:		See "General Optional Properties"
- qcom,supply-group:	See "General Optional Properties"
- qcom,clk-fmax:	See "General Optional Properties"

gpll4: gpll4 {
	compatible = "qcom,votable-pll";
	qcom,en-offset = <GCC_APCS_GPLL_ENA_VOTE>;
	qcom,en-bit = <4>;
	qcom,status-offset = <GCC_GPLL4_MODE>;
	qcom,status-bit = <30>;
	qcom,pll-config-rate = <1536000000>;
	qcom,parent = <&gcc_xo>;
	qcom,supply-group = <&gcc_vdd_dig>;
	qcom,clk-fmax =
			<FMAX_LOWER 400000000>,
			<FMAX_LOW 800000000>,
			<FMAX_NOM 1600000000>,
			<FMAX_TURBO 1600000000>;
};

*****************************************************************************

"qcom,sleep-active-pll"

A software construct wrapping the normal votable pll hw. Like rpm_clocks,
these clocks also support "active" and "sleep" modes of operation.

Required Properties:
- compatible:		"qcom,active-only-pll", "qcom,sleep-active-pll"
- qcom,en-offset:	Register offset from the region described in parent
			clock controller.
- qcom,en-bit:		Bit used to enable the clock
- qcom,status-offset:	Register offset from the region described in parent
			clock controller.
- qcom,status-bit:	Status bit indicating the clock is on
- qcom,peer:		Phandle to the other clock in the pair
- qcom,pll-config-rate:	The rate this clock runs at. This rate is not changeable.

Recommended Properties:
- qcom,parent:		See "General Optional Properties"
- qcom,clk-fmax:	See "General Optional Properties"

gpll0: gpll0 {
	compatible = "qcom,sleep-active-pll";
	qcom,en-offset = <GCC_APCS_GPLL_ENA_VOTE>;
	qcom,en-bit = <0>;
	qcom,status-offset = <GCC_GPLL0_MODE>;
	qcom,status-bit = <30>;
	qcom,pll-config-rate = <600000000>;
	qcom,parent = <&gcc_xo>;
	qcom,peer = <&gpll0_ao>;
};

gpll0_ao: gpll0_ao {
	compatible = "qcom,active-only-pll";
	qcom,en-offset = <GCC_APCS_GPLL_ENA_VOTE>;
	qcom,en-bit = <0>;
	qcom,status-offset = <GCC_GPLL0_MODE>;
	qcom,status-bit = <30>;
	qcom,pll-config-rate = <600000000>;
	qcom,parent = <&gcc_xo_ao>;
	qcom,peer = <&gpll0>;
};
+92 −0
Original line number Diff line number Diff line
@@ -12,12 +12,15 @@
 *
 */

#define pr_fmt(fmt) "%s: " fmt, __func__

#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <soc/qcom/clock-pll.h>
#include <soc/qcom/msm-clock-controller.h>

#include "clock.h"

@@ -829,3 +832,92 @@ void configure_sr_hpm_lp_pll(struct pll_config *config,
		__set_fsm_mode(PLL_MODE_REG(regs), 0x1, 0x0);
}

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);
}
MSMCLK_PARSER(votable_pll_clk_dt_parser, "qcom,active-only-pll", 0);
MSMCLK_PARSER(votable_pll_clk_dt_parser, "qcom,sleep-active-pll", 1);
MSMCLK_PARSER(votable_pll_clk_dt_parser, "qcom,votable-pll", 2);
+3 −3
Original line number Diff line number Diff line
@@ -82,11 +82,11 @@ struct pll_config_vals {
 */
struct pll_vote_clk {
	u32 *soft_vote;
	const u32 soft_vote_mask;
	u32 soft_vote_mask;
	void __iomem *const en_reg;
	const u32 en_mask;
	u32 en_mask;
	void __iomem *const status_reg;
	const u32 status_mask;
	u32 status_mask;

	struct clk c;
	void *const __iomem *base;