Commit cd8ca300 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-mvebu-periph-pm', 'clk-meson', 'clk-allwinner',...

Merge branches 'clk-mvebu-periph-pm', 'clk-meson', 'clk-allwinner', 'clk-mvebu-dup' and 'clk-davinci' into clk-next

 - S2RAM support for Marvell mvebu periph clks

* clk-mvebu-periph-pm:
  clk: mvebu: armada-37xx-periph: add suspend/resume support
  clk: mvebu: armada-37xx-periph: save the IP base address in the driver data

* clk-meson:
  clk: meson: meson8b: use the regmap in the internal reset controller
  clk: meson: meson8b: register the clock controller early
  clk: meson-axg: pcie: drop the mpll3 clock parent
  clk: meson: axg: round audio system master clocks down
  clk: meson: clk-pll: drop hard-coded rates from pll tables
  clk: meson: clk-pll: remove od parameters
  clk: meson: clk-pll: drop CLK_GET_RATE_NOCACHE where unnecessary
  clk: meson: clk-pll: add enable bit

* clk-allwinner:
  dt-bindings: clock: sun50i-a64-ccu: Add PLL_VIDEO0 macro
  clk: sunxi-ng: a64: Add max. rate constraint to video PLLs
  clk: sunxi-ng: a64: Add minimal rate for video PLLs
  clk: sunxi-ng: sun50i: h6: Add 2x fixed post-divider to MMC module clocks
  clk: sunxi-ng: a83t: Add max. rate constraint to video PLLs
  clk: sunxi-ng: nkmp: Add constraint for maximum rate
  clk: sunxi-ng: r40: Add max. rate constraint to video PLLs
  clk: sunxi-ng: h3/h5: Add max. rate constraint to pll-video
  clk: sunxi-ng: Add maximum rate constraint to NM PLLs
  clk: sunxi-ng: h6: fix PWM gate/reset offset
  clk: sunxi-ng: h6: fix bus clocks' divider position

* clk-mvebu-dup:
  clk: mvebu: ap806: Remove superfluous of_clk_add_provider

* clk-davinci:
  clk: davinci: kill davinci_clk_reset_assert/deassert()
/*
* arch/arm/mach-davinci/include/mach/clock.h
*
* Clock control driver for DaVinci - header file
*
* Authors: Vladimir Barinov <source@mvista.com>
*
* 2007 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
#define __ASM_ARCH_DAVINCI_CLOCK_H
struct clk;
int davinci_clk_reset_assert(struct clk *c);
int davinci_clk_reset_deassert(struct clk *c);
#endif
...@@ -303,24 +303,6 @@ static int davinci_lpsc_clk_reset(struct clk *clk, bool reset) ...@@ -303,24 +303,6 @@ static int davinci_lpsc_clk_reset(struct clk *clk, bool reset)
return 0; return 0;
} }
/*
* REVISIT: These exported functions can be removed after a non-DT lookup is
* added to the reset controller framework and the davinci-rproc driver is
* updated to use the generic reset controller framework.
*/
int davinci_clk_reset_assert(struct clk *clk)
{
return davinci_lpsc_clk_reset(clk, true);
}
EXPORT_SYMBOL(davinci_clk_reset_assert);
int davinci_clk_reset_deassert(struct clk *clk)
{
return davinci_lpsc_clk_reset(clk, false);
}
EXPORT_SYMBOL(davinci_clk_reset_deassert);
static int davinci_psc_reset_assert(struct reset_controller_dev *rcdev, static int davinci_psc_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id) unsigned long id)
{ {
......
...@@ -101,10 +101,16 @@ static const char * const mst_mux_parent_names[] = { ...@@ -101,10 +101,16 @@ static const char * const mst_mux_parent_names[] = {
"axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7", "axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7",
}; };
#define AXG_MST_MCLK_MUX(_name, _reg) \ #define AXG_MST_MUX(_name, _reg, _flag) \
AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, CLK_MUX_ROUND_CLOSEST, \ AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
mst_mux_parent_names, CLK_SET_RATE_PARENT) mst_mux_parent_names, CLK_SET_RATE_PARENT)
#define AXG_MST_MCLK_MUX(_name, _reg) \
AXG_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
#define AXG_MST_SYS_MUX(_name, _reg) \
AXG_MST_MUX(_name, _reg, 0)
static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL); static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL); static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL);
static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL); static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL);
...@@ -112,14 +118,20 @@ static AXG_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL); ...@@ -112,14 +118,20 @@ static AXG_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL); static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL); static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL); static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
static AXG_MST_MCLK_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0); static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
static AXG_MST_MCLK_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1); static AXG_MST_SYS_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_SYS_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
#define AXG_MST_MCLK_DIV(_name, _reg) \ #define AXG_MST_DIV(_name, _reg, _flag) \
AXG_AUD_DIV(_name##_div, _reg, 0, 16, CLK_DIVIDER_ROUND_CLOSEST, \ AXG_AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
"axg_"#_name"_sel", CLK_SET_RATE_PARENT) \ "axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
#define AXG_MST_MCLK_DIV(_name, _reg) \
AXG_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
#define AXG_MST_SYS_DIV(_name, _reg) \
AXG_MST_DIV(_name, _reg, 0)
static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL); static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL); static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL);
static AXG_MST_MCLK_DIV(mst_c_mclk, AUDIO_MCLK_C_CTRL); static AXG_MST_MCLK_DIV(mst_c_mclk, AUDIO_MCLK_C_CTRL);
...@@ -127,9 +139,9 @@ static AXG_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL); ...@@ -127,9 +139,9 @@ static AXG_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL); static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL); static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL); static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
static AXG_MST_MCLK_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0); static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
static AXG_MST_MCLK_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1); static AXG_MST_SYS_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
#define AXG_MST_MCLK_GATE(_name, _reg) \ #define AXG_MST_MCLK_GATE(_name, _reg) \
AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \ AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
......
This diff is collapsed.
...@@ -133,8 +133,14 @@ ...@@ -133,8 +133,14 @@
#define CLKID_PCIE_REF 78 #define CLKID_PCIE_REF 78
#define CLKID_GEN_CLK_SEL 82 #define CLKID_GEN_CLK_SEL 82
#define CLKID_GEN_CLK_DIV 83 #define CLKID_GEN_CLK_DIV 83
#define CLKID_SYS_PLL_DCO 85
#define CLKID_FIXED_PLL_DCO 86
#define CLKID_GP0_PLL_DCO 87
#define CLKID_HIFI_PLL_DCO 88
#define CLKID_PCIE_PLL_DCO 89
#define CLKID_PCIE_PLL_OD 90
#define NR_CLKS 85 #define NR_CLKS 91
/* include the CLKIDs that have been made part of the DT binding */ /* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/axg-clkc.h> #include <dt-bindings/clock/axg-clkc.h>
......
...@@ -11,15 +11,19 @@ ...@@ -11,15 +11,19 @@
* In the most basic form, a Meson PLL is composed as follows: * In the most basic form, a Meson PLL is composed as follows:
* *
* PLL * PLL
* +------------------------------+ * +--------------------------------+
* | | * | |
* in -----[ /N ]---[ *M ]---[ >>OD ]----->> out * | +--+ |
* | ^ ^ | * in >>-----[ /N ]--->| | +-----+ |
* +------------------------------+ * | | |------| DCO |---->> out
* | +--------->| | +--v--+ |
* | | +--+ | |
* | | | |
* | +--[ *(M + (F/Fmax) ]<--+ |
* | | * | |
* FREF VCO * +--------------------------------+
* *
* out = in * (m + frac / frac_max) / (n << sum(ods)) * out = in * (m + frac / frac_max) / n
*/ */
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
...@@ -41,12 +45,11 @@ meson_clk_pll_data(struct clk_regmap *clk) ...@@ -41,12 +45,11 @@ meson_clk_pll_data(struct clk_regmap *clk)
} }
static unsigned long __pll_params_to_rate(unsigned long parent_rate, static unsigned long __pll_params_to_rate(unsigned long parent_rate,
const struct pll_rate_table *pllt, const struct pll_params_table *pllt,
u16 frac, u16 frac,
struct meson_clk_pll_data *pll) struct meson_clk_pll_data *pll)
{ {
u64 rate = (u64)parent_rate * pllt->m; u64 rate = (u64)parent_rate * pllt->m;
unsigned int od = pllt->od + pllt->od2 + pllt->od3;
if (frac && MESON_PARM_APPLICABLE(&pll->frac)) { if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
u64 frac_rate = (u64)parent_rate * frac; u64 frac_rate = (u64)parent_rate * frac;
...@@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate, ...@@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
(1 << pll->frac.width)); (1 << pll->frac.width));
} }
return DIV_ROUND_UP_ULL(rate, pllt->n << od); return DIV_ROUND_UP_ULL(rate, pllt->n);
} }
static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
...@@ -63,20 +66,11 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, ...@@ -63,20 +66,11 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
{ {
struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
struct pll_rate_table pllt; struct pll_params_table pllt;
u16 frac; u16 frac;
pllt.n = meson_parm_read(clk->map, &pll->n); pllt.n = meson_parm_read(clk->map, &pll->n);
pllt.m = meson_parm_read(clk->map, &pll->m); pllt.m = meson_parm_read(clk->map, &pll->m);
pllt.od = meson_parm_read(clk->map, &pll->od);
pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
meson_parm_read(clk->map, &pll->od2) :
0;
pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
meson_parm_read(clk->map, &pll->od3) :
0;
frac = MESON_PARM_APPLICABLE(&pll->frac) ? frac = MESON_PARM_APPLICABLE(&pll->frac) ?
meson_parm_read(clk->map, &pll->frac) : meson_parm_read(clk->map, &pll->frac) :
...@@ -87,14 +81,12 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, ...@@ -87,14 +81,12 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
static u16 __pll_params_with_frac(unsigned long rate, static u16 __pll_params_with_frac(unsigned long rate,
unsigned long parent_rate, unsigned long parent_rate,
const struct pll_rate_table *pllt, const struct pll_params_table *pllt,
struct meson_clk_pll_data *pll) struct meson_clk_pll_data *pll)
{ {
u16 frac_max = (1 << pll->frac.width); u16 frac_max = (1 << pll->frac.width);
u64 val = (u64)rate * pllt->n; u64 val = (u64)rate * pllt->n;
val <<= pllt->od + pllt->od2 + pllt->od3;
if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate); val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
else else
...@@ -105,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate, ...@@ -105,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
return min((u16)val, (u16)(frac_max - 1)); return min((u16)val, (u16)(frac_max - 1));
} }
static const struct pll_rate_table * static bool meson_clk_pll_is_better(unsigned long rate,
unsigned long best,
unsigned long now,
struct meson_clk_pll_data *pll)
{
if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
MESON_PARM_APPLICABLE(&pll->frac)) {
/* Round down */
if (now < rate && best < now)
return true;
} else {
/* Round Closest */
if (abs(now - rate) < abs(best - rate))
return true;
}
return false;
}
static const struct pll_params_table *
meson_clk_get_pll_settings(unsigned long rate, meson_clk_get_pll_settings(unsigned long rate,
unsigned long parent_rate,
struct meson_clk_pll_data *pll) struct meson_clk_pll_data *pll)
{ {
const struct pll_rate_table *table = pll->table; const struct pll_params_table *table = pll->table;
unsigned int i = 0; unsigned long best = 0, now = 0;
unsigned int i, best_i = 0;
if (!table) if (!table)
return NULL; return NULL;
/* Find the first table element exceeding rate */ for (i = 0; table[i].n; i++) {
while (table[i].rate && table[i].rate <= rate) now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
i++;
if (i != 0) { /* If we get an exact match, don't bother any further */
if (MESON_PARM_APPLICABLE(&pll->frac) || if (now == rate) {
!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) || return &table[i];
(abs(rate - table[i - 1].rate) < } else if (meson_clk_pll_is_better(rate, best, now, pll)) {
abs(rate - table[i].rate))) best = now;
i--; best_i = i;
}
} }
return (struct pll_rate_table *)&table[i]; return (struct pll_params_table *)&table[best_i];
} }
static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
...@@ -135,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -135,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
{ {
struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
const struct pll_rate_table *pllt = const struct pll_params_table *pllt =
meson_clk_get_pll_settings(rate, pll); meson_clk_get_pll_settings(rate, *parent_rate, pll);
unsigned long round;
u16 frac; u16 frac;
if (!pllt) if (!pllt)
return meson_clk_pll_recalc_rate(hw, *parent_rate); return meson_clk_pll_recalc_rate(hw, *parent_rate);
if (!MESON_PARM_APPLICABLE(&pll->frac) round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
|| rate == pllt->rate)
return pllt->rate; if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
return round;
/* /*
* The rate provided by the setting is not an exact match, let's * The rate provided by the setting is not an exact match, let's
...@@ -185,12 +200,45 @@ static void meson_clk_pll_init(struct clk_hw *hw) ...@@ -185,12 +200,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
} }
} }
static int meson_clk_pll_enable(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Make sure the pll is in reset */
meson_parm_write(clk->map, &pll->rst, 1);
/* Enable the pll */
meson_parm_write(clk->map, &pll->en, 1);
/* Take the pll out reset */
meson_parm_write(clk->map, &pll->rst, 0);
if (meson_clk_pll_wait_lock(hw))
return -EIO;
return 0;
}
static void meson_clk_pll_disable(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Put the pll is in reset */
meson_parm_write(clk->map, &pll->rst, 1);
/* Disable the pll */
meson_parm_write(clk->map, &pll->en, 0);
}
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
const struct pll_rate_table *pllt; const struct pll_params_table *pllt;
unsigned int enabled;
unsigned long old_rate; unsigned long old_rate;
u16 frac = 0; u16 frac = 0;
...@@ -199,32 +247,28 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -199,32 +247,28 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
old_rate = rate; old_rate = rate;
pllt = meson_clk_get_pll_settings(rate, pll); pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
if (!pllt) if (!pllt)
return -EINVAL; return -EINVAL;
/* Put the pll in reset to write the params */ enabled = meson_parm_read(clk->map, &pll->en);
meson_parm_write(clk->map, &pll->rst, 1); if (enabled)
meson_clk_pll_disable(hw);
meson_parm_write(clk->map, &pll->n, pllt->n); meson_parm_write(clk->map, &pll->n, pllt->n);
meson_parm_write(clk->map, &pll->m, pllt->m); meson_parm_write(clk->map, &pll->m, pllt->m);
meson_parm_write(clk->map, &pll->od, pllt->od);
if (MESON_PARM_APPLICABLE(&pll->od2))
meson_parm_write(clk->map, &pll->od2, pllt->od2);
if (MESON_PARM_APPLICABLE(&pll->od3))
meson_parm_write(clk->map, &pll->od3, pllt->od3);
if (MESON_PARM_APPLICABLE(&pll->frac)) { if (MESON_PARM_APPLICABLE(&pll->frac)) {
frac = __pll_params_with_frac(rate, parent_rate, pllt, pll); frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
meson_parm_write(clk->map, &pll->frac, frac); meson_parm_write(clk->map, &pll->frac, frac);
} }
/* make sure the reset is cleared at this point */ /* If the pll is stopped, bail out now */
meson_parm_write(clk->map, &pll->rst, 0); if (!enabled)
return 0;
if (meson_clk_pll_wait_lock(hw)) { if (meson_clk_pll_enable(hw)) {
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
__func__, old_rate); __func__, old_rate);
/* /*
...@@ -244,6 +288,8 @@ const struct clk_ops meson_clk_pll_ops = { ...@@ -244,6 +288,8 @@ const struct clk_ops meson_clk_pll_ops = {
.recalc_rate = meson_clk_pll_recalc_rate, .recalc_rate = meson_clk_pll_recalc_rate,
.round_rate = meson_clk_pll_round_rate, .round_rate = meson_clk_pll_round_rate,
.set_rate = meson_clk_pll_set_rate, .set_rate = meson_clk_pll_set_rate,
.enable = meson_clk_pll_enable,
.disable = meson_clk_pll_disable
}; };
const struct clk_ops meson_clk_pll_ro_ops = { const struct clk_ops meson_clk_pll_ro_ops = {
......
...@@ -43,37 +43,29 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p, ...@@ -43,37 +43,29 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
} }
struct pll_rate_table { struct pll_params_table {
unsigned long rate;
u16 m; u16 m;
u16 n; u16 n;
u16 od;
u16 od2;
u16 od3;
}; };
#define PLL_RATE(_r, _m, _n, _od) \ #define PLL_PARAMS(_m, _n) \
{ \ { \
.rate = (_r), \
.m = (_m), \ .m = (_m), \
.n = (_n), \ .n = (_n), \
.od = (_od), \
} }
#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) #define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
struct meson_clk_pll_data { struct meson_clk_pll_data {
struct parm en;
struct parm m; struct parm m;
struct parm n; struct parm n;
struct parm frac; struct parm frac;
struct parm od;
struct parm od2;
struct parm od3;
struct parm l; struct parm l;
struct parm rst; struct parm rst;
const struct reg_sequence *init_regs; const struct reg_sequence *init_regs;
unsigned int init_count; unsigned int init_count;
const struct pll_rate_table *table; const struct pll_params_table *table;
u8 flags; u8 flags;
}; };
......
This diff is collapsed.
...@@ -159,8 +159,14 @@ ...@@ -159,8 +159,14 @@
#define CLKID_VDEC_HEVC_DIV 155 #define CLKID_VDEC_HEVC_DIV 155
#define CLKID_GEN_CLK_SEL 157 #define CLKID_GEN_CLK_SEL 157
#define CLKID_GEN_CLK_DIV 158 #define CLKID_GEN_CLK_DIV 158
#define CLKID_FIXED_PLL_DCO 160
#define NR_CLKS 160 #define CLKID_HDMI_PLL_DCO 161
#define CLKID_HDMI_PLL_OD 162
#define CLKID_HDMI_PLL_OD2 163
#define CLKID_SYS_PLL_DCO 164
#define CLKID_GP0_PLL_DCO 165
#define NR_CLKS 166
/* include the CLKIDs that have been made part of the DT binding */ /* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/gxbb-clkc.h> #include <dt-bindings/clock/gxbb-clkc.h>
......
This diff is collapsed.
...@@ -75,8 +75,11 @@ ...@@ -75,8 +75,11 @@
#define CLKID_FCLK_DIV7_DIV 109 #define CLKID_FCLK_DIV7_DIV 109
#define CLKID_NAND_SEL 110 #define CLKID_NAND_SEL 110
#define CLKID_NAND_DIV 111 #define CLKID_NAND_DIV 111
#define CLKID_PLL_FIXED_DCO 113
#define CLKID_PLL_VID_DCO 114
#define CLKID_PLL_SYS_DCO 115
#define CLK_NR_CLKS 113 #define CLK_NR_CLKS 116
/* /*
* include the CLKID and RESETID that have * include the CLKID and RESETID that have
......
...@@ -153,7 +153,6 @@ static int ap806_syscon_common_probe(struct platform_device *pdev, ...@@ -153,7 +153,6 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
goto fail4; goto fail4;
} }
of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
if (ret) if (ret)
goto fail_clk_add; goto fail_clk_add;
......
...@@ -56,6 +56,15 @@ ...@@ -56,6 +56,15 @@
struct clk_periph_driver_data { struct clk_periph_driver_data {
struct clk_hw_onecell_data *hw_data; struct clk_hw_onecell_data *hw_data;
spinlock_t lock; spinlock_t lock;
void __iomem *reg;
/* Storage registers for suspend/resume operations */
u32 tbg_sel;
u32 div_sel0;
u32 div_sel1;
u32 div_sel2;
u32 clk_sel;
u32 clk_dis;
}; };
struct clk_double_div { struct clk_double_div {
...@@ -672,6 +681,40 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data, ...@@ -672,6 +681,40 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
return PTR_ERR_OR_ZERO(*hw); return PTR_ERR_OR_ZERO(*hw);
} }
static int __maybe_unused armada_3700_periph_clock_suspend(struct device *dev)
{
struct clk_periph_driver_data *data = dev_get_drvdata(dev);
data->tbg_sel = readl(data->reg + TBG_SEL);
data->div_sel0 = readl(data->reg + DIV_SEL0);
data->div_sel1 = readl(data->reg + DIV_SEL1);
data->div_sel2 = readl(data->reg + DIV_SEL2);
data->clk_sel = readl(data->reg + CLK_SEL);
data->clk_dis = readl(data->reg + CLK_DIS);
return 0;
}
static int __maybe_unused armada_3700_periph_clock_resume(struct device *dev)
{
struct clk_periph_driver_data *data = dev_get_drvdata(dev);
/* Follow the same order than what the Cortex-M3 does (ATF code) */
writel(data->clk_dis, data->reg + CLK_DIS);
writel(data->div_sel0, data->reg + DIV_SEL0);
writel(data->div_sel1, data->reg + DIV_SEL1);
writel(data->div_sel2, data->reg + DIV_SEL2);
writel(data->tbg_sel, data->reg + TBG_SEL);
writel(data->clk_sel, data->reg + CLK_SEL);
return 0;
}
static const struct dev_pm_ops armada_3700_periph_clock_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(armada_3700_periph_clock_suspend,
armada_3700_periph_clock_resume)
};
static int armada_3700_periph_clock_probe(struct platform_device *pdev) static int armada_3700_periph_clock_probe(struct platform_device *pdev)
{ {
struct clk_periph_driver_data *driver_data; struct clk_periph_driver_data *driver_data;
...@@ -680,7 +723,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev) ...@@ -680,7 +723,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int num_periph = 0, i, ret; int num_periph = 0, i, ret;
struct resource *res; struct resource *res;
void __iomem *reg;
data = of_device_get_match_data(dev); data = of_device_get_match_data(dev);
if (!data) if (!data)
...@@ -689,11 +731,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev) ...@@ -689,11 +731,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
while (data[num_periph].name) while (data[num_periph].name)
num_periph++; num_periph++;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg = devm_ioremap_resource(dev, res);
if (IS_ERR(reg))
return PTR_ERR(reg);
driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL); driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL);
if (!driver_data) if (!driver_data)
return -ENOMEM; return -ENOMEM;
...@@ -706,12 +743,16 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev) ...@@ -706,12 +743,16 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
driver_data->hw_data->num = num_periph; driver_data->hw_data->num = num_periph;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
driver_data->reg = devm_ioremap_resource(dev, res);
if (IS_ERR(driver_data->reg))
return PTR_ERR(driver_data->reg);
spin_lock_init(&driver_data->lock); spin_lock_init(&driver_data->lock);
for (i = 0; i < num_periph; i++) { for (i = 0; i < num_periph; i++) {
struct clk_hw **hw = &driver_data->hw_data->hws[i]; struct clk_hw **hw = &driver_data->hw_data->hws[i];
if (armada_3700_add_composite_clk(&data[i], driver_data->reg,
if (armada_3700_add_composite_clk(&data[i], reg,
&driver_data->lock, dev, hw)) &driver_data->lock, dev, hw))
dev_err(dev, "Can't register periph clock %s\n", dev_err(dev, "Can't register periph clock %s\n",
data[i].name); data[i].name);
...@@ -749,6 +790,7 @@ static struct platform_driver armada_3700_periph_clock_driver = { ...@@ -749,6 +790,7 @@ static struct platform_driver armada_3700_periph_clock_driver = {
.driver = { .driver = {
.name = "marvell-armada-3700-periph-clock", .name = "marvell-armada-3700-periph-clock",
.of_match_table = armada_3700_periph_clock_of_match, .of_match_table = armada_3700_periph_clock_of_match,
.pm = &armada_3700_periph_clock_pm_ops,
}, },
}; };
......
...@@ -64,8 +64,10 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", ...@@ -64,8 +64,10 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
BIT(28), /* lock */ BIT(28), /* lock */
CLK_SET_RATE_UNGATE); CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0",
"osc24M", 0x010, "osc24M", 0x010,
192000000, /* Minimum rate */
1008000000, /* Maximum rate */
8, 7, /* N */ 8, 7, /* N */
0, 4, /* M */ 0, 4, /* M */
BIT(24), /* frac enable */ BIT(24), /* frac enable */
...@@ -125,8 +127,10 @@ static struct ccu_nk pll_periph1_clk = { ...@@ -125,8 +127,10 @@ static struct ccu_nk pll_periph1_clk = {
}, },
}; };
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1",
"osc24M", 0x030, "osc24M", 0x030,
192000000, /* Minimum rate */
1008000000, /* Maximum rate */
8, 7, /* N */ 8, 7, /* N */
0, 4, /* M */ 0, 4, /* M */
BIT(24), /* frac enable */ BIT(24), /* frac enable */
......
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#define CLK_PLL_AUDIO_2X 4 #define CLK_PLL_AUDIO_2X 4
#define CLK_PLL_AUDIO_4X 5 #define CLK_PLL_AUDIO_4X 5
#define CLK_PLL_AUDIO_8X 6 #define CLK_PLL_AUDIO_8X 6
#define CLK_PLL_VIDEO0 7
/* PLL_VIDEO0 exported for HDMI PHY */
#define CLK_PLL_VIDEO0_2X 8 #define CLK_PLL_VIDEO0_2X 8
#define CLK_PLL_VE 9 #define CLK_PLL_VE 9
#define CLK_PLL_DDR0 10 #define CLK_PLL_DDR0 10
......
...@@ -224,7 +224,7 @@ static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", ...@@ -224,7 +224,7 @@ static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
psi_ahb1_ahb2_parents, psi_ahb1_ahb2_parents,
0x510, 0x510,
0, 5, /* M */ 0, 5, /* M */
16, 2, /* P */ 8, 2, /* P */
24, 2, /* mux */ 24, 2, /* mux */
0); 0);
...@@ -233,19 +233,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", ...@@ -233,19 +233,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
"pll-periph0" }; "pll-periph0" };
static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
0, 5, /* M */ 0, 5, /* M */
16, 2, /* P */ 8, 2, /* P */
24, 2, /* mux */ 24, 2, /* mux */
0); 0);
static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
0, 5, /* M */ 0, 5, /* M */
16, 2, /* P */ 8, 2, /* P */
24, 2, /* mux */ 24, 2, /* mux */
0); 0);
static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
0, 5, /* M */ 0, 5, /* M */
16, 2, /* P */ 8, 2, /* P */
24, 2, /* mux */ 24, 2, /* mux */
0); 0);
...@@ -352,7 +352,7 @@ static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2", ...@@ -352,7 +352,7 @@ static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2", static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
0x79c, BIT(0), 0); 0x79c, BIT(0), 0);
static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x79c, BIT(0), 0); static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0); static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
...@@ -408,25 +408,28 @@ static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0); ...@@ -408,25 +408,28 @@ static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x", static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
"pll-periph1-2x" }; "pll-periph1-2x" };
static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_parents, 0x830, static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
0, 4, /* M */ 0, 4, /* M */
8, 2, /* N */ 8, 2, /* N */
24, 3, /* mux */ 24, 3, /* mux */
BIT(31),/* gate */ BIT(31), /* gate */
2, /* post-div */
0); 0);
static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_parents, 0x834, static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
0, 4, /* M */ 0, 4, /* M */
8, 2, /* N */ 8, 2, /* N */
24, 3, /* mux */ 24, 3, /* mux */
BIT(31),/* gate */ BIT(31), /* gate */
2, /* post-div */
0); 0);
static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_parents, 0x838, static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
0, 4, /* M */ 0, 4, /* M */
8, 2, /* N */ 8, 2, /* N */
24, 3, /* mux */ 24, 3, /* mux */
BIT(31),/* gate */ BIT(31), /* gate */
2, /* post-div */
0); 0);
static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0); static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
......
...@@ -108,6 +108,7 @@ static struct ccu_nkmp pll_video0_clk = { ...@@ -108,6 +108,7 @@ static struct ccu_nkmp pll_video0_clk = {
.n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
.m = _SUNXI_CCU_DIV(16, 1), /* input divider */ .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
.p = _SUNXI_CCU_DIV(0, 2), /* output divider */ .p = _SUNXI_CCU_DIV(0, 2), /* output divider */
.max_rate = 3000000000UL,
.common = { .common = {
.reg = 0x010, .reg = 0x010,
.lock_reg = CCU_SUN8I_A83T_LOCK_REG, .lock_reg = CCU_SUN8I_A83T_LOCK_REG,
...@@ -220,6 +221,7 @@ static struct ccu_nkmp pll_video1_clk = { ...@@ -220,6 +221,7 @@ static struct ccu_nkmp pll_video1_clk = {
.n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
.m = _SUNXI_CCU_DIV(16, 1), /* input divider */ .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
.p = _SUNXI_CCU_DIV(0, 2), /* external divider p */ .p = _SUNXI_CCU_DIV(0, 2), /* external divider p */
.max_rate = 3000000000UL,
.common = { .common = {
.reg = 0x04c, .reg = 0x04c,
.lock_reg = CCU_SUN8I_A83T_LOCK_REG, .lock_reg = CCU_SUN8I_A83T_LOCK_REG,
......
...@@ -69,9 +69,10 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", ...@@ -69,9 +69,10 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
BIT(28), /* lock */ BIT(28), /* lock */
CLK_SET_RATE_UNGATE); CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video_clk, "pll-video", static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video_clk, "pll-video",
"osc24M", 0x0010, "osc24M", 0x0010,
192000000, /* Minimum rate */ 192000000, /* Minimum rate */
912000000, /* Maximum rate */
8, 7, /* N */ 8, 7, /* N */
0, 4, /* M */ 0, 4, /* M */
BIT(24), /* frac enable */ BIT(24), /* frac enable */
......
...@@ -65,10 +65,10 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", ...@@ -65,10 +65,10 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
BIT(28), /* lock */ BIT(28), /* lock */
CLK_SET_RATE_UNGATE); CLK_SET_RATE_UNGATE);
/* TODO: The result of N/M is required to be in [8, 25] range. */ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0",
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0",
"osc24M", 0x0010, "osc24M", 0x0010,
192000000, /* Minimum rate */ 192000000, /* Minimum rate */
1008000000, /* Maximum rate */
8, 7, /* N */ 8, 7, /* N */
0, 4, /* M */ 0, 4, /* M */
BIT(24), /* frac enable */ BIT(24), /* frac enable */
...@@ -152,10 +152,10 @@ static struct ccu_nk pll_periph1_clk = { ...@@ -152,10 +152,10 @@ static struct ccu_nk pll_periph1_clk = {
}, },
}; };
/* TODO: The result of N/M is required to be in [8, 25] range. */ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1",
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1",
"osc24M", 0x030, "osc24M", 0x030,
192000000, /* Minimum rate */ 192000000, /* Minimum rate */
1008000000, /* Maximum rate */
8, 7, /* N */ 8, 7, /* N */
0, 4, /* M */ 0, 4, /* M */
BIT(24), /* frac enable */ BIT(24), /* frac enable */
......
...@@ -137,6 +137,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -137,6 +137,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nkmp->fixed_post_div; rate *= nkmp->fixed_post_div;
if (nkmp->max_rate && rate > nkmp->max_rate) {
rate = nkmp->max_rate;
if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate /= nkmp->fixed_post_div;
return rate;
}
_nkmp.min_n = nkmp->n.min ?: 1; _nkmp.min_n = nkmp->n.min ?: 1;
_nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width; _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
_nkmp.min_k = nkmp->k.min ?: 1; _nkmp.min_k = nkmp->k.min ?: 1;
......
...@@ -35,6 +35,7 @@ struct ccu_nkmp { ...@@ -35,6 +35,7 @@ struct ccu_nkmp {
struct ccu_div_internal p; struct ccu_div_internal p;
unsigned int fixed_post_div; unsigned int fixed_post_div;
unsigned int max_rate;
struct ccu_common common; struct ccu_common common;
}; };
......
...@@ -124,6 +124,13 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -124,6 +124,13 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
return rate; return rate;
} }
if (nm->max_rate && rate > nm->max_rate) {
rate = nm->max_rate;
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate /= nm->fixed_post_div;
return rate;
}
if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) { if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV) if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate /= nm->fixed_post_div; rate /= nm->fixed_post_div;
......
...@@ -38,6 +38,7 @@ struct ccu_nm { ...@@ -38,6 +38,7 @@ struct ccu_nm {
unsigned int fixed_post_div; unsigned int fixed_post_div;
unsigned int min_rate; unsigned int min_rate;
unsigned int max_rate;
struct ccu_common common; struct ccu_common common;
}; };
...@@ -115,6 +116,35 @@ struct ccu_nm { ...@@ -115,6 +116,35 @@ struct ccu_nm {
}, \ }, \
} }
#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name, \
_parent, _reg, \
_min_rate, _max_rate, \
_nshift, _nwidth, \
_mshift, _mwidth, \
_frac_en, _frac_sel, \
_frac_rate_0, \
_frac_rate_1, \
_gate, _lock, _flags) \
struct ccu_nm _struct = { \
.enable = _gate, \
.lock = _lock, \
.n = _SUNXI_CCU_MULT(_nshift, _nwidth), \
.m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
.frac = _SUNXI_CCU_FRAC(_frac_en, _frac_sel, \
_frac_rate_0, \
_frac_rate_1), \
.min_rate = _min_rate, \
.max_rate = _max_rate, \
.common = { \
.reg = _reg, \
.features = CCU_FEATURE_FRACTIONAL, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&ccu_nm_ops, \
_flags), \
}, \
}
#define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \ #define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \
_nshift, _nwidth, \ _nshift, _nwidth, \
_mshift, _mwidth, \ _mshift, _mwidth, \
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_ #ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_
#define _DT_BINDINGS_CLK_SUN50I_A64_H_ #define _DT_BINDINGS_CLK_SUN50I_A64_H_
#define CLK_PLL_VIDEO0 7
#define CLK_PLL_PERIPH0 11 #define CLK_PLL_PERIPH0 11
#define CLK_BUS_MIPI_DSI 28 #define CLK_BUS_MIPI_DSI 28
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment