251 lines
6.3 KiB
C
251 lines
6.3 KiB
C
|
/*
|
||
|
* Copyright (c) 2014 MundoReader S.L.
|
||
|
* Author: Heiko Stuebner <heiko@sntech.de>
|
||
|
*
|
||
|
* based on
|
||
|
*
|
||
|
* samsung/clk.h
|
||
|
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||
|
* Copyright (c) 2013 Linaro Ltd.
|
||
|
* Author: Thomas Abraham <thomas.ab@samsung.com>
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*/
|
||
|
|
||
|
#ifndef CLK_ROCKCHIP_CLK_H
|
||
|
#define CLK_ROCKCHIP_CLK_H
|
||
|
|
||
|
#include <linux/io.h>
|
||
|
#include <linux/clk.h>
|
||
|
#include <linux/clk-provider.h>
|
||
|
|
||
|
#define HIWORD_UPDATE(val, mask, shift) \
|
||
|
((val) << (shift) | (mask) << ((shift) + 16))
|
||
|
|
||
|
/* register positions shared by RK2928, RK3066 and RK3188 */
|
||
|
#define RK2928_PLL_CON(x) (x * 0x4)
|
||
|
#define RK2928_MODE_CON 0x40
|
||
|
#define RK2928_CLKSEL_CON(x) (x * 0x4 + 0x44)
|
||
|
#define RK2928_CLKGATE_CON(x) (x * 0x4 + 0xd0)
|
||
|
#define RK2928_GLB_SRST_FST 0x100
|
||
|
#define RK2928_GLB_SRST_SND 0x104
|
||
|
#define RK2928_SOFTRST_CON(x) (x * 0x4 + 0x110)
|
||
|
#define RK2928_MISC_CON 0x134
|
||
|
|
||
|
#define PNAME(x) static const char *x[] __initconst
|
||
|
|
||
|
enum rockchip_clk_branch_type {
|
||
|
branch_composite,
|
||
|
branch_mux,
|
||
|
branch_divider,
|
||
|
branch_fraction_divider,
|
||
|
branch_gate,
|
||
|
};
|
||
|
|
||
|
struct rockchip_clk_branch {
|
||
|
unsigned int id;
|
||
|
enum rockchip_clk_branch_type branch_type;
|
||
|
const char *name;
|
||
|
const char **parent_names;
|
||
|
u8 num_parents;
|
||
|
unsigned long flags;
|
||
|
int muxdiv_offset;
|
||
|
u8 mux_shift;
|
||
|
u8 mux_width;
|
||
|
u8 mux_flags;
|
||
|
u8 div_shift;
|
||
|
u8 div_width;
|
||
|
u8 div_flags;
|
||
|
struct clk_div_table *div_table;
|
||
|
int gate_offset;
|
||
|
u8 gate_shift;
|
||
|
u8 gate_flags;
|
||
|
};
|
||
|
|
||
|
#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
|
||
|
df, go, gs, gf) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_composite, \
|
||
|
.name = cname, \
|
||
|
.parent_names = pnames, \
|
||
|
.num_parents = ARRAY_SIZE(pnames), \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = mo, \
|
||
|
.mux_shift = ms, \
|
||
|
.mux_width = mw, \
|
||
|
.mux_flags = mf, \
|
||
|
.div_shift = ds, \
|
||
|
.div_width = dw, \
|
||
|
.div_flags = df, \
|
||
|
.gate_offset = go, \
|
||
|
.gate_shift = gs, \
|
||
|
.gate_flags = gf, \
|
||
|
}
|
||
|
|
||
|
#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
|
||
|
go, gs, gf) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_composite, \
|
||
|
.name = cname, \
|
||
|
.parent_names = (const char *[]){ pname }, \
|
||
|
.num_parents = 1, \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = mo, \
|
||
|
.div_shift = ds, \
|
||
|
.div_width = dw, \
|
||
|
.div_flags = df, \
|
||
|
.gate_offset = go, \
|
||
|
.gate_shift = gs, \
|
||
|
.gate_flags = gf, \
|
||
|
}
|
||
|
|
||
|
#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
|
||
|
df, dt, go, gs, gf) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_composite, \
|
||
|
.name = cname, \
|
||
|
.parent_names = (const char *[]){ pname }, \
|
||
|
.num_parents = 1, \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = mo, \
|
||
|
.div_shift = ds, \
|
||
|
.div_width = dw, \
|
||
|
.div_flags = df, \
|
||
|
.div_table = dt, \
|
||
|
.gate_offset = go, \
|
||
|
.gate_shift = gs, \
|
||
|
.gate_flags = gf, \
|
||
|
}
|
||
|
|
||
|
#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \
|
||
|
go, gs, gf) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_composite, \
|
||
|
.name = cname, \
|
||
|
.parent_names = pnames, \
|
||
|
.num_parents = ARRAY_SIZE(pnames), \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = mo, \
|
||
|
.mux_shift = ms, \
|
||
|
.mux_width = mw, \
|
||
|
.mux_flags = mf, \
|
||
|
.gate_offset = go, \
|
||
|
.gate_shift = gs, \
|
||
|
.gate_flags = gf, \
|
||
|
}
|
||
|
|
||
|
#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
|
||
|
ds, dw, df) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_composite, \
|
||
|
.name = cname, \
|
||
|
.parent_names = pnames, \
|
||
|
.num_parents = ARRAY_SIZE(pnames), \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = mo, \
|
||
|
.mux_shift = ms, \
|
||
|
.mux_width = mw, \
|
||
|
.mux_flags = mf, \
|
||
|
.div_shift = ds, \
|
||
|
.div_width = dw, \
|
||
|
.div_flags = df, \
|
||
|
.gate_offset = -1, \
|
||
|
}
|
||
|
|
||
|
#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_fraction_divider, \
|
||
|
.name = cname, \
|
||
|
.parent_names = (const char *[]){ pname }, \
|
||
|
.num_parents = 1, \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = mo, \
|
||
|
.div_shift = 16, \
|
||
|
.div_width = 16, \
|
||
|
.div_flags = df, \
|
||
|
.gate_offset = go, \
|
||
|
.gate_shift = gs, \
|
||
|
.gate_flags = gf, \
|
||
|
}
|
||
|
|
||
|
#define MUX(_id, cname, pnames, f, o, s, w, mf) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_mux, \
|
||
|
.name = cname, \
|
||
|
.parent_names = pnames, \
|
||
|
.num_parents = ARRAY_SIZE(pnames), \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = o, \
|
||
|
.mux_shift = s, \
|
||
|
.mux_width = w, \
|
||
|
.mux_flags = mf, \
|
||
|
.gate_offset = -1, \
|
||
|
}
|
||
|
|
||
|
#define DIV(_id, cname, pname, f, o, s, w, df) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_divider, \
|
||
|
.name = cname, \
|
||
|
.parent_names = (const char *[]){ pname }, \
|
||
|
.num_parents = 1, \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = o, \
|
||
|
.div_shift = s, \
|
||
|
.div_width = w, \
|
||
|
.div_flags = df, \
|
||
|
.gate_offset = -1, \
|
||
|
}
|
||
|
|
||
|
#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_divider, \
|
||
|
.name = cname, \
|
||
|
.parent_names = (const char *[]){ pname }, \
|
||
|
.num_parents = 1, \
|
||
|
.flags = f, \
|
||
|
.muxdiv_offset = o, \
|
||
|
.div_shift = s, \
|
||
|
.div_width = w, \
|
||
|
.div_flags = df, \
|
||
|
.div_table = dt, \
|
||
|
}
|
||
|
|
||
|
#define GATE(_id, cname, pname, f, o, b, gf) \
|
||
|
{ \
|
||
|
.id = _id, \
|
||
|
.branch_type = branch_gate, \
|
||
|
.name = cname, \
|
||
|
.parent_names = (const char *[]){ pname }, \
|
||
|
.num_parents = 1, \
|
||
|
.flags = f, \
|
||
|
.gate_offset = o, \
|
||
|
.gate_shift = b, \
|
||
|
.gate_flags = gf, \
|
||
|
}
|
||
|
|
||
|
|
||
|
void rockchip_clk_init(struct device_node *np, void __iomem *base,
|
||
|
unsigned long nr_clks);
|
||
|
void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
|
||
|
void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
|
||
|
unsigned int nr_clk);
|
||
|
|
||
|
#endif
|