OpenCloudOS-Kernel/drivers/clk/samsung/clk-pll.h

134 lines
2.8 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Copyright (c) 2013 Linaro Ltd.
*
* Common Clock Framework support for all PLL's in Samsung platforms
*/
#ifndef __SAMSUNG_CLK_PLL_H
#define __SAMSUNG_CLK_PLL_H
enum samsung_pll_type {
pll_2126,
pll_3000,
pll_35xx,
pll_36xx,
pll_2550,
pll_2650,
pll_4500,
pll_4502,
pll_4508,
pll_4600,
pll_4650,
pll_4650c,
pll_6552,
pll_6552_s3c2416,
pll_6553,
pll_s3c2410_mpll,
pll_s3c2410_upll,
pll_s3c2440_mpll,
pll_2550x,
pll_2550xx,
pll_2650x,
pll_2650xx,
pll_1450x,
pll_1451x,
pll_1452x,
pll_1460x,
clk: samsung: clk-pll: Implement pll0822x PLL type pll0822x PLL is used in Exynos850 SoC for top-level integer PLLs. The code was derived from very similar pll35xx type, with next differences: 1. Lock time for pll0822x is 150*P_DIV, when for pll35xx it's 270*P_DIV 2. It's not suggested in Exynos850 TRM that S_DIV change doesn't require performing PLL lock procedure (which is done in pll35xx implementation) When defining pll0822x type, CON3 register offset should be provided as a "con" parameter of PLL() macro, like this: PLL(pll_0822x, 0, "fout_shared0_pll", "oscclk", PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0, exynos850_shared0_pll_rates), To define PLL rates table, one can use PLL_35XX_RATE() macro, e.g.: PLL_35XX_RATE(26 * MHZ, 1600 * MHZ, 800, 13, 0) as it's completely appropriate for pl0822x type and there is no sense in duplicating that. If bit #1 (MANUAL_PLL_CTRL) is not set in CON1 register, it won't be possible to set new rate, with next error showing in kernel log: Could not lock PLL fout_shared1_pll That can happen for example if bootloader clears that bit beforehand. PLL driver doesn't account for that, so if MANUAL_PLL_CTRL bit was cleared, it's assumed it was done for a reason and it shouldn't be possible to change that PLL's rate at all. Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> Acked-by: Chanwoo Choi <cw00.choi@samsung.com> Link: https://lore.kernel.org/r/20211008154352.19519-2-semen.protsenko@linaro.org Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
2021-10-08 23:43:48 +08:00
pll_0822x,
clk: samsung: clk-pll: Implement pll0831x PLL type pll0831x PLL is used in Exynos850 SoC for top-level fractional PLLs. The code was derived from very similar pll36xx type, with next differences: 1. Lock time for pll0831x is 500*P_DIV, when for pll36xx it's 3000*P_DIV 2. It's not suggested in Exynos850 TRM that S_DIV change doesn't require performing PLL lock procedure (which is done in pll36xx implementation) 3. The offset from PMS-values register to K-value register is 0x8 for pll0831x, when for pll36xx it's 0x4 When defining pll0831x type, CON3 register offset should be provided as a "con" parameter of PLL() macro, like this: PLL(pll_0831x, 0, "fout_mmc_pll", "oscclk", PLL_LOCKTIME_PLL_MMC, PLL_CON3_PLL_MMC, pll0831x_26mhz_tbl), To define PLL rates table, one can use PLL_36XX_RATE() macro, e.g.: PLL_36XX_RATE(26 * MHZ, 799999877, 31, 1, 0, -15124) as it's completely appropriate for pl0831x type and there is no sense in duplicating that. If bit #1 (MANUAL_PLL_CTRL) is not set in CON1 register, it won't be possible to set new rate, with next error showing in kernel log: Could not lock PLL fout_mmc_pll That can happen for example if bootloader clears that bit beforehand. PLL driver doesn't account for that, so if MANUAL_PLL_CTRL bit was cleared, it's assumed it was done for a reason and it shouldn't be possible to change that PLL's rate at all. Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> Acked-by: Chanwoo Choi <cw00.choi@samsung.com> Link: https://lore.kernel.org/r/20211008154352.19519-3-semen.protsenko@linaro.org Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
2021-10-08 23:43:49 +08:00
pll_0831x,
};
#define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \
((u64)(_fin) * (BIT(_ks) * (_m) + (_k)) / BIT(_ks) / ((_p) << (_s)))
#define PLL_VALID_RATE(_fin, _fout, _m, _p, _s, _k, _ks) ((_fout) + \
BUILD_BUG_ON_ZERO(PLL_RATE(_fin, _m, _p, _s, _k, _ks) != (_fout)))
#define PLL_35XX_RATE(_fin, _rate, _m, _p, _s) \
{ \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s, 0, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
}
#define PLL_S3C2410_MPLL_RATE(_fin, _rate, _m, _p, _s) \
{ \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m + 8, _p + 2, _s, 0, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
}
#define PLL_S3C2440_MPLL_RATE(_fin, _rate, _m, _p, _s) \
{ \
.rate = PLL_VALID_RATE(_fin, _rate, \
2 * (_m + 8), _p + 2, _s, 0, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
}
#define PLL_36XX_RATE(_fin, _rate, _m, _p, _s, _k) \
{ \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s, _k, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
}
#define PLL_4508_RATE(_fin, _rate, _m, _p, _s, _afc) \
{ \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s - 1, 0, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.afc = (_afc), \
}
#define PLL_4600_RATE(_fin, _rate, _m, _p, _s, _k, _vsel) \
{ \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s, _k, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
.vsel = (_vsel), \
}
#define PLL_4650_RATE(_fin, _rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \
{ \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s, _k, 10), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
.mfr = (_mfr), \
.mrr = (_mrr), \
.vsel = (_vsel), \
}
/* NOTE: Rate table should be kept sorted in descending order. */
struct samsung_pll_rate_table {
unsigned int rate;
unsigned int pdiv;
unsigned int mdiv;
unsigned int sdiv;
unsigned int kdiv;
unsigned int afc;
unsigned int mfr;
unsigned int mrr;
unsigned int vsel;
};
#endif /* __SAMSUNG_CLK_PLL_H */