// SPDX-License-Identifier: GPL-2.0 // // Spreadtrum pll clock driver // // Copyright (C) 2015~2017 Spreadtrum, Inc. // Author: Chunyan Zhang #ifndef _SPRD_PLL_H_ #define _SPRD_PLL_H_ #include #include #include #include #include #include #include #define INVALID_MAX_IBIAS 0xFF #define INVALID_MAX_FREQ 0xFFFFFFFF #define INVALID_MAX_VCO_SEL 0xFF /* * Divide positive or negative dividend by positive or negative divisor * and round to closest integer. Result is undefined for negative * divisors if the dividend variable type is unsigned and for negative * dividends if the divisor variable type is unsigned. */ /* * Same as above but for u64 dividends. divisor must be a 32-bit * number. */ #define DIV_ROUND_CLOSEST_ULL(x, divisor)( \ { \ typeof(divisor) __d = divisor; \ unsigned long long _tmp = (x) + (__d) / 2; \ do_div(_tmp, __d); \ _tmp; \ } \ ) #define GENMASK(h, l) \ (((~0U) << (l)) & (~0U >> (BITS_PER_LONG - 1 - (h)))) /* * ffs: find first bit set. This is defined the same way as * the libc and compiler builtin ffs routines, therefore * differs in spirit from the above ffz (man ffs). */ static inline int generic_ffs(int x) { int r = 1; if (!x) return 0; if (!(x & 0xffff)) { x >>= 16; r += 16; } if (!(x & 0xff)) { x >>= 8; r += 8; } if (!(x & 0xf)) { x >>= 4; r += 4; } if (!(x & 3)) { x >>= 2; r += 2; } if (!(x & 1)) { x >>= 1; r += 1; } return r; } #define __ffs(x) generic_ffs(x) struct reg_cfg { u32 val; /* reg value */ u32 msk; /* mask */ }; struct clk_bit_field { u8 shift; /* shift */ u8 width; /* width */ }; struct freq_table { u32 ibias; u64 max_freq; /* max frequecy*/ u32 vco_sel; }; enum { PLL_LOCK_DONE, /* 0 */ PLL_DIV_S, /* 1 */ PLL_MOD_EN, PLL_SDM_EN, PLL_REFIN, /* 4 */ PLL_IBIAS, PLL_N, PLL_NINT, PLL_KINT, /* 8 */ PLL_PREDIV, PLL_POSTDIV, /* 10 */ PLL_REFDIV, PLL_VCOSEL, PLL_FACT_MAX }; struct sprd_clk_common { u32 reg_base; union { u32 reg; u32 id; }; const char *name; const char *parent_name; }; /* * struct sprd_pll - definition of adjustable pll clock * * @reg: it is registers used to set the configuration of pll clock, * and reg[0] shows how many registers this pll clock uses. * @ftable: it is pll freq table * @udelay it is delay time after setting rate * @factors it is used to calculate the pll clock rate * @fvco: it is the fvco threshold rate * @fflag: it is the fvco flag */ struct sprd_pll { u32 regs_num; const struct freq_table *ftable; const struct clk_bit_field *factors; u16 udelay; u16 k1; u16 k2; u16 fflag; u64 fvco; struct sprd_clk_common common; }; #define SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg_base, \ _reg, _regs_num, _ftable, _factors, \ _udelay, _k_1, _k_2, _fflag, _fvco) \ struct sprd_pll _struct = { \ .regs_num = _regs_num, \ .ftable = _ftable, \ .factors = _factors, \ .udelay = _udelay, \ .k1 = _k_1, \ .k2 = _k_2, \ .fflag = _fflag, \ .fvco = _fvco, \ .common = { \ .reg_base = _reg_base, \ .reg = _reg, \ .name = _name, \ .parent_name = _parent, \ }, \ } #define SPRD_PLL_WITH_ITABLE_K(_struct, _name, _parent, _reg_base, \ _reg, _regs_num, _ftable, _factors, \ _udelay, _k_1, _k_2) \ SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg_base, \ _reg, _regs_num, _ftable, _factors,\ _udelay, _k_1, _k_2, 0, 0) #define SPRD_PLL_WITH_ITABLE_1K(_struct, _name, _parent, _reg_base, \ _reg, _regs_num, _ftable, _factors, _udelay) \ SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg_base, \ _reg, _regs_num, _ftable, _factors, \ _udelay, 1000, 1000, 0, 0) unsigned long sprd_pll_recalc_rate(const struct sprd_pll *pll, unsigned long parent_rate); int sprd_pll_set_rate(const struct sprd_pll *pll, unsigned long rate, unsigned long parent_rate); #endif /* _SPRD_PLL_H_ */