278 lines
6.5 KiB
C
278 lines
6.5 KiB
C
/*
|
|
* Copyright (c) 2017 Rockchip Electronics Co., Ltd.
|
|
*
|
|
* 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_REGMAP_H__
|
|
#define __CLK_REGMAP_H__
|
|
|
|
#include <linux/regmap.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/device.h>
|
|
#include <linux/delay.h>
|
|
|
|
#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
|
|
#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16))
|
|
|
|
struct clk_pll_data {
|
|
unsigned int id;
|
|
const char *name;
|
|
const char *parent_name;
|
|
u32 reg;
|
|
u8 pd_shift;
|
|
u8 dsmpd_shift;
|
|
u8 lock_shift;
|
|
unsigned long flags;
|
|
};
|
|
|
|
#define PLL(_id, _name, _parent_name, _reg, _pd_shift, _dsmpd_shift, \
|
|
_lock_shift, _flags) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = _name, \
|
|
.parent_name = _parent_name, \
|
|
.reg = _reg, \
|
|
.pd_shift = _pd_shift, \
|
|
.dsmpd_shift = _dsmpd_shift, \
|
|
.lock_shift = _lock_shift, \
|
|
.flags = _flags, \
|
|
}
|
|
|
|
#define RK618_PLL(_id, _name, _parent_name, _reg, _flags) \
|
|
PLL(_id, _name, _parent_name, _reg, 10, 9, 15, _flags)
|
|
|
|
struct clk_mux_data {
|
|
unsigned int id;
|
|
const char *name;
|
|
const char *const *parent_names;
|
|
u8 num_parents;
|
|
u32 reg;
|
|
u8 shift;
|
|
u8 width;
|
|
unsigned long flags;
|
|
};
|
|
|
|
#define MUX(_id, _name, _parent_names, _reg, _shift, _width, _flags) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = _name, \
|
|
.parent_names = _parent_names, \
|
|
.num_parents = ARRAY_SIZE(_parent_names), \
|
|
.reg = _reg, \
|
|
.shift = _shift, \
|
|
.width = _width, \
|
|
.flags = _flags, \
|
|
}
|
|
|
|
struct clk_gate_data {
|
|
unsigned int id;
|
|
const char *name;
|
|
const char *parent_name;
|
|
u32 reg;
|
|
u8 shift;
|
|
unsigned long flags;
|
|
};
|
|
|
|
#define GATE(_id, _name, _parent_name, _reg, _shift, _flags) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = _name, \
|
|
.parent_name = _parent_name, \
|
|
.reg = _reg, \
|
|
.shift = _shift, \
|
|
.flags = _flags, \
|
|
}
|
|
|
|
struct clk_divider_data {
|
|
unsigned int id;
|
|
const char *name;
|
|
const char *parent_name;
|
|
u32 reg;
|
|
u8 shift;
|
|
u8 width;
|
|
unsigned long flags;
|
|
};
|
|
|
|
#define DIV(_id, _name, _parent_name, _reg, _shift, _width, _flags) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = _name, \
|
|
.parent_name = _parent_name, \
|
|
.reg = _reg, \
|
|
.shift = _shift, \
|
|
.width = _width, \
|
|
.flags = _flags, \
|
|
}
|
|
|
|
struct clk_composite_data {
|
|
unsigned int id;
|
|
const char *name;
|
|
const char *const *parent_names;
|
|
u8 num_parents;
|
|
u32 mux_reg;
|
|
u8 mux_shift;
|
|
u8 mux_width;
|
|
u32 div_reg;
|
|
u8 div_shift;
|
|
u8 div_width;
|
|
u8 div_flags;
|
|
u32 gate_reg;
|
|
u8 gate_shift;
|
|
unsigned long flags;
|
|
};
|
|
|
|
#define COMPOSITE(_id, _name, _parent_names, \
|
|
_mux_reg, _mux_shift, _mux_width, \
|
|
_div_reg, _div_shift, _div_width, \
|
|
_gate_reg, _gate_shift, _flags) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = _name, \
|
|
.parent_names = _parent_names, \
|
|
.num_parents = ARRAY_SIZE(_parent_names), \
|
|
.mux_reg = _mux_reg, \
|
|
.mux_shift = _mux_shift, \
|
|
.mux_width = _mux_width, \
|
|
.div_reg = _div_reg, \
|
|
.div_shift = _div_shift, \
|
|
.div_width = _div_width, \
|
|
.div_flags = CLK_DIVIDER_HIWORD_MASK, \
|
|
.gate_reg = _gate_reg, \
|
|
.gate_shift = _gate_shift, \
|
|
.flags = _flags, \
|
|
}
|
|
|
|
#define COMPOSITE_NODIV(_id, _name, _parent_names, \
|
|
_mux_reg, _mux_shift, _mux_width, \
|
|
_gate_reg, _gate_shift, _flags) \
|
|
COMPOSITE(_id, _name, _parent_names, \
|
|
_mux_reg, _mux_shift, _mux_width, \
|
|
0, 0, 0, \
|
|
_gate_reg, _gate_shift, _flags)
|
|
|
|
#define COMPOSITE_FRAC(_id, _name, _parent_names, \
|
|
_mux_reg, _mux_shift, _mux_width, \
|
|
_div_reg, \
|
|
_gate_reg, _gate_shift, _flags) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = _name, \
|
|
.parent_names = _parent_names, \
|
|
.num_parents = ARRAY_SIZE(_parent_names), \
|
|
.mux_reg = _mux_reg, \
|
|
.mux_shift = _mux_shift, \
|
|
.mux_width = _mux_width, \
|
|
.div_reg = _div_reg, \
|
|
.gate_reg = _gate_reg, \
|
|
.gate_shift = _gate_shift, \
|
|
.flags = _flags, \
|
|
}
|
|
|
|
#define COMPOSITE_FRAC_NOGATE(_id, _name, _parent_names, \
|
|
_mux_reg, _mux_shift, _mux_width, \
|
|
_div_reg, \
|
|
_flags) \
|
|
COMPOSITE_FRAC(_id, _name, _parent_names, \
|
|
_mux_reg, _mux_shift, _mux_width, \
|
|
_div_reg, 0, 0, _flags)
|
|
|
|
struct clk_regmap_fractional_divider {
|
|
struct clk_hw hw;
|
|
struct device *dev;
|
|
struct regmap *regmap;
|
|
u32 reg;
|
|
u8 mshift;
|
|
u8 mwidth;
|
|
u32 mmask;
|
|
u8 nshift;
|
|
u8 nwidth;
|
|
u32 nmask;
|
|
};
|
|
|
|
struct clk_regmap_divider {
|
|
struct clk_hw hw;
|
|
struct device *dev;
|
|
struct regmap *regmap;
|
|
u32 reg;
|
|
u8 shift;
|
|
u8 width;
|
|
};
|
|
|
|
struct clk_regmap_gate {
|
|
struct clk_hw hw;
|
|
struct device *dev;
|
|
struct regmap *regmap;
|
|
u32 reg;
|
|
u8 shift;
|
|
};
|
|
|
|
struct clk_regmap_mux {
|
|
struct clk_hw hw;
|
|
struct device *dev;
|
|
struct regmap *regmap;
|
|
u32 reg;
|
|
u32 mask;
|
|
u8 shift;
|
|
};
|
|
|
|
extern const struct clk_ops clk_regmap_mux_ops;
|
|
extern const struct clk_ops clk_regmap_divider_ops;
|
|
extern const struct clk_ops clk_regmap_gate_ops;
|
|
extern const struct clk_ops clk_regmap_fractional_divider_ops;
|
|
|
|
struct clk *
|
|
devm_clk_regmap_register_pll(struct device *dev, const char *name,
|
|
const char *parent_name,
|
|
struct regmap *regmap, u32 reg, u8 pd_shift,
|
|
u8 dsmpd_shift, u8 lock_shift,
|
|
unsigned long flags);
|
|
|
|
struct clk *
|
|
devm_clk_regmap_register_mux(struct device *dev, const char *name,
|
|
const char * const *parent_names, u8 num_parents,
|
|
struct regmap *regmap, u32 reg, u8 shift, u8 width,
|
|
unsigned long flags);
|
|
|
|
struct clk *
|
|
devm_clk_regmap_register_divider(struct device *dev, const char *name,
|
|
const char *parent_name, struct regmap *regmap,
|
|
u32 reg, u8 shift, u8 width,
|
|
unsigned long flags);
|
|
|
|
struct clk *
|
|
devm_clk_regmap_register_gate(struct device *dev, const char *name,
|
|
const char *parent_name,
|
|
struct regmap *regmap, u32 reg, u8 shift,
|
|
unsigned long flags);
|
|
|
|
struct clk *
|
|
devm_clk_regmap_register_fractional_divider(struct device *dev,
|
|
const char *name,
|
|
const char *parent_name,
|
|
struct regmap *regmap,
|
|
u32 reg, unsigned long flags);
|
|
|
|
struct clk *
|
|
devm_clk_regmap_register_composite(struct device *dev, const char *name,
|
|
const char *const *parent_names,
|
|
u8 num_parents, struct regmap *regmap,
|
|
u32 mux_reg, u8 mux_shift, u8 mux_width,
|
|
u32 div_reg, u8 div_shift, u8 div_width,
|
|
u8 div_flags,
|
|
u32 gate_reg, u8 gate_shift,
|
|
unsigned long flags);
|
|
|
|
#endif
|