/* 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 #include #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