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

Commit fd152ec3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "clk: msm: Add support to set desired duty-cycle for a clock"

parents 1aaee421 4680f6aa
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -346,6 +346,48 @@ static void disable_unprepare_rcg_srcs(struct clk *c, struct clk *curr,
		clk_unprepare(curr);
}

static int rcg_clk_set_duty_cycle(struct clk *c, u32 numerator,
				u32 denominator)
{
	struct rcg_clk *rcg = to_rcg_clk(c);
	u32 notn_m_val, n_val, m_val, d_val, not2d_val;
	u32 max_n_value;

	if (!numerator || numerator == denominator)
		return -EINVAL;

	if (!rcg->mnd_reg_width)
		rcg->mnd_reg_width = 8;

	max_n_value = 1 << (rcg->mnd_reg_width - 1);

	notn_m_val = readl_relaxed(N_REG(rcg));
	m_val = readl_relaxed(M_REG(rcg));
	n_val = ((~notn_m_val) + m_val) & BM((rcg->mnd_reg_width - 1), 0);

	if (n_val > max_n_value) {
		pr_warn("%s duty-cycle cannot be set for required frequency %ld\n",
				c->dbg_name, clk_get_rate(c));
		return -EINVAL;
	}

	/* Calculate the 2d value */
	d_val = DIV_ROUND_CLOSEST((numerator * n_val * 2),  denominator);

	/* Check BIT WIDTHS OF 2d.  If D is too big reduce Duty cycle. */
	if (d_val > (BIT(rcg->mnd_reg_width) - 1)) {
		d_val = (BIT(rcg->mnd_reg_width) - 1) / 2;
		d_val *= 2;
	}

	not2d_val = (~d_val) & BM((rcg->mnd_reg_width - 1), 0);

	writel_relaxed(not2d_val, D_REG(rcg));
	rcg_update_config(rcg);

	return 0;
}

static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
{
	struct clk_freq_tbl *cf, *nf;
@@ -2119,6 +2161,7 @@ struct clk_ops clk_ops_rcg_mnd = {
	.enable = rcg_clk_enable,
	.disable = rcg_clk_disable,
	.set_rate = rcg_clk_set_rate,
	.set_duty_cycle = rcg_clk_set_duty_cycle,
	.list_rate = rcg_clk_list_rate,
	.round_rate = rcg_clk_round_rate,
	.handoff = rcg_mnd_clk_handoff,
+22 −0
Original line number Diff line number Diff line
@@ -825,6 +825,28 @@ int clk_set_flags(struct clk *clk, unsigned long flags)
}
EXPORT_SYMBOL(clk_set_flags);

int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator)
{
	if (IS_ERR_OR_NULL(clk))
		return -EINVAL;

	if (numerator > denominator) {
		pr_err("Numerator cannot be > denominator\n");
		return -EINVAL;
	}

	if (!denominator) {
		pr_err("Denominator can not be Zero\n");
		return -EINVAL;
	}

	if (!clk->ops->set_duty_cycle)
		return -ENOSYS;

	return clk->ops->set_duty_cycle(clk, numerator, denominator);
}
EXPORT_SYMBOL(clk_set_duty_cycle);

static LIST_HEAD(initdata_list);

static void init_sibling_lists(struct clk_lookup *clock_tbl, size_t num_clocks)
+2 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 Google, Inc.
 * Copyright (c) 2007-2015, The Linux Foundation. All rights reserved.
 * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -146,6 +146,7 @@ struct clk_ops {
	void (*post_set_rate)(struct clk *clk, unsigned long old_rate);
	int (*set_max_rate)(struct clk *clk, unsigned long rate);
	int (*set_flags)(struct clk *clk, unsigned flags);
	int (*set_duty_cycle)(struct clk *clk, u32 numerator, u32 denominator);
	unsigned long (*get_rate)(struct clk *clk);
	long (*list_rate)(struct clk *clk, unsigned n);
	int (*is_enabled)(struct clk *clk);
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2009, 2012-2015 The Linux Foundation. All rights reserved.
/* Copyright (c) 2009, 2012-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -55,6 +55,11 @@ int clk_reset(struct clk *clk, enum clk_reset_action action);
/* Set clock-specific configuration parameters */
int clk_set_flags(struct clk *clk, unsigned long flags);

/* Set clock duty-cycle as a ratio of numerator/denominator for the desired
 * duty cycle
 */
int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator);

/* returns the mux selection index associated with a particular parent */
int parent_to_src_sel(struct clk_src *parents, int num_parents, struct clk *p);

+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct clk_freq_tbl {
/**
 * struct rcg_clk - root clock generator
 * @cmd_rcgr_reg: command register
 * @mnd_reg_width: Width of MND register
 * @set_rate: function to set frequency
 * @freq_tbl: frequency table for this RCG
 * @current_freq: current RCG frequency
@@ -66,6 +67,7 @@ struct clk_freq_tbl {
 */
struct rcg_clk {
	u32 cmd_rcgr_reg;
	u32 mnd_reg_width;

	void   (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);