diff options
Diffstat (limited to 'drivers/clk/zte/clk.h')
-rw-r--r-- | drivers/clk/zte/clk.h | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/drivers/clk/zte/clk.h b/drivers/clk/zte/clk.h new file mode 100644 index 000000000..aeaf2a380 --- /dev/null +++ b/drivers/clk/zte/clk.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2015 Linaro Ltd. + * Copyright (C) 2014 ZTE Corporation. + */ + +#ifndef __ZTE_CLK_H +#define __ZTE_CLK_H +#include <linux/clk-provider.h> +#include <linux/spinlock.h> + +#define PNAME(x) static const char *x[] + +struct zx_pll_config { + unsigned long rate; + u32 cfg0; + u32 cfg1; +}; + +struct clk_zx_pll { + struct clk_hw hw; + void __iomem *reg_base; + const struct zx_pll_config *lookup_table; /* order by rate asc */ + int count; + spinlock_t *lock; + u8 pd_bit; /* power down bit */ + u8 lock_bit; /* pll lock flag bit */ +}; + +#define PLL_RATE(_rate, _cfg0, _cfg1) \ +{ \ + .rate = _rate, \ + .cfg0 = _cfg0, \ + .cfg1 = _cfg1, \ +} + +#define ZX_PLL(_name, _parent, _reg, _table, _pd, _lock) \ +{ \ + .reg_base = (void __iomem *) _reg, \ + .lookup_table = _table, \ + .count = ARRAY_SIZE(_table), \ + .pd_bit = _pd, \ + .lock_bit = _lock, \ + .hw.init = CLK_HW_INIT(_name, _parent, &zx_pll_ops, \ + CLK_GET_RATE_NOCACHE), \ +} + +/* + * The pd_bit is not available on ZX296718, so let's pass something + * bigger than 31, e.g. 0xff, to indicate that. + */ +#define ZX296718_PLL(_name, _parent, _reg, _table) \ +ZX_PLL(_name, _parent, _reg, _table, 0xff, 30) + +struct zx_clk_gate { + struct clk_gate gate; + u16 id; +}; + +#define GATE(_id, _name, _parent, _reg, _bit, _flag, _gflags) \ +{ \ + .gate = { \ + .reg = (void __iomem *) _reg, \ + .bit_idx = (_bit), \ + .flags = _gflags, \ + .lock = &clk_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_gate_ops, \ + _flag | CLK_IGNORE_UNUSED), \ + }, \ + .id = _id, \ +} + +struct zx_clk_fixed_factor { + struct clk_fixed_factor factor; + u16 id; +}; + +#define FFACTOR(_id, _name, _parent, _mult, _div, _flag) \ +{ \ + .factor = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flag), \ + }, \ + .id = _id, \ +} + +struct zx_clk_mux { + struct clk_mux mux; + u16 id; +}; + +#define MUX_F(_id, _name, _parent, _reg, _shift, _width, _flag, _mflag) \ +{ \ + .mux = { \ + .reg = (void __iomem *) _reg, \ + .mask = BIT(_width) - 1, \ + .shift = _shift, \ + .flags = _mflag, \ + .lock = &clk_lock, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parent, \ + &clk_mux_ops, \ + _flag), \ + }, \ + .id = _id, \ +} + +#define MUX(_id, _name, _parent, _reg, _shift, _width) \ +MUX_F(_id, _name, _parent, _reg, _shift, _width, 0, 0) + +struct zx_clk_div { + struct clk_divider div; + u16 id; +}; + +#define DIV_T(_id, _name, _parent, _reg, _shift, _width, _flag, _table) \ +{ \ + .div = { \ + .reg = (void __iomem *) _reg, \ + .shift = _shift, \ + .width = _width, \ + .flags = 0, \ + .table = _table, \ + .lock = &clk_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_divider_ops, \ + _flag), \ + }, \ + .id = _id, \ +} + +struct clk_zx_audio_divider { + struct clk_hw hw; + void __iomem *reg_base; + unsigned int rate_count; + spinlock_t *lock; + u16 id; +}; + +#define AUDIO_DIV(_id, _name, _parent, _reg) \ +{ \ + .reg_base = (void __iomem *) _reg, \ + .lock = &clk_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &zx_audio_div_ops, \ + 0), \ + .id = _id, \ +} + +struct clk *clk_register_zx_pll(const char *name, const char *parent_name, + unsigned long flags, void __iomem *reg_base, + const struct zx_pll_config *lookup_table, int count, spinlock_t *lock); + +struct clk_zx_audio { + struct clk_hw hw; + void __iomem *reg_base; +}; + +struct clk *clk_register_zx_audio(const char *name, + const char * const parent_name, + unsigned long flags, void __iomem *reg_base); + +extern const struct clk_ops zx_pll_ops; +extern const struct clk_ops zx_audio_div_ops; + +#endif |