Commit 74b48999 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-qcom-alpha-pll', 'clk-check-ops-ptr', 'clk-protect-rate'...

Merge branches 'clk-qcom-alpha-pll', 'clk-check-ops-ptr', 'clk-protect-rate' and 'clk-omap' into clk-next

* clk-qcom-alpha-pll:
  clk: qcom: add read-only alpha pll post divider operations
  clk: qcom: support for 2 bit PLL post divider
  clk: qcom: support Brammo type Alpha PLL
  clk: qcom: support Huayra type Alpha PLL
  clk: qcom: support for dynamic updating the PLL
  clk: qcom: support for alpha mode configuration
  clk: qcom: flag for 64 bit CONFIG_CTL
  clk: qcom: fix 16 bit alpha support calculation
  clk: qcom: support for alpha pll properties

* clk-check-ops-ptr:
  clk: check ops pointer on clock register

* clk-protect-rate:
  clk: fix set_rate_range when current rate is out of range
  clk: add clk_rate_exclusive api
  clk: cosmetic changes to clk_summary debugfs entry
  clk: add clock protection mechanism to clk core
  clk: use round rate to bail out early in set_rate
  clk: rework calls to round and determine rate callbacks
  clk: add clk_core_set_phase_nolock function
  clk: take the prepare lock out of clk_core_set_parent
  clk: fix incorrect usage of ENOSYS

* clk-omap:
  clk: ti: Drop legacy clk-3xxx-legacy code
This diff is collapsed.
This diff is collapsed.
......@@ -17,6 +17,30 @@
#include <linux/clk-provider.h>
#include "clk-regmap.h"
/* Alpha PLL types */
enum {
CLK_ALPHA_PLL_TYPE_DEFAULT,
CLK_ALPHA_PLL_TYPE_HUAYRA,
CLK_ALPHA_PLL_TYPE_BRAMMO,
CLK_ALPHA_PLL_TYPE_MAX,
};
enum {
PLL_OFF_L_VAL,
PLL_OFF_ALPHA_VAL,
PLL_OFF_ALPHA_VAL_U,
PLL_OFF_USER_CTL,
PLL_OFF_USER_CTL_U,
PLL_OFF_CONFIG_CTL,
PLL_OFF_CONFIG_CTL_U,
PLL_OFF_TEST_CTL,
PLL_OFF_TEST_CTL_U,
PLL_OFF_STATUS,
PLL_OFF_MAX_REGS
};
extern const u8 clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_MAX][PLL_OFF_MAX_REGS];
struct pll_vco {
unsigned long min_freq;
unsigned long max_freq;
......@@ -27,16 +51,18 @@ struct pll_vco {
* struct clk_alpha_pll - phase locked loop (PLL)
* @offset: base address of registers
* @vco_table: array of VCO settings
* @regs: alpha pll register map (see @clk_alpha_pll_regs)
* @clkr: regmap clock handle
*/
struct clk_alpha_pll {
u32 offset;
const u8 *regs;
const struct pll_vco *vco_table;
size_t num_vco;
#define SUPPORTS_OFFLINE_REQ BIT(0)
#define SUPPORTS_16BIT_ALPHA BIT(1)
#define SUPPORTS_FSM_MODE BIT(2)
#define SUPPORTS_DYNAMIC_UPDATE BIT(3)
u8 flags;
struct clk_regmap clkr;
......@@ -45,12 +71,14 @@ struct clk_alpha_pll {
/**
* struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
* @offset: base address of registers
* @regs: alpha pll register map (see @clk_alpha_pll_regs)
* @width: width of post-divider
* @clkr: regmap clock handle
*/
struct clk_alpha_pll_postdiv {
u32 offset;
u8 width;
const u8 *regs;
struct clk_regmap clkr;
};
......@@ -58,12 +86,15 @@ struct clk_alpha_pll_postdiv {
struct alpha_pll_config {
u32 l;
u32 alpha;
u32 alpha_hi;
u32 config_ctl_val;
u32 config_ctl_hi_val;
u32 main_output_mask;
u32 aux_output_mask;
u32 aux2_output_mask;
u32 early_output_mask;
u32 alpha_en_mask;
u32 alpha_mode_mask;
u32 pre_div_val;
u32 pre_div_mask;
u32 post_div_val;
......@@ -75,6 +106,8 @@ struct alpha_pll_config {
extern const struct clk_ops clk_alpha_pll_ops;
extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_ops;
extern const struct clk_ops clk_alpha_pll_huayra_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_ro_ops;
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
......
......@@ -52,6 +52,7 @@ static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = {
static struct clk_alpha_pll gpll0_main = {
.offset = 0x21000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x0b000,
.enable_mask = BIT(0),
......@@ -82,6 +83,7 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
static struct clk_alpha_pll_postdiv gpll0 = {
.offset = 0x21000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll0",
.parent_names = (const char *[]){
......
......@@ -73,6 +73,7 @@ static struct clk_fixed_factor xo = {
static struct clk_alpha_pll gpll0_early = {
.offset = 0x00000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x1480,
.enable_mask = BIT(0),
......@@ -88,6 +89,7 @@ static struct clk_alpha_pll gpll0_early = {
static struct clk_alpha_pll_postdiv gpll0 = {
.offset = 0x00000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data)
{
.name = "gpll0",
......@@ -99,6 +101,7 @@ static struct clk_alpha_pll_postdiv gpll0 = {
static struct clk_alpha_pll gpll4_early = {
.offset = 0x1dc0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x1480,
.enable_mask = BIT(4),
......@@ -114,6 +117,7 @@ static struct clk_alpha_pll gpll4_early = {
static struct clk_alpha_pll_postdiv gpll4 = {
.offset = 0x1dc0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data)
{
.name = "gpll4",
......
......@@ -227,6 +227,7 @@ static struct clk_fixed_factor xo = {
static struct clk_alpha_pll gpll0_early = {
.offset = 0x00000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x52000,
.enable_mask = BIT(0),
......@@ -252,6 +253,7 @@ static struct clk_fixed_factor gpll0_early_div = {
static struct clk_alpha_pll_postdiv gpll0 = {
.offset = 0x00000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll0",
.parent_names = (const char *[]){ "gpll0_early" },
......@@ -262,6 +264,7 @@ static struct clk_alpha_pll_postdiv gpll0 = {
static struct clk_alpha_pll gpll4_early = {
.offset = 0x77000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x52000,
.enable_mask = BIT(4),
......@@ -276,6 +279,7 @@ static struct clk_alpha_pll gpll4_early = {
static struct clk_alpha_pll_postdiv gpll4 = {
.offset = 0x77000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll4",
.parent_names = (const char *[]){ "gpll4_early" },
......
......@@ -267,6 +267,7 @@ static struct pll_vco mmpll_t_vco[] = {
static struct clk_alpha_pll mmpll0_early = {
.offset = 0x0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr = {
......@@ -283,6 +284,7 @@ static struct clk_alpha_pll mmpll0_early = {
static struct clk_alpha_pll_postdiv mmpll0 = {
.offset = 0x0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll0",
......@@ -295,6 +297,7 @@ static struct clk_alpha_pll_postdiv mmpll0 = {
static struct clk_alpha_pll mmpll1_early = {
.offset = 0x30,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr = {
......@@ -311,6 +314,7 @@ static struct clk_alpha_pll mmpll1_early = {
static struct clk_alpha_pll_postdiv mmpll1 = {
.offset = 0x30,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll1",
......@@ -323,6 +327,7 @@ static struct clk_alpha_pll_postdiv mmpll1 = {
static struct clk_alpha_pll mmpll2_early = {
.offset = 0x4100,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_gfx_vco,
.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
.clkr.hw.init = &(struct clk_init_data){
......@@ -335,6 +340,7 @@ static struct clk_alpha_pll mmpll2_early = {
static struct clk_alpha_pll_postdiv mmpll2 = {
.offset = 0x4100,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll2",
......@@ -347,6 +353,7 @@ static struct clk_alpha_pll_postdiv mmpll2 = {
static struct clk_alpha_pll mmpll3_early = {
.offset = 0x60,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr.hw.init = &(struct clk_init_data){
......@@ -359,6 +366,7 @@ static struct clk_alpha_pll mmpll3_early = {
static struct clk_alpha_pll_postdiv mmpll3 = {
.offset = 0x60,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll3",
......@@ -371,6 +379,7 @@ static struct clk_alpha_pll_postdiv mmpll3 = {
static struct clk_alpha_pll mmpll4_early = {
.offset = 0x90,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_t_vco,
.num_vco = ARRAY_SIZE(mmpll_t_vco),
.clkr.hw.init = &(struct clk_init_data){
......@@ -383,6 +392,7 @@ static struct clk_alpha_pll mmpll4_early = {
static struct clk_alpha_pll_postdiv mmpll4 = {
.offset = 0x90,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 2,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll4",
......@@ -395,6 +405,7 @@ static struct clk_alpha_pll_postdiv mmpll4 = {
static struct clk_alpha_pll mmpll5_early = {
.offset = 0xc0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr.hw.init = &(struct clk_init_data){
......@@ -407,6 +418,7 @@ static struct clk_alpha_pll mmpll5_early = {
static struct clk_alpha_pll_postdiv mmpll5 = {
.offset = 0xc0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll5",
......@@ -419,6 +431,7 @@ static struct clk_alpha_pll_postdiv mmpll5 = {
static struct clk_alpha_pll mmpll8_early = {
.offset = 0x4130,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_gfx_vco,
.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
.clkr.hw.init = &(struct clk_init_data){
......@@ -431,6 +444,7 @@ static struct clk_alpha_pll mmpll8_early = {
static struct clk_alpha_pll_postdiv mmpll8 = {
.offset = 0x4130,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll8",
......@@ -443,6 +457,7 @@ static struct clk_alpha_pll_postdiv mmpll8 = {
static struct clk_alpha_pll mmpll9_early = {
.offset = 0x4200,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_t_vco,
.num_vco = ARRAY_SIZE(mmpll_t_vco),
.clkr.hw.init = &(struct clk_init_data){
......@@ -455,6 +470,7 @@ static struct clk_alpha_pll mmpll9_early = {
static struct clk_alpha_pll_postdiv mmpll9 = {
.offset = 0x4200,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 2,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll9",
......
......@@ -19,10 +19,6 @@ obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \
clk-dra7-atl.o dpll3xxx.o dpll44xx.o
obj-$(CONFIG_SOC_AM43XX) += $(clk-common) dpll3xxx.o clk-43xx.o
ifdef CONFIG_ATAGS
obj-$(CONFIG_ARCH_OMAP3) += clk-3xxx-legacy.o
endif
endif # CONFIG_ARCH_OMAP2PLUS
obj-$(CONFIG_COMMON_CLK_TI_ADPLL) += adpll.o
This diff is collapsed.
......@@ -336,141 +336,6 @@ void ti_dt_clk_init_retry_clks(void)
}
}
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
void __init ti_clk_patch_legacy_clks(struct ti_clk **patch)
{
while (*patch) {
memcpy((*patch)->patch, *patch, sizeof(**patch));
patch++;
}
}
struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
{
struct clk *clk;
struct ti_clk_fixed *fixed;
struct ti_clk_fixed_factor *fixed_factor;
struct clk_hw *clk_hw;
int ret;
if (setup->clk)
return setup->clk;
switch (setup->type) {
case TI_CLK_FIXED:
fixed = setup->data;
clk = clk_register_fixed_rate(NULL, setup->name, NULL, 0,
fixed->frequency);
if (!IS_ERR(clk)) {
ret = ti_clk_add_alias(NULL, clk, setup->name);
if (ret) {
clk_unregister(clk);
clk = ERR_PTR(ret);
}
}
break;
case TI_CLK_MUX:
clk = ti_clk_register_mux(setup);
break;
case TI_CLK_DIVIDER:
clk = ti_clk_register_divider(setup);
break;
case TI_CLK_COMPOSITE:
clk = ti_clk_register_composite(setup);
break;
case TI_CLK_FIXED_FACTOR:
fixed_factor = setup->data;
clk = clk_register_fixed_factor(NULL, setup->name,
fixed_factor->parent,
0, fixed_factor->mult,
fixed_factor->div);
if (!IS_ERR(clk)) {
ret = ti_clk_add_alias(NULL, clk, setup->name);
if (ret) {
clk_unregister(clk);
clk = ERR_PTR(ret);
}
}
break;
case TI_CLK_GATE:
clk = ti_clk_register_gate(setup);
break;
case TI_CLK_DPLL:
clk = ti_clk_register_dpll(setup);
break;
default:
pr_err("bad type for %s!\n", setup->name);
clk = ERR_PTR(-EINVAL);
}
if (!IS_ERR(clk)) {
setup->clk = clk;
if (setup->clkdm_name) {
clk_hw = __clk_get_hw(clk);
if (clk_hw_get_flags(clk_hw) & CLK_IS_BASIC) {
pr_warn("can't setup clkdm for basic clk %s\n",
setup->name);
} else {
to_clk_hw_omap(clk_hw)->clkdm_name =
setup->clkdm_name;
omap2_init_clk_clkdm(clk_hw);
}
}
}
return clk;
}
int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
{
struct clk *clk;
bool retry;
struct ti_clk_alias *retry_clk;
struct ti_clk_alias *tmp;
while (clks->clk) {
clk = ti_clk_register_clk(clks->clk);
if (IS_ERR(clk)) {
if (PTR_ERR(clk) == -EAGAIN) {
list_add(&clks->link, &retry_list);
} else {
pr_err("register for %s failed: %ld\n",
clks->clk->name, PTR_ERR(clk));
return PTR_ERR(clk);
}
}
clks++;
}
retry = true;
while (!list_empty(&retry_list) && retry) {
retry = false;
list_for_each_entry_safe(retry_clk, tmp, &retry_list, link) {
pr_debug("retry-init: %s\n", retry_clk->clk->name);
clk = ti_clk_register_clk(retry_clk->clk);
if (IS_ERR(clk)) {
if (PTR_ERR(clk) == -EAGAIN) {
continue;
} else {
pr_err("register for %s failed: %ld\n",
retry_clk->clk->name,
PTR_ERR(clk));
return PTR_ERR(clk);
}
} else {
retry = true;
list_del(&retry_clk->link);
}
}
}
return 0;
}
#endif
static const struct of_device_id simple_clk_match_table[] __initconst = {
{ .compatible = "fixed-clock" },
{ .compatible = "fixed-factor-clock" },
......
......@@ -92,17 +92,6 @@ struct ti_clk {
struct clk *clk;
};
struct ti_clk_alias {
struct ti_clk *clk;
struct clk_lookup lk;
struct list_head link;
};
struct ti_clk_fixed {
u32 frequency;
u16 flags;
};
struct ti_clk_mux {
u8 bit_shift;
int num_parents;
......@@ -123,13 +112,6 @@ struct ti_clk_divider {
u16 flags;
};
struct ti_clk_fixed_factor {
const char *parent;
u16 div;
u16 mult;
u16 flags;
};
struct ti_clk_gate {
const char *parent;
u8 bit_shift;
......@@ -138,44 +120,6 @@ struct ti_clk_gate {
u16 flags;
};
struct ti_clk_composite {
struct ti_clk_divider *divider;
struct ti_clk_mux *mux;
struct ti_clk_gate *gate;
u16 flags;
};
struct ti_clk_clkdm_gate {
const char *parent;
u16 flags;
};
struct ti_clk_dpll {
int num_parents;
u16 control_reg;
u16 idlest_reg;
u16 autoidle_reg;
u16 mult_div1_reg;
u8 module;
const char **parents;
u16 flags;
u8 modes;
u32 mult_mask;
u32 div1_mask;
u32 enable_mask;
u32 autoidle_mask;
u32 freqsel_mask;
u32 idlest_mask;
u32 dco_mask;
u32 sddiv_mask;
u16 max_multiplier;
u16 max_divider;
u8 min_divider;
u8 auto_recal_bit;
u8 recal_en_bit;
u8 recal_st_bit;
};
/* Composite clock component types */
enum {
CLK_COMPONENT_TYPE_GATE = 0,
......@@ -245,29 +189,17 @@ extern const struct omap_clkctrl_data dm816_clkctrl_data[];
typedef void (*ti_of_clk_init_cb_t)(void *, struct device_node *);
struct clk *ti_clk_register_gate(struct ti_clk *setup);
struct clk *ti_clk_register_interface(struct ti_clk *setup);
struct clk *ti_clk_register_mux(struct ti_clk *setup);
struct clk *ti_clk_register_divider(struct ti_clk *setup);
struct clk *ti_clk_register_composite(struct ti_clk *setup);
struct clk *ti_clk_register_dpll(struct ti_clk *setup);
struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
const char *con);
int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
void ti_clk_add_aliases(void);
struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup);
struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup);
struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
u8 flags, u8 *width,
const struct clk_div_table **table);
void ti_clk_patch_legacy_clks(struct ti_clk **patch);
struct clk *ti_clk_register_clk(struct ti_clk *setup);
int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
int ti_clk_get_reg_addr(struct device_node *node, int index,
struct clk_omap_reg *reg);
void ti_dt_clocks_register(struct ti_dt_clk *oclks);
......
......@@ -116,51 +116,6 @@ static inline struct clk_hw *_get_hw(struct clk_hw_omap_comp *clk, int idx)
#define to_clk_hw_comp(_hw) container_of(_hw, struct clk_hw_omap_comp, hw)
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
struct clk *ti_clk_register_composite(struct ti_clk *setup)
{
struct ti_clk_composite *comp;
struct clk_hw *gate;
struct clk_hw *mux;
struct clk_hw *div;
int num_parents = 1;
const char * const *parent_names = NULL;
struct clk *clk;
int ret;
comp = setup->data;
div = ti_clk_build_component_div(comp->divider);
gate = ti_clk_build_component_gate(comp->gate);
mux = ti_clk_build_component_mux(comp->mux);
if (div)
parent_names = &comp->divider->parent;
if (gate)
parent_names = &comp->gate->parent;
if (mux) {
num_parents = comp->mux->num_parents;
parent_names = comp->mux->parents;
}
clk = clk_register_composite(NULL, setup->name,
parent_names, num_parents, mux,
&ti_clk_mux_ops, div,
&ti_composite_divider_ops, gate,
&ti_composite_gate_ops, 0);
ret = ti_clk_add_alias(NULL, clk, setup->name);
if (ret) {
clk_unregister(clk);
return ERR_PTR(ret);
}
return clk;
}
#endif
static void __init _register_composite(void *user,
struct device_node *node)
{
......
......@@ -203,96 +203,6 @@ static void __init _register_dpll(void *user,
kfree(clk_hw);
}
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
void _get_reg(u8 module, u16 offset, struct clk_omap_reg *reg)
{
reg->index = module;
reg->offset = offset;
}
struct clk *ti_clk_register_dpll(struct ti_clk *setup)
{
struct clk_hw_omap *clk_hw;
struct clk_init_data init = { NULL };
struct dpll_data *dd;
struct clk *clk;
struct ti_clk_dpll *dpll;
const struct clk_ops *ops = &omap3_dpll_ck_ops;
struct clk *clk_ref;
struct clk *clk_bypass;
dpll = setup->data;
if (dpll->num_parents < 2)
return ERR_PTR(-EINVAL);
clk_ref = clk_get_sys(NULL, dpll->parents[0]);
clk_bypass = clk_get_sys(NULL, dpll->parents[1]);
if (IS_ERR_OR_NULL(clk_ref) || IS_ERR_OR_NULL(clk_bypass))
return ERR_PTR(-EAGAIN);
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
if (!dd || !clk_hw) {
clk = ERR_PTR(-ENOMEM);
goto cleanup;
}
clk_hw->dpll_data = dd;
clk_hw->ops = &clkhwops_omap3_dpll;
clk_hw->hw.init = &init;
init.name = setup->name;
init.ops = ops;
init.num_parents = dpll->num_parents;
init.parent_names = dpll->parents;
_get_reg(dpll->module, dpll->control_reg, &dd->control_reg);
_get_reg(dpll->module, dpll->idlest_reg, &dd->idlest_reg);
_get_reg(dpll->module, dpll->mult_div1_reg, &dd->mult_div1_reg);
_get_reg(dpll->module, dpll->autoidle_reg, &dd->autoidle_reg);
dd->modes = dpll->modes;
dd->div1_mask = dpll->div1_mask;
dd->idlest_mask = dpll->idlest_mask;
dd->mult_mask = dpll->mult_mask;
dd->autoidle_mask = dpll->autoidle_mask;
dd->enable_mask = dpll->enable_mask;
dd->sddiv_mask = dpll->sddiv_mask;
dd->dco_mask = dpll->dco_mask;
dd->max_divider = dpll->max_divider;
dd->min_divider = dpll->min_divider;
dd->max_multiplier = dpll->max_multiplier;
dd->auto_recal_bit = dpll->auto_recal_bit;
dd->recal_en_bit = dpll->recal_en_bit;
dd->recal_st_bit = dpll->recal_st_bit;
dd->clk_ref = __clk_get_hw(clk_ref);
dd->clk_bypass = __clk_get_hw(clk_bypass);
if (dpll->flags & CLKF_CORE)
ops = &omap3_dpll_core_ck_ops;
if (dpll->flags & CLKF_PER)
ops = &omap3_dpll_per_ck_ops;
if (dpll->flags & CLKF_J_TYPE)
dd->flags |= DPLL_J_TYPE;
clk = ti_clk_register(NULL, &clk_hw->hw, setup->name);
if (!IS_ERR(clk))
return clk;
cleanup:
kfree(dd);
kfree(clk_hw);
return clk;
}
#endif
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX) || \
defined(CONFIG_SOC_AM43XX)
......
......@@ -128,53 +128,6 @@ static struct clk *_register_gate(struct device *dev, const char *name,
return clk;
}
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
struct clk *ti_clk_register_gate(struct ti_clk *setup)
{
const struct clk_ops *ops = &omap_gate_clk_ops;
const struct clk_hw_omap_ops *hw_ops = NULL;
struct clk_omap_reg reg;
u32 flags = 0;
u8 clk_gate_flags = 0;
struct ti_clk_gate *gate;
gate = setup->data;
if (gate->flags & CLKF_INTERFACE)
return ti_clk_register_interface(setup);
if (gate->flags & CLKF_SET_RATE_PARENT)
flags |= CLK_SET_RATE_PARENT;
if (gate->flags & CLKF_SET_BIT_TO_DISABLE)
clk_gate_flags |= INVERT_ENABLE;
if (gate->flags & CLKF_HSDIV) {
ops = &omap_gate_clk_hsdiv_restore_ops;
hw_ops = &clkhwops_wait;
}
if (gate->flags & CLKF_DSS)
hw_ops = &clkhwops_omap3430es2_dss_usbhost_wait;
if (gate->flags & CLKF_WAIT)
hw_ops = &clkhwops_wait;
if (gate->flags & CLKF_CLKDM)
ops = &omap_gate_clkdm_clk_ops;
if (gate->flags & CLKF_AM35XX)
hw_ops = &clkhwops_am35xx_ipss_module_wait;
reg.index = gate->module;
reg.offset = gate->reg;
reg.ptr = NULL;
return _register_gate(NULL, setup->name, gate->parent, flags,
&reg, gate->bit_shift,
clk_gate_flags, ops, hw_ops);
}
struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup)
{
struct clk_hw_omap *gate;
......@@ -204,7 +157,6 @@ struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup)
return &gate->hw;
}
#endif
static void __init _of_ti_gate_clk_setup(struct device_node *node,
const struct clk_ops *ops,
......
......@@ -67,38 +67,6 @@ static struct clk *_register_interface(struct device *dev, const char *name,
return clk;
}
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
struct clk *ti_clk_register_interface(struct ti_clk *setup)
{
const struct clk_hw_omap_ops *ops = &clkhwops_iclk_wait;
struct clk_omap_reg reg;
struct ti_clk_gate *gate;
gate = setup->data;
reg.index = gate->module;
reg.offset = gate->reg;
reg.ptr = NULL;
if (gate->flags & CLKF_NO_WAIT)
ops = &clkhwops_iclk;
if (gate->flags & CLKF_HSOTGUSB)
ops = &clkhwops_omap3430es2_iclk_hsotgusb_wait;
if (gate->flags & CLKF_DSS)
ops = &clkhwops_omap3430es2_iclk_dss_usbhost_wait;
if (gate->flags & CLKF_SSI)
ops = &clkhwops_omap3430es2_iclk_ssi_wait;
if (gate->flags & CLKF_AM35XX)
ops = &clkhwops_am35xx_ipss_wait;
return _register_interface(NULL, setup->name, gate->parent,
&reg, gate->bit_shift, ops);
}
#endif
static void __init _of_ti_interface_clk_setup(struct device_node *node,
const struct clk_hw_omap_ops *ops)
{
......
......@@ -744,6 +744,7 @@ unsigned long clk_hw_get_rate(const struct clk_hw *hw);
unsigned long __clk_get_flags(struct clk *clk);
unsigned long clk_hw_get_flags(const struct clk_hw *hw);
bool clk_hw_is_prepared(const struct clk_hw *hw);
bool clk_hw_rate_is_protected(const struct clk_hw *hw);
bool clk_hw_is_enabled(const struct clk_hw *hw);
bool __clk_is_enabled(struct clk *clk);
struct clk *__clk_lookup(const char *name);
......
......@@ -331,6 +331,38 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
*/
struct clk *devm_get_clk_from_child(struct device *dev,
struct device_node *np, const char *con_id);
/**
* clk_rate_exclusive_get - get exclusivity over the rate control of a
* producer
* @clk: clock source
*
* This function allows drivers to get exclusive control over the rate of a
* provider. It prevents any other consumer to execute, even indirectly,
* opereation which could alter the rate of the provider or cause glitches
*
* If exlusivity is claimed more than once on clock, even by the same driver,
* the rate effectively gets locked as exclusivity can't be preempted.
*
* Must not be called from within atomic context.
*
* Returns success (0) or negative errno.
*/
int clk_rate_exclusive_get(struct clk *clk);
/**
* clk_rate_exclusive_put - release exclusivity over the rate control of a
* producer
* @clk: clock source
*
* This function allows drivers to release the exclusivity it previously got
* from clk_rate_exclusive_get()
*
* The caller must balance the number of clk_rate_exclusive_get() and
* clk_rate_exclusive_put() calls.
*
* Must not be called from within atomic context.
*/
void clk_rate_exclusive_put(struct clk *clk);
/**
* clk_enable - inform the system when the clock source should be running.
......@@ -472,6 +504,23 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
*/
int clk_set_rate(struct clk *clk, unsigned long rate);
/**
* clk_set_rate_exclusive- set the clock rate and claim exclusivity over
* clock source
* @clk: clock source
* @rate: desired clock rate in Hz
*
* This helper function allows drivers to atomically set the rate of a producer
* and claim exclusivity over the rate control of the producer.
*
* It is essentially a combination of clk_set_rate() and
* clk_rate_exclusite_get(). Caller must balance this call with a call to
* clk_rate_exclusive_put()
*
* Returns success (0) or negative errno.
*/
int clk_set_rate_exclusive(struct clk *clk, unsigned long rate);
/**
* clk_has_parent - check if a clock is a possible parent for another
* @clk: clock source
......@@ -583,6 +632,14 @@ static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
static inline int clk_rate_exclusive_get(struct clk *clk)
{
return 0;
}
static inline void clk_rate_exclusive_put(struct clk *clk) {}
static inline int clk_enable(struct clk *clk)
{
return 0;
......@@ -609,6 +666,11 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
return 0;
}
static inline int clk_set_rate_exclusive(struct clk *clk, unsigned long rate)
{
return 0;
}
static inline long clk_round_rate(struct clk *clk, unsigned long rate)
{
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment