diff options
Diffstat (limited to 'drivers/clk/mediatek')
-rw-r--r-- | drivers/clk/mediatek/clk-gate.h | 3 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt8135.c | 1 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt8173.c | 25 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mtk.h | 9 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-pll.c | 39 |
5 files changed, 60 insertions, 17 deletions
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h index 6b6780b1e9c5..11e25c992948 100644 --- a/drivers/clk/mediatek/clk-gate.h +++ b/drivers/clk/mediatek/clk-gate.h @@ -16,9 +16,10 @@ #define __DRV_CLK_GATE_H #include <linux/regmap.h> -#include <linux/clk.h> #include <linux/clk-provider.h> +struct clk; + struct mtk_clk_gate { struct clk_hw hw; struct regmap *regmap; diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c index 08b4b849b491..07c21e44b4b3 100644 --- a/drivers/clk/mediatek/clk-mt8135.c +++ b/drivers/clk/mediatek/clk-mt8135.c @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#include <linux/clk.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/slab.h> diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 8b6523d15fb8..90eff85f4285 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#include <linux/clk.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/slab.h> @@ -795,8 +796,9 @@ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init); #define CON0_MT8173_RST_BAR BIT(24) -#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \ - _tuner_reg, _pcw_reg, _pcw_shift) { \ +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table) { \ .id = _id, \ .name = _name, \ .reg = _reg, \ @@ -811,14 +813,31 @@ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init); .tuner_reg = _tuner_reg, \ .pcw_reg = _pcw_reg, \ .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ } +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL) + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT8173_PLL_FMAX }, + { .div = 1, .freq = 1000000000 }, + { .div = 2, .freq = 702000000 }, + { .div = 3, .freq = 253500000 }, + { .div = 4, .freq = 126750000 }, + { } /* sentinel */ +}; + static const struct mtk_pll_data plls[] = { PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0), PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0), PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0, mmpll_div_table), PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0), PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0), PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0), diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 9dda9d8ad10b..c5cbecb3d218 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -17,9 +17,10 @@ #include <linux/regmap.h> #include <linux/bitops.h> -#include <linux/clk.h> #include <linux/clk-provider.h> +struct clk; + #define MAX_MUX_GATE_BIT 31 #define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) @@ -134,6 +135,11 @@ struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); #define HAVE_RST_BAR BIT(0) +struct mtk_pll_div_table { + u32 div; + unsigned long freq; +}; + struct mtk_pll_data { int id; const char *name; @@ -150,6 +156,7 @@ struct mtk_pll_data { int pcwbits; uint32_t pcw_reg; int pcw_shift; + const struct mtk_pll_div_table *div_table; }; void __init mtk_clk_register_plls(struct device_node *node, diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index 44409e98c52f..622e7b6c62b4 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -90,20 +90,23 @@ static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw, int postdiv) { - u32 con1, pd, val; + u32 con1, val; int pll_en; - /* set postdiv */ - pd = readl(pll->pd_addr); - pd &= ~(POSTDIV_MASK << pll->data->pd_shift); - pd |= (ffs(postdiv) - 1) << pll->data->pd_shift; - writel(pd, pll->pd_addr); - pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN; - /* set pcw */ - val = readl(pll->pcw_addr); + /* set postdiv */ + val = readl(pll->pd_addr); + val &= ~(POSTDIV_MASK << pll->data->pd_shift); + val |= (ffs(postdiv) - 1) << pll->data->pd_shift; + + /* postdiv and pcw need to set at the same time if on same register */ + if (pll->pd_addr != pll->pcw_addr) { + writel(val, pll->pd_addr); + val = readl(pll->pcw_addr); + } + /* set pcw */ val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1, pll->data->pcw_shift); val |= pcw << pll->data->pcw_shift; @@ -135,16 +138,28 @@ static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, u32 freq, u32 fin) { unsigned long fmin = 1000 * MHZ; + const struct mtk_pll_div_table *div_table = pll->data->div_table; u64 _pcw; u32 val; if (freq > pll->data->fmax) freq = pll->data->fmax; - for (val = 0; val < 4; val++) { + if (div_table) { + if (freq > div_table[0].freq) + freq = div_table[0].freq; + + for (val = 0; div_table[val + 1].freq != 0; val++) { + if (freq > div_table[val + 1].freq) + break; + } *postdiv = 1 << val; - if (freq * *postdiv >= fmin) - break; + } else { + for (val = 0; val < 5; val++) { + *postdiv = 1 << val; + if ((u64)freq * *postdiv >= fmin) + break; + } } /* _pcw = freq * postdiv / fin * 2^pcwfbits */ |