Commit 15afa044 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-ti', 'clk-amlogic', 'clk-tegra' and 'clk-samsung' into clk-next

* clk-ti:
  clk: keystone: sci-clk: add support for dynamically probing clocks
  clk: ti: add support for clock latching to mux clocks
  clk: ti: add support for clock latching to divider clocks
  clk: ti: add generic support for clock latching
  clk: ti: add support for register read-modify-write low-level operation
  dt-bindings: clock: ti: add latching support to mux and divider clocks

* clk-amlogic: (50 commits)
  clk: meson: Drop unused local variable and add static
  clk: meson: clean-up clk81 clocks
  clk: meson: add fdiv clock gates
  clk: meson: add mpll pre-divider
  clk: meson: axg: add hifi pll clock
  clk: meson: axg: add hifi clock bindings
  clk: meson: add ROUND_CLOSEST to the pll driver
  clk: meson: add gp0 frac parameter for axg and gxl
  clk: meson: improve pll driver results with frac
  clk: meson: remove special gp0 lock loop
  clk: meson: poke pll CNTL last
  clk: meson: add fractional part of meson8b fixed_pll
  clk: meson: use hhi syscon if available
  clk: meson: remove obsolete cpu_clk
  clk: meson: rework meson8b cpu clock
  clk: meson: split divider and gate part of mpll
  clk: meson: migrate plls clocks to clk_regmap
  clk: meson: migrate the audio divider clock to clk_regmap
  clk: meson: migrate mplls clocks to clk_regmap
  clk: meson: add regmap helpers for parm
  ...

* clk-tegra:
  clk: tegra: Fix pll_u rate configuration
  clk: tegra: Specify VDE clock rate
  clk: tegra20: Correct PLL_C_OUT1 setup
  clk: tegra: Mark HCLK, SCLK and EMC as critical
  clk: tegra: MBIST work around for Tegra210
  clk: tegra: add fence_delay for clock registers
  clk: tegra: Add la clock for Tegra210

* clk-samsung: (22 commits)
  clk: samsung: Mark a few things static
  clk: samsung: Add fout=196608001 Hz EPLL rate entry for exynos4412
  clk: samsung: exynos5250: Add missing clocks for FIMC LITE SYSMMU devices
  clk: samsung: exynos5420: Add more entries to EPLL rate table
  clk: samsung: exynos5420: Add CLK_SET_RATE_PARENT flag to mout_mau_epll_clk
  clk: samsung: exynos5250: Move PD-dependent clocks to Exynos5 sub-CMU
  clk: samsung: exynos5420: Move PD-dependent clocks to Exynos5 sub-CMU
  clk: samsung: Add Exynos5 sub-CMU clock driver
  soc: samsung: pm_domains: Add blacklisting clock handling
  clk: samsung: Add compile time PLL rate validators
  clk: samsung: s3c2410: Fix PLL rates
  clk: samsung: exynos7: Fix PLL rates
  clk: samsung: exynos5433: Fix PLL rates
  clk: samsung: exynos5260: Fix PLL rates
  clk: samsung: exynos5250: Fix PLL rates
  clk: samsung: exynos3250: Fix PLL rates
  clk: exynos5433: Extend list of available AUD_PLL output frequencies
  clk: exynos5433: Add CLK_IGNORE_UNUSED flag to sclk_ioclk_i2s1_bclk
  clk: samsung: Add a git tree entry to MAINTAINERS
  clk: samsung: Remove redundant dev_err call in exynos_audss_clk_probe()
  ...
......@@ -12189,6 +12189,7 @@ M: Tomasz Figa <tomasz.figa@gmail.com>
M: Chanwoo Choi <cw00.choi@samsung.com>
S: Supported
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
F: drivers/clk/samsung/
F: include/dt-bindings/clock/exynos*.h
F: Documentation/devicetree/bindings/clock/exynos*.txt
......
......@@ -28,12 +28,10 @@
* parent - fixed parent. No clk_set_parent support
*/
#define div_mask(width) ((1 << (width)) - 1)
static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
u8 width)
{
unsigned int maxdiv = 0, mask = div_mask(width);
unsigned int maxdiv = 0, mask = clk_div_mask(width);
const struct clk_div_table *clkt;
for (clkt = table; clkt->div; clkt++)
......@@ -57,12 +55,12 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
unsigned long flags)
{
if (flags & CLK_DIVIDER_ONE_BASED)
return div_mask(width);
return clk_div_mask(width);
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << div_mask(width);
return 1 << clk_div_mask(width);
if (table)
return _get_table_maxdiv(table, width);
return div_mask(width) + 1;
return clk_div_mask(width) + 1;
}
static unsigned int _get_table_div(const struct clk_div_table *table,
......@@ -84,7 +82,7 @@ static unsigned int _get_div(const struct clk_div_table *table,
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << val;
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return val ? val : div_mask(width) + 1;
return val ? val : clk_div_mask(width) + 1;
if (table)
return _get_table_div(table, val);
return val + 1;
......@@ -109,7 +107,7 @@ static unsigned int _get_val(const struct clk_div_table *table,
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return __ffs(div);
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return (div == div_mask(width) + 1) ? 0 : div;
return (div == clk_div_mask(width) + 1) ? 0 : div;
if (table)
return _get_table_val(table, div);
return div - 1;
......@@ -141,7 +139,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
unsigned int val;
val = clk_readl(divider->reg) >> divider->shift;
val &= div_mask(divider->width);
val &= clk_div_mask(divider->width);
return divider_recalc_rate(hw, parent_rate, val, divider->table,
divider->flags, divider->width);
......@@ -344,19 +342,43 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
}
EXPORT_SYMBOL_GPL(divider_round_rate_parent);
long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
unsigned long rate, unsigned long *prate,
const struct clk_div_table *table, u8 width,
unsigned long flags, unsigned int val)
{
int div;
div = _get_div(table, val, flags, width);
/* Even a read-only clock can propagate a rate change */
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
if (!parent)
return -EINVAL;
*prate = clk_hw_round_rate(parent, rate * div);
}
return DIV_ROUND_UP_ULL((u64)*prate, div);
}
EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent);
static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_divider *divider = to_clk_divider(hw);
int bestdiv;
/* if read only, just return current value */
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
bestdiv = clk_readl(divider->reg) >> divider->shift;
bestdiv &= div_mask(divider->width);
bestdiv = _get_div(divider->table, bestdiv, divider->flags,
divider->width);
return DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
u32 val;
val = clk_readl(divider->reg) >> divider->shift;
val &= clk_div_mask(divider->width);
return divider_ro_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags,
val);
}
return divider_round_rate(hw, rate, prate, divider->table,
......@@ -376,7 +398,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
value = _get_val(table, div, flags, width);
return min_t(unsigned int, value, div_mask(width));
return min_t(unsigned int, value, clk_div_mask(width));
}
EXPORT_SYMBOL_GPL(divider_get_val);
......@@ -399,10 +421,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
__acquire(divider->lock);
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
val = div_mask(divider->width) << (divider->shift + 16);
val = clk_div_mask(divider->width) << (divider->shift + 16);
} else {
val = clk_readl(divider->reg);
val &= ~(div_mask(divider->width) << divider->shift);
val &= ~(clk_div_mask(divider->width) << divider->shift);
}
val |= (u32)value << divider->shift;
clk_writel(val, divider->reg);
......
......@@ -26,35 +26,24 @@
* parent - parent is adjustable through clk_set_parent
*/
static u8 clk_mux_get_parent(struct clk_hw *hw)
int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
unsigned int val)
{
struct clk_mux *mux = to_clk_mux(hw);
int num_parents = clk_hw_get_num_parents(hw);
u32 val;
/*
* FIXME need a mux-specific flag to determine if val is bitwise or numeric
* e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
* to 0x7 (index starts at one)
* OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
* val = 0x4 really means "bit 2, index starts at bit 0"
*/
val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
if (mux->table) {
if (table) {
int i;
for (i = 0; i < num_parents; i++)
if (mux->table[i] == val)
if (table[i] == val)
return i;
return -EINVAL;
}
if (val && (mux->flags & CLK_MUX_INDEX_BIT))
if (val && (flags & CLK_MUX_INDEX_BIT))
val = ffs(val) - 1;
if (val && (mux->flags & CLK_MUX_INDEX_ONE))
if (val && (flags & CLK_MUX_INDEX_ONE))
val--;
if (val >= num_parents)
......@@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
return val;
}
EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val;
unsigned long flags = 0;
unsigned int val = index;
if (mux->table) {
index = mux->table[index];
if (table) {
val = table[index];
} else {
if (mux->flags & CLK_MUX_INDEX_BIT)
index = 1 << index;
if (flags & CLK_MUX_INDEX_BIT)
val = 1 << index;
if (mux->flags & CLK_MUX_INDEX_ONE)
index++;
if (flags & CLK_MUX_INDEX_ONE)
val++;
}
return val;
}
EXPORT_SYMBOL_GPL(clk_mux_index_to_val);
static u8 clk_mux_get_parent(struct clk_hw *hw)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val;
val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
}
static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
unsigned long flags = 0;
u32 reg;
if (mux->lock)
spin_lock_irqsave(mux->lock, flags);
else
__acquire(mux->lock);
if (mux->flags & CLK_MUX_HIWORD_MASK) {
val = mux->mask << (mux->shift + 16);
reg = mux->mask << (mux->shift + 16);
} else {
val = clk_readl(mux->reg);
val &= ~(mux->mask << mux->shift);
reg = clk_readl(mux->reg);
reg &= ~(mux->mask << mux->shift);
}
val |= index << mux->shift;
clk_writel(val, mux->reg);
val = val << mux->shift;
reg |= val;
clk_writel(reg, mux->reg);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
......
......@@ -1125,8 +1125,10 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
{
lockdep_assert_held(&prepare_lock);
if (!core)
if (!core) {
req->rate = 0;
return 0;
}
clk_core_init_rate_req(core, req);
......@@ -2927,6 +2929,17 @@ static int __clk_core_init(struct clk_core *core)
core->orphan = true;
}
/*
* optional platform-specific magic
*
* The .init callback is not used by any of the basic clock types, but
* exists for weird hardware that must perform initialization magic.
* Please consider other ways of solving initialization problems before
* using this callback, as its use is discouraged.
*/
if (core->ops->init)
core->ops->init(core->hw);
/*
* Set clk's accuracy. The preferred method is to use
* .recalc_accuracy. For simple clocks and lazy developers the default
......@@ -2967,49 +2980,43 @@ static int __clk_core_init(struct clk_core *core)
rate = 0;
core->rate = core->req_rate = rate;
/*
* Enable CLK_IS_CRITICAL clocks so newly added critical clocks
* don't get accidentally disabled when walking the orphan tree and
* reparenting clocks
*/
if (core->flags & CLK_IS_CRITICAL) {
unsigned long flags;
clk_core_prepare(core);
flags = clk_enable_lock();
clk_core_enable(core);
clk_enable_unlock(flags);
}
/*
* walk the list of orphan clocks and reparent any that newly finds a
* parent.
*/
hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
struct clk_core *parent = __clk_init_parent(orphan);
unsigned long flags;
/*
* we could call __clk_set_parent, but that would result in a
* redundant call to the .set_rate op, if it exists
* We need to use __clk_set_parent_before() and _after() to
* to properly migrate any prepare/enable count of the orphan
* clock. This is important for CLK_IS_CRITICAL clocks, which
* are enabled during init but might not have a parent yet.
*/
if (parent) {
/* update the clk tree topology */
flags = clk_enable_lock();
clk_reparent(orphan, parent);
clk_enable_unlock(flags);
__clk_set_parent_before(orphan, parent);
__clk_set_parent_after(orphan, parent, NULL);
__clk_recalc_accuracies(orphan);
__clk_recalc_rates(orphan, 0);
}
}
/*
* optional platform-specific magic
*
* The .init callback is not used by any of the basic clock types, but
* exists for weird hardware that must perform initialization magic.
* Please consider other ways of solving initialization problems before
* using this callback, as its use is discouraged.
*/
if (core->ops->init)
core->ops->init(core->hw);
if (core->flags & CLK_IS_CRITICAL) {
unsigned long flags;
clk_core_prepare(core);
flags = clk_enable_lock();
clk_core_enable(core);
clk_enable_unlock(flags);
}
kref_init(&core->ref);
out:
clk_pm_runtime_put(core);
......
......@@ -3,10 +3,15 @@ config COMMON_CLK_AMLOGIC
depends on OF
depends on ARCH_MESON || COMPILE_TEST
config COMMON_CLK_REGMAP_MESON
bool
select REGMAP
config COMMON_CLK_MESON8B
bool
depends on COMMON_CLK_AMLOGIC
select RESET_CONTROLLER
select COMMON_CLK_REGMAP_MESON
help
Support for the clock controller on AmLogic S802 (Meson8),
S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you
......@@ -16,6 +21,8 @@ config COMMON_CLK_GXBB
bool
depends on COMMON_CLK_AMLOGIC
select RESET_CONTROLLER
select COMMON_CLK_REGMAP_MESON
select MFD_SYSCON
help
Support for the clock controller on AmLogic S905 devices, aka gxbb.
Say Y if you want peripherals and CPU frequency scaling to work.
......@@ -24,6 +31,8 @@ config COMMON_CLK_AXG
bool
depends on COMMON_CLK_AMLOGIC
select RESET_CONTROLLER
select COMMON_CLK_REGMAP_MESON
select MFD_SYSCON
help
Support for the clock controller on AmLogic A113D devices, aka axg.
Say Y if you want peripherals and CPU frequency scaling to work.
......@@ -2,7 +2,8 @@
# Makefile for Meson specific clk
#
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-audio-divider.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o
obj-$(CONFIG_COMMON_CLK_AXG) += axg.o
obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o
This diff is collapsed.
......@@ -117,8 +117,18 @@
#define CLKID_SD_EMMC_B_CLK0_DIV 62
#define CLKID_SD_EMMC_C_CLK0_SEL 63
#define CLKID_SD_EMMC_C_CLK0_DIV 64
#define CLKID_MPLL0_DIV 65
#define CLKID_MPLL1_DIV 66
#define CLKID_MPLL2_DIV 67
#define CLKID_MPLL3_DIV 68
#define CLKID_MPLL_PREDIV 70
#define CLKID_FCLK_DIV2_DIV 71
#define CLKID_FCLK_DIV3_DIV 72
#define CLKID_FCLK_DIV4_DIV 73
#define CLKID_FCLK_DIV5_DIV 74
#define CLKID_FCLK_DIV7_DIV 75
#define NR_CLKS 65
#define NR_CLKS 76
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/axg-clkc.h>
......
......@@ -28,8 +28,11 @@
#include <linux/clk-provider.h>
#include "clkc.h"
#define to_meson_clk_audio_divider(_hw) container_of(_hw, \
struct meson_clk_audio_divider, hw)
static inline struct meson_clk_audio_div_data *
meson_clk_audio_div_data(struct clk_regmap *clk)
{
return (struct meson_clk_audio_div_data *)clk->data;
}
static int _div_round(unsigned long parent_rate, unsigned long rate,
unsigned long flags)
......@@ -45,15 +48,9 @@ static int _get_val(unsigned long parent_rate, unsigned long rate)
return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
}
static int _valid_divider(struct clk_hw *hw, int divider)
static int _valid_divider(unsigned int width, int divider)
{
struct meson_clk_audio_divider *adiv =
to_meson_clk_audio_divider(hw);
int max_divider;
u8 width;
width = adiv->div.width;
max_divider = 1 << width;
int max_divider = 1 << width;
return clamp(divider, 1, max_divider);
}
......@@ -61,14 +58,11 @@ static int _valid_divider(struct clk_hw *hw, int divider)
static unsigned long audio_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct meson_clk_audio_divider *adiv =
to_meson_clk_audio_divider(hw);
struct parm *p;
unsigned long reg, divider;
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
unsigned long divider;
p = &adiv->div;
reg = readl(adiv->base + p->reg_off);
divider = PARM_GET(p->width, p->shift, reg) + 1;
divider = meson_parm_read(clk->map, &adiv->div);
return DIV_ROUND_UP_ULL((u64)parent_rate, divider);
}
......@@ -77,14 +71,14 @@ static long audio_divider_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
{
struct meson_clk_audio_divider *adiv =
to_meson_clk_audio_divider(hw);
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
unsigned long max_prate;
int divider;
if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
divider = _div_round(*parent_rate, rate, adiv->flags);
divider = _valid_divider(hw, divider);
divider = _valid_divider(adiv->div.width, divider);
return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
}
......@@ -93,7 +87,7 @@ static long audio_divider_round_rate(struct clk_hw *hw,
/* Get the corresponding rounded down divider */
divider = max_prate / rate;
divider = _valid_divider(hw, divider);
divider = _valid_divider(adiv->div.width, divider);
/* Get actual rate of the parent */
*parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
......@@ -106,28 +100,11 @@ static int audio_divider_set_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate)
{
struct meson_clk_audio_divider *adiv =
to_meson_clk_audio_divider(hw);
struct parm *p;
unsigned long reg, flags = 0;
int val;
val = _get_val(parent_rate, rate);
if (adiv->lock)
spin_lock_irqsave(adiv->lock, flags);
else
__acquire(adiv->lock);
p = &adiv->div;
reg = readl(adiv->base + p->reg_off);
reg = PARM_SET(p->width, p->shift, reg, val);
writel(reg, adiv->base + p->reg_off);
if (adiv->lock)
spin_unlock_irqrestore(adiv->lock, flags);
else
__release(adiv->lock);
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
int val = _get_val(parent_rate, rate);
meson_parm_write(clk->map, &adiv->div, val);
return 0;
}
......
/*
* Copyright (c) 2015 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* CPU clock path:
*
* +-[/N]-----|3|
* MUX2 +--[/3]-+----------|2| MUX1
* [sys_pll]---|1| |--[/2]------------|1|-|1|
* | |---+------------------|0| | |----- [a5_clk]
* +--|0| | |
* [xtal]---+-------------------------------|0|
*
*
*
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#define MESON_CPU_CLK_CNTL1 0x00
#define MESON_CPU_CLK_CNTL 0x40
#define MESON_CPU_CLK_MUX1 BIT(7)
#define MESON_CPU_CLK_MUX2 BIT(0)
#define MESON_N_WIDTH 9
#define MESON_N_SHIFT 20
#define MESON_SEL_WIDTH 2
#define MESON_SEL_SHIFT 2
#include "clkc.h"
#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
return divider_round_rate(hw, rate, prate, clk_cpu->div_table,
MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
}
static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
unsigned int div, sel, N = 0;
u32 reg;
div = DIV_ROUND_UP(parent_rate, rate);
if (div <= 3) {
sel = div - 1;
} else {
sel = 3;
N = div / 2;
}
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N);
writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel);
writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
return 0;
}
static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
unsigned int N, sel;
unsigned int div = 1;
u32 reg;
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg);
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg);
if (sel < 3)
div = sel + 1;
else
div = 2 * N;
return parent_rate / div;
}
/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
struct clk_notifier_data *ndata)
{
u32 cpu_clk_cntl;
/* switch MUX1 to xtal */
cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+ MESON_CPU_CLK_CNTL);
cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1;
writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+ MESON_CPU_CLK_CNTL);
udelay(100);
/* switch MUX2 to sys-pll */
cpu_clk_cntl |= MESON_CPU_CLK_MUX2;
writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+ MESON_CPU_CLK_CNTL);
return 0;
}
/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
struct clk_notifier_data *ndata)
{
u32 cpu_clk_cntl;
/* switch MUX1 to divisors' output */
cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+ MESON_CPU_CLK_CNTL);
cpu_clk_cntl |= MESON_CPU_CLK_MUX1;
writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+ MESON_CPU_CLK_CNTL);
udelay(100);
return 0;
}
/*
* This clock notifier is called when the frequency of the of the parent
* PLL clock is to be changed. We use the xtal input as temporary parent
* while the PLL frequency is stabilized.
*/
int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
unsigned long event, void *data)
{
struct clk_notifier_data *ndata = data;
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb);
int ret = 0;
if (event == PRE_RATE_CHANGE)
ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata);
else if (event == POST_RATE_CHANGE)
ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata);
return notifier_from_errno(ret);
}
const struct clk_ops meson_clk_cpu_ops = {
.recalc_rate = meson_clk_cpu_recalc_rate,
.round_rate = meson_clk_cpu_round_rate,
.set_rate = meson_clk_cpu_set_rate,
};
......@@ -68,11 +68,15 @@
#define N2_MIN 4
#define N2_MAX 511
#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
static inline struct meson_clk_mpll_data *
meson_clk_mpll_data(struct clk_regmap *clk)
{
return (struct meson_clk_mpll_data *)clk->data;
}
static long rate_from_params(unsigned long parent_rate,
unsigned long sdm,
unsigned long n2)
unsigned int sdm,
unsigned int n2)
{
unsigned long divisor = (SDM_DEN * n2) + sdm;
......@@ -84,8 +88,8 @@ static long rate_from_params(unsigned long parent_rate,
static void params_from_rate(unsigned long requested_rate,
unsigned long parent_rate,
unsigned long *sdm,
unsigned long *n2)
unsigned int *sdm,
unsigned int *n2)
{
uint64_t div = parent_rate;
unsigned long rem = do_div(div, requested_rate);
......@@ -105,31 +109,23 @@ static void params_from_rate(unsigned long requested_rate,
static unsigned long mpll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
struct parm *p;
unsigned long reg, sdm, n2;
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
unsigned int sdm, n2;
long rate;
p = &mpll->sdm;
reg = readl(mpll->base + p->reg_off);
sdm = PARM_GET(p->width, p->shift, reg);
p = &mpll->n2;
reg = readl(mpll->base + p->reg_off);
n2 = PARM_GET(p->width, p->shift, reg);
sdm = meson_parm_read(clk->map, &mpll->sdm);
n2 = meson_parm_read(clk->map, &mpll->n2);
rate = rate_from_params(parent_rate, sdm, n2);
if (rate < 0)
return 0;
return rate;
return rate < 0 ? 0 : rate;
}
static long mpll_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
{
unsigned long sdm, n2;
unsigned int sdm, n2;
params_from_rate(rate, *parent_rate, &sdm, &n2);
return rate_from_params(*parent_rate, sdm, n2);
......@@ -139,9 +135,9 @@ static int mpll_set_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate)
{
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
struct parm *p;
unsigned long reg, sdm, n2;
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
unsigned int sdm, n2;
unsigned long flags = 0;
params_from_rate(rate, parent_rate, &sdm, &n2);
......@@ -151,97 +147,36 @@ static int mpll_set_rate(struct clk_hw *hw,
else
__acquire(mpll->lock);
p = &mpll->sdm;
reg = readl(mpll->base + p->reg_off);
reg = PARM_SET(p->width, p->shift, reg, sdm);
writel(reg, mpll->base + p->reg_off);
p = &mpll->sdm_en;
reg = readl(mpll->base + p->reg_off);
reg = PARM_SET(p->width, p->shift, reg, 1);
writel(reg, mpll->base + p->reg_off);
p = &mpll->ssen;
if (p->width != 0) {
reg = readl(mpll->base + p->reg_off);
reg = PARM_SET(p->width, p->shift, reg, 1);
writel(reg, mpll->base + p->reg_off);
}
p = &mpll->n2;
reg = readl(mpll->base + p->reg_off);
reg = PARM_SET(p->width, p->shift, reg, n2);
writel(reg, mpll->base + p->reg_off);
if (mpll->lock)
spin_unlock_irqrestore(mpll->lock, flags);
else
__release(mpll->lock);
return 0;
}
/* Enable and set the fractional part */
meson_parm_write(clk->map, &mpll->sdm, sdm);
meson_parm_write(clk->map, &mpll->sdm_en, 1);
static void mpll_enable_core(struct clk_hw *hw, int enable)
{
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
struct parm *p;
unsigned long reg;
unsigned long flags = 0;
/* Set additional fractional part enable if required */
if (MESON_PARM_APPLICABLE(&mpll->ssen))
meson_parm_write(clk->map, &mpll->ssen, 1);
if (mpll->lock)
spin_lock_irqsave(mpll->lock, flags);
else
__acquire(mpll->lock);
/* Set the integer divider part */
meson_parm_write(clk->map, &mpll->n2, n2);
p = &mpll->en;
reg = readl(mpll->base + p->reg_off);
reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
writel(reg, mpll->base + p->reg_off);
/* Set the magic misc bit if required */
if (MESON_PARM_APPLICABLE(&mpll->misc))
meson_parm_write(clk->map, &mpll->misc, 1);
if (mpll->lock)
spin_unlock_irqrestore(mpll->lock, flags);
else
__release(mpll->lock);
}
static int mpll_enable(struct clk_hw *hw)
{
mpll_enable_core(hw, 1);
return 0;
}
static void mpll_disable(struct clk_hw *hw)
{
mpll_enable_core(hw, 0);
}
static int mpll_is_enabled(struct clk_hw *hw)
{
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
struct parm *p;
unsigned long reg;
int en;
p = &mpll->en;
reg = readl(mpll->base + p->reg_off);
en = PARM_GET(p->width, p->shift, reg);
return en;
}
const struct clk_ops meson_clk_mpll_ro_ops = {
.recalc_rate = mpll_recalc_rate,
.round_rate = mpll_round_rate,
.is_enabled = mpll_is_enabled,
};
const struct clk_ops meson_clk_mpll_ops = {
.recalc_rate = mpll_recalc_rate,
.round_rate = mpll_round_rate,
.set_rate = mpll_set_rate,
.enable = mpll_enable,
.disable = mpll_disable,
.is_enabled = mpll_is_enabled,
};
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018 BayLibre, SAS.
// Author: Jerome Brunet <jbrunet@baylibre.com>
#include "clk-regmap.h"
static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
set ^= enable;
return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx),
set ? BIT(gate->bit_idx) : 0);
}
static int clk_regmap_gate_enable(struct clk_hw *hw)
{
return clk_regmap_gate_endisable(hw, 1);
}
static void clk_regmap_gate_disable(struct clk_hw *hw)
{
clk_regmap_gate_endisable(hw, 0);
}
static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
unsigned int val;
regmap_read(clk->map, gate->offset, &val);
if (gate->flags & CLK_GATE_SET_TO_DISABLE)
val ^= BIT(gate->bit_idx);
val &= BIT(gate->bit_idx);
return val ? 1 : 0;
}
const struct clk_ops clk_regmap_gate_ops = {
.enable = clk_regmap_gate_enable,
.disable = clk_regmap_gate_disable,
.is_enabled = clk_regmap_gate_is_enabled,
};
EXPORT_SYMBOL_GPL(clk_regmap_gate_ops);
static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
unsigned int val;
int ret;
ret = regmap_read(clk->map, div->offset, &val);
if (ret)
/* Gives a hint that something is wrong */
return 0;
val >>= div->shift;
val &= clk_div_mask(div->width);
return divider_recalc_rate(hw, prate, val, div->table, div->flags,
div->width);
}
static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
unsigned int val;
int ret;
/* if read only, just return current value */
if (div->flags & CLK_DIVIDER_READ_ONLY) {
ret = regmap_read(clk->map, div->offset, &val);
if (ret)
/* Gives a hint that something is wrong */
return 0;
val >>= div->shift;
val &= clk_div_mask(div->width);
return divider_ro_round_rate(hw, rate, prate, div->table,
div->width, div->flags, val);
}
return divider_round_rate(hw, rate, prate, div->table, div->width,
div->flags);
}
static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
unsigned int val;
int ret;
ret = divider_get_val(rate, parent_rate, div->table, div->width,
div->flags);
if (ret < 0)
return ret;
val = (unsigned int)ret << div->shift;
return regmap_update_bits(clk->map, div->offset,
clk_div_mask(div->width) << div->shift, val);
};
/* Would prefer clk_regmap_div_ro_ops but clashes with qcom */
const struct clk_ops clk_regmap_divider_ops = {
.recalc_rate = clk_regmap_div_recalc_rate,
.round_rate = clk_regmap_div_round_rate,
.set_rate = clk_regmap_div_set_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_divider_ops);
const struct clk_ops clk_regmap_divider_ro_ops = {
.recalc_rate = clk_regmap_div_recalc_rate,
.round_rate = clk_regmap_div_round_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops);
static u8 clk_regmap_mux_get_parent(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
unsigned int val;
int ret;
ret = regmap_read(clk->map, mux->offset, &val);
if (ret)
return ret;
val >>= mux->shift;
val &= mux->mask;
return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
}
static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index);
return regmap_update_bits(clk->map, mux->offset,
mux->mask << mux->shift,
val << mux->shift);
}
const struct clk_ops clk_regmap_mux_ops = {
.get_parent = clk_regmap_mux_get_parent,
.set_parent = clk_regmap_mux_set_parent,
.determine_rate = __clk_mux_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_mux_ops);
const struct clk_ops clk_regmap_mux_ro_ops = {
.get_parent = clk_regmap_mux_get_parent,
};
EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018 BayLibre, SAS.
// Author: Jerome Brunet <jbrunet@baylibre.com>
#ifndef __CLK_REGMAP_H
#define __CLK_REGMAP_H
#include <linux/clk-provider.h>
#include <linux/regmap.h>
/**
* struct clk_regmap - regmap backed clock
*
* @hw: handle between common and hardware-specific interfaces
* @map: pointer to the regmap structure controlling the clock
* @data: data specific to the clock type
*
* Clock which is controlled by regmap backed registers. The actual type of
* of the clock is controlled by the clock_ops and data.
*/
struct clk_regmap {
struct clk_hw hw;
struct regmap *map;
void *data;
};
#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
/**
* struct clk_regmap_gate_data - regmap backed gate specific data
*
* @offset: offset of the register controlling gate
* @bit_idx: single bit controlling gate
* @flags: hardware-specific flags
*
* Flags:
* Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored
*/
struct clk_regmap_gate_data {
unsigned int offset;
u8 bit_idx;
u8 flags;
};
static inline struct clk_regmap_gate_data *
clk_get_regmap_gate_data(struct clk_regmap *clk)
{
return (struct clk_regmap_gate_data *)clk->data;
}
extern const struct clk_ops clk_regmap_gate_ops;
/**
* struct clk_regmap_div_data - regmap backed adjustable divider specific data
*
* @offset: offset of the register controlling the divider
* @shift: shift to the divider bit field
* @width: width of the divider bit field
* @table: array of value/divider pairs, last entry should have div = 0
*
* Flags:
* Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored
*/
struct clk_regmap_div_data {
unsigned int offset;
u8 shift;
u8 width;
u8 flags;
const struct clk_div_table *table;
};
static inline struct clk_regmap_div_data *
clk_get_regmap_div_data(struct clk_regmap *clk)
{
return (struct clk_regmap_div_data *)clk->data;
}
extern const struct clk_ops clk_regmap_divider_ops;
extern const struct clk_ops clk_regmap_divider_ro_ops;
/**
* struct clk_regmap_mux_data - regmap backed multiplexer clock specific data
*
* @hw: handle between common and hardware-specific interfaces
* @offset: offset of theregister controlling multiplexer
* @table: array of parent indexed register values
* @shift: shift to multiplexer bit field
* @mask: mask of mutliplexer bit field
* @flags: hardware-specific flags
*
* Flags:
* Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored
*/
struct clk_regmap_mux_data {
unsigned int offset;
u32 *table;
u32 mask;
u8 shift;
u8 flags;
};
static inline struct clk_regmap_mux_data *
clk_get_regmap_mux_data(struct clk_regmap *clk)
{
return (struct clk_regmap_mux_data *)clk->data;
}
extern const struct clk_ops clk_regmap_mux_ops;
extern const struct clk_ops clk_regmap_mux_ro_ops;
#endif /* __CLK_REGMAP_H */
......@@ -18,6 +18,9 @@
#ifndef __CLKC_H
#define __CLKC_H
#include <linux/clk-provider.h>
#include "clk-regmap.h"
#define PMASK(width) GENMASK(width - 1, 0)
#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
......@@ -35,13 +38,29 @@ struct parm {
u8 width;
};
static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
{
unsigned int val;
regmap_read(map, p->reg_off, &val);
return PARM_GET(p->width, p->shift, val);
}
static inline void meson_parm_write(struct regmap *map, struct parm *p,
unsigned int val)
{
regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
val << p->shift);
}
struct pll_rate_table {
unsigned long rate;
u16 m;
u16 n;
u16 od;
u16 od2;
u16 frac;
u16 od3;
};
#define PLL_RATE(_r, _m, _n, _od) \
......@@ -50,97 +69,53 @@ struct pll_rate_table {
.m = (_m), \
.n = (_n), \
.od = (_od), \
} \
#define PLL_FRAC_RATE(_r, _m, _n, _od, _od2, _frac) \
{ \
.rate = (_r), \
.m = (_m), \
.n = (_n), \
.od = (_od), \
.od2 = (_od2), \
.frac = (_frac), \
} \
struct pll_params_table {
unsigned int reg_off;
unsigned int value;
};
#define PLL_PARAM(_reg, _val) \
{ \
.reg_off = (_reg), \
.value = (_val), \
}
struct pll_setup_params {
struct pll_params_table *params_table;
unsigned int params_count;
/* Workaround for GP0, do not reset before configuring */
bool no_init_reset;
/* Workaround for GP0, unreset right before checking for lock */
bool clear_reset_for_lock;
/* Workaround for GXL GP0, reset in the lock checking loop */
bool reset_lock_loop;
};
#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
struct meson_clk_pll {
struct clk_hw hw;
void __iomem *base;
struct meson_clk_pll_data {
struct parm m;
struct parm n;
struct parm frac;
struct parm od;
struct parm od2;
const struct pll_setup_params params;
const struct pll_rate_table *rate_table;
unsigned int rate_count;
spinlock_t *lock;
struct parm od3;
struct parm l;
struct parm rst;
const struct reg_sequence *init_regs;
unsigned int init_count;
const struct pll_rate_table *table;
u8 flags;
};
#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
struct meson_clk_cpu {
struct clk_hw hw;
void __iomem *base;
u16 reg_off;
struct notifier_block clk_nb;
const struct clk_div_table *div_table;
};
int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event,
void *data);
struct meson_clk_mpll {
struct clk_hw hw;
void __iomem *base;
struct meson_clk_mpll_data {
struct parm sdm;
struct parm sdm_en;
struct parm n2;
struct parm en;
struct parm ssen;
struct parm misc;
spinlock_t *lock;
};
struct meson_clk_audio_divider {
struct clk_hw hw;
void __iomem *base;
struct meson_clk_audio_div_data {
struct parm div;
u8 flags;
spinlock_t *lock;
};
#define MESON_GATE(_name, _reg, _bit) \
struct clk_gate _name = { \
.reg = (void __iomem *) _reg, \
.bit_idx = (_bit), \
.lock = &meson_clk_lock, \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = &clk_gate_ops, \
struct clk_regmap _name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (_reg), \
.bit_idx = (_bit), \
}, \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ "clk81" }, \
.num_parents = 1, \
.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
}, \
};
......
/*
* Copyright (c) 2017 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/clk-provider.h>
#include <linux/bitfield.h>
#include <linux/regmap.h>
#include "gxbb-aoclk.h"
static int aoclk_gate_regmap_enable(struct clk_hw *hw)
{
struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
return regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0,
BIT(gate->bit_idx), BIT(gate->bit_idx));
}
static void aoclk_gate_regmap_disable(struct clk_hw *hw)
{
struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0,
BIT(gate->bit_idx), 0);
}
static int aoclk_gate_regmap_is_enabled(struct clk_hw *hw)
{
struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
unsigned int val;
int ret;
ret = regmap_read(gate->regmap, AO_RTI_GEN_CNTL_REG0, &val);
if (ret)
return ret;
return (val & BIT(gate->bit_idx)) != 0;
}
const struct clk_ops meson_aoclk_gate_regmap_ops = {
.enable = aoclk_gate_regmap_enable,
.disable = aoclk_gate_regmap_disable,
.is_enabled = aoclk_gate_regmap_is_enabled,
};
......@@ -62,10 +62,9 @@
#include <linux/delay.h>
#include <dt-bindings/clock/gxbb-aoclkc.h>
#include <dt-bindings/reset/gxbb-aoclkc.h>
#include "clk-regmap.h"
#include "gxbb-aoclk.h"
static DEFINE_SPINLOCK(gxbb_aoclk_lock);
struct gxbb_aoclk_reset_controller {
struct reset_controller_dev reset;
unsigned int *data;
......@@ -87,12 +86,14 @@ static const struct reset_control_ops gxbb_aoclk_reset_ops = {
};
#define GXBB_AO_GATE(_name, _bit) \
static struct aoclk_gate_regmap _name##_ao = { \
.bit_idx = (_bit), \
.lock = &gxbb_aoclk_lock, \
static struct clk_regmap _name##_ao = { \
.data = &(struct clk_regmap_gate_data) { \
.offset = AO_RTI_GEN_CNTL_REG0, \
.bit_idx = (_bit), \
}, \
.hw.init = &(struct clk_init_data) { \
.name = #_name "_ao", \
.ops = &meson_aoclk_gate_regmap_ops, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ "clk81" }, \
.num_parents = 1, \
.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
......@@ -107,7 +108,6 @@ GXBB_AO_GATE(uart2, 5);
GXBB_AO_GATE(ir_blaster, 6);
static struct aoclk_cec_32k cec_32k_ao = {
.lock = &gxbb_aoclk_lock,
.hw.init = &(struct clk_init_data) {
.name = "cec_32k_ao",
.ops = &meson_aoclk_cec_32k_ops,
......@@ -126,7 +126,7 @@ static unsigned int gxbb_aoclk_reset[] = {
[RESET_AO_IR_BLASTER] = 23,
};
static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = {
static struct clk_regmap *gxbb_aoclk_gate[] = {
[CLKID_AO_REMOTE] = &remote_ao,
[CLKID_AO_I2C_MASTER] = &i2c_master_ao,
[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
......@@ -177,10 +177,10 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev)
* Populate regmap and register all clks
*/
for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) {
gxbb_aoclk_gate[clkid]->regmap = regmap;
gxbb_aoclk_gate[clkid]->map = regmap;
ret = devm_clk_hw_register(dev,
gxbb_aoclk_onecell_data.hws[clkid]);
gxbb_aoclk_onecell_data.hws[clkid]);
if (ret)
return ret;
}
......
......@@ -17,22 +17,11 @@
#define AO_RTC_ALT_CLK_CNTL0 0x94
#define AO_RTC_ALT_CLK_CNTL1 0x98
struct aoclk_gate_regmap {
struct clk_hw hw;
unsigned bit_idx;
struct regmap *regmap;
spinlock_t *lock;
};
#define to_aoclk_gate_regmap(_hw) \
container_of(_hw, struct aoclk_gate_regmap, hw)
extern const struct clk_ops meson_aoclk_gate_regmap_ops;
struct aoclk_cec_32k {
struct clk_hw hw;
struct regmap *regmap;
spinlock_t *lock;
};
#define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw)
......
This diff is collapsed.
......@@ -194,8 +194,18 @@
#define CLKID_VPU_1_DIV 130
#define CLKID_VAPB_0_DIV 134
#define CLKID_VAPB_1_DIV 137
#define NR_CLKS 141
#define CLKID_HDMI_PLL_PRE_MULT 141
#define CLKID_MPLL0_DIV 142
#define CLKID_MPLL1_DIV 143
#define CLKID_MPLL2_DIV 144
#define CLKID_MPLL_PREDIV 145
#define CLKID_FCLK_DIV2_DIV 146
#define CLKID_FCLK_DIV3_DIV 147
#define CLKID_FCLK_DIV4_DIV 148
#define CLKID_FCLK_DIV5_DIV 149
#define CLKID_FCLK_DIV7_DIV 150
#define NR_CLKS 151
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/gxbb-clkc.h>
......
This diff is collapsed.
......@@ -69,7 +69,22 @@
* will remain defined here.
*/
#define CLK_NR_CLKS 96
#define CLKID_MPLL0_DIV 96
#define CLKID_MPLL1_DIV 97
#define CLKID_MPLL2_DIV 98
#define CLKID_CPU_IN_SEL 99
#define CLKID_CPU_DIV2 100
#define CLKID_CPU_DIV3 101
#define CLKID_CPU_SCALE_DIV 102
#define CLKID_CPU_SCALE_OUT_SEL 103
#define CLKID_MPLL_PREDIV 104
#define CLKID_FCLK_DIV2_DIV 105
#define CLKID_FCLK_DIV3_DIV 106
#define CLKID_FCLK_DIV4_DIV 107
#define CLKID_FCLK_DIV5_DIV 108
#define CLKID_FCLK_DIV7_DIV 109
#define CLK_NR_CLKS 110
/*
* include the CLKID and RESETID that have
......
......@@ -28,22 +28,14 @@ static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_regmap_div *divider = to_clk_regmap_div(hw);
struct clk_regmap *clkr = &divider->clkr;
u32 div;
struct clk_hw *hw_parent = clk_hw_get_parent(hw);
regmap_read(clkr->regmap, divider->reg, &div);
div >>= divider->shift;
div &= BIT(divider->width) - 1;
div += 1;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
if (!hw_parent)
return -EINVAL;
u32 val;
*prate = clk_hw_round_rate(hw_parent, rate * div);
}
regmap_read(clkr->regmap, divider->reg, &val);
val >>= divider->shift;
val &= BIT(divider->width) - 1;
return DIV_ROUND_UP_ULL((u64)*prate, div);
return divider_ro_round_rate(hw, rate, prate, NULL, divider->width,
CLK_DIVIDER_ROUND_CLOSEST, val);
}
static long div_round_rate(struct clk_hw *hw, unsigned long rate,
......
......@@ -8,9 +8,11 @@ obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4412-isp.o
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5-subcmu.o
obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o
obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
......
......@@ -143,10 +143,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(reg_base)) {
dev_err(dev, "failed to map audss registers\n");
if (IS_ERR(reg_base))
return PTR_ERR(reg_base);
}
epll = ERR_PTR(-ENODEV);
......
......@@ -670,73 +670,73 @@ static const struct samsung_gate_clock gate_clks[] __initconst = {
/* APLL & MPLL & BPLL & UPLL */
static const struct samsung_pll_rate_table exynos3250_pll_rates[] __initconst = {
PLL_35XX_RATE(1200000000, 400, 4, 1),
PLL_35XX_RATE(1100000000, 275, 3, 1),
PLL_35XX_RATE(1066000000, 533, 6, 1),
PLL_35XX_RATE(1000000000, 250, 3, 1),
PLL_35XX_RATE( 960000000, 320, 4, 1),
PLL_35XX_RATE( 900000000, 300, 4, 1),
PLL_35XX_RATE( 850000000, 425, 6, 1),
PLL_35XX_RATE( 800000000, 200, 3, 1),
PLL_35XX_RATE( 700000000, 175, 3, 1),
PLL_35XX_RATE( 667000000, 667, 12, 1),
PLL_35XX_RATE( 600000000, 400, 4, 2),
PLL_35XX_RATE( 533000000, 533, 6, 2),
PLL_35XX_RATE( 520000000, 260, 3, 2),
PLL_35XX_RATE( 500000000, 250, 3, 2),
PLL_35XX_RATE( 400000000, 200, 3, 2),
PLL_35XX_RATE( 200000000, 200, 3, 3),
PLL_35XX_RATE( 100000000, 200, 3, 4),
PLL_35XX_RATE(24 * MHZ, 1200000000, 400, 4, 1),
PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1),
PLL_35XX_RATE(24 * MHZ, 1066000000, 533, 6, 1),
PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1),
PLL_35XX_RATE(24 * MHZ, 960000000, 320, 4, 1),
PLL_35XX_RATE(24 * MHZ, 900000000, 300, 4, 1),
PLL_35XX_RATE(24 * MHZ, 850000000, 425, 6, 1),
PLL_35XX_RATE(24 * MHZ, 800000000, 200, 3, 1),
PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1),
PLL_35XX_RATE(24 * MHZ, 667000000, 667, 12, 1),
PLL_35XX_RATE(24 * MHZ, 600000000, 400, 4, 2),
PLL_35XX_RATE(24 * MHZ, 533000000, 533, 6, 2),
PLL_35XX_RATE(24 * MHZ, 520000000, 260, 3, 2),
PLL_35XX_RATE(24 * MHZ, 500000000, 250, 3, 2),
PLL_35XX_RATE(24 * MHZ, 400000000, 200, 3, 2),
PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3),
PLL_35XX_RATE(24 * MHZ, 100000000, 200, 3, 4),
{ /* sentinel */ }
};
/* EPLL */
static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst = {
PLL_36XX_RATE(800000000, 200, 3, 1, 0),
PLL_36XX_RATE(288000000, 96, 2, 2, 0),
PLL_36XX_RATE(192000000, 128, 2, 3, 0),
PLL_36XX_RATE(144000000, 96, 2, 3, 0),
PLL_36XX_RATE( 96000000, 128, 2, 4, 0),
PLL_36XX_RATE( 84000000, 112, 2, 4, 0),
PLL_36XX_RATE( 80000004, 106, 2, 4, 43691),
PLL_36XX_RATE( 73728000, 98, 2, 4, 19923),
PLL_36XX_RATE( 67737598, 270, 3, 5, 62285),
PLL_36XX_RATE( 65535999, 174, 2, 5, 49982),
PLL_36XX_RATE( 50000000, 200, 3, 5, 0),
PLL_36XX_RATE( 49152002, 131, 2, 5, 4719),
PLL_36XX_RATE( 48000000, 128, 2, 5, 0),
PLL_36XX_RATE( 45158401, 180, 3, 5, 41524),
PLL_36XX_RATE(24 * MHZ, 800000000, 200, 3, 1, 0),
PLL_36XX_RATE(24 * MHZ, 288000000, 96, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 192000000, 128, 2, 3, 0),
PLL_36XX_RATE(24 * MHZ, 144000000, 96, 2, 3, 0),
PLL_36XX_RATE(24 * MHZ, 96000000, 128, 2, 4, 0),
PLL_36XX_RATE(24 * MHZ, 84000000, 112, 2, 4, 0),
PLL_36XX_RATE(24 * MHZ, 80000003, 106, 2, 4, 43691),
PLL_36XX_RATE(24 * MHZ, 73728000, 98, 2, 4, 19923),
PLL_36XX_RATE(24 * MHZ, 67737598, 270, 3, 5, 62285),
PLL_36XX_RATE(24 * MHZ, 65535999, 174, 2, 5, 49982),
PLL_36XX_RATE(24 * MHZ, 50000000, 200, 3, 5, 0),
PLL_36XX_RATE(24 * MHZ, 49152002, 131, 2, 5, 4719),
PLL_36XX_RATE(24 * MHZ, 48000000, 128, 2, 5, 0),
PLL_36XX_RATE(24 * MHZ, 45158401, 180, 3, 5, 41524),
{ /* sentinel */ }
};
/* VPLL */
static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst = {
PLL_36XX_RATE(600000000, 100, 2, 1, 0),
PLL_36XX_RATE(533000000, 266, 3, 2, 32768),
PLL_36XX_RATE(519230987, 173, 2, 2, 5046),
PLL_36XX_RATE(500000000, 250, 3, 2, 0),
PLL_36XX_RATE(445500000, 148, 2, 2, 32768),
PLL_36XX_RATE(445055007, 148, 2, 2, 23047),
PLL_36XX_RATE(400000000, 200, 3, 2, 0),
PLL_36XX_RATE(371250000, 123, 2, 2, 49152),
PLL_36XX_RATE(370878997, 185, 3, 2, 28803),
PLL_36XX_RATE(340000000, 170, 3, 2, 0),
PLL_36XX_RATE(335000015, 111, 2, 2, 43691),
PLL_36XX_RATE(333000000, 111, 2, 2, 0),
PLL_36XX_RATE(330000000, 110, 2, 2, 0),
PLL_36XX_RATE(320000015, 106, 2, 2, 43691),
PLL_36XX_RATE(300000000, 100, 2, 2, 0),
PLL_36XX_RATE(275000000, 275, 3, 3, 0),
PLL_36XX_RATE(222750000, 148, 2, 3, 32768),
PLL_36XX_RATE(222528007, 148, 2, 3, 23069),
PLL_36XX_RATE(160000000, 160, 3, 3, 0),
PLL_36XX_RATE(148500000, 99, 2, 3, 0),
PLL_36XX_RATE(148352005, 98, 2, 3, 59070),
PLL_36XX_RATE(108000000, 144, 2, 4, 0),
PLL_36XX_RATE( 74250000, 99, 2, 4, 0),
PLL_36XX_RATE( 74176002, 98, 3, 4, 59070),
PLL_36XX_RATE( 54054000, 216, 3, 5, 14156),
PLL_36XX_RATE( 54000000, 144, 2, 5, 0),
PLL_36XX_RATE(24 * MHZ, 600000000, 100, 2, 1, 0),
PLL_36XX_RATE(24 * MHZ, 533000000, 266, 3, 2, 32768),
PLL_36XX_RATE(24 * MHZ, 519230987, 173, 2, 2, 5046),
PLL_36XX_RATE(24 * MHZ, 500000000, 250, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 445500000, 148, 2, 2, 32768),
PLL_36XX_RATE(24 * MHZ, 445055007, 148, 2, 2, 23047),
PLL_36XX_RATE(24 * MHZ, 400000000, 200, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 371250000, 123, 2, 2, 49152),
PLL_36XX_RATE(24 * MHZ, 370878997, 185, 3, 2, 28803),
PLL_36XX_RATE(24 * MHZ, 340000000, 170, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 335000015, 111, 2, 2, 43691),
PLL_36XX_RATE(24 * MHZ, 333000000, 111, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 330000000, 110, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 320000015, 106, 2, 2, 43691),
PLL_36XX_RATE(24 * MHZ, 300000000, 100, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 275000000, 275, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 222750000, 148, 2, 3, 32768),
PLL_36XX_RATE(24 * MHZ, 222528007, 148, 2, 3, 23069),
PLL_36XX_RATE(24 * MHZ, 160000000, 160, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 148500000, 99, 2, 3, 0),
PLL_36XX_RATE(24 * MHZ, 148352005, 98, 2, 3, 59070),
PLL_36XX_RATE(24 * MHZ, 108000000, 144, 2, 4, 0),
PLL_36XX_RATE(24 * MHZ, 74250000, 99, 2, 4, 0),
PLL_36XX_RATE(24 * MHZ, 74176002, 98, 2, 4, 59070),
PLL_36XX_RATE(24 * MHZ, 54054000, 216, 3, 5, 14156),
PLL_36XX_RATE(24 * MHZ, 54000000, 144, 2, 5, 0),
{ /* sentinel */ }
};
......
......@@ -1266,77 +1266,78 @@ static const struct of_device_id ext_clk_match[] __initconst = {
/* PLLs PMS values */
static const struct samsung_pll_rate_table exynos4210_apll_rates[] __initconst = {
PLL_45XX_RATE(1200000000, 150, 3, 1, 28),
PLL_45XX_RATE(1000000000, 250, 6, 1, 28),
PLL_45XX_RATE( 800000000, 200, 6, 1, 28),
PLL_45XX_RATE( 666857142, 389, 14, 1, 13),
PLL_45XX_RATE( 600000000, 100, 4, 1, 13),
PLL_45XX_RATE( 533000000, 533, 24, 1, 5),
PLL_45XX_RATE( 500000000, 250, 6, 2, 28),
PLL_45XX_RATE( 400000000, 200, 6, 2, 28),
PLL_45XX_RATE( 200000000, 200, 6, 3, 28),
PLL_4508_RATE(24 * MHZ, 1200000000, 150, 3, 1, 28),
PLL_4508_RATE(24 * MHZ, 1000000000, 250, 6, 1, 28),
PLL_4508_RATE(24 * MHZ, 800000000, 200, 6, 1, 28),
PLL_4508_RATE(24 * MHZ, 666857142, 389, 14, 1, 13),
PLL_4508_RATE(24 * MHZ, 600000000, 100, 4, 1, 13),
PLL_4508_RATE(24 * MHZ, 533000000, 533, 24, 1, 5),
PLL_4508_RATE(24 * MHZ, 500000000, 250, 6, 2, 28),
PLL_4508_RATE(24 * MHZ, 400000000, 200, 6, 2, 28),
PLL_4508_RATE(24 * MHZ, 200000000, 200, 6, 3, 28),
{ /* sentinel */ }
};
static const struct samsung_pll_rate_table exynos4210_epll_rates[] __initconst = {
PLL_4600_RATE(192000000, 48, 3, 1, 0, 0),
PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0),
PLL_4600_RATE(180000000, 45, 3, 1, 0, 0),
PLL_4600_RATE( 73727996, 73, 3, 3, 47710, 1),
PLL_4600_RATE( 67737602, 90, 4, 3, 20762, 1),
PLL_4600_RATE( 49151992, 49, 3, 3, 9961, 0),
PLL_4600_RATE( 45158401, 45, 3, 3, 10381, 0),
PLL_4600_RATE(24 * MHZ, 192000000, 48, 3, 1, 0, 0),
PLL_4600_RATE(24 * MHZ, 180633605, 45, 3, 1, 10381, 0),
PLL_4600_RATE(24 * MHZ, 180000000, 45, 3, 1, 0, 0),
PLL_4600_RATE(24 * MHZ, 73727996, 73, 3, 3, 47710, 1),
PLL_4600_RATE(24 * MHZ, 67737602, 90, 4, 3, 20762, 1),
PLL_4600_RATE(24 * MHZ, 49151992, 49, 3, 3, 9961, 0),
PLL_4600_RATE(24 * MHZ, 45158401, 45, 3, 3, 10381, 0),
{ /* sentinel */ }
};
static const struct samsung_pll_rate_table exynos4210_vpll_rates[] __initconst = {
PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0),
PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1, 1, 1),
PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1),
PLL_4650_RATE(110000000, 53, 3, 2, 2048, 0, 17, 0),
PLL_4650_RATE( 55360351, 53, 3, 3, 2417, 0, 17, 0),
PLL_4650_RATE(24 * MHZ, 360000000, 44, 3, 0, 1024, 0, 14, 0),
PLL_4650_RATE(24 * MHZ, 324000000, 53, 2, 1, 1024, 1, 1, 1),
PLL_4650_RATE(24 * MHZ, 259617187, 63, 3, 1, 1950, 0, 20, 1),
PLL_4650_RATE(24 * MHZ, 110000000, 53, 3, 2, 2048, 0, 17, 0),
PLL_4650_RATE(24 * MHZ, 55360351, 53, 3, 3, 2417, 0, 17, 0),
{ /* sentinel */ }
};
static const struct samsung_pll_rate_table exynos4x12_apll_rates[] __initconst = {
PLL_35XX_RATE(1704000000, 213, 3, 0),
PLL_35XX_RATE(1600000000, 200, 3, 0),
PLL_35XX_RATE(1500000000, 250, 4, 0),
PLL_35XX_RATE(1400000000, 175, 3, 0),
PLL_35XX_RATE(1300000000, 325, 6, 0),
PLL_35XX_RATE(1200000000, 200, 4, 0),
PLL_35XX_RATE(1100000000, 275, 6, 0),
PLL_35XX_RATE(1000000000, 125, 3, 0),
PLL_35XX_RATE( 900000000, 150, 4, 0),
PLL_35XX_RATE( 800000000, 100, 3, 0),
PLL_35XX_RATE( 700000000, 175, 3, 1),
PLL_35XX_RATE( 600000000, 200, 4, 1),
PLL_35XX_RATE( 500000000, 125, 3, 1),
PLL_35XX_RATE( 400000000, 100, 3, 1),
PLL_35XX_RATE( 300000000, 200, 4, 2),
PLL_35XX_RATE( 200000000, 100, 3, 2),
PLL_35XX_RATE(24 * MHZ, 1704000000, 213, 3, 0),
PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0),
PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0),
PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0),
PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 4, 0),
PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1000000000, 125, 3, 0),
PLL_35XX_RATE(24 * MHZ, 900000000, 150, 4, 0),
PLL_35XX_RATE(24 * MHZ, 800000000, 100, 3, 0),
PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1),
PLL_35XX_RATE(24 * MHZ, 600000000, 200, 4, 1),
PLL_35XX_RATE(24 * MHZ, 500000000, 125, 3, 1),
PLL_35XX_RATE(24 * MHZ, 400000000, 100, 3, 1),
PLL_35XX_RATE(24 * MHZ, 300000000, 200, 4, 2),
PLL_35XX_RATE(24 * MHZ, 200000000, 100, 3, 2),
{ /* sentinel */ }
};
static const struct samsung_pll_rate_table exynos4x12_epll_rates[] __initconst = {
PLL_36XX_RATE(192000000, 48, 3, 1, 0),
PLL_36XX_RATE(180633605, 45, 3, 1, 10381),
PLL_36XX_RATE(180000000, 45, 3, 1, 0),
PLL_36XX_RATE( 73727996, 73, 3, 3, 47710),
PLL_36XX_RATE( 67737602, 90, 4, 3, 20762),
PLL_36XX_RATE( 49151992, 49, 3, 3, 9961),
PLL_36XX_RATE( 45158401, 45, 3, 3, 10381),
PLL_36XX_RATE(24 * MHZ, 196608001, 197, 3, 3, -25690),
PLL_36XX_RATE(24 * MHZ, 192000000, 48, 3, 1, 0),
PLL_36XX_RATE(24 * MHZ, 180633605, 45, 3, 1, 10381),
PLL_36XX_RATE(24 * MHZ, 180000000, 45, 3, 1, 0),
PLL_36XX_RATE(24 * MHZ, 73727996, 73, 3, 3, 47710),
PLL_36XX_RATE(24 * MHZ, 67737602, 90, 4, 3, 20762),
PLL_36XX_RATE(24 * MHZ, 49151992, 49, 3, 3, 9961),
PLL_36XX_RATE(24 * MHZ, 45158401, 45, 3, 3, 10381),
{ /* sentinel */ }
};
static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = {
PLL_36XX_RATE(533000000, 133, 3, 1, 16384),
PLL_36XX_RATE(440000000, 110, 3, 1, 0),
PLL_36XX_RATE(350000000, 175, 3, 2, 0),
PLL_36XX_RATE(266000000, 133, 3, 2, 0),
PLL_36XX_RATE(160000000, 160, 3, 3, 0),
PLL_36XX_RATE(106031250, 53, 3, 2, 1024),
PLL_36XX_RATE( 53015625, 53, 3, 3, 1024),
PLL_36XX_RATE(24 * MHZ, 533000000, 133, 3, 1, 16384),
PLL_36XX_RATE(24 * MHZ, 440000000, 110, 3, 1, 0),
PLL_36XX_RATE(24 * MHZ, 350000000, 175, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 266000000, 133, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 160000000, 160, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 106031250, 53, 3, 2, 1024),
PLL_36XX_RATE(24 * MHZ, 53015625, 53, 3, 3, 1024),
{ /* sentinel */ }
};
......
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2018 Samsung Electronics Co., Ltd.
// Author: Marek Szyprowski <m.szyprowski@samsung.com>
// Common Clock Framework support for Exynos5 power-domain dependent clocks
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include "clk.h"
#include "clk-exynos5-subcmu.h"
static struct samsung_clk_provider *ctx;
static const struct exynos5_subcmu_info *cmu;
static int nr_cmus;
static void exynos5_subcmu_clk_save(void __iomem *base,
struct exynos5_subcmu_reg_dump *rd,
unsigned int num_regs)
{
for (; num_regs > 0; --num_regs, ++rd) {
rd->save = readl(base + rd->offset);
writel((rd->save & ~rd->mask) | rd->value, base + rd->offset);
rd->save &= rd->mask;
}
};
static void exynos5_subcmu_clk_restore(void __iomem *base,
struct exynos5_subcmu_reg_dump *rd,
unsigned int num_regs)
{
for (; num_regs > 0; --num_regs, ++rd)
writel((readl(base + rd->offset) & ~rd->mask) | rd->save,
base + rd->offset);
}
static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx,
const struct samsung_gate_clock *list, int nr_clk)
{
while (nr_clk--)
samsung_clk_add_lookup(ctx, ERR_PTR(-EPROBE_DEFER), list++->id);
}
/*
* Pass the needed clock provider context and register sub-CMU clocks
*
* NOTE: This function has to be called from the main, OF_CLK_DECLARE-
* initialized clock provider driver. This happens very early during boot
* process. Then this driver, during core_initcall registers two platform
* drivers: one which binds to the same device-tree node as OF_CLK_DECLARE
* driver and second, for handling its per-domain child-devices. Those
* platform drivers are bound to their devices a bit later in arch_initcall,
* when OF-core populates all device-tree nodes.
*/
void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus,
const struct exynos5_subcmu_info *_cmu)
{
ctx = _ctx;
cmu = _cmu;
nr_cmus = _nr_cmus;
for (; _nr_cmus--; _cmu++) {
exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks,
_cmu->nr_gate_clks);
exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs,
_cmu->nr_suspend_regs);
}
}
static int __maybe_unused exynos5_subcmu_suspend(struct device *dev)
{
struct exynos5_subcmu_info *info = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&ctx->lock, flags);
exynos5_subcmu_clk_save(ctx->reg_base, info->suspend_regs,
info->nr_suspend_regs);
spin_unlock_irqrestore(&ctx->lock, flags);
return 0;
}
static int __maybe_unused exynos5_subcmu_resume(struct device *dev)
{
struct exynos5_subcmu_info *info = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&ctx->lock, flags);
exynos5_subcmu_clk_restore(ctx->reg_base, info->suspend_regs,
info->nr_suspend_regs);
spin_unlock_irqrestore(&ctx->lock, flags);
return 0;
}
static int __init exynos5_subcmu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct exynos5_subcmu_info *info = dev_get_drvdata(dev);
pm_runtime_set_suspended(dev);
pm_runtime_enable(dev);
pm_runtime_get(dev);
ctx->dev = dev;
samsung_clk_register_div(ctx, info->div_clks, info->nr_div_clks);
samsung_clk_register_gate(ctx, info->gate_clks, info->nr_gate_clks);
ctx->dev = NULL;
pm_runtime_put_sync(dev);
return 0;
}
static const struct dev_pm_ops exynos5_subcmu_pm_ops = {
SET_RUNTIME_PM_OPS(exynos5_subcmu_suspend,
exynos5_subcmu_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver exynos5_subcmu_driver __refdata = {
.driver = {
.name = "exynos5-subcmu",
.suppress_bind_attrs = true,
.pm = &exynos5_subcmu_pm_ops,
},
.probe = exynos5_subcmu_probe,
};
static int __init exynos5_clk_register_subcmu(struct device *parent,
const struct exynos5_subcmu_info *info,
struct device_node *pd_node)
{
struct of_phandle_args genpdspec = { .np = pd_node };
struct platform_device *pdev;
pdev = platform_device_alloc(info->pd_name, -1);
pdev->dev.parent = parent;
pdev->driver_override = "exynos5-subcmu";
platform_set_drvdata(pdev, (void *)info);
of_genpd_add_device(&genpdspec, &pdev->dev);
platform_device_add(pdev);
return 0;
}
static int __init exynos5_clk_probe(struct platform_device *pdev)
{
struct device_node *np;
const char *name;
int i;
for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
if (of_property_read_string(np, "label", &name) < 0)
continue;
for (i = 0; i < nr_cmus; i++)
if (strcmp(cmu[i].pd_name, name) == 0)
exynos5_clk_register_subcmu(&pdev->dev,
&cmu[i], np);
}
return 0;
}
static const struct of_device_id exynos5_clk_of_match[] = {
{ .compatible = "samsung,exynos5250-clock", },
{ .compatible = "samsung,exynos5420-clock", },
{ .compatible = "samsung,exynos5800-clock", },
{ },
};
static struct platform_driver exynos5_clk_driver __refdata = {
.driver = {
.name = "exynos5-clock",
.of_match_table = exynos5_clk_of_match,
.suppress_bind_attrs = true,
},
.probe = exynos5_clk_probe,
};
static int __init exynos5_clk_drv_init(void)
{
platform_driver_register(&exynos5_clk_driver);
platform_driver_register(&exynos5_subcmu_driver);
return 0;
}
core_initcall(exynos5_clk_drv_init);
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __CLK_EXYNOS5_SUBCMU_H
#define __CLK_EXYNOS5_SUBCMU_H
struct exynos5_subcmu_reg_dump {
u32 offset;
u32 value;
u32 mask;
u32 save;
};
struct exynos5_subcmu_info {
const struct samsung_div_clock *div_clks;
unsigned int nr_div_clks;
const struct samsung_gate_clock *gate_clks;
unsigned int nr_gate_clks;
struct exynos5_subcmu_reg_dump *suspend_regs;
unsigned int nr_suspend_regs;
const char *pd_name;
};
void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus,
const struct exynos5_subcmu_info *cmu);
#endif
......@@ -18,6 +18,7 @@
#include "clk.h"
#include "clk-cpu.h"
#include "clk-exynos5-subcmu.h"
#define APLL_LOCK 0x0
#define APLL_CON0 0x100
......@@ -560,6 +561,8 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
0),
GATE(CLK_GSCL3, "gscl3", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 3, 0,
0),
GATE(CLK_CAMIF_TOP, "camif_top", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 4, 0, 0),
GATE(CLK_GSCL_WA, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0),
GATE(CLK_GSCL_WB, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0),
GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "mout_aclk266_gscl_sub",
......@@ -570,18 +573,11 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
GATE_IP_GSCL, 9, 0, 0),
GATE(CLK_SMMU_GSCL3, "smmu_gscl3", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 10, 0, 0),
GATE(CLK_SMMU_FIMC_LITE0, "smmu_fimc_lite0", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 11, 0, 0),
GATE(CLK_SMMU_FIMC_LITE1, "smmu_fimc_lite1", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 12, 0, 0),
GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0,
0),
GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0,
0),
GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0,
0),
GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0),
GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0,
0),
GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0,
0),
GATE(CLK_MFC, "mfc", "mout_aclk333_sub", GATE_IP_MFC, 0, 0, 0),
GATE(CLK_SMMU_MFCR, "smmu_mfcr", "mout_aclk333_sub", GATE_IP_MFC, 1, 0,
......@@ -671,10 +667,6 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0),
GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0),
GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0),
GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub",
GATE_IP_DISP1, 9, 0, 0),
GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub",
GATE_IP_DISP1, 8, 0, 0),
GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0),
GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub",
GATE_IP_ISP0, 8, 0, 0),
......@@ -698,48 +690,80 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
GATE_IP_ISP1, 7, 0, 0),
};
static const struct samsung_gate_clock exynos5250_disp_gate_clks[] __initconst = {
GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0,
0),
GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0,
0),
GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0,
0),
GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0),
GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0,
0),
GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0,
0),
GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub",
GATE_IP_DISP1, 9, 0, 0),
GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub",
GATE_IP_DISP1, 8, 0, 0),
};
static struct exynos5_subcmu_reg_dump exynos5250_disp_suspend_regs[] = {
{ GATE_IP_DISP1, 0xffffffff, 0xffffffff }, /* DISP1 gates */
{ SRC_TOP3, 0, BIT(4) }, /* MUX mout_aclk200_disp1_sub */
{ SRC_TOP3, 0, BIT(6) }, /* MUX mout_aclk300_disp1_sub */
};
static const struct exynos5_subcmu_info exynos5250_disp_subcmu = {
.gate_clks = exynos5250_disp_gate_clks,
.nr_gate_clks = ARRAY_SIZE(exynos5250_disp_gate_clks),
.suspend_regs = exynos5250_disp_suspend_regs,
.nr_suspend_regs = ARRAY_SIZE(exynos5250_disp_suspend_regs),
.pd_name = "DISP1",
};
static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
PLL_36XX_RATE(266000000, 266, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 266000000, 266, 3, 3, 0),
/* Not in UM, but need for eDP on snow */
PLL_36XX_RATE(70500000, 94, 2, 4, 0),
PLL_36XX_RATE(24 * MHZ, 70500000, 94, 2, 4, 0),
{ },
};
static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = {
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
PLL_36XX_RATE(192000000, 64, 2, 2, 0),
PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
PLL_36XX_RATE(180000000, 90, 3, 2, 0),
PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
PLL_36XX_RATE(24 * MHZ, 192000000, 64, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 180633605, 90, 3, 2, 20762),
PLL_36XX_RATE(24 * MHZ, 180000000, 90, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 73728000, 98, 2, 4, 19923),
PLL_36XX_RATE(24 * MHZ, 67737602, 90, 2, 4, 20762),
PLL_36XX_RATE(24 * MHZ, 49152000, 98, 3, 4, 19923),
PLL_36XX_RATE(24 * MHZ, 45158401, 90, 3, 4, 20762),
PLL_36XX_RATE(24 * MHZ, 32768001, 131, 3, 5, 4719),
{ },
};
static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = {
/* sorted in descending order */
/* PLL_35XX_RATE(rate, m, p, s) */
PLL_35XX_RATE(1700000000, 425, 6, 0),
PLL_35XX_RATE(1600000000, 200, 3, 0),
PLL_35XX_RATE(1500000000, 250, 4, 0),
PLL_35XX_RATE(1400000000, 175, 3, 0),
PLL_35XX_RATE(1300000000, 325, 6, 0),
PLL_35XX_RATE(1200000000, 200, 4, 0),
PLL_35XX_RATE(1100000000, 275, 6, 0),
PLL_35XX_RATE(1000000000, 125, 3, 0),
PLL_35XX_RATE(900000000, 150, 4, 0),
PLL_35XX_RATE(800000000, 100, 3, 0),
PLL_35XX_RATE(700000000, 175, 3, 1),
PLL_35XX_RATE(600000000, 200, 4, 1),
PLL_35XX_RATE(500000000, 125, 3, 1),
PLL_35XX_RATE(400000000, 100, 3, 1),
PLL_35XX_RATE(300000000, 200, 4, 2),
PLL_35XX_RATE(200000000, 100, 3, 2),
/* PLL_35XX_RATE(fin, rate, m, p, s) */
PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0),
PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0),
PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0),
PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 4, 0),
PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1000000000, 125, 3, 0),
PLL_35XX_RATE(24 * MHZ, 900000000, 150, 4, 0),
PLL_35XX_RATE(24 * MHZ, 800000000, 100, 3, 0),
PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1),
PLL_35XX_RATE(24 * MHZ, 600000000, 200, 4, 1),
PLL_35XX_RATE(24 * MHZ, 500000000, 125, 3, 1),
PLL_35XX_RATE(24 * MHZ, 400000000, 100, 3, 1),
PLL_35XX_RATE(24 * MHZ, 300000000, 200, 4, 2),
PLL_35XX_RATE(24 * MHZ, 200000000, 100, 3, 2),
};
static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
......@@ -859,10 +883,11 @@ static void __init exynos5250_clk_init(struct device_node *np)
__raw_writel(tmp, reg_base + PWR_CTRL2);
exynos5250_clk_sleep_init();
exynos5_subcmus_init(ctx, 1, &exynos5250_disp_subcmu);
samsung_clk_of_add_provider(np, ctx);
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
_get_rate("div_arm2"));
}
CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
CLK_OF_DECLARE_DRIVER(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
......@@ -23,57 +23,57 @@
* DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL.
*/
static const struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initconst = {
PLL_35XX_RATE(1700000000, 425, 6, 0),
PLL_35XX_RATE(1600000000, 200, 3, 0),
PLL_35XX_RATE(1500000000, 250, 4, 0),
PLL_35XX_RATE(1400000000, 175, 3, 0),
PLL_35XX_RATE(1300000000, 325, 6, 0),
PLL_35XX_RATE(1200000000, 400, 4, 1),
PLL_35XX_RATE(1100000000, 275, 3, 1),
PLL_35XX_RATE(1000000000, 250, 3, 1),
PLL_35XX_RATE(933000000, 311, 4, 1),
PLL_35XX_RATE(900000000, 300, 4, 1),
PLL_35XX_RATE(800000000, 200, 3, 1),
PLL_35XX_RATE(733000000, 733, 12, 1),
PLL_35XX_RATE(700000000, 175, 3, 1),
PLL_35XX_RATE(667000000, 667, 12, 1),
PLL_35XX_RATE(633000000, 211, 4, 1),
PLL_35XX_RATE(620000000, 310, 3, 2),
PLL_35XX_RATE(600000000, 400, 4, 2),
PLL_35XX_RATE(543000000, 362, 4, 2),
PLL_35XX_RATE(533000000, 533, 6, 2),
PLL_35XX_RATE(500000000, 250, 3, 2),
PLL_35XX_RATE(450000000, 300, 4, 2),
PLL_35XX_RATE(400000000, 200, 3, 2),
PLL_35XX_RATE(350000000, 175, 3, 2),
PLL_35XX_RATE(300000000, 400, 4, 3),
PLL_35XX_RATE(266000000, 266, 3, 3),
PLL_35XX_RATE(200000000, 200, 3, 3),
PLL_35XX_RATE(160000000, 160, 3, 3),
PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0),
PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0),
PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0),
PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1200000000, 400, 4, 1),
PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1),
PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1),
PLL_35XX_RATE(24 * MHZ, 933000000, 311, 4, 1),
PLL_35XX_RATE(24 * MHZ, 900000000, 300, 4, 1),
PLL_35XX_RATE(24 * MHZ, 800000000, 200, 3, 1),
PLL_35XX_RATE(24 * MHZ, 733000000, 733, 12, 1),
PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1),
PLL_35XX_RATE(24 * MHZ, 667000000, 667, 12, 1),
PLL_35XX_RATE(24 * MHZ, 633000000, 211, 4, 1),
PLL_35XX_RATE(24 * MHZ, 620000000, 310, 3, 2),
PLL_35XX_RATE(24 * MHZ, 600000000, 400, 4, 2),
PLL_35XX_RATE(24 * MHZ, 543000000, 362, 4, 2),
PLL_35XX_RATE(24 * MHZ, 533000000, 533, 6, 2),
PLL_35XX_RATE(24 * MHZ, 500000000, 250, 3, 2),
PLL_35XX_RATE(24 * MHZ, 450000000, 300, 4, 2),
PLL_35XX_RATE(24 * MHZ, 400000000, 200, 3, 2),
PLL_35XX_RATE(24 * MHZ, 350000000, 175, 3, 2),
PLL_35XX_RATE(24 * MHZ, 300000000, 400, 4, 3),
PLL_35XX_RATE(24 * MHZ, 266000000, 266, 3, 3),
PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3),
PLL_35XX_RATE(24 * MHZ, 160000000, 160, 3, 3),
};
/*
* Applicable for 2650 Type PLL for AUD_PLL.
*/
static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = {
PLL_36XX_RATE(1600000000, 200, 3, 0, 0),
PLL_36XX_RATE(1200000000, 100, 2, 0, 0),
PLL_36XX_RATE(1000000000, 250, 3, 1, 0),
PLL_36XX_RATE(800000000, 200, 3, 1, 0),
PLL_36XX_RATE(600000000, 100, 2, 1, 0),
PLL_36XX_RATE(532000000, 266, 3, 2, 0),
PLL_36XX_RATE(480000000, 160, 2, 2, 0),
PLL_36XX_RATE(432000000, 144, 2, 2, 0),
PLL_36XX_RATE(400000000, 200, 3, 2, 0),
PLL_36XX_RATE(394073130, 459, 7, 2, 49282),
PLL_36XX_RATE(333000000, 111, 2, 2, 0),
PLL_36XX_RATE(300000000, 100, 2, 2, 0),
PLL_36XX_RATE(266000000, 266, 3, 3, 0),
PLL_36XX_RATE(200000000, 200, 3, 3, 0),
PLL_36XX_RATE(166000000, 166, 3, 3, 0),
PLL_36XX_RATE(133000000, 266, 3, 4, 0),
PLL_36XX_RATE(100000000, 200, 3, 4, 0),
PLL_36XX_RATE(66000000, 176, 2, 5, 0),
PLL_36XX_RATE(24 * MHZ, 1600000000, 200, 3, 0, 0),
PLL_36XX_RATE(24 * MHZ, 1200000000, 100, 2, 0, 0),
PLL_36XX_RATE(24 * MHZ, 1000000000, 250, 3, 1, 0),
PLL_36XX_RATE(24 * MHZ, 800000000, 200, 3, 1, 0),
PLL_36XX_RATE(24 * MHZ, 600000000, 100, 2, 1, 0),
PLL_36XX_RATE(24 * MHZ, 532000000, 266, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 480000000, 160, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 432000000, 144, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 400000000, 200, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 394073128, 459, 7, 2, 49282),
PLL_36XX_RATE(24 * MHZ, 333000000, 111, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 300000000, 100, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 266000000, 266, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 200000000, 200, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 166000000, 166, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 133000000, 266, 3, 4, 0),
PLL_36XX_RATE(24 * MHZ, 100000000, 200, 3, 4, 0),
PLL_36XX_RATE(24 * MHZ, 66000000, 176, 2, 5, 0),
};
/* CMU_AUD */
......
......@@ -226,16 +226,16 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = {
};
static const struct samsung_pll_rate_table exynos5410_pll2550x_24mhz_tbl[] __initconst = {
PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
PLL_36XX_RATE(333000000U, 111, 2, 2, 0),
PLL_36XX_RATE(300000000U, 100, 2, 2, 0),
PLL_36XX_RATE(266000000U, 266, 3, 3, 0),
PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
PLL_36XX_RATE(192000000U, 192, 3, 3, 0),
PLL_36XX_RATE(166000000U, 166, 3, 3, 0),
PLL_36XX_RATE(133000000U, 266, 3, 4, 0),
PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
PLL_36XX_RATE(66000000U, 176, 2, 5, 0),
PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 333000000U, 111, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 300000000U, 100, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 266000000U, 266, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 200000000U, 200, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 192000000U, 192, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 166000000U, 166, 3, 3, 0),
PLL_36XX_RATE(24 * MHZ, 133000000U, 266, 3, 4, 0),
PLL_36XX_RATE(24 * MHZ, 100000000U, 200, 3, 4, 0),
PLL_36XX_RATE(24 * MHZ, 66000000U, 176, 2, 5, 0),
};
static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
......
This diff is collapsed.
......@@ -703,68 +703,69 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
* & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL
*/
static const struct samsung_pll_rate_table exynos5433_pll_rates[] __initconst = {
PLL_35XX_RATE(2500000000U, 625, 6, 0),
PLL_35XX_RATE(2400000000U, 500, 5, 0),
PLL_35XX_RATE(2300000000U, 575, 6, 0),
PLL_35XX_RATE(2200000000U, 550, 6, 0),
PLL_35XX_RATE(2100000000U, 350, 4, 0),
PLL_35XX_RATE(2000000000U, 500, 6, 0),
PLL_35XX_RATE(1900000000U, 475, 6, 0),
PLL_35XX_RATE(1800000000U, 375, 5, 0),
PLL_35XX_RATE(1700000000U, 425, 6, 0),
PLL_35XX_RATE(1600000000U, 400, 6, 0),
PLL_35XX_RATE(1500000000U, 250, 4, 0),
PLL_35XX_RATE(1400000000U, 350, 6, 0),
PLL_35XX_RATE(1332000000U, 222, 4, 0),
PLL_35XX_RATE(1300000000U, 325, 6, 0),
PLL_35XX_RATE(1200000000U, 500, 5, 1),
PLL_35XX_RATE(1100000000U, 550, 6, 1),
PLL_35XX_RATE(1086000000U, 362, 4, 1),
PLL_35XX_RATE(1066000000U, 533, 6, 1),
PLL_35XX_RATE(1000000000U, 500, 6, 1),
PLL_35XX_RATE(933000000U, 311, 4, 1),
PLL_35XX_RATE(921000000U, 307, 4, 1),
PLL_35XX_RATE(900000000U, 375, 5, 1),
PLL_35XX_RATE(825000000U, 275, 4, 1),
PLL_35XX_RATE(800000000U, 400, 6, 1),
PLL_35XX_RATE(733000000U, 733, 12, 1),
PLL_35XX_RATE(700000000U, 175, 3, 1),
PLL_35XX_RATE(667000000U, 222, 4, 1),
PLL_35XX_RATE(633000000U, 211, 4, 1),
PLL_35XX_RATE(600000000U, 500, 5, 2),
PLL_35XX_RATE(552000000U, 460, 5, 2),
PLL_35XX_RATE(550000000U, 550, 6, 2),
PLL_35XX_RATE(543000000U, 362, 4, 2),
PLL_35XX_RATE(533000000U, 533, 6, 2),
PLL_35XX_RATE(500000000U, 500, 6, 2),
PLL_35XX_RATE(444000000U, 370, 5, 2),
PLL_35XX_RATE(420000000U, 350, 5, 2),
PLL_35XX_RATE(400000000U, 400, 6, 2),
PLL_35XX_RATE(350000000U, 350, 6, 2),
PLL_35XX_RATE(333000000U, 222, 4, 2),
PLL_35XX_RATE(300000000U, 500, 5, 3),
PLL_35XX_RATE(278000000U, 556, 6, 3),
PLL_35XX_RATE(266000000U, 532, 6, 3),
PLL_35XX_RATE(250000000U, 500, 6, 3),
PLL_35XX_RATE(200000000U, 400, 6, 3),
PLL_35XX_RATE(166000000U, 332, 6, 3),
PLL_35XX_RATE(160000000U, 320, 6, 3),
PLL_35XX_RATE(133000000U, 532, 6, 4),
PLL_35XX_RATE(100000000U, 400, 6, 4),
PLL_35XX_RATE(24 * MHZ, 2500000000U, 625, 6, 0),
PLL_35XX_RATE(24 * MHZ, 2400000000U, 500, 5, 0),
PLL_35XX_RATE(24 * MHZ, 2300000000U, 575, 6, 0),
PLL_35XX_RATE(24 * MHZ, 2200000000U, 550, 6, 0),
PLL_35XX_RATE(24 * MHZ, 2100000000U, 350, 4, 0),
PLL_35XX_RATE(24 * MHZ, 2000000000U, 500, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1900000000U, 475, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1800000000U, 375, 5, 0),
PLL_35XX_RATE(24 * MHZ, 1700000000U, 425, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1600000000U, 400, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1500000000U, 250, 4, 0),
PLL_35XX_RATE(24 * MHZ, 1400000000U, 350, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1332000000U, 222, 4, 0),
PLL_35XX_RATE(24 * MHZ, 1300000000U, 325, 6, 0),
PLL_35XX_RATE(24 * MHZ, 1200000000U, 500, 5, 1),
PLL_35XX_RATE(24 * MHZ, 1100000000U, 550, 6, 1),
PLL_35XX_RATE(24 * MHZ, 1086000000U, 362, 4, 1),
PLL_35XX_RATE(24 * MHZ, 1066000000U, 533, 6, 1),
PLL_35XX_RATE(24 * MHZ, 1000000000U, 500, 6, 1),
PLL_35XX_RATE(24 * MHZ, 933000000U, 311, 4, 1),
PLL_35XX_RATE(24 * MHZ, 921000000U, 307, 4, 1),
PLL_35XX_RATE(24 * MHZ, 900000000U, 375, 5, 1),
PLL_35XX_RATE(24 * MHZ, 825000000U, 275, 4, 1),
PLL_35XX_RATE(24 * MHZ, 800000000U, 400, 6, 1),
PLL_35XX_RATE(24 * MHZ, 733000000U, 733, 12, 1),
PLL_35XX_RATE(24 * MHZ, 700000000U, 175, 3, 1),
PLL_35XX_RATE(24 * MHZ, 666000000U, 222, 4, 1),
PLL_35XX_RATE(24 * MHZ, 633000000U, 211, 4, 1),
PLL_35XX_RATE(24 * MHZ, 600000000U, 500, 5, 2),
PLL_35XX_RATE(24 * MHZ, 552000000U, 460, 5, 2),
PLL_35XX_RATE(24 * MHZ, 550000000U, 550, 6, 2),
PLL_35XX_RATE(24 * MHZ, 543000000U, 362, 4, 2),
PLL_35XX_RATE(24 * MHZ, 533000000U, 533, 6, 2),
PLL_35XX_RATE(24 * MHZ, 500000000U, 500, 6, 2),
PLL_35XX_RATE(24 * MHZ, 444000000U, 370, 5, 2),
PLL_35XX_RATE(24 * MHZ, 420000000U, 350, 5, 2),
PLL_35XX_RATE(24 * MHZ, 400000000U, 400, 6, 2),
PLL_35XX_RATE(24 * MHZ, 350000000U, 350, 6, 2),
PLL_35XX_RATE(24 * MHZ, 333000000U, 222, 4, 2),
PLL_35XX_RATE(24 * MHZ, 300000000U, 500, 5, 3),
PLL_35XX_RATE(24 * MHZ, 278000000U, 556, 6, 3),
PLL_35XX_RATE(24 * MHZ, 266000000U, 532, 6, 3),
PLL_35XX_RATE(24 * MHZ, 250000000U, 500, 6, 3),
PLL_35XX_RATE(24 * MHZ, 200000000U, 400, 6, 3),
PLL_35XX_RATE(24 * MHZ, 166000000U, 332, 6, 3),
PLL_35XX_RATE(24 * MHZ, 160000000U, 320, 6, 3),
PLL_35XX_RATE(24 * MHZ, 133000000U, 532, 6, 4),
PLL_35XX_RATE(24 * MHZ, 100000000U, 400, 6, 4),
{ /* sentinel */ }
};
/* AUD_PLL */
static const struct samsung_pll_rate_table exynos5433_aud_pll_rates[] __initconst = {
PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
PLL_36XX_RATE(384000000U, 128, 2, 2, 0),
PLL_36XX_RATE(368640000U, 246, 4, 2, -15729),
PLL_36XX_RATE(361507200U, 181, 3, 2, -16148),
PLL_36XX_RATE(338688000U, 113, 2, 2, -6816),
PLL_36XX_RATE(294912000U, 98, 1, 3, 19923),
PLL_36XX_RATE(288000000U, 96, 1, 3, 0),
PLL_36XX_RATE(252000000U, 84, 1, 3, 0),
PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0),
PLL_36XX_RATE(24 * MHZ, 393216003U, 197, 3, 2, -25690),
PLL_36XX_RATE(24 * MHZ, 384000000U, 128, 2, 2, 0),
PLL_36XX_RATE(24 * MHZ, 368639991U, 246, 4, 2, -15729),
PLL_36XX_RATE(24 * MHZ, 361507202U, 181, 3, 2, -16148),
PLL_36XX_RATE(24 * MHZ, 338687988U, 113, 2, 2, -6816),
PLL_36XX_RATE(24 * MHZ, 294912002U, 98, 1, 3, 19923),
PLL_36XX_RATE(24 * MHZ, 288000000U, 96, 1, 3, 0),
PLL_36XX_RATE(24 * MHZ, 252000000U, 84, 1, 3, 0),
PLL_36XX_RATE(24 * MHZ, 196608001U, 197, 3, 3, -25690),
{ /* sentinel */ }
};
......@@ -1672,7 +1673,7 @@ static const struct samsung_gate_clock peric_gate_clks[] __initconst = {
ENABLE_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_IOCLK_I2S1_BCLK, "sclk_ioclk_i2s1_bclk",
"ioclk_i2s1_bclk_in", ENABLE_SCLK_PERIC, 10,
CLK_SET_RATE_PARENT, 0),
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
GATE(CLK_SCLK_SPDIF, "sclk_spdif", "sclk_spdif_peric",
ENABLE_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_PCM1, "sclk_pcm1", "sclk_pcm1_peric",
......@@ -5513,10 +5514,8 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(reg_base)) {
dev_err(dev, "failed to map registers\n");
if (IS_ERR(reg_base))
return PTR_ERR(reg_base);
}
for (i = 0; i < info->nr_clk_ids; ++i)
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
......
......@@ -140,7 +140,7 @@ static const struct samsung_div_clock topc_div_clks[] __initconst = {
};
static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = {
PLL_36XX_RATE(491520000, 20, 1, 0, 31457),
PLL_36XX_RATE(24 * MHZ, 491519897, 20, 1, 0, 31457),
{},
};
......
......@@ -41,35 +41,62 @@ enum samsung_pll_type {
pll_1460x,
};
#define PLL_35XX_RATE(_rate, _m, _p, _s) \
#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 = (_rate), \
.rate = PLL_VALID_RATE(_fin, _rate, \
2 * (_m + 8), _p + 2, _s, 0, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
}
#define PLL_36XX_RATE(_rate, _m, _p, _s, _k) \
#define PLL_36XX_RATE(_fin, _rate, _m, _p, _s, _k) \
{ \
.rate = (_rate), \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s, _k, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
}
#define PLL_45XX_RATE(_rate, _m, _p, _s, _afc) \
#define PLL_4508_RATE(_fin, _rate, _m, _p, _s, _afc) \
{ \
.rate = (_rate), \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s - 1, 0, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.afc = (_afc), \
}
#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel) \
#define PLL_4600_RATE(_fin, _rate, _m, _p, _s, _k, _vsel) \
{ \
.rate = (_rate), \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s, _k, 16), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
......@@ -77,9 +104,10 @@ enum samsung_pll_type {
.vsel = (_vsel), \
}
#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \
#define PLL_4650_RATE(_fin, _rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \
{ \
.rate = (_rate), \
.rate = PLL_VALID_RATE(_fin, _rate, \
_m, _p, _s, _k, 10), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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