clk: Add support to set custom flags with clk_set_flags
The new API clk_set_flags could be used by hardware specific clock drivers or clients for specific hardware requirements. These flags could be custom defined as per hardware needs. Change-Id: Ia67373ee2b8934c898052c68338fa86cb16070dd Signed-off-by: Taniya Das <tdas@codeaurora.org> Signed-off-by: Deepak Katragadda <dkatraga@codeaurora.org> Signed-off-by: David Dai <daidavid1@codeaurora.org>
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
parent
72969e942f
commit
b904878a04
@@ -2604,6 +2604,18 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_is_match);
|
||||
|
||||
int clk_set_flags(struct clk *clk, unsigned long flags)
|
||||
{
|
||||
if (!clk)
|
||||
return 0;
|
||||
|
||||
if (!clk->core->ops->set_flags)
|
||||
return -EINVAL;
|
||||
|
||||
return clk->core->ops->set_flags(clk->core->hw, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_flags);
|
||||
|
||||
/*** debugfs support ***/
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013, 2017, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@@ -117,15 +117,62 @@ static int clk_branch_enable(struct clk_hw *hw)
|
||||
return clk_branch_toggle(hw, true, clk_branch_check_halt);
|
||||
}
|
||||
|
||||
static int clk_cbcr_set_flags(struct regmap *regmap, unsigned int reg,
|
||||
unsigned long flags)
|
||||
{
|
||||
u32 cbcr_val;
|
||||
|
||||
regmap_read(regmap, reg, &cbcr_val);
|
||||
|
||||
switch (flags) {
|
||||
case CLKFLAG_PERIPH_OFF_SET:
|
||||
cbcr_val |= BIT(12);
|
||||
break;
|
||||
case CLKFLAG_PERIPH_OFF_CLEAR:
|
||||
cbcr_val &= ~BIT(12);
|
||||
break;
|
||||
case CLKFLAG_RETAIN_PERIPH:
|
||||
cbcr_val |= BIT(13);
|
||||
break;
|
||||
case CLKFLAG_NORETAIN_PERIPH:
|
||||
cbcr_val &= ~BIT(13);
|
||||
break;
|
||||
case CLKFLAG_RETAIN_MEM:
|
||||
cbcr_val |= BIT(14);
|
||||
break;
|
||||
case CLKFLAG_NORETAIN_MEM:
|
||||
cbcr_val &= ~BIT(14);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_write(regmap, reg, cbcr_val);
|
||||
|
||||
/* Make sure power is enabled/disabled before returning. */
|
||||
mb();
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clk_branch_disable(struct clk_hw *hw)
|
||||
{
|
||||
clk_branch_toggle(hw, false, clk_branch_check_halt);
|
||||
}
|
||||
|
||||
static int clk_branch_set_flags(struct clk_hw *hw, unsigned int flags)
|
||||
{
|
||||
struct clk_branch *br = to_clk_branch(hw);
|
||||
|
||||
return clk_cbcr_set_flags(br->clkr.regmap, br->halt_reg, flags);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_branch_ops = {
|
||||
.enable = clk_branch_enable,
|
||||
.disable = clk_branch_disable,
|
||||
.is_enabled = clk_is_enabled_regmap,
|
||||
.set_flags = clk_branch_set_flags,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_branch_ops);
|
||||
|
||||
@@ -143,6 +190,7 @@ const struct clk_ops clk_branch2_ops = {
|
||||
.enable = clk_branch2_enable,
|
||||
.disable = clk_branch2_disable,
|
||||
.is_enabled = clk_is_enabled_regmap,
|
||||
.set_flags = clk_branch_set_flags,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_branch2_ops);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2013, 2017, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef __QCOM_CLK_BRANCH_H__
|
||||
#define __QCOM_CLK_BRANCH_H__
|
||||
@@ -44,4 +44,13 @@ extern const struct clk_ops clk_branch_simple_ops;
|
||||
#define to_clk_branch(_hw) \
|
||||
container_of(to_clk_regmap(_hw), struct clk_branch, clkr)
|
||||
|
||||
enum branch_mem_flags {
|
||||
CLKFLAG_RETAIN_PERIPH,
|
||||
CLKFLAG_NORETAIN_PERIPH,
|
||||
CLKFLAG_RETAIN_MEM,
|
||||
CLKFLAG_NORETAIN_MEM,
|
||||
CLKFLAG_PERIPH_OFF_SET,
|
||||
CLKFLAG_PERIPH_OFF_CLEAR,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -43,10 +43,16 @@ static unsigned long dummy_clk_recalc_rate(struct clk_hw *hw,
|
||||
return dummy->rrate;
|
||||
}
|
||||
|
||||
static int dummy_clk_set_flags(struct clk_hw *hw, unsigned int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct clk_ops clk_dummy_ops = {
|
||||
.set_rate = dummy_clk_set_rate,
|
||||
.round_rate = dummy_clk_round_rate,
|
||||
.recalc_rate = dummy_clk_recalc_rate,
|
||||
.set_flags = dummy_clk_set_flags,
|
||||
};
|
||||
EXPORT_SYMBOL(clk_dummy_ops);
|
||||
|
||||
|
||||
@@ -202,6 +202,8 @@ struct clk_duty {
|
||||
* directory is provided as an argument. Called with
|
||||
* prepare_lock held. Returns 0 on success, -EERROR otherwise.
|
||||
*
|
||||
* @set_flags: Set custom flags which deal with hardware specifics. Returns 0
|
||||
* on success, -EERROR otherwise.
|
||||
*
|
||||
* The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
|
||||
* implementations to split any work between atomic (enable) and sleepable
|
||||
@@ -246,6 +248,7 @@ struct clk_ops {
|
||||
struct clk_duty *duty);
|
||||
void (*init)(struct clk_hw *hw);
|
||||
void (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
|
||||
int (*set_flags)(struct clk_hw *hw, unsigned int flags);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -629,6 +629,15 @@ struct clk *clk_get_parent(struct clk *clk);
|
||||
*/
|
||||
struct clk *clk_get_sys(const char *dev_id, const char *con_id);
|
||||
|
||||
/**
|
||||
* clk_set_flags - set the custom HW specific flags for this clock
|
||||
* @clk: clock source
|
||||
* @flags: custom flags which would be hardware specific.
|
||||
*
|
||||
* Returns success 0 or negative errno.
|
||||
*/
|
||||
int clk_set_flags(struct clk *clk, unsigned long flags);
|
||||
|
||||
#else /* !CONFIG_HAVE_CLK */
|
||||
|
||||
static inline struct clk *clk_get(struct device *dev, const char *id)
|
||||
@@ -728,6 +737,11 @@ static inline struct clk *clk_get_sys(const char *dev_id, const char *con_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int clk_set_flags(struct clk *clk, unsigned long flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
|
||||
|
||||
Reference in New Issue
Block a user