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);
|
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 ***/
|
/*** debugfs support ***/
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// 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>
|
#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);
|
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)
|
static void clk_branch_disable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
clk_branch_toggle(hw, false, clk_branch_check_halt);
|
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 = {
|
const struct clk_ops clk_branch_ops = {
|
||||||
.enable = clk_branch_enable,
|
.enable = clk_branch_enable,
|
||||||
.disable = clk_branch_disable,
|
.disable = clk_branch_disable,
|
||||||
.is_enabled = clk_is_enabled_regmap,
|
.is_enabled = clk_is_enabled_regmap,
|
||||||
|
.set_flags = clk_branch_set_flags,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(clk_branch_ops);
|
EXPORT_SYMBOL_GPL(clk_branch_ops);
|
||||||
|
|
||||||
@@ -143,6 +190,7 @@ const struct clk_ops clk_branch2_ops = {
|
|||||||
.enable = clk_branch2_enable,
|
.enable = clk_branch2_enable,
|
||||||
.disable = clk_branch2_disable,
|
.disable = clk_branch2_disable,
|
||||||
.is_enabled = clk_is_enabled_regmap,
|
.is_enabled = clk_is_enabled_regmap,
|
||||||
|
.set_flags = clk_branch_set_flags,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(clk_branch2_ops);
|
EXPORT_SYMBOL_GPL(clk_branch2_ops);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* 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__
|
#ifndef __QCOM_CLK_BRANCH_H__
|
||||||
#define __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) \
|
#define to_clk_branch(_hw) \
|
||||||
container_of(to_clk_regmap(_hw), struct clk_branch, clkr)
|
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
|
#endif
|
||||||
|
|||||||
@@ -43,10 +43,16 @@ static unsigned long dummy_clk_recalc_rate(struct clk_hw *hw,
|
|||||||
return dummy->rrate;
|
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 = {
|
const struct clk_ops clk_dummy_ops = {
|
||||||
.set_rate = dummy_clk_set_rate,
|
.set_rate = dummy_clk_set_rate,
|
||||||
.round_rate = dummy_clk_round_rate,
|
.round_rate = dummy_clk_round_rate,
|
||||||
.recalc_rate = dummy_clk_recalc_rate,
|
.recalc_rate = dummy_clk_recalc_rate,
|
||||||
|
.set_flags = dummy_clk_set_flags,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(clk_dummy_ops);
|
EXPORT_SYMBOL(clk_dummy_ops);
|
||||||
|
|
||||||
|
|||||||
@@ -202,6 +202,8 @@ struct clk_duty {
|
|||||||
* directory is provided as an argument. Called with
|
* directory is provided as an argument. Called with
|
||||||
* prepare_lock held. Returns 0 on success, -EERROR otherwise.
|
* 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
|
* The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
|
||||||
* implementations to split any work between atomic (enable) and sleepable
|
* implementations to split any work between atomic (enable) and sleepable
|
||||||
@@ -246,6 +248,7 @@ struct clk_ops {
|
|||||||
struct clk_duty *duty);
|
struct clk_duty *duty);
|
||||||
void (*init)(struct clk_hw *hw);
|
void (*init)(struct clk_hw *hw);
|
||||||
void (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
|
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);
|
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 */
|
#else /* !CONFIG_HAVE_CLK */
|
||||||
|
|
||||||
static inline struct clk *clk_get(struct device *dev, const char *id)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int clk_set_flags(struct clk *clk, unsigned long flags)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
|
/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
|
||||||
|
|||||||
Reference in New Issue
Block a user