blob: 5b051b011c1806eb6d837ab7e3500a04a36472e4 [file] [log] [blame]
/*
* 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