mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
clk: mmp: add basic support functions for DT support
In order to support DT for mmp SOC clocks, it defines some basic APIs which are shared by all mmp SOC clock units. Signed-off-by: Chao Xie <chao.xie@marvell.com> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> Signed-off-by: Michael Turquette <mturquette@linaro.org>
This commit is contained in:
parent
cdce35460f
commit
4661fda10f
@ -2,7 +2,7 @@
|
||||
# Makefile for mmp specific clk
|
||||
#
|
||||
|
||||
obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
|
||||
obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
|
||||
|
||||
obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
|
||||
obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
|
||||
|
192
drivers/clk/mmp/clk.c
Normal file
192
drivers/clk/mmp/clk.c
Normal file
@ -0,0 +1,192 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
|
||||
int nr_clks)
|
||||
{
|
||||
static struct clk **clk_table;
|
||||
|
||||
clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
return;
|
||||
|
||||
unit->clk_table = clk_table;
|
||||
unit->nr_clks = nr_clks;
|
||||
unit->clk_data.clks = clk_table;
|
||||
unit->clk_data.clk_num = nr_clks;
|
||||
of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
|
||||
}
|
||||
|
||||
void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_fixed_rate_clk *clks,
|
||||
int size)
|
||||
{
|
||||
int i;
|
||||
struct clk *clk;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
clk = clk_register_fixed_rate(NULL, clks[i].name,
|
||||
clks[i].parent_name,
|
||||
clks[i].flags,
|
||||
clks[i].fixed_rate);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
if (clks[i].id)
|
||||
unit->clk_table[clks[i].id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_fixed_factor_clk *clks,
|
||||
int size)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
clk = clk_register_fixed_factor(NULL, clks[i].name,
|
||||
clks[i].parent_name,
|
||||
clks[i].flags, clks[i].mult,
|
||||
clks[i].div);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
if (clks[i].id)
|
||||
unit->clk_table[clks[i].id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_general_gate_clk *clks,
|
||||
void __iomem *base, int size)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
clk = clk_register_gate(NULL, clks[i].name,
|
||||
clks[i].parent_name,
|
||||
clks[i].flags,
|
||||
base + clks[i].offset,
|
||||
clks[i].bit_idx,
|
||||
clks[i].gate_flags,
|
||||
clks[i].lock);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
if (clks[i].id)
|
||||
unit->clk_table[clks[i].id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void mmp_register_gate_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_gate_clk *clks,
|
||||
void __iomem *base, int size)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
clk = mmp_clk_register_gate(NULL, clks[i].name,
|
||||
clks[i].parent_name,
|
||||
clks[i].flags,
|
||||
base + clks[i].offset,
|
||||
clks[i].mask,
|
||||
clks[i].val_enable,
|
||||
clks[i].val_disable,
|
||||
clks[i].gate_flags,
|
||||
clks[i].lock);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
if (clks[i].id)
|
||||
unit->clk_table[clks[i].id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void mmp_register_mux_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_mux_clk *clks,
|
||||
void __iomem *base, int size)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
clk = clk_register_mux(NULL, clks[i].name,
|
||||
clks[i].parent_name,
|
||||
clks[i].num_parents,
|
||||
clks[i].flags,
|
||||
base + clks[i].offset,
|
||||
clks[i].shift,
|
||||
clks[i].width,
|
||||
clks[i].mux_flags,
|
||||
clks[i].lock);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
if (clks[i].id)
|
||||
unit->clk_table[clks[i].id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void mmp_register_div_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_div_clk *clks,
|
||||
void __iomem *base, int size)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
clk = clk_register_divider(NULL, clks[i].name,
|
||||
clks[i].parent_name,
|
||||
clks[i].flags,
|
||||
base + clks[i].offset,
|
||||
clks[i].shift,
|
||||
clks[i].width,
|
||||
clks[i].div_flags,
|
||||
clks[i].lock);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
if (clks[i].id)
|
||||
unit->clk_table[clks[i].id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
|
||||
struct clk *clk)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(clk)) {
|
||||
pr_err("CLK %d has invalid pointer %p\n", id, clk);
|
||||
return;
|
||||
}
|
||||
if (id > unit->nr_clks) {
|
||||
pr_err("CLK %d is invalid\n", id);
|
||||
return;
|
||||
}
|
||||
|
||||
unit->clk_table[id] = clk;
|
||||
}
|
@ -96,8 +96,8 @@ struct mmp_clk_mix {
|
||||
extern const struct clk_ops mmp_clk_mix_ops;
|
||||
extern struct clk *mmp_clk_register_mix(struct device *dev,
|
||||
const char *name,
|
||||
u8 num_parents,
|
||||
const char **parent_names,
|
||||
u8 num_parents,
|
||||
unsigned long flags,
|
||||
struct mmp_clk_mix_config *config,
|
||||
spinlock_t *lock);
|
||||
@ -132,4 +132,108 @@ extern struct clk *mmp_clk_register_apbc(const char *name,
|
||||
extern struct clk *mmp_clk_register_apmu(const char *name,
|
||||
const char *parent_name, void __iomem *base, u32 enable_mask,
|
||||
spinlock_t *lock);
|
||||
|
||||
struct mmp_clk_unit {
|
||||
unsigned int nr_clks;
|
||||
struct clk **clk_table;
|
||||
struct clk_onecell_data clk_data;
|
||||
};
|
||||
|
||||
struct mmp_param_fixed_rate_clk {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long fixed_rate;
|
||||
};
|
||||
void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_fixed_rate_clk *clks,
|
||||
int size);
|
||||
|
||||
struct mmp_param_fixed_factor_clk {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
const char *parent_name;
|
||||
unsigned long mult;
|
||||
unsigned long div;
|
||||
unsigned long flags;
|
||||
};
|
||||
void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_fixed_factor_clk *clks,
|
||||
int size);
|
||||
|
||||
struct mmp_param_general_gate_clk {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u8 bit_idx;
|
||||
u8 gate_flags;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_general_gate_clk *clks,
|
||||
void __iomem *base, int size);
|
||||
|
||||
struct mmp_param_gate_clk {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u32 mask;
|
||||
u32 val_enable;
|
||||
u32 val_disable;
|
||||
unsigned int gate_flags;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
void mmp_register_gate_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_gate_clk *clks,
|
||||
void __iomem *base, int size);
|
||||
|
||||
struct mmp_param_mux_clk {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
const char **parent_name;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
u8 mux_flags;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
void mmp_register_mux_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_mux_clk *clks,
|
||||
void __iomem *base, int size);
|
||||
|
||||
struct mmp_param_div_clk {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
u8 div_flags;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
void mmp_register_div_clks(struct mmp_clk_unit *unit,
|
||||
struct mmp_param_div_clk *clks,
|
||||
void __iomem *base, int size);
|
||||
|
||||
#define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc) \
|
||||
{ \
|
||||
.width_div = (w_d), \
|
||||
.shift_div = (s_d), \
|
||||
.width_mux = (w_m), \
|
||||
.shift_mux = (s_m), \
|
||||
.bit_fc = (fc), \
|
||||
}
|
||||
|
||||
void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
|
||||
int nr_clks);
|
||||
void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
|
||||
struct clk *clk);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user