summaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/Kconfig26
-rw-r--r--drivers/clk/Makefile5
-rw-r--r--drivers/clk/clk-divider.c58
-rw-r--r--drivers/clk/clk-gpio.c4
-rw-r--r--drivers/clk/clk-mux.c75
-rw-r--r--drivers/clk/clk-stm32f4.c14
-rw-r--r--drivers/clk/clk-stm32mp1.c2117
-rw-r--r--drivers/clk/clk.c131
-rw-r--r--drivers/clk/keystone/sci-clk.c380
-rw-r--r--drivers/clk/mediatek/clk-mt2712.c69
-rw-r--r--drivers/clk/meson/Kconfig9
-rw-r--r--drivers/clk/meson/Makefile5
-rw-r--r--drivers/clk/meson/axg.c955
-rw-r--r--drivers/clk/meson/axg.h12
-rw-r--r--drivers/clk/meson/clk-audio-divider.c63
-rw-r--r--drivers/clk/meson/clk-cpu.c178
-rw-r--r--drivers/clk/meson/clk-mpll.c125
-rw-r--r--drivers/clk/meson/clk-pll.c306
-rw-r--r--drivers/clk/meson/clk-regmap.c166
-rw-r--r--drivers/clk/meson/clk-regmap.h111
-rw-r--r--drivers/clk/meson/clkc.h107
-rw-r--r--drivers/clk/meson/gxbb-aoclk-regmap.c46
-rw-r--r--drivers/clk/meson/gxbb-aoclk.c20
-rw-r--r--drivers/clk/meson/gxbb-aoclk.h11
-rw-r--r--drivers/clk/meson/gxbb.c1591
-rw-r--r--drivers/clk/meson/gxbb.h14
-rw-r--r--drivers/clk/meson/meson8b.c705
-rw-r--r--drivers/clk/meson/meson8b.h17
-rw-r--r--drivers/clk/mvebu/armada-38x.c14
-rw-r--r--drivers/clk/mvebu/cp110-system-controller.c94
-rw-r--r--drivers/clk/qcom/clk-regmap-divider.c20
-rw-r--r--drivers/clk/qcom/clk-rpm.c79
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c9
-rw-r--r--drivers/clk/qcom/gcc-msm8996.c8
-rw-r--r--drivers/clk/samsung/Makefile2
-rw-r--r--drivers/clk/samsung/clk-exynos-audss.c4
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c114
-rw-r--r--drivers/clk/samsung/clk-exynos4.c103
-rw-r--r--drivers/clk/samsung/clk-exynos5-subcmu.c189
-rw-r--r--drivers/clk/samsung/clk-exynos5-subcmu.h26
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c111
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c90
-rw-r--r--drivers/clk/samsung/clk-exynos5410.c20
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c189
-rw-r--r--drivers/clk/samsung/clk-exynos5433.c121
-rw-r--r--drivers/clk/samsung/clk-exynos7.c2
-rw-r--r--drivers/clk/samsung/clk-pll.h48
-rw-r--r--drivers/clk/samsung/clk-s3c2410.c148
-rw-r--r--drivers/clk/samsung/clk-s3c2412.c25
-rw-r--r--drivers/clk/samsung/clk-s3c2443.c55
-rw-r--r--drivers/clk/samsung/clk-s3c64xx.c17
-rw-r--r--drivers/clk/sprd/sc9860-clk.c76
-rw-r--r--drivers/clk/tegra/clk-emc.c2
-rw-r--r--drivers/clk/tegra/clk-pll.c2
-rw-r--r--drivers/clk/tegra/clk-tegra-periph.c2
-rw-r--r--drivers/clk/tegra/clk-tegra-super-gen4.c8
-rw-r--r--drivers/clk/tegra/clk-tegra114.c4
-rw-r--r--drivers/clk/tegra/clk-tegra124.c9
-rw-r--r--drivers/clk/tegra/clk-tegra20.c24
-rw-r--r--drivers/clk/tegra/clk-tegra210.c361
-rw-r--r--drivers/clk/tegra/clk-tegra30.c15
-rw-r--r--drivers/clk/tegra/clk.h7
-rw-r--r--drivers/clk/ti/clk.c38
-rw-r--r--drivers/clk/ti/clock.h4
-rw-r--r--drivers/clk/ti/divider.c26
-rw-r--r--drivers/clk/ti/mux.c13
-rw-r--r--drivers/clk/versatile/clk-vexpress-osc.c5
67 files changed, 6366 insertions, 3038 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 98ce9fc6e6c0..ede9cb0b79d6 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -55,8 +55,10 @@ config COMMON_CLK_RK808
by control register.
config COMMON_CLK_HI655X
- tristate "Clock driver for Hi655x"
- depends on MFD_HI655X_PMIC || COMPILE_TEST
+ tristate "Clock driver for Hi655x" if EXPERT
+ depends on (MFD_HI655X_PMIC || COMPILE_TEST)
+ depends on REGMAP
+ default MFD_HI655X_PMIC
---help---
This driver supports the hi655x PMIC clock. This
multi-function device has one fixed-rate oscillator, clocked
@@ -238,6 +240,26 @@ config COMMON_CLK_VC5
This driver supports the IDT VersaClock 5 and VersaClock 6
programmable clock generators.
+config COMMON_CLK_STM32MP157
+ def_bool COMMON_CLK && MACH_STM32MP157
+ help
+ ---help---
+ Support for stm32mp157 SoC family clocks
+
+config COMMON_CLK_STM32F
+ bool "Clock driver for stm32f4 and stm32f7 SoC families"
+ depends on MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746
+ help
+ ---help---
+ Support for stm32f4 and stm32f7 SoC families clocks
+
+config COMMON_CLK_STM32H7
+ bool "Clock driver for stm32h7 SoC family"
+ depends on MACH_STM32H743
+ help
+ ---help---
+ Support for stm32h7 SoC family clocks
+
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/imgtec/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71ec41e6364f..e0c106ed9407 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -45,8 +45,9 @@ obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
-obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o
-obj-$(CONFIG_ARCH_STM32) += clk-stm32h7.o
+obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o
+obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
+obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_ARCH_U300) += clk-u300.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index b49942b9fe50..b6234a5da12d 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -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);
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
index 151513c655c3..40af4fbab4d2 100644
--- a/drivers/clk/clk-gpio.c
+++ b/drivers/clk/clk-gpio.c
@@ -73,14 +73,14 @@ static u8 clk_gpio_mux_get_parent(struct clk_hw *hw)
{
struct clk_gpio *clk = to_clk_gpio(hw);
- return gpiod_get_value(clk->gpiod);
+ return gpiod_get_value_cansleep(clk->gpiod);
}
static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_gpio *clk = to_clk_gpio(hw);
- gpiod_set_value(clk->gpiod, index);
+ gpiod_set_value_cansleep(clk->gpiod, index);
return 0;
}
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 39cabe157163..ac4a042f8658 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -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);
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index da44f8dc1d29..294850bdc195 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -282,6 +282,7 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 7, "sdmmc2", "sdmux" },
{ STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
@@ -315,7 +316,7 @@ static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
0x0000000000000003ull,
- 0x04f77f033e01c9ffull };
+ 0x04f77f833e01c9ffull };
static const u64 *stm32f4_gate_map;
@@ -521,7 +522,7 @@ static const struct stm32f4_pll_data stm32f429_pll[MAX_PLL_DIV] = {
};
static const struct stm32f4_pll_data stm32f469_pll[MAX_PLL_DIV] = {
- { PLL, 50, { "pll", "pll-q", NULL } },
+ { PLL, 50, { "pll", "pll-q", "pll-r" } },
{ PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
{ PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
};
@@ -1047,6 +1048,8 @@ static const char *rtc_parents[4] = {
"no-clock", "lse", "lsi", "hse-rtc"
};
+static const char *dsi_parent[2] = { NULL, "pll-r" };
+
static const char *lcd_parent[1] = { "pllsai-r-div" };
static const char *i2s_parents[2] = { "plli2s-r", NULL };
@@ -1156,6 +1159,12 @@ static const struct stm32_aux_clk stm32f469_aux_clk[] = {
NO_GATE, 0,
0
},
+ {
+ CLK_F469_DSI, "dsi", dsi_parent, ARRAY_SIZE(dsi_parent),
+ STM32F4_RCC_DCKCFGR, 29, 1,
+ STM32F4_RCC_APB2ENR, 27,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+ },
};
static const struct stm32_aux_clk stm32f746_aux_clk[] = {
@@ -1450,6 +1459,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
stm32f4_gate_map = data->gates_map;
hse_clk = of_clk_get_parent_name(np, 0);
+ dsi_parent[0] = hse_clk;
i2s_in_clk = of_clk_get_parent_name(np, 1);
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
new file mode 100644
index 000000000000..f1d5967b4b39
--- /dev/null
+++ b/drivers/clk/clk-stm32mp1.c
@@ -0,0 +1,2117 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Olivier Bideau <olivier.bideau@st.com> for STMicroelectronics.
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/stm32mp1-clks.h>
+
+static DEFINE_SPINLOCK(rlock);
+
+#define RCC_OCENSETR 0x0C
+#define RCC_HSICFGR 0x18
+#define RCC_RDLSICR 0x144
+#define RCC_PLL1CR 0x80
+#define RCC_PLL1CFGR1 0x84
+#define RCC_PLL1CFGR2 0x88
+#define RCC_PLL2CR 0x94
+#define RCC_PLL2CFGR1 0x98
+#define RCC_PLL2CFGR2 0x9C
+#define RCC_PLL3CR 0x880
+#define RCC_PLL3CFGR1 0x884
+#define RCC_PLL3CFGR2 0x888
+#define RCC_PLL4CR 0x894
+#define RCC_PLL4CFGR1 0x898
+#define RCC_PLL4CFGR2 0x89C
+#define RCC_APB1ENSETR 0xA00
+#define RCC_APB2ENSETR 0xA08
+#define RCC_APB3ENSETR 0xA10
+#define RCC_APB4ENSETR 0x200
+#define RCC_APB5ENSETR 0x208
+#define RCC_AHB2ENSETR 0xA18
+#define RCC_AHB3ENSETR 0xA20
+#define RCC_AHB4ENSETR 0xA28
+#define RCC_AHB5ENSETR 0x210
+#define RCC_AHB6ENSETR 0x218
+#define RCC_AHB6LPENSETR 0x318
+#define RCC_RCK12SELR 0x28
+#define RCC_RCK3SELR 0x820
+#define RCC_RCK4SELR 0x824
+#define RCC_MPCKSELR 0x20
+#define RCC_ASSCKSELR 0x24
+#define RCC_MSSCKSELR 0x48
+#define RCC_SPI6CKSELR 0xC4
+#define RCC_SDMMC12CKSELR 0x8F4
+#define RCC_SDMMC3CKSELR 0x8F8
+#define RCC_FMCCKSELR 0x904
+#define RCC_I2C46CKSELR 0xC0
+#define RCC_I2C12CKSELR 0x8C0
+#define RCC_I2C35CKSELR 0x8C4
+#define RCC_UART1CKSELR 0xC8
+#define RCC_QSPICKSELR 0x900
+#define RCC_ETHCKSELR 0x8FC
+#define RCC_RNG1CKSELR 0xCC
+#define RCC_RNG2CKSELR 0x920
+#define RCC_GPUCKSELR 0x938
+#define RCC_USBCKSELR 0x91C
+#define RCC_STGENCKSELR 0xD4
+#define RCC_SPDIFCKSELR 0x914
+#define RCC_SPI2S1CKSELR 0x8D8
+#define RCC_SPI2S23CKSELR 0x8DC
+#define RCC_SPI2S45CKSELR 0x8E0
+#define RCC_CECCKSELR 0x918
+#define RCC_LPTIM1CKSELR 0x934
+#define RCC_LPTIM23CKSELR 0x930
+#define RCC_LPTIM45CKSELR 0x92C
+#define RCC_UART24CKSELR 0x8E8
+#define RCC_UART35CKSELR 0x8EC
+#define RCC_UART6CKSELR 0x8E4
+#define RCC_UART78CKSELR 0x8F0
+#define RCC_FDCANCKSELR 0x90C
+#define RCC_SAI1CKSELR 0x8C8
+#define RCC_SAI2CKSELR 0x8CC
+#define RCC_SAI3CKSELR 0x8D0
+#define RCC_SAI4CKSELR 0x8D4
+#define RCC_ADCCKSELR 0x928
+#define RCC_MPCKDIVR 0x2C
+#define RCC_DSICKSELR 0x924
+#define RCC_CPERCKSELR 0xD0
+#define RCC_MCO1CFGR 0x800
+#define RCC_MCO2CFGR 0x804
+#define RCC_BDCR 0x140
+#define RCC_AXIDIVR 0x30
+#define RCC_MCUDIVR 0x830
+#define RCC_APB1DIVR 0x834
+#define RCC_APB2DIVR 0x838
+#define RCC_APB3DIVR 0x83C
+#define RCC_APB4DIVR 0x3C
+#define RCC_APB5DIVR 0x40
+#define RCC_TIMG1PRER 0x828
+#define RCC_TIMG2PRER 0x82C
+#define RCC_RTCDIVR 0x44
+#define RCC_DBGCFGR 0x80C
+
+#define RCC_CLR 0x4
+
+static const char * const ref12_parents[] = {
+ "ck_hsi", "ck_hse"
+};
+
+static const char * const ref3_parents[] = {
+ "ck_hsi", "ck_hse", "ck_csi"
+};
+
+static const char * const ref4_parents[] = {
+ "ck_hsi", "ck_hse", "ck_csi"
+};
+
+static const char * const cpu_src[] = {
+ "ck_hsi", "ck_hse", "pll1_p"
+};
+
+static const char * const axi_src[] = {
+ "ck_hsi", "ck_hse", "pll2_p", "pll3_p"
+};
+
+static const char * const per_src[] = {
+ "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const mcu_src[] = {
+ "ck_hsi", "ck_hse", "ck_csi", "pll3_p"
+};
+
+static const char * const sdmmc12_src[] = {
+ "ck_axi", "pll3_r", "pll4_p", "ck_hsi"
+};
+
+static const char * const sdmmc3_src[] = {
+ "ck_mcu", "pll3_r", "pll4_p", "ck_hsi"
+};
+
+static const char * const fmc_src[] = {
+ "ck_axi", "pll3_r", "pll4_p", "ck_per"
+};
+
+static const char * const qspi_src[] = {
+ "ck_axi", "pll3_r", "pll4_p", "ck_per"
+};
+
+static const char * const eth_src[] = {
+ "pll4_p", "pll3_q"
+};
+
+static const char * const rng_src[] = {
+ "ck_csi", "pll4_r", "ck_lse", "ck_lsi"
+};
+
+static const char * const usbphy_src[] = {
+ "ck_hse", "pll4_r", "clk-hse-div2"
+};
+
+static const char * const usbo_src[] = {
+ "pll4_r", "ck_usbo_48m"
+};
+
+static const char * const stgen_src[] = {
+ "ck_hsi", "ck_hse"
+};
+
+static const char * const spdif_src[] = {
+ "pll4_p", "pll3_q", "ck_hsi"
+};
+
+static const char * const spi123_src[] = {
+ "pll4_p", "pll3_q", "i2s_ckin", "ck_per", "pll3_r"
+};
+
+static const char * const spi45_src[] = {
+ "pclk2", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const spi6_src[] = {
+ "pclk5", "pll4_q", "ck_hsi", "ck_csi", "ck_hse", "pll3_q"
+};
+
+static const char * const cec_src[] = {
+ "ck_lse", "ck_lsi", "ck_csi"
+};
+
+static const char * const i2c12_src[] = {
+ "pclk1", "pll4_r", "ck_hsi", "ck_csi"
+};
+
+static const char * const i2c35_src[] = {
+ "pclk1", "pll4_r", "ck_hsi", "ck_csi"
+};
+
+static const char * const i2c46_src[] = {
+ "pclk5", "pll3_q", "ck_hsi", "ck_csi"
+};
+
+static const char * const lptim1_src[] = {
+ "pclk1", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per"
+};
+
+static const char * const lptim23_src[] = {
+ "pclk3", "pll4_q", "ck_per", "ck_lse", "ck_lsi"
+};
+
+static const char * const lptim45_src[] = {
+ "pclk3", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per"
+};
+
+static const char * const usart1_src[] = {
+ "pclk5", "pll3_q", "ck_hsi", "ck_csi", "pll4_q", "ck_hse"
+};
+
+const char * const usart234578_src[] = {
+ "pclk1", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const usart6_src[] = {
+ "pclk2", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const dfsdm_src[] = {
+ "pclk2", "ck_mcu"
+};
+
+static const char * const fdcan_src[] = {
+ "ck_hse", "pll3_q", "pll4_q"
+};
+
+static const char * const sai_src[] = {
+ "pll4_q", "pll3_q", "i2s_ckin", "ck_per"
+};
+
+static const char * const sai2_src[] = {
+ "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb"
+};
+
+static const char * const adc12_src[] = {
+ "pll4_q", "ck_per"
+};
+
+static const char * const dsi_src[] = {
+ "ck_dsi_phy", "pll4_p"
+};
+
+static const char * const rtc_src[] = {
+ "off", "ck_lse", "ck_lsi", "ck_hse_rtc"
+};
+
+static const char * const mco1_src[] = {
+ "ck_hsi", "ck_hse", "ck_csi", "ck_lsi", "ck_lse"
+};
+
+static const char * const mco2_src[] = {
+ "ck_mpu", "ck_axi", "ck_mcu", "pll4_p", "ck_hse", "ck_hsi"
+};
+
+static const char * const ck_trace_src[] = {
+ "ck_axi"
+};
+
+static const struct clk_div_table axi_div_table[] = {
+ { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
+ { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 },
+ { 0 },
+};
+
+static const struct clk_div_table mcu_div_table[] = {
+ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+ { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 },
+ { 8, 512 }, { 9, 512 }, { 10, 512}, { 11, 512 },
+ { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 },
+ { 0 },
+};
+
+static const struct clk_div_table apb_div_table[] = {
+ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+ { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 },
+ { 0 },
+};
+
+static const struct clk_div_table ck_trace_div_table[] = {
+ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+ { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 },
+ { 0 },
+};
+
+#define MAX_MUX_CLK 2
+
+struct stm32_mmux {
+ u8 nbr_clk;
+ struct clk_hw *hws[MAX_MUX_CLK];
+};
+
+struct stm32_clk_mmux {
+ struct clk_mux mux;
+ struct stm32_mmux *mmux;
+};
+
+struct stm32_mgate {
+ u8 nbr_clk;
+ u32 flag;
+};
+
+struct stm32_clk_mgate {
+ struct clk_gate gate;
+ struct stm32_mgate *mgate;
+ u32 mask;
+};
+
+struct clock_config {
+ u32 id;
+ const char *name;
+ union {
+ const char *parent_name;
+ const char * const *parent_names;
+ };
+ int num_parents;
+ unsigned long flags;
+ void *cfg;
+ struct clk_hw * (*func)(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg);
+};
+
+#define NO_ID ~0
+
+struct gate_cfg {
+ u32 reg_off;
+ u8 bit_idx;
+ u8 gate_flags;
+};
+
+struct fixed_factor_cfg {
+ unsigned int mult;
+ unsigned int div;
+};
+
+struct div_cfg {
+ u32 reg_off;
+ u8 shift;
+ u8 width;
+ u8 div_flags;
+ const struct clk_div_table *table;
+};
+
+struct mux_cfg {
+ u32 reg_off;
+ u8 shift;
+ u8 width;
+ u8 mux_flags;
+ u32 *table;
+};
+
+struct stm32_gate_cfg {
+ struct gate_cfg *gate;
+ struct stm32_mgate *mgate;
+ const struct clk_ops *ops;
+};
+
+struct stm32_div_cfg {
+ struct div_cfg *div;
+ const struct clk_ops *ops;
+};
+
+struct stm32_mux_cfg {
+ struct mux_cfg *mux;
+ struct stm32_mmux *mmux;
+ const struct clk_ops *ops;
+};
+
+/* STM32 Composite clock */
+struct stm32_composite_cfg {
+ const struct stm32_gate_cfg *gate;
+ const struct stm32_div_cfg *div;
+ const struct stm32_mux_cfg *mux;
+};
+
+static struct clk_hw *
+_clk_hw_register_gate(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct gate_cfg *gate_cfg = cfg->cfg;
+
+ return clk_hw_register_gate(dev,
+ cfg->name,
+ cfg->parent_name,
+ cfg->flags,
+ gate_cfg->reg_off + base,
+ gate_cfg->bit_idx,
+ gate_cfg->gate_flags,
+ lock);
+}
+
+static struct clk_hw *
+_clk_hw_register_fixed_factor(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct fixed_factor_cfg *ff_cfg = cfg->cfg;
+
+ return clk_hw_register_fixed_factor(dev, cfg->name, cfg->parent_name,
+ cfg->flags, ff_cfg->mult,
+ ff_cfg->div);
+}
+
+static struct clk_hw *
+_clk_hw_register_divider_table(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct div_cfg *div_cfg = cfg->cfg;
+
+ return clk_hw_register_divider_table(dev,
+ cfg->name,
+ cfg->parent_name,
+ cfg->flags,
+ div_cfg->reg_off + base,
+ div_cfg->shift,
+ div_cfg->width,
+ div_cfg->div_flags,
+ div_cfg->table,
+ lock);
+}
+
+static struct clk_hw *
+_clk_hw_register_mux(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct mux_cfg *mux_cfg = cfg->cfg;
+
+ return clk_hw_register_mux(dev, cfg->name, cfg->parent_names,
+ cfg->num_parents, cfg->flags,
+ mux_cfg->reg_off + base, mux_cfg->shift,
+ mux_cfg->width, mux_cfg->mux_flags, lock);
+}
+
+/* MP1 Gate clock with set & clear registers */
+
+static int mp1_gate_clk_enable(struct clk_hw *hw)
+{
+ if (!clk_gate_ops.is_enabled(hw))
+ clk_gate_ops.enable(hw);
+
+ return 0;
+}
+
+static void mp1_gate_clk_disable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ unsigned long flags = 0;
+
+ if (clk_gate_ops.is_enabled(hw)) {
+ spin_lock_irqsave(gate->lock, flags);
+ writel_relaxed(BIT(gate->bit_idx), gate->reg + RCC_CLR);
+ spin_unlock_irqrestore(gate->lock, flags);
+ }
+}
+
+const struct clk_ops mp1_gate_clk_ops = {
+ .enable = mp1_gate_clk_enable,
+ .disable = mp1_gate_clk_disable,
+ .is_enabled = clk_gate_is_enabled,
+};
+
+static struct clk_hw *_get_stm32_mux(void __iomem *base,
+ const struct stm32_mux_cfg *cfg,
+ spinlock_t *lock)
+{
+ struct stm32_clk_mmux *mmux;
+ struct clk_mux *mux;
+ struct clk_hw *mux_hw;
+
+ if (cfg->mmux) {
+ mmux = kzalloc(sizeof(*mmux), GFP_KERNEL);
+ if (!mmux)
+ return ERR_PTR(-ENOMEM);
+
+ mmux->mux.reg = cfg->mux->reg_off + base;
+ mmux->mux.shift = cfg->mux->shift;
+ mmux->mux.mask = (1 << cfg->mux->width) - 1;
+ mmux->mux.flags = cfg->mux->mux_flags;
+ mmux->mux.table = cfg->mux->table;
+ mmux->mux.lock = lock;
+ mmux->mmux = cfg->mmux;
+ mux_hw = &mmux->mux.hw;
+ cfg->mmux->hws[cfg->mmux->nbr_clk++] = mux_hw;
+
+ } else {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ mux->reg = cfg->mux->reg_off + base;
+ mux->shift = cfg->mux->shift;
+ mux->mask = (1 << cfg->mux->width) - 1;
+ mux->flags = cfg->mux->mux_flags;
+ mux->table = cfg->mux->table;
+ mux->lock = lock;
+ mux_hw = &mux->hw;
+ }
+
+ return mux_hw;
+}
+
+static struct clk_hw *_get_stm32_div(void __iomem *base,
+ const struct stm32_div_cfg *cfg,
+ spinlock_t *lock)
+{
+ struct clk_divider *div;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = cfg->div->reg_off + base;
+ div->shift = cfg->div->shift;
+ div->width = cfg->div->width;
+ div->flags = cfg->div->div_flags;
+ div->table = cfg->div->table;
+ div->lock = lock;
+
+ return &div->hw;
+}
+
+static struct clk_hw *
+_get_stm32_gate(void __iomem *base,
+ const struct stm32_gate_cfg *cfg, spinlock_t *lock)
+{
+ struct stm32_clk_mgate *mgate;
+ struct clk_gate *gate;
+ struct clk_hw *gate_hw;
+
+ if (cfg->mgate) {
+ mgate = kzalloc(sizeof(*mgate), GFP_KERNEL);
+ if (!mgate)
+ return ERR_PTR(-ENOMEM);
+
+ mgate->gate.reg = cfg->gate->reg_off + base;
+ mgate->gate.bit_idx = cfg->gate->bit_idx;
+ mgate->gate.flags = cfg->gate->gate_flags;
+ mgate->gate.lock = lock;
+ mgate->mask = BIT(cfg->mgate->nbr_clk++);
+
+ mgate->mgate = cfg->mgate;
+
+ gate_hw = &mgate->gate.hw;
+
+ } else {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ gate->reg = cfg->gate->reg_off + base;
+ gate->bit_idx = cfg->gate->bit_idx;
+ gate->flags = cfg->gate->gate_flags;
+ gate->lock = lock;
+
+ gate_hw = &gate->hw;
+ }
+
+ return gate_hw;
+}
+
+static struct clk_hw *
+clk_stm32_register_gate_ops(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *base,
+ const struct stm32_gate_cfg *cfg,
+ spinlock_t *lock)
+{
+ struct clk_init_data init = { NULL };
+ struct clk_gate *gate;
+ struct clk_hw *hw;
+ int ret;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = flags;
+
+ init.ops = &clk_gate_ops;
+
+ if (cfg->ops)
+ init.ops = cfg->ops;
+
+ hw = _get_stm32_gate(base, cfg, lock);
+ if (IS_ERR(hw))
+ return ERR_PTR(-ENOMEM);
+
+ hw->init = &init;
+
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(gate);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
+static struct clk_hw *
+clk_stm32_register_composite(struct device *dev,
+ const char *name, const char * const *parent_names,
+ int num_parents, void __iomem *base,
+ const struct stm32_composite_cfg *cfg,
+ unsigned long flags, spinlock_t *lock)
+{
+ const struct clk_ops *mux_ops, *div_ops, *gate_ops;
+ struct clk_hw *mux_hw, *div_hw, *gate_hw;
+
+ mux_hw = NULL;
+ div_hw = NULL;
+ gate_hw = NULL;
+ mux_ops = NULL;
+ div_ops = NULL;
+ gate_ops = NULL;
+
+ if (cfg->mux) {
+ mux_hw = _get_stm32_mux(base, cfg->mux, lock);
+
+ if (!IS_ERR(mux_hw)) {
+ mux_ops = &clk_mux_ops;
+
+ if (cfg->mux->ops)
+ mux_ops = cfg->mux->ops;
+ }
+ }
+
+ if (cfg->div) {
+ div_hw = _get_stm32_div(base, cfg->div, lock);
+
+ if (!IS_ERR(div_hw)) {
+ div_ops = &clk_divider_ops;
+
+ if (cfg->div->ops)
+ div_ops = cfg->div->ops;
+ }
+ }
+
+ if (cfg->gate) {
+ gate_hw = _get_stm32_gate(base, cfg->gate, lock);
+
+ if (!IS_ERR(gate_hw)) {
+ gate_ops = &clk_gate_ops;
+
+ if (cfg->gate->ops)
+ gate_ops = cfg->gate->ops;
+ }
+ }
+
+ return clk_hw_register_composite(dev, name, parent_names, num_parents,
+ mux_hw, mux_ops, div_hw, div_ops,
+ gate_hw, gate_ops, flags);
+}
+
+#define to_clk_mgate(_gate) container_of(_gate, struct stm32_clk_mgate, gate)
+
+static int mp1_mgate_clk_enable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate);
+
+ clk_mgate->mgate->flag |= clk_mgate->mask;
+
+ mp1_gate_clk_enable(hw);
+
+ return 0;
+}
+
+static void mp1_mgate_clk_disable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate);
+
+ clk_mgate->mgate->flag &= ~clk_mgate->mask;
+
+ if (clk_mgate->mgate->flag == 0)
+ mp1_gate_clk_disable(hw);
+}
+
+const struct clk_ops mp1_mgate_clk_ops = {
+ .enable = mp1_mgate_clk_enable,
+ .disable = mp1_mgate_clk_disable,
+ .is_enabled = clk_gate_is_enabled,
+
+};
+
+#define to_clk_mmux(_mux) container_of(_mux, struct stm32_clk_mmux, mux)
+
+static u8 clk_mmux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int clk_mmux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_mux *mux = to_clk_mux(hw);
+ struct stm32_clk_mmux *clk_mmux = to_clk_mmux(mux);
+ struct clk_hw *hwp;
+ int ret, n;
+
+ ret = clk_mux_ops.set_parent(hw, index);
+ if (ret)
+ return ret;
+
+ hwp = clk_hw_get_parent(hw);
+
+ for (n = 0; n < clk_mmux->mmux->nbr_clk; n++)
+ if (clk_mmux->mmux->hws[n] != hw)
+ clk_hw_reparent(clk_mmux->mmux->hws[n], hwp);
+
+ return 0;
+}
+
+const struct clk_ops clk_mmux_ops = {
+ .get_parent = clk_mmux_get_parent,
+ .set_parent = clk_mmux_set_parent,
+ .determine_rate = __clk_mux_determine_rate,
+};
+
+/* STM32 PLL */
+struct stm32_pll_obj {
+ /* lock pll enable/disable registers */
+ spinlock_t *lock;
+ void __iomem *reg;
+ struct clk_hw hw;
+};
+
+#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw)
+
+#define PLL_ON BIT(0)
+#define PLL_RDY BIT(1)
+#define DIVN_MASK 0x1FF
+#define DIVM_MASK 0x3F
+#define DIVM_SHIFT 16
+#define DIVN_SHIFT 0
+#define FRAC_OFFSET 0xC
+#define FRAC_MASK 0x1FFF
+#define FRAC_SHIFT 3
+#define FRACLE BIT(16)
+
+static int __pll_is_enabled(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+
+ return readl_relaxed(clk_elem->reg) & PLL_ON;
+}
+
+#define TIMEOUT 5
+
+static int pll_enable(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ u32 reg;
+ unsigned long flags = 0;
+ unsigned int timeout = TIMEOUT;
+ int bit_status = 0;
+
+ spin_lock_irqsave(clk_elem->lock, flags);
+
+ if (__pll_is_enabled(hw))
+ goto unlock;
+
+ reg = readl_relaxed(clk_elem->reg);
+ reg |= PLL_ON;
+ writel_relaxed(reg, clk_elem->reg);
+
+ /* We can't use readl_poll_timeout() because we can be blocked if
+ * someone enables this clock before clocksource changes.
+ * Only jiffies counter is available. Jiffies are incremented by
+ * interruptions and enable op does not allow to be interrupted.
+ */
+ do {
+ bit_status = !(readl_relaxed(clk_elem->reg) & PLL_RDY);
+
+ if (bit_status)
+ udelay(120);
+
+ } while (bit_status && --timeout);
+
+unlock:
+ spin_unlock_irqrestore(clk_elem->lock, flags);
+
+ return bit_status;
+}
+
+static void pll_disable(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ u32 reg;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(clk_elem->lock, flags);
+
+ reg = readl_relaxed(clk_elem->reg);
+ reg &= ~PLL_ON;
+ writel_relaxed(reg, clk_elem->reg);
+
+ spin_unlock_irqrestore(clk_elem->lock, flags);
+}
+
+static u32 pll_frac_val(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ u32 reg, frac = 0;
+
+ reg = readl_relaxed(clk_elem->reg + FRAC_OFFSET);
+ if (reg & FRACLE)
+ frac = (reg >> FRAC_SHIFT) & FRAC_MASK;
+
+ return frac;
+}
+
+static unsigned long pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ u32 reg;
+ u32 frac, divm, divn;
+ u64 rate, rate_frac = 0;
+
+ reg = readl_relaxed(clk_elem->reg + 4);
+
+ divm = ((reg >> DIVM_SHIFT) & DIVM_MASK) + 1;
+ divn = ((reg >> DIVN_SHIFT) & DIVN_MASK) + 1;
+ rate = (u64)parent_rate * divn;
+
+ do_div(rate, divm);
+
+ frac = pll_frac_val(hw);
+ if (frac) {
+ rate_frac = (u64)parent_rate * (u64)frac;
+ do_div(rate_frac, (divm * 8192));
+ }
+
+ return rate + rate_frac;
+}
+
+static int pll_is_enabled(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ unsigned long flags = 0;
+ int ret;
+
+ spin_lock_irqsave(clk_elem->lock, flags);
+ ret = __pll_is_enabled(hw);
+ spin_unlock_irqrestore(clk_elem->lock, flags);
+
+ return ret;
+}
+
+static const struct clk_ops pll_ops = {
+ .enable = pll_enable,
+ .disable = pll_disable,
+ .recalc_rate = pll_recalc_rate,
+ .is_enabled = pll_is_enabled,
+};
+
+static struct clk_hw *clk_register_pll(struct device *dev, const char *name,
+ const char *parent_name,
+ void __iomem *reg,
+ unsigned long flags,
+ spinlock_t *lock)
+{
+ struct stm32_pll_obj *element;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int err;
+
+ element = kzalloc(sizeof(*element), GFP_KERNEL);
+ if (!element)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &pll_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ element->hw.init = &init;
+ element->reg = reg;
+ element->lock = lock;
+
+ hw = &element->hw;
+ err = clk_hw_register(dev, hw);
+
+ if (err) {
+ kfree(element);
+ return ERR_PTR(err);
+ }
+
+ return hw;
+}
+
+/* Kernel Timer */
+struct timer_cker {
+ /* lock the kernel output divider register */
+ spinlock_t *lock;
+ void __iomem *apbdiv;
+ void __iomem *timpre;
+ struct clk_hw hw;
+};
+
+#define to_timer_cker(_hw) container_of(_hw, struct timer_cker, hw)
+
+#define APB_DIV_MASK 0x07
+#define TIM_PRE_MASK 0x01
+
+static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct timer_cker *tim_ker = to_timer_cker(hw);
+ u32 prescaler;
+ unsigned int mult = 0;
+
+ prescaler = readl_relaxed(tim_ker->apbdiv) & APB_DIV_MASK;
+ if (prescaler < 2)
+ return 1;
+
+ mult = 2;
+
+ if (rate / parent_rate >= 4)
+ mult = 4;
+
+ return mult;
+}
+
+static long timer_ker_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long factor = __bestmult(hw, rate, *parent_rate);
+
+ return *parent_rate * factor;
+}
+
+static int timer_ker_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct timer_cker *tim_ker = to_timer_cker(hw);
+ unsigned long flags = 0;
+ unsigned long factor = __bestmult(hw, rate, parent_rate);
+ int ret = 0;
+
+ spin_lock_irqsave(tim_ker->lock, flags);
+
+ switch (factor) {
+ case 1:
+ break;
+ case 2:
+ writel_relaxed(0, tim_ker->timpre);
+ break;
+ case 4:
+ writel_relaxed(1, tim_ker->timpre);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ spin_unlock_irqrestore(tim_ker->lock, flags);
+
+ return ret;
+}
+
+static unsigned long timer_ker_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct timer_cker *tim_ker = to_timer_cker(hw);
+ u32 prescaler, timpre;
+ u32 mul;
+
+ prescaler = readl_relaxed(tim_ker->apbdiv) & APB_DIV_MASK;
+
+ timpre = readl_relaxed(tim_ker->timpre) & TIM_PRE_MASK;
+
+ if (!prescaler)
+ return parent_rate;
+
+ mul = (timpre + 1) * 2;
+
+ return parent_rate * mul;
+}
+
+static const struct clk_ops timer_ker_ops = {
+ .recalc_rate = timer_ker_recalc_rate,
+ .round_rate = timer_ker_round_rate,
+ .set_rate = timer_ker_set_rate,
+
+};
+
+static struct clk_hw *clk_register_cktim(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *apbdiv,
+ void __iomem *timpre,
+ spinlock_t *lock)
+{
+ struct timer_cker *tim_ker;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int err;
+
+ tim_ker = kzalloc(sizeof(*tim_ker), GFP_KERNEL);
+ if (!tim_ker)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &timer_ker_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ tim_ker->hw.init = &init;
+ tim_ker->lock = lock;
+ tim_ker->apbdiv = apbdiv;
+ tim_ker->timpre = timpre;
+
+ hw = &tim_ker->hw;
+ err = clk_hw_register(dev, hw);
+
+ if (err) {
+ kfree(tim_ker);
+ return ERR_PTR(err);
+ }
+
+ return hw;
+}
+
+struct stm32_pll_cfg {
+ u32 offset;
+};
+
+struct clk_hw *_clk_register_pll(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct stm32_pll_cfg *stm_pll_cfg = cfg->cfg;
+
+ return clk_register_pll(dev, cfg->name, cfg->parent_name,
+ base + stm_pll_cfg->offset, cfg->flags, lock);
+}
+
+struct stm32_cktim_cfg {
+ u32 offset_apbdiv;
+ u32 offset_timpre;
+};
+
+static struct clk_hw *_clk_register_cktim(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct stm32_cktim_cfg *cktim_cfg = cfg->cfg;
+
+ return clk_register_cktim(dev, cfg->name, cfg->parent_name, cfg->flags,
+ cktim_cfg->offset_apbdiv + base,
+ cktim_cfg->offset_timpre + base, lock);
+}
+
+static struct clk_hw *
+_clk_stm32_register_gate(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ return clk_stm32_register_gate_ops(dev,
+ cfg->name,
+ cfg->parent_name,
+ cfg->flags,
+ base,
+ cfg->cfg,
+ lock);
+}
+
+static struct clk_hw *
+_clk_stm32_register_composite(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ return clk_stm32_register_composite(dev, cfg->name, cfg->parent_names,
+ cfg->num_parents, base, cfg->cfg,
+ cfg->flags, lock);
+}
+
+#define GATE(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\
+{\
+ .id = _id,\
+ .name = _name,\
+ .parent_name = _parent,\
+ .flags = _flags,\
+ .cfg = &(struct gate_cfg) {\
+ .reg_off = _offset,\
+ .bit_idx = _bit_idx,\
+ .gate_flags = _gate_flags,\
+ },\
+ .func = _clk_hw_register_gate,\
+}
+
+#define FIXED_FACTOR(_id, _name, _parent, _flags, _mult, _div)\
+{\
+ .id = _id,\
+ .name = _name,\
+ .parent_name = _parent,\
+ .flags = _flags,\
+ .cfg = &(struct fixed_factor_cfg) {\
+ .mult = _mult,\
+ .div = _div,\
+ },\
+ .func = _clk_hw_register_fixed_factor,\
+}
+
+#define DIV_TABLE(_id, _name, _parent, _flags, _offset, _shift, _width,\
+ _div_flags, _div_table)\
+{\
+ .id = _id,\
+ .name = _name,\
+ .parent_name = _parent,\
+ .flags = _flags,\
+ .cfg = &(struct div_cfg) {\
+ .reg_off = _offset,\
+ .shift = _shift,\
+ .width = _width,\
+ .div_flags = _div_flags,\
+ .table = _div_table,\
+ },\
+ .func = _clk_hw_register_divider_table,\
+}
+
+#define DIV(_id, _name, _parent, _flags, _offset, _shift, _width, _div_flags)\
+ DIV_TABLE(_id, _name, _parent, _flags, _offset, _shift, _width,\
+ _div_flags, NULL)
+
+#define MUX(_id, _name, _parents, _flags, _offset, _shift, _width, _mux_flags)\
+{\
+ .id = _id,\
+ .name = _name,\
+ .parent_names = _parents,\
+ .num_parents = ARRAY_SIZE(_parents),\
+ .flags = _flags,\
+ .cfg = &(struct mux_cfg) {\
+ .reg_off = _offset,\
+ .shift = _shift,\
+ .width = _width,\
+ .mux_flags = _mux_flags,\
+ },\
+ .func = _clk_hw_register_mux,\
+}
+
+#define PLL(_id, _name, _parent, _flags, _offset)\
+{\
+ .id = _id,\
+ .name = _name,\
+ .parent_name = _parent,\
+ .flags = _flags,\
+ .cfg = &(struct stm32_pll_cfg) {\
+ .offset = _offset,\
+ },\
+ .func = _clk_register_pll,\
+}
+
+#define STM32_CKTIM(_name, _parent, _flags, _offset_apbdiv, _offset_timpre)\
+{\
+ .id = NO_ID,\
+ .name = _name,\
+ .parent_name = _parent,\
+ .flags = _flags,\
+ .cfg = &(struct stm32_cktim_cfg) {\
+ .offset_apbdiv = _offset_apbdiv,\
+ .offset_timpre = _offset_timpre,\
+ },\
+ .func = _clk_register_cktim,\
+}
+
+#define STM32_TIM(_id, _name, _parent, _offset_set, _bit_idx)\
+ GATE_MP1(_id, _name, _parent, CLK_SET_RATE_PARENT,\
+ _offset_set, _bit_idx, 0)
+
+/* STM32 GATE */
+#define STM32_GATE(_id, _name, _parent, _flags, _gate)\
+{\
+ .id = _id,\
+ .name = _name,\
+ .parent_name = _parent,\
+ .flags = _flags,\
+ .cfg = (struct stm32_gate_cfg *) {_gate},\
+ .func = _clk_stm32_register_gate,\
+}
+
+#define _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags, _mgate, _ops)\
+ (&(struct stm32_gate_cfg) {\
+ &(struct gate_cfg) {\
+ .reg_off = _gate_offset,\
+ .bit_idx = _gate_bit_idx,\
+ .gate_flags = _gate_flags,\
+ },\
+ .mgate = _mgate,\
+ .ops = _ops,\
+ })
+
+#define _STM32_MGATE(_mgate)\
+ (&per_gate_cfg[_mgate])
+
+#define _GATE(_gate_offset, _gate_bit_idx, _gate_flags)\
+ _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\
+ NULL, NULL)\
+
+#define _GATE_MP1(_gate_offset, _gate_bit_idx, _gate_flags)\
+ _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\
+ NULL, &mp1_gate_clk_ops)\
+
+#define _MGATE_MP1(_mgate)\
+ .gate = &per_gate_cfg[_mgate]
+
+#define GATE_MP1(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\
+ STM32_GATE(_id, _name, _parent, _flags,\
+ _GATE_MP1(_offset, _bit_idx, _gate_flags))
+
+#define MGATE_MP1(_id, _name, _parent, _flags, _mgate)\
+ STM32_GATE(_id, _name, _parent, _flags,\
+ _STM32_MGATE(_mgate))
+
+#define _STM32_DIV(_div_offset, _div_shift, _div_width,\
+ _div_flags, _div_table, _ops)\
+ .div = &(struct stm32_div_cfg) {\
+ &(struct div_cfg) {\
+ .reg_off = _div_offset,\
+ .shift = _div_shift,\
+ .width = _div_width,\
+ .div_flags = _div_flags,\
+ .table = _div_table,\
+ },\
+ .ops = _ops,\
+ }
+
+#define _DIV(_div_offset, _div_shift, _div_width, _div_flags, _div_table)\
+ _STM32_DIV(_div_offset, _div_shift, _div_width,\
+ _div_flags, _div_table, NULL)\
+
+#define _STM32_MUX(_offset, _shift, _width, _mux_flags, _mmux, _ops)\
+ .mux = &(struct stm32_mux_cfg) {\
+ &(struct mux_cfg) {\
+ .reg_off = _offset,\
+ .shift = _shift,\
+ .width = _width,\
+ .mux_flags = _mux_flags,\
+ .table = NULL,\
+ },\
+ .mmux = _mmux,\
+ .ops = _ops,\
+ }
+
+#define _MUX(_offset, _shift, _width, _mux_flags)\
+ _STM32_MUX(_offset, _shift, _width, _mux_flags, NULL, NULL)\
+
+#define _MMUX(_mmux) .mux = &ker_mux_cfg[_mmux]
+
+#define PARENT(_parent) ((const char *[]) { _parent})
+
+#define _NO_MUX .mux = NULL
+#define _NO_DIV .div = NULL
+#define _NO_GATE .gate = NULL
+
+#define COMPOSITE(_id, _name, _parents, _flags, _gate, _mux, _div)\
+{\
+ .id = _id,\
+ .name = _name,\
+ .parent_names = _parents,\
+ .num_parents = ARRAY_SIZE(_parents),\
+ .flags = _flags,\
+ .cfg = &(struct stm32_composite_cfg) {\
+ _gate,\
+ _mux,\
+ _div,\
+ },\
+ .func = _clk_stm32_register_composite,\
+}
+
+#define PCLK(_id, _name, _parent, _flags, _mgate)\
+ MGATE_MP1(_id, _name, _parent, _flags, _mgate)
+
+#define KCLK(_id, _name, _parents, _flags, _mgate, _mmux)\
+ COMPOSITE(_id, _name, _parents, CLK_OPS_PARENT_ENABLE | _flags,\
+ _MGATE_MP1(_mgate),\
+ _MMUX(_mmux),\
+ _NO_DIV)
+
+enum {
+ G_SAI1,
+ G_SAI2,
+ G_SAI3,
+ G_SAI4,
+ G_SPI1,
+ G_SPI2,
+ G_SPI3,
+ G_SPI4,
+ G_SPI5,
+ G_SPI6,
+ G_SPDIF,
+ G_I2C1,
+ G_I2C2,
+ G_I2C3,
+ G_I2C4,
+ G_I2C5,
+ G_I2C6,
+ G_USART2,
+ G_UART4,
+ G_USART3,
+ G_UART5,
+ G_USART1,
+ G_USART6,
+ G_UART7,
+ G_UART8,
+ G_LPTIM1,
+ G_LPTIM2,
+ G_LPTIM3,
+ G_LPTIM4,
+ G_LPTIM5,
+ G_LTDC,
+ G_DSI,
+ G_QSPI,
+ G_FMC,
+ G_SDMMC1,
+ G_SDMMC2,
+ G_SDMMC3,
+ G_USBO,
+ G_USBPHY,
+ G_RNG1,
+ G_RNG2,
+ G_FDCAN,
+ G_DAC12,
+ G_CEC,
+ G_ADC12,
+ G_GPU,
+ G_STGEN,
+ G_DFSDM,
+ G_ADFSDM,
+ G_TIM2,
+ G_TIM3,
+ G_TIM4,
+ G_TIM5,
+ G_TIM6,
+ G_TIM7,
+ G_TIM12,
+ G_TIM13,
+ G_TIM14,
+ G_MDIO,
+ G_TIM1,
+ G_TIM8,
+ G_TIM15,
+ G_TIM16,
+ G_TIM17,
+ G_SYSCFG,
+ G_VREF,
+ G_TMPSENS,
+ G_PMBCTRL,
+ G_HDP,
+ G_IWDG2,
+ G_STGENRO,
+ G_DMA1,
+ G_DMA2,
+ G_DMAMUX,
+ G_DCMI,
+ G_CRYP2,
+ G_HASH2,
+ G_CRC2,
+ G_HSEM,
+ G_IPCC,
+ G_GPIOA,
+ G_GPIOB,
+ G_GPIOC,
+ G_GPIOD,
+ G_GPIOE,
+ G_GPIOF,
+ G_GPIOG,
+ G_GPIOH,
+ G_GPIOI,
+ G_GPIOJ,
+ G_GPIOK,
+ G_MDMA,
+ G_ETHCK,
+ G_ETHTX,
+ G_ETHRX,
+ G_ETHMAC,
+ G_CRC1,
+ G_USBH,
+ G_ETHSTP,
+ G_RTCAPB,
+ G_TZC,
+ G_TZPC,
+ G_IWDG1,
+ G_BSEC,
+ G_GPIOZ,
+ G_CRYP1,
+ G_HASH1,
+ G_BKPSRAM,
+
+ G_LAST
+};
+
+struct stm32_mgate mp1_mgate[G_LAST];
+
+#define _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
+ _mgate, _ops)\
+ [_id] = {\
+ &(struct gate_cfg) {\
+ .reg_off = _gate_offset,\
+ .bit_idx = _gate_bit_idx,\
+ .gate_flags = _gate_flags,\
+ },\
+ .mgate = _mgate,\
+ .ops = _ops,\
+ }
+
+#define K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags)\
+ _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
+ NULL, &mp1_gate_clk_ops)
+
+#define K_MGATE(_id, _gate_offset, _gate_bit_idx, _gate_flags)\
+ _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
+ &mp1_mgate[_id], &mp1_mgate_clk_ops)
+
+/* Peripheral gates */
+struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
+ /* Multi gates */
+ K_GATE(G_MDIO, RCC_APB1ENSETR, 31, 0),
+ K_MGATE(G_DAC12, RCC_APB1ENSETR, 29, 0),
+ K_MGATE(G_CEC, RCC_APB1ENSETR, 27, 0),
+ K_MGATE(G_SPDIF, RCC_APB1ENSETR, 26, 0),
+ K_MGATE(G_I2C5, RCC_APB1ENSETR, 24, 0),
+ K_MGATE(G_I2C3, RCC_APB1ENSETR, 23, 0),
+ K_MGATE(G_I2C2, RCC_APB1ENSETR, 22, 0),
+ K_MGATE(G_I2C1, RCC_APB1ENSETR, 21, 0),
+ K_MGATE(G_UART8, RCC_APB1ENSETR, 19, 0),
+ K_MGATE(G_UART7, RCC_APB1ENSETR, 18, 0),
+ K_MGATE(G_UART5, RCC_APB1ENSETR, 17, 0),
+ K_MGATE(G_UART4, RCC_APB1ENSETR, 16, 0),
+ K_MGATE(G_USART3, RCC_APB1ENSETR, 15, 0),
+ K_MGATE(G_USART2, RCC_APB1ENSETR, 14, 0),
+ K_MGATE(G_SPI3, RCC_APB1ENSETR, 12, 0),
+ K_MGATE(G_SPI2, RCC_APB1ENSETR, 11, 0),
+ K_MGATE(G_LPTIM1, RCC_APB1ENSETR, 9, 0),
+ K_GATE(G_TIM14, RCC_APB1ENSETR, 8, 0),
+ K_GATE(G_TIM13, RCC_APB1ENSETR, 7, 0),
+ K_GATE(G_TIM12, RCC_APB1ENSETR, 6, 0),
+ K_GATE(G_TIM7, RCC_APB1ENSETR, 5, 0),
+ K_GATE(G_TIM6, RCC_APB1ENSETR, 4, 0),
+ K_GATE(G_TIM5, RCC_APB1ENSETR, 3, 0),
+ K_GATE(G_TIM4, RCC_APB1ENSETR, 2, 0),
+ K_GATE(G_TIM3, RCC_APB1ENSETR, 1, 0),
+ K_GATE(G_TIM2, RCC_APB1ENSETR, 0, 0),
+
+ K_MGATE(G_FDCAN, RCC_APB2ENSETR, 24, 0),
+ K_GATE(G_ADFSDM, RCC_APB2ENSETR, 21, 0),
+ K_GATE(G_DFSDM, RCC_APB2ENSETR, 20, 0),
+ K_MGATE(G_SAI3, RCC_APB2ENSETR, 18, 0),
+ K_MGATE(G_SAI2, RCC_APB2ENSETR, 17, 0),
+ K_MGATE(G_SAI1, RCC_APB2ENSETR, 16, 0),
+ K_MGATE(G_USART6, RCC_APB2ENSETR, 13, 0),
+ K_MGATE(G_SPI5, RCC_APB2ENSETR, 10, 0),
+ K_MGATE(G_SPI4, RCC_APB2ENSETR, 9, 0),
+ K_MGATE(G_SPI1, RCC_APB2ENSETR, 8, 0),
+ K_GATE(G_TIM17, RCC_APB2ENSETR, 4, 0),
+ K_GATE(G_TIM16, RCC_APB2ENSETR, 3, 0),
+ K_GATE(G_TIM15, RCC_APB2ENSETR, 2, 0),
+ K_GATE(G_TIM8, RCC_APB2ENSETR, 1, 0),
+ K_GATE(G_TIM1, RCC_APB2ENSETR, 0, 0),
+
+ K_GATE(G_HDP, RCC_APB3ENSETR, 20, 0),
+ K_GATE(G_PMBCTRL, RCC_APB3ENSETR, 17, 0),
+ K_GATE(G_TMPSENS, RCC_APB3ENSETR, 16, 0),
+ K_GATE(G_VREF, RCC_APB3ENSETR, 13, 0),
+ K_GATE(G_SYSCFG, RCC_APB3ENSETR, 11, 0),
+ K_MGATE(G_SAI4, RCC_APB3ENSETR, 8, 0),
+ K_MGATE(G_LPTIM5, RCC_APB3ENSETR, 3, 0),
+ K_MGATE(G_LPTIM4, RCC_APB3ENSETR, 2, 0),
+ K_MGATE(G_LPTIM3, RCC_APB3ENSETR, 1, 0),
+ K_MGATE(G_LPTIM2, RCC_APB3ENSETR, 0, 0),
+
+ K_GATE(G_STGENRO, RCC_APB4ENSETR, 20, 0),
+ K_MGATE(G_USBPHY, RCC_APB4ENSETR, 16, 0),
+ K_GATE(G_IWDG2, RCC_APB4ENSETR, 15, 0),
+ K_MGATE(G_DSI, RCC_APB4ENSETR, 4, 0),
+ K_MGATE(G_LTDC, RCC_APB4ENSETR, 0, 0),
+
+ K_GATE(G_STGEN, RCC_APB5ENSETR, 20, 0),
+ K_GATE(G_BSEC, RCC_APB5ENSETR, 16, 0),
+ K_GATE(G_IWDG1, RCC_APB5ENSETR, 15, 0),
+ K_GATE(G_TZPC, RCC_APB5ENSETR, 13, 0),
+ K_GATE(G_TZC, RCC_APB5ENSETR, 12, 0),
+ K_GATE(G_RTCAPB, RCC_APB5ENSETR, 8, 0),
+ K_MGATE(G_USART1, RCC_APB5ENSETR, 4, 0),
+ K_MGATE(G_I2C6, RCC_APB5ENSETR, 3, 0),
+ K_MGATE(G_I2C4, RCC_APB5ENSETR, 2, 0),
+ K_MGATE(G_SPI6, RCC_APB5ENSETR, 0, 0),
+
+ K_MGATE(G_SDMMC3, RCC_AHB2ENSETR, 16, 0),
+ K_MGATE(G_USBO, RCC_AHB2ENSETR, 8, 0),
+ K_MGATE(G_ADC12, RCC_AHB2ENSETR, 5, 0),
+ K_GATE(G_DMAMUX, RCC_AHB2ENSETR, 2, 0),
+ K_GATE(G_DMA2, RCC_AHB2ENSETR, 1, 0),
+ K_GATE(G_DMA1, RCC_AHB2ENSETR, 0, 0),
+
+ K_GATE(G_IPCC, RCC_AHB3ENSETR, 12, 0),
+ K_GATE(G_HSEM, RCC_AHB3ENSETR, 11, 0),
+ K_GATE(G_CRC2, RCC_AHB3ENSETR, 7, 0),
+ K_MGATE(G_RNG2, RCC_AHB3ENSETR, 6, 0),
+ K_GATE(G_HASH2, RCC_AHB3ENSETR, 5, 0),
+ K_GATE(G_CRYP2, RCC_AHB3ENSETR, 4, 0),
+ K_GATE(G_DCMI, RCC_AHB3ENSETR, 0, 0),
+
+ K_GATE(G_GPIOK, RCC_AHB4ENSETR, 10, 0),
+ K_GATE(G_GPIOJ, RCC_AHB4ENSETR, 9, 0),
+ K_GATE(G_GPIOI, RCC_AHB4ENSETR, 8, 0),
+ K_GATE(G_GPIOH, RCC_AHB4ENSETR, 7, 0),
+ K_GATE(G_GPIOG, RCC_AHB4ENSETR, 6, 0),
+ K_GATE(G_GPIOF, RCC_AHB4ENSETR, 5, 0),
+ K_GATE(G_GPIOE, RCC_AHB4ENSETR, 4, 0),
+ K_GATE(G_GPIOD, RCC_AHB4ENSETR, 3, 0),
+ K_GATE(G_GPIOC, RCC_AHB4ENSETR, 2, 0),
+ K_GATE(G_GPIOB, RCC_AHB4ENSETR, 1, 0),
+ K_GATE(G_GPIOA, RCC_AHB4ENSETR, 0, 0),
+
+ K_GATE(G_BKPSRAM, RCC_AHB5ENSETR, 8, 0),
+ K_MGATE(G_RNG1, RCC_AHB5ENSETR, 6, 0),
+ K_GATE(G_HASH1, RCC_AHB5ENSETR, 5, 0),
+ K_GATE(G_CRYP1, RCC_AHB5ENSETR, 4, 0),
+ K_GATE(G_GPIOZ, RCC_AHB5ENSETR, 0, 0),
+
+ K_GATE(G_USBH, RCC_AHB6ENSETR, 24, 0),
+ K_GATE(G_CRC1, RCC_AHB6ENSETR, 20, 0),
+ K_MGATE(G_SDMMC2, RCC_AHB6ENSETR, 17, 0),
+ K_MGATE(G_SDMMC1, RCC_AHB6ENSETR, 16, 0),
+ K_MGATE(G_QSPI, RCC_AHB6ENSETR, 14, 0),
+ K_MGATE(G_FMC, RCC_AHB6ENSETR, 12, 0),
+ K_GATE(G_ETHMAC, RCC_AHB6ENSETR, 10, 0),
+ K_GATE(G_ETHRX, RCC_AHB6ENSETR, 9, 0),
+ K_GATE(G_ETHTX, RCC_AHB6ENSETR, 8, 0),
+ K_GATE(G_ETHCK, RCC_AHB6ENSETR, 7, 0),
+ K_MGATE(G_GPU, RCC_AHB6ENSETR, 5, 0),
+ K_GATE(G_MDMA, RCC_AHB6ENSETR, 0, 0),
+ K_GATE(G_ETHSTP, RCC_AHB6LPENSETR, 11, 0),
+};
+
+enum {
+ M_SDMMC12,
+ M_SDMMC3,
+ M_FMC,
+ M_QSPI,
+ M_RNG1,
+ M_RNG2,
+ M_USBPHY,
+ M_USBO,
+ M_STGEN,
+ M_SPDIF,
+ M_SPI1,
+ M_SPI23,
+ M_SPI45,
+ M_SPI6,
+ M_CEC,
+ M_I2C12,
+ M_I2C35,
+ M_I2C46,
+ M_LPTIM1,
+ M_LPTIM23,
+ M_LPTIM45,
+ M_USART1,
+ M_UART24,
+ M_UART35,
+ M_USART6,
+ M_UART78,
+ M_SAI1,
+ M_SAI2,
+ M_SAI3,
+ M_SAI4,
+ M_DSI,
+ M_FDCAN,
+ M_ADC12,
+ M_ETHCK,
+ M_CKPER,
+ M_LAST
+};
+
+struct stm32_mmux ker_mux[M_LAST];
+
+#define _K_MUX(_id, _offset, _shift, _width, _mux_flags, _mmux, _ops)\
+ [_id] = {\
+ &(struct mux_cfg) {\
+ .reg_off = _offset,\
+ .shift = _shift,\
+ .width = _width,\
+ .mux_flags = _mux_flags,\
+ .table = NULL,\
+ },\
+ .mmux = _mmux,\
+ .ops = _ops,\
+ }
+
+#define K_MUX(_id, _offset, _shift, _width, _mux_flags)\
+ _K_MUX(_id, _offset, _shift, _width, _mux_flags,\
+ NULL, NULL)
+
+#define K_MMUX(_id, _offset, _shift, _width, _mux_flags)\
+ _K_MUX(_id, _offset, _shift, _width, _mux_flags,\
+ &ker_mux[_id], &clk_mmux_ops)
+
+const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
+ /* Kernel multi mux */
+ K_MMUX(M_SDMMC12, RCC_SDMMC12CKSELR, 0, 3, 0),
+ K_MMUX(M_SPI23, RCC_SPI2S23CKSELR, 0, 3, 0),
+ K_MMUX(M_SPI45, RCC_SPI2S45CKSELR, 0, 3, 0),
+ K_MMUX(M_I2C12, RCC_I2C12CKSELR, 0, 3, 0),
+ K_MMUX(M_I2C35, RCC_I2C35CKSELR, 0, 3, 0),
+ K_MMUX(M_LPTIM23, RCC_LPTIM23CKSELR, 0, 3, 0),
+ K_MMUX(M_LPTIM45, RCC_LPTIM45CKSELR, 0, 3, 0),
+ K_MMUX(M_UART24, RCC_UART24CKSELR, 0, 3, 0),
+ K_MMUX(M_UART35, RCC_UART35CKSELR, 0, 3, 0),
+ K_MMUX(M_UART78, RCC_UART78CKSELR, 0, 3, 0),
+ K_MMUX(M_SAI1, RCC_SAI1CKSELR, 0, 3, 0),
+ K_MMUX(M_ETHCK, RCC_ETHCKSELR, 0, 2, 0),
+ K_MMUX(M_I2C46, RCC_I2C46CKSELR, 0, 3, 0),
+
+ /* Kernel simple mux */
+ K_MUX(M_RNG2, RCC_RNG2CKSELR, 0, 2, 0),
+ K_MUX(M_SDMMC3, RCC_SDMMC3CKSELR, 0, 3, 0),
+ K_MUX(M_FMC, RCC_FMCCKSELR, 0, 2, 0),
+ K_MUX(M_QSPI, RCC_QSPICKSELR, 0, 2, 0),
+ K_MUX(M_USBPHY, RCC_USBCKSELR, 0, 2, 0),
+ K_MUX(M_USBO, RCC_USBCKSELR, 4, 1, 0),
+ K_MUX(M_SPDIF, RCC_SPDIFCKSELR, 0, 2, 0),
+ K_MUX(M_SPI1, RCC_SPI2S1CKSELR, 0, 3, 0),
+ K_MUX(M_CEC, RCC_CECCKSELR, 0, 2, 0),
+ K_MUX(M_LPTIM1, RCC_LPTIM1CKSELR, 0, 3, 0),
+ K_MUX(M_USART6, RCC_UART6CKSELR, 0, 3, 0),
+ K_MUX(M_FDCAN, RCC_FDCANCKSELR, 0, 2, 0),
+ K_MUX(M_SAI2, RCC_SAI2CKSELR, 0, 3, 0),
+ K_MUX(M_SAI3, RCC_SAI3CKSELR, 0, 3, 0),
+ K_MUX(M_SAI4, RCC_SAI4CKSELR, 0, 3, 0),
+ K_MUX(M_ADC12, RCC_ADCCKSELR, 0, 2, 0),
+ K_MUX(M_DSI, RCC_DSICKSELR, 0, 1, 0),
+ K_MUX(M_CKPER, RCC_CPERCKSELR, 0, 2, 0),
+ K_MUX(M_RNG1, RCC_RNG1CKSELR, 0, 2, 0),
+ K_MUX(M_STGEN, RCC_STGENCKSELR, 0, 2, 0),
+ K_MUX(M_USART1, RCC_UART1CKSELR, 0, 3, 0),
+ K_MUX(M_SPI6, RCC_SPI6CKSELR, 0, 3, 0),
+};
+
+static const struct clock_config stm32mp1_clock_cfg[] = {
+ /* Oscillator divider */
+ DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2,
+ CLK_DIVIDER_READ_ONLY),
+
+ /* External / Internal Oscillators */
+ GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0),
+ GATE_MP1(CK_CSI, "ck_csi", "clk-csi", 0, RCC_OCENSETR, 4, 0),
+ GATE_MP1(CK_HSI, "ck_hsi", "clk-hsi-div", 0, RCC_OCENSETR, 0, 0),
+ GATE(CK_LSI, "ck_lsi", "clk-lsi", 0, RCC_RDLSICR, 0, 0),
+ GATE(CK_LSE, "ck_lse", "clk-lse", 0, RCC_BDCR, 0, 0),
+
+ FIXED_FACTOR(CK_HSE_DIV2, "clk-hse-div2", "ck_hse", 0, 1, 2),
+
+ /* ref clock pll */
+ MUX(NO_ID, "ref1", ref12_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK12SELR,
+ 0, 2, CLK_MUX_READ_ONLY),
+
+ MUX(NO_ID, "ref3", ref3_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK3SELR,
+ 0, 2, CLK_MUX_READ_ONLY),
+
+ MUX(NO_ID, "ref4", ref4_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK4SELR,
+ 0, 2, CLK_MUX_READ_ONLY),
+
+ /* PLLs */
+ PLL(PLL1, "pll1", "ref1", CLK_IGNORE_UNUSED, RCC_PLL1CR),
+ PLL(PLL2, "pll2", "ref1", CLK_IGNORE_UNUSED, RCC_PLL2CR),
+ PLL(PLL3, "pll3", "ref3", CLK_IGNORE_UNUSED, RCC_PLL3CR),
+ PLL(PLL4, "pll4", "ref4", CLK_IGNORE_UNUSED, RCC_PLL4CR),
+
+ /* ODF */
+ COMPOSITE(PLL1_P, "pll1_p", PARENT("pll1"), 0,
+ _GATE(RCC_PLL1CR, 4, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL1CFGR2, 0, 7, 0, NULL)),
+
+ COMPOSITE(PLL2_P, "pll2_p", PARENT("pll2"), 0,
+ _GATE(RCC_PLL2CR, 4, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL2CFGR2, 0, 7, 0, NULL)),
+
+ COMPOSITE(PLL2_Q, "pll2_q", PARENT("pll2"), 0,
+ _GATE(RCC_PLL2CR, 5, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL2CFGR2, 8, 7, 0, NULL)),
+
+ COMPOSITE(PLL2_R, "pll2_r", PARENT("pll2"), CLK_IS_CRITICAL,
+ _GATE(RCC_PLL2CR, 6, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL2CFGR2, 16, 7, 0, NULL)),
+
+ COMPOSITE(PLL3_P, "pll3_p", PARENT("pll3"), 0,
+ _GATE(RCC_PLL3CR, 4, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL3CFGR2, 0, 7, 0, NULL)),
+
+ COMPOSITE(PLL3_Q, "pll3_q", PARENT("pll3"), 0,
+ _GATE(RCC_PLL3CR, 5, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL3CFGR2, 8, 7, 0, NULL)),
+
+ COMPOSITE(PLL3_R, "pll3_r", PARENT("pll3"), 0,
+ _GATE(RCC_PLL3CR, 6, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL3CFGR2, 16, 7, 0, NULL)),
+
+ COMPOSITE(PLL4_P, "pll4_p", PARENT("pll4"), 0,
+ _GATE(RCC_PLL4CR, 4, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL4CFGR2, 0, 7, 0, NULL)),
+
+ COMPOSITE(PLL4_Q, "pll4_q", PARENT("pll4"), 0,
+ _GATE(RCC_PLL4CR, 5, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL4CFGR2, 8, 7, 0, NULL)),
+
+ COMPOSITE(PLL4_R, "pll4_r", PARENT("pll4"), 0,
+ _GATE(RCC_PLL4CR, 6, 0),
+ _NO_MUX,
+ _DIV(RCC_PLL4CFGR2, 16, 7, 0, NULL)),
+
+ /* MUX system clocks */
+ MUX(CK_PER, "ck_per", per_src, CLK_OPS_PARENT_ENABLE,
+ RCC_CPERCKSELR, 0, 2, 0),
+
+ MUX(CK_MPU, "ck_mpu", cpu_src, CLK_OPS_PARENT_ENABLE |
+ CLK_IS_CRITICAL, RCC_MPCKSELR, 0, 2, 0),
+
+ COMPOSITE(CK_AXI, "ck_axi", axi_src, CLK_IS_CRITICAL |
+ CLK_OPS_PARENT_ENABLE,
+ _NO_GATE,
+ _MUX(RCC_ASSCKSELR, 0, 2, 0),
+ _DIV(RCC_AXIDIVR, 0, 3, 0, axi_div_table)),
+
+ COMPOSITE(CK_MCU, "ck_mcu", mcu_src, CLK_IS_CRITICAL |
+ CLK_OPS_PARENT_ENABLE,
+ _NO_GATE,
+ _MUX(RCC_MSSCKSELR, 0, 2, 0),
+ _DIV(RCC_MCUDIVR, 0, 4, 0, mcu_div_table)),
+
+ DIV_TABLE(NO_ID, "pclk1", "ck_mcu", CLK_IGNORE_UNUSED, RCC_APB1DIVR, 0,
+ 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+ DIV_TABLE(NO_ID, "pclk2", "ck_mcu", CLK_IGNORE_UNUSED, RCC_APB2DIVR, 0,
+ 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+ DIV_TABLE(NO_ID, "pclk3", "ck_mcu", CLK_IGNORE_UNUSED, RCC_APB3DIVR, 0,
+ 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+ DIV_TABLE(NO_ID, "pclk4", "ck_axi", CLK_IGNORE_UNUSED, RCC_APB4DIVR, 0,
+ 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+ DIV_TABLE(NO_ID, "pclk5", "ck_axi", CLK_IGNORE_UNUSED, RCC_APB5DIVR, 0,
+ 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+ /* Kernel Timers */
+ STM32_CKTIM("ck1_tim", "pclk1", 0, RCC_APB1DIVR, RCC_TIMG1PRER),
+ STM32_CKTIM("ck2_tim", "pclk2", 0, RCC_APB2DIVR, RCC_TIMG2PRER),
+
+ STM32_TIM(TIM2_K, "tim2_k", "ck1_tim", RCC_APB1ENSETR, 0),
+ STM32_TIM(TIM3_K, "tim3_k", "ck1_tim", RCC_APB1ENSETR, 1),
+ STM32_TIM(TIM4_K, "tim4_k", "ck1_tim", RCC_APB1ENSETR, 2),
+ STM32_TIM(TIM5_K, "tim5_k", "ck1_tim", RCC_APB1ENSETR, 3),
+ STM32_TIM(TIM6_K, "tim6_k", "ck1_tim", RCC_APB1ENSETR, 4),
+ STM32_TIM(TIM7_K, "tim7_k", "ck1_tim", RCC_APB1ENSETR, 5),
+ STM32_TIM(TIM12_K, "tim12_k", "ck1_tim", RCC_APB1ENSETR, 6),
+ STM32_TIM(TIM13_K, "tim13_k", "ck1_tim", RCC_APB1ENSETR, 7),
+ STM32_TIM(TIM14_K, "tim14_k", "ck1_tim", RCC_APB1ENSETR, 8),
+ STM32_TIM(TIM1_K, "tim1_k", "ck2_tim", RCC_APB2ENSETR, 0),
+ STM32_TIM(TIM8_K, "tim8_k", "ck2_tim", RCC_APB2ENSETR, 1),
+ STM32_TIM(TIM15_K, "tim15_k", "ck2_tim", RCC_APB2ENSETR, 2),
+ STM32_TIM(TIM16_K, "tim16_k", "ck2_tim", RCC_APB2ENSETR, 3),
+ STM32_TIM(TIM17_K, "tim17_k", "ck2_tim", RCC_APB2ENSETR, 4),
+
+ /* Peripheral clocks */
+ PCLK(TIM2, "tim2", "pclk1", CLK_IGNORE_UNUSED, G_TIM2),
+ PCLK(TIM3, "tim3", "pclk1", CLK_IGNORE_UNUSED, G_TIM3),
+ PCLK(TIM4, "tim4", "pclk1", CLK_IGNORE_UNUSED, G_TIM4),
+ PCLK(TIM5, "tim5", "pclk1", CLK_IGNORE_UNUSED, G_TIM5),
+ PCLK(TIM6, "tim6", "pclk1", CLK_IGNORE_UNUSED, G_TIM6),
+ PCLK(TIM7, "tim7", "pclk1", CLK_IGNORE_UNUSED, G_TIM7),
+ PCLK(TIM12, "tim12", "pclk1", CLK_IGNORE_UNUSED, G_TIM12),
+ PCLK(TIM13, "tim13", "pclk1", CLK_IGNORE_UNUSED, G_TIM13),
+ PCLK(TIM14, "tim14", "pclk1", CLK_IGNORE_UNUSED, G_TIM14),
+ PCLK(LPTIM1, "lptim1", "pclk1", 0, G_LPTIM1),
+ PCLK(SPI2, "spi2", "pclk1", 0, G_SPI2),
+ PCLK(SPI3, "spi3", "pclk1", 0, G_SPI3),
+ PCLK(USART2, "usart2", "pclk1", 0, G_USART2),
+ PCLK(USART3, "usart3", "pclk1", 0, G_USART3),
+ PCLK(UART4, "uart4", "pclk1", 0, G_UART4),
+ PCLK(UART5, "uart5", "pclk1", 0, G_UART5),
+ PCLK(UART7, "uart7", "pclk1", 0, G_UART7),
+ PCLK(UART8, "uart8", "pclk1", 0, G_UART8),
+ PCLK(I2C1, "i2c1", "pclk1", 0, G_I2C1),
+ PCLK(I2C2, "i2c2", "pclk1", 0, G_I2C2),
+ PCLK(I2C3, "i2c3", "pclk1", 0, G_I2C3),
+ PCLK(I2C5, "i2c5", "pclk1", 0, G_I2C5),
+ PCLK(SPDIF, "spdif", "pclk1", 0, G_SPDIF),
+ PCLK(CEC, "cec", "pclk1", 0, G_CEC),
+ PCLK(DAC12, "dac12", "pclk1", 0, G_DAC12),
+ PCLK(MDIO, "mdio", "pclk1", 0, G_MDIO),
+ PCLK(TIM1, "tim1", "pclk2", CLK_IGNORE_UNUSED, G_TIM1),
+ PCLK(TIM8, "tim8", "pclk2", CLK_IGNORE_UNUSED, G_TIM8),
+ PCLK(TIM15, "tim15", "pclk2", CLK_IGNORE_UNUSED, G_TIM15),
+ PCLK(TIM16, "tim16", "pclk2", CLK_IGNORE_UNUSED, G_TIM16),
+ PCLK(TIM17, "tim17", "pclk2", CLK_IGNORE_UNUSED, G_TIM17),
+ PCLK(SPI1, "spi1", "pclk2", 0, G_SPI1),
+ PCLK(SPI4, "spi4", "pclk2", 0, G_SPI4),
+ PCLK(SPI5, "spi5", "pclk2", 0, G_SPI5),
+ PCLK(USART6, "usart6", "pclk2", 0, G_USART6),
+ PCLK(SAI1, "sai1", "pclk2", 0, G_SAI1),
+ PCLK(SAI2, "sai2", "pclk2", 0, G_SAI2),
+ PCLK(SAI3, "sai3", "pclk2", 0, G_SAI3),
+ PCLK(DFSDM, "dfsdm", "pclk2", 0, G_DFSDM),
+ PCLK(FDCAN, "fdcan", "pclk2", 0, G_FDCAN),
+ PCLK(LPTIM2, "lptim2", "pclk3", 0, G_LPTIM2),
+ PCLK(LPTIM3, "lptim3", "pclk3", 0, G_LPTIM3),
+ PCLK(LPTIM4, "lptim4", "pclk3", 0, G_LPTIM4),
+ PCLK(LPTIM5, "lptim5", "pclk3", 0, G_LPTIM5),
+ PCLK(SAI4, "sai4", "pclk3", 0, G_SAI4),
+ PCLK(SYSCFG, "syscfg", "pclk3", 0, G_SYSCFG),
+ PCLK(VREF, "vref", "pclk3", 13, G_VREF),
+ PCLK(TMPSENS, "tmpsens", "pclk3", 0, G_TMPSENS),
+ PCLK(PMBCTRL, "pmbctrl", "pclk3", 0, G_PMBCTRL),
+ PCLK(HDP, "hdp", "pclk3", 0, G_HDP),
+ PCLK(LTDC, "ltdc", "pclk4", 0, G_LTDC),
+ PCLK(DSI, "dsi", "pclk4", 0, G_DSI),
+ PCLK(IWDG2, "iwdg2", "pclk4", 0, G_IWDG2),
+ PCLK(USBPHY, "usbphy", "pclk4", 0, G_USBPHY),
+ PCLK(STGENRO, "stgenro", "pclk4", 0, G_STGENRO),
+ PCLK(SPI6, "spi6", "pclk5", 0, G_SPI6),
+ PCLK(I2C4, "i2c4", "pclk5", 0, G_I2C4),
+ PCLK(I2C6, "i2c6", "pclk5", 0, G_I2C6),
+ PCLK(USART1, "usart1", "pclk5", 0, G_USART1),
+ PCLK(RTCAPB, "rtcapb", "pclk5", CLK_IGNORE_UNUSED |
+ CLK_IS_CRITICAL, G_RTCAPB),
+ PCLK(TZC, "tzc", "pclk5", CLK_IGNORE_UNUSED, G_TZC),
+ PCLK(TZPC, "tzpc", "pclk5", CLK_IGNORE_UNUSED, G_TZPC),
+ PCLK(IWDG1, "iwdg1", "pclk5", 0, G_IWDG1),
+ PCLK(BSEC, "bsec", "pclk5", CLK_IGNORE_UNUSED, G_BSEC),
+ PCLK(STGEN, "stgen", "pclk5", CLK_IGNORE_UNUSED, G_STGEN),
+ PCLK(DMA1, "dma1", "ck_mcu", 0, G_DMA1),
+ PCLK(DMA2, "dma2", "ck_mcu", 0, G_DMA2),
+ PCLK(DMAMUX, "dmamux", "ck_mcu", 0, G_DMAMUX),
+ PCLK(ADC12, "adc12", "ck_mcu", 0, G_ADC12),
+ PCLK(USBO, "usbo", "ck_mcu", 0, G_USBO),
+ PCLK(SDMMC3, "sdmmc3", "ck_mcu", 0, G_SDMMC3),
+ PCLK(DCMI, "dcmi", "ck_mcu", 0, G_DCMI),
+ PCLK(CRYP2, "cryp2", "ck_mcu", 0, G_CRYP2),
+ PCLK(HASH2, "hash2", "ck_mcu", 0, G_HASH2),
+ PCLK(RNG2, "rng2", "ck_mcu", 0, G_RNG2),
+ PCLK(CRC2, "crc2", "ck_mcu", 0, G_CRC2),
+ PCLK(HSEM, "hsem", "ck_mcu", 0, G_HSEM),
+ PCLK(IPCC, "ipcc", "ck_mcu", 0, G_IPCC),
+ PCLK(GPIOA, "gpioa", "ck_mcu", 0, G_GPIOA),
+ PCLK(GPIOB, "gpiob", "ck_mcu", 0, G_GPIOB),
+ PCLK(GPIOC, "gpioc", "ck_mcu", 0, G_GPIOC),
+ PCLK(GPIOD, "gpiod", "ck_mcu", 0, G_GPIOD),
+ PCLK(GPIOE, "gpioe", "ck_mcu", 0, G_GPIOE),
+ PCLK(GPIOF, "gpiof", "ck_mcu", 0, G_GPIOF),
+ PCLK(GPIOG, "gpiog", "ck_mcu", 0, G_GPIOG),
+ PCLK(GPIOH, "gpioh", "ck_mcu", 0, G_GPIOH),
+ PCLK(GPIOI, "gpioi", "ck_mcu", 0, G_GPIOI),
+ PCLK(GPIOJ, "gpioj", "ck_mcu", 0, G_GPIOJ),
+ PCLK(GPIOK, "gpiok", "ck_mcu", 0, G_GPIOK),
+ PCLK(GPIOZ, "gpioz", "ck_axi", CLK_IGNORE_UNUSED, G_GPIOZ),
+ PCLK(CRYP1, "cryp1", "ck_axi", CLK_IGNORE_UNUSED, G_CRYP1),
+ PCLK(HASH1, "hash1", "ck_axi", CLK_IGNORE_UNUSED, G_HASH1),
+ PCLK(RNG1, "rng1", "ck_axi", 0, G_RNG1),
+ PCLK(BKPSRAM, "bkpsram", "ck_axi", CLK_IGNORE_UNUSED, G_BKPSRAM),
+ PCLK(MDMA, "mdma", "ck_axi", 0, G_MDMA),
+ PCLK(GPU, "gpu", "ck_axi", 0, G_GPU),
+ PCLK(ETHTX, "ethtx", "ck_axi", 0, G_ETHTX),
+ PCLK(ETHRX, "ethrx", "ck_axi", 0, G_ETHRX),
+ PCLK(ETHMAC, "ethmac", "ck_axi", 0, G_ETHMAC),
+ PCLK(FMC, "fmc", "ck_axi", CLK_IGNORE_UNUSED, G_FMC),
+ PCLK(QSPI, "qspi", "ck_axi", CLK_IGNORE_UNUSED, G_QSPI),
+ PCLK(SDMMC1, "sdmmc1", "ck_axi", 0, G_SDMMC1),
+ PCLK(SDMMC2, "sdmmc2", "ck_axi", 0, G_SDMMC2),
+ PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1),
+ PCLK(USBH, "usbh", "ck_axi", 0, G_USBH),
+ PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP),
+
+ /* Kernel clocks */
+ KCLK(SDMMC1_K, "sdmmc1_k", sdmmc12_src, 0, G_SDMMC1, M_SDMMC12),
+ KCLK(SDMMC2_K, "sdmmc2_k", sdmmc12_src, 0, G_SDMMC2, M_SDMMC12),
+ KCLK(SDMMC3_K, "sdmmc3_k", sdmmc3_src, 0, G_SDMMC3, M_SDMMC3),
+ KCLK(FMC_K, "fmc_k", fmc_src, 0, G_FMC, M_FMC),
+ KCLK(QSPI_K, "qspi_k", qspi_src, 0, G_QSPI, M_QSPI),
+ KCLK(RNG1_K, "rng1_k", rng_src, 0, G_RNG1, M_RNG1),
+ KCLK(RNG2_K, "rng2_k", rng_src, 0, G_RNG2, M_RNG2),
+ KCLK(USBPHY_K, "usbphy_k", usbphy_src, 0, G_USBPHY, M_USBPHY),
+ KCLK(STGEN_K, "stgen_k", stgen_src, CLK_IGNORE_UNUSED,
+ G_STGEN, M_STGEN),
+ KCLK(SPDIF_K, "spdif_k", spdif_src, 0, G_SPDIF, M_SPDIF),
+ KCLK(SPI1_K, "spi1_k", spi123_src, 0, G_SPI1, M_SPI1),
+ KCLK(SPI2_K, "spi2_k", spi123_src, 0, G_SPI2, M_SPI23),
+ KCLK(SPI3_K, "spi3_k", spi123_src, 0, G_SPI3, M_SPI23),
+ KCLK(SPI4_K, "spi4_k", spi45_src, 0, G_SPI4, M_SPI45),
+ KCLK(SPI5_K, "spi5_k", spi45_src, 0, G_SPI5, M_SPI45),
+ KCLK(SPI6_K, "spi6_k", spi6_src, 0, G_SPI6, M_SPI6),
+ KCLK(CEC_K, "cec_k", cec_src, 0, G_CEC, M_CEC),
+ KCLK(I2C1_K, "i2c1_k", i2c12_src, 0, G_I2C1, M_I2C12),
+ KCLK(I2C2_K, "i2c2_k", i2c12_src, 0, G_I2C2, M_I2C12),
+ KCLK(I2C3_K, "i2c3_k", i2c35_src, 0, G_I2C3, M_I2C35),
+ KCLK(I2C5_K, "i2c5_k", i2c35_src, 0, G_I2C5, M_I2C35),
+ KCLK(I2C4_K, "i2c4_k", i2c46_src, 0, G_I2C4, M_I2C46),
+ KCLK(I2C6_K, "i2c6_k", i2c46_src, 0, G_I2C6, M_I2C46),
+ KCLK(LPTIM1_K, "lptim1_k", lptim1_src, 0, G_LPTIM1, M_LPTIM1),
+ KCLK(LPTIM2_K, "lptim2_k", lptim23_src, 0, G_LPTIM2, M_LPTIM23),
+ KCLK(LPTIM3_K, "lptim3_k", lptim23_src, 0, G_LPTIM3, M_LPTIM23),
+ KCLK(LPTIM4_K, "lptim4_k", lptim45_src, 0, G_LPTIM4, M_LPTIM45),
+ KCLK(LPTIM5_K, "lptim5_k", lptim45_src, 0, G_LPTIM5, M_LPTIM45),
+ KCLK(USART1_K, "usart1_k", usart1_src, 0, G_USART1, M_USART1),
+ KCLK(USART2_K, "usart2_k", usart234578_src, 0, G_USART2, M_UART24),
+ KCLK(USART3_K, "usart3_k", usart234578_src, 0, G_USART3, M_UART35),
+ KCLK(UART4_K, "uart4_k", usart234578_src, 0, G_UART4, M_UART24),
+ KCLK(UART5_K, "uart5_k", usart234578_src, 0, G_UART5, M_UART35),
+ KCLK(USART6_K, "uart6_k", usart6_src, 0, G_USART6, M_USART6),
+ KCLK(UART7_K, "uart7_k", usart234578_src, 0, G_UART7, M_UART78),
+ KCLK(UART8_K, "uart8_k", usart234578_src, 0, G_UART8, M_UART78),
+ KCLK(FDCAN_K, "fdcan_k", fdcan_src, 0, G_FDCAN, M_FDCAN),
+ KCLK(SAI1_K, "sai1_k", sai_src, 0, G_SAI1, M_SAI1),
+ KCLK(SAI2_K, "sai2_k", sai2_src, 0, G_SAI2, M_SAI2),
+ KCLK(SAI3_K, "sai3_k", sai_src, 0, G_SAI2, M_SAI3),
+ KCLK(SAI4_K, "sai4_k", sai_src, 0, G_SAI2, M_SAI4),
+ KCLK(ADC12_K, "adc12_k", adc12_src, 0, G_ADC12, M_ADC12),
+ KCLK(DSI_K, "dsi_k", dsi_src, 0, G_DSI, M_DSI),
+ KCLK(ADFSDM_K, "adfsdm_k", sai_src, 0, G_ADFSDM, M_SAI1),
+ KCLK(USBO_K, "usbo_k", usbo_src, 0, G_USBO, M_USBO),
+ KCLK(ETHCK_K, "ethck_k", eth_src, 0, G_ETHCK, M_ETHCK),
+
+ /* Particulary Kernel Clocks (no mux or no gate) */
+ MGATE_MP1(DFSDM_K, "dfsdm_k", "ck_mcu", 0, G_DFSDM),
+ MGATE_MP1(DSI_PX, "dsi_px", "pll4_q", CLK_SET_RATE_PARENT, G_DSI),
+ MGATE_MP1(LTDC_PX, "ltdc_px", "pll4_q", CLK_SET_RATE_PARENT, G_LTDC),
+ MGATE_MP1(GPU_K, "gpu_k", "pll2_q", 0, G_GPU),
+ MGATE_MP1(DAC12_K, "dac12_k", "ck_lsi", 0, G_DAC12),
+
+ COMPOSITE(ETHPTP_K, "ethptp_k", eth_src, CLK_OPS_PARENT_ENABLE,
+ _NO_GATE,
+ _MMUX(M_ETHCK),
+ _DIV(RCC_ETHCKSELR, 4, 4, CLK_DIVIDER_ALLOW_ZERO, NULL)),
+
+ /* RTC clock */
+ DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7,
+ CLK_DIVIDER_ALLOW_ZERO),
+
+ COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
+ CLK_SET_RATE_PARENT,
+ _GATE(RCC_BDCR, 20, 0),
+ _MUX(RCC_BDCR, 16, 2, 0),
+ _NO_DIV),
+
+ /* MCO clocks */
+ COMPOSITE(CK_MCO1, "ck_mco1", mco1_src, CLK_OPS_PARENT_ENABLE |
+ CLK_SET_RATE_NO_REPARENT,
+ _GATE(RCC_MCO1CFGR, 12, 0),
+ _MUX(RCC_MCO1CFGR, 0, 3, 0),
+ _DIV(RCC_MCO1CFGR, 4, 4, 0, NULL)),
+
+ COMPOSITE(CK_MCO2, "ck_mco2", mco2_src, CLK_OPS_PARENT_ENABLE |
+ CLK_SET_RATE_NO_REPARENT,
+ _GATE(RCC_MCO2CFGR, 12, 0),
+ _MUX(RCC_MCO2CFGR, 0, 3, 0),
+ _DIV(RCC_MCO2CFGR, 4, 4, 0, NULL)),
+
+ /* Debug clocks */
+ FIXED_FACTOR(NO_ID, "ck_axi_div2", "ck_axi", 0, 1, 2),
+
+ GATE(DBG, "ck_apb_dbg", "ck_axi_div2", 0, RCC_DBGCFGR, 8, 0),
+
+ GATE(CK_DBG, "ck_sys_dbg", "ck_axi", 0, RCC_DBGCFGR, 8, 0),
+
+ COMPOSITE(CK_TRACE, "ck_trace", ck_trace_src, CLK_OPS_PARENT_ENABLE,
+ _GATE(RCC_DBGCFGR, 9, 0),
+ _NO_MUX,
+ _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)),
+};
+
+struct stm32_clock_match_data {
+ const struct clock_config *cfg;
+ unsigned int num;
+ unsigned int maxbinding;
+};
+
+static struct stm32_clock_match_data stm32mp1_data = {
+ .cfg = stm32mp1_clock_cfg,
+ .num = ARRAY_SIZE(stm32mp1_clock_cfg),
+ .maxbinding = STM32MP1_LAST_CLK,
+};
+
+static const struct of_device_id stm32mp1_match_data[] = {
+ {
+ .compatible = "st,stm32mp1-rcc",
+ .data = &stm32mp1_data,
+ },
+ { }
+};
+
+static int stm32_register_hw_clk(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ static struct clk_hw **hws;
+ struct clk_hw *hw = ERR_PTR(-ENOENT);
+
+ hws = clk_data->hws;
+
+ if (cfg->func)
+ hw = (*cfg->func)(dev, clk_data, base, lock, cfg);
+
+ if (IS_ERR(hw)) {
+ pr_err("Unable to register %s\n", cfg->name);
+ return PTR_ERR(hw);
+ }
+
+ if (cfg->id != NO_ID)
+ hws[cfg->id] = hw;
+
+ return 0;
+}
+
+static int stm32_rcc_init(struct device_node *np,
+ void __iomem *base,
+ const struct of_device_id *match_data)
+{
+ struct clk_hw_onecell_data *clk_data;
+ struct clk_hw **hws;
+ const struct of_device_id *match;
+ const struct stm32_clock_match_data *data;
+ int err, n, max_binding;
+
+ match = of_match_node(match_data, np);
+ if (!match) {
+ pr_err("%s: match data not found\n", __func__);
+ return -ENODEV;
+ }
+
+ data = match->data;
+
+ max_binding = data->maxbinding;
+
+ clk_data = kzalloc(sizeof(*clk_data) +
+ sizeof(*clk_data->hws) * max_binding,
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = max_binding;
+
+ hws = clk_data->hws;
+
+ for (n = 0; n < max_binding; n++)
+ hws[n] = ERR_PTR(-ENOENT);
+
+ for (n = 0; n < data->num; n++) {
+ err = stm32_register_hw_clk(NULL, clk_data, base, &rlock,
+ &data->cfg[n]);
+ if (err) {
+ pr_err("%s: can't register %s\n", __func__,
+ data->cfg[n].name);
+
+ kfree(clk_data);
+
+ return err;
+ }
+ }
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static void stm32mp1_rcc_init(struct device_node *np)
+{
+ void __iomem *base;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%s: unable to map resource", np->name);
+ of_node_put(np);
+ return;
+ }
+
+ if (stm32_rcc_init(np, base, stm32mp1_match_data)) {
+ iounmap(base);
+ of_node_put(np);
+ }
+}
+
+CLK_OF_DECLARE_DRIVER(stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_rcc_init);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0f686a9dac3e..ea67ac81c6f9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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);
@@ -2309,8 +2311,11 @@ static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
trace_clk_set_phase(core, degrees);
- if (core->ops->set_phase)
+ if (core->ops->set_phase) {
ret = core->ops->set_phase(core->hw, degrees);
+ if (!ret)
+ core->phase = degrees;
+ }
trace_clk_set_phase_complete(core, degrees);
@@ -2370,6 +2375,9 @@ static int clk_core_get_phase(struct clk_core *core)
int ret;
clk_prepare_lock();
+ /* Always try to update cached phase if possible */
+ if (core->ops->get_phase)
+ core->phase = core->ops->get_phase(core->hw);
ret = core->phase;
clk_prepare_unlock();
@@ -2486,19 +2494,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
return 0;
}
-
-
-static int clk_summary_open(struct inode *inode, struct file *file)
-{
- return single_open(file, clk_summary_show, inode->i_private);
-}
-
-static const struct file_operations clk_summary_fops = {
- .open = clk_summary_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(clk_summary);
static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
@@ -2532,7 +2528,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
seq_putc(s, '}');
}
-static int clk_dump(struct seq_file *s, void *data)
+static int clk_dump_show(struct seq_file *s, void *data)
{
struct clk_core *c;
bool first_node = true;
@@ -2555,19 +2551,7 @@ static int clk_dump(struct seq_file *s, void *data)
seq_puts(s, "}\n");
return 0;
}
-
-
-static int clk_dump_open(struct inode *inode, struct file *file)
-{
- return single_open(file, clk_dump, inode->i_private);
-}
-
-static const struct file_operations clk_dump_fops = {
- .open = clk_dump_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(clk_dump);
static const struct {
unsigned long flag;
@@ -2589,7 +2573,7 @@ static const struct {
#undef ENTRY
};
-static int clk_flags_dump(struct seq_file *s, void *data)
+static int clk_flags_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
unsigned long flags = core->flags;
@@ -2608,20 +2592,9 @@ static int clk_flags_dump(struct seq_file *s, void *data)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(clk_flags);
-static int clk_flags_open(struct inode *inode, struct file *file)
-{
- return single_open(file, clk_flags_dump, inode->i_private);
-}
-
-static const struct file_operations clk_flags_fops = {
- .open = clk_flags_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int possible_parents_dump(struct seq_file *s, void *data)
+static int possible_parents_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
int i;
@@ -2633,18 +2606,7 @@ static int possible_parents_dump(struct seq_file *s, void *data)
return 0;
}
-
-static int possible_parents_open(struct inode *inode, struct file *file)
-{
- return single_open(file, possible_parents_dump, inode->i_private);
-}
-
-static const struct file_operations possible_parents_fops = {
- .open = possible_parents_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(possible_parents);
static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
@@ -2928,6 +2890,17 @@ static int __clk_core_init(struct clk_core *core)
}
/*
+ * 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
* fallback is to use the parent's accuracy. If a clock doesn't have a
@@ -2968,48 +2941,42 @@ static int __clk_core_init(struct clk_core *core)
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);
diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c
index 9cdf9d5050ac..4cb70bed89a9 100644
--- a/drivers/clk/keystone/sci-clk.c
+++ b/drivers/clk/keystone/sci-clk.c
@@ -29,21 +29,10 @@
#define SCI_CLK_INPUT_TERMINATION BIT(2)
/**
- * struct sci_clk_data - TI SCI clock data
- * @dev: device index
- * @num_clks: number of clocks for this device
- */
-struct sci_clk_data {
- u16 dev;
- u16 num_clks;
-};
-
-/**
* struct sci_clk_provider - TI SCI clock provider representation
* @sci: Handle to the System Control Interface protocol handler
* @ops: Pointer to the SCI ops to be used by the clocks
* @dev: Device pointer for the clock provider
- * @clk_data: Clock data
* @clocks: Clocks array for this device
* @num_clocks: Total number of clocks for this provider
*/
@@ -51,8 +40,7 @@ struct sci_clk_provider {
const struct ti_sci_handle *sci;
const struct ti_sci_clk_ops *ops;
struct device *dev;
- const struct sci_clk_data *clk_data;
- struct clk_hw **clocks;
+ struct sci_clk **clocks;
int num_clocks;
};
@@ -61,6 +49,7 @@ struct sci_clk_provider {
* @hw: Hardware clock cookie for common clock framework
* @dev_id: Device index
* @clk_id: Clock index
+ * @num_parents: Number of parents for this clock
* @provider: Master clock provider
* @flags: Flags for the clock
*/
@@ -68,6 +57,7 @@ struct sci_clk {
struct clk_hw hw;
u16 dev_id;
u8 clk_id;
+ u8 num_parents;
struct sci_clk_provider *provider;
u8 flags;
};
@@ -273,38 +263,22 @@ static const struct clk_ops sci_clk_ops = {
/**
* _sci_clk_get - Gets a handle for an SCI clock
* @provider: Handle to SCI clock provider
- * @dev_id: device ID for the clock to register
- * @clk_id: clock ID for the clock to register
+ * @sci_clk: Handle to the SCI clock to populate
*
* Gets a handle to an existing TI SCI hw clock, or builds a new clock
* entry and registers it with the common clock framework. Called from
* the common clock framework, when a corresponding of_clk_get call is
* executed, or recursively from itself when parsing parent clocks.
- * Returns a pointer to the hw clock struct, or ERR_PTR value in failure.
+ * Returns 0 on success, negative error code on failure.
*/
-static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
- u16 dev_id, u8 clk_id)
+static int _sci_clk_build(struct sci_clk_provider *provider,
+ struct sci_clk *sci_clk)
{
struct clk_init_data init = { NULL };
- struct sci_clk *sci_clk = NULL;
char *name = NULL;
char **parent_names = NULL;
int i;
- int ret;
-
- sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL);
- if (!sci_clk)
- return ERR_PTR(-ENOMEM);
-
- sci_clk->dev_id = dev_id;
- sci_clk->clk_id = clk_id;
- sci_clk->provider = provider;
-
- ret = provider->ops->get_num_parents(provider->sci, dev_id,
- clk_id,
- &init.num_parents);
- if (ret)
- goto err;
+ int ret = 0;
name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
sci_clk->dev_id, sci_clk->clk_id);
@@ -317,11 +291,11 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
* to have mux functionality. Otherwise it is going to act as a root
* clock.
*/
- if (init.num_parents < 2)
- init.num_parents = 0;
+ if (sci_clk->num_parents < 2)
+ sci_clk->num_parents = 0;
- if (init.num_parents) {
- parent_names = kcalloc(init.num_parents, sizeof(char *),
+ if (sci_clk->num_parents) {
+ parent_names = kcalloc(sci_clk->num_parents, sizeof(char *),
GFP_KERNEL);
if (!parent_names) {
@@ -329,7 +303,7 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
goto err;
}
- for (i = 0; i < init.num_parents; i++) {
+ for (i = 0; i < sci_clk->num_parents; i++) {
char *parent_name;
parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
@@ -346,6 +320,7 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
}
init.ops = &sci_clk_ops;
+ init.num_parents = sci_clk->num_parents;
sci_clk->hw.init = &init;
ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
@@ -354,7 +329,7 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
err:
if (parent_names) {
- for (i = 0; i < init.num_parents; i++)
+ for (i = 0; i < sci_clk->num_parents; i++)
kfree(parent_names[i]);
kfree(parent_names);
@@ -362,10 +337,7 @@ err:
kfree(name);
- if (ret)
- return ERR_PTR(ret);
-
- return &sci_clk->hw;
+ return ret;
}
static int _cmp_sci_clk(const void *a, const void *b)
@@ -414,253 +386,20 @@ static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
static int ti_sci_init_clocks(struct sci_clk_provider *p)
{
- const struct sci_clk_data *data = p->clk_data;
- struct clk_hw *hw;
int i;
- int num_clks = 0;
-
- while (data->num_clks) {
- num_clks += data->num_clks;
- data++;
- }
-
- p->num_clocks = num_clks;
-
- p->clocks = devm_kcalloc(p->dev, num_clks, sizeof(struct sci_clk),
- GFP_KERNEL);
- if (!p->clocks)
- return -ENOMEM;
-
- num_clks = 0;
-
- data = p->clk_data;
-
- while (data->num_clks) {
- for (i = 0; i < data->num_clks; i++) {
- hw = _sci_clk_build(p, data->dev, i);
- if (!IS_ERR(hw)) {
- p->clocks[num_clks++] = hw;
- continue;
- }
-
- /* Skip any holes in the clock lists */
- if (PTR_ERR(hw) == -ENODEV)
- continue;
+ int ret;
- return PTR_ERR(hw);
- }
- data++;
+ for (i = 0; i < p->num_clocks; i++) {
+ ret = _sci_clk_build(p, p->clocks[i]);
+ if (ret)
+ return ret;
}
return 0;
}
-static const struct sci_clk_data k2g_clk_data[] = {
- /* pmmc */
- { .dev = 0x0, .num_clks = 4 },
-
- /* mlb0 */
- { .dev = 0x1, .num_clks = 5 },
-
- /* dss0 */
- { .dev = 0x2, .num_clks = 2 },
-
- /* mcbsp0 */
- { .dev = 0x3, .num_clks = 8 },
-
- /* mcasp0 */
- { .dev = 0x4, .num_clks = 8 },
-
- /* mcasp1 */
- { .dev = 0x5, .num_clks = 8 },
-
- /* mcasp2 */
- { .dev = 0x6, .num_clks = 8 },
-
- /* dcan0 */
- { .dev = 0x8, .num_clks = 2 },
-
- /* dcan1 */
- { .dev = 0x9, .num_clks = 2 },
-
- /* emif0 */
- { .dev = 0xa, .num_clks = 6 },
-
- /* mmchs0 */
- { .dev = 0xb, .num_clks = 3 },
-
- /* mmchs1 */
- { .dev = 0xc, .num_clks = 3 },
-
- /* gpmc0 */
- { .dev = 0xd, .num_clks = 1 },
-
- /* elm0 */
- { .dev = 0xe, .num_clks = 1 },
-
- /* spi0 */
- { .dev = 0x10, .num_clks = 1 },
-
- /* spi1 */
- { .dev = 0x11, .num_clks = 1 },
-
- /* spi2 */
- { .dev = 0x12, .num_clks = 1 },
-
- /* spi3 */
- { .dev = 0x13, .num_clks = 1 },
-
- /* icss0 */
- { .dev = 0x14, .num_clks = 6 },
-
- /* icss1 */
- { .dev = 0x15, .num_clks = 6 },
-
- /* usb0 */
- { .dev = 0x16, .num_clks = 7 },
-
- /* usb1 */
- { .dev = 0x17, .num_clks = 7 },
-
- /* nss0 */
- { .dev = 0x18, .num_clks = 14 },
-
- /* pcie0 */
- { .dev = 0x19, .num_clks = 1 },
-
- /* gpio0 */
- { .dev = 0x1b, .num_clks = 1 },
-
- /* gpio1 */
- { .dev = 0x1c, .num_clks = 1 },
-
- /* timer64_0 */
- { .dev = 0x1d, .num_clks = 9 },
-
- /* timer64_1 */
- { .dev = 0x1e, .num_clks = 9 },
-
- /* timer64_2 */
- { .dev = 0x1f, .num_clks = 9 },
-
- /* timer64_3 */
- { .dev = 0x20, .num_clks = 9 },
-
- /* timer64_4 */
- { .dev = 0x21, .num_clks = 9 },
-
- /* timer64_5 */
- { .dev = 0x22, .num_clks = 9 },
-
- /* timer64_6 */
- { .dev = 0x23, .num_clks = 9 },
-
- /* msgmgr0 */
- { .dev = 0x25, .num_clks = 1 },
-
- /* bootcfg0 */
- { .dev = 0x26, .num_clks = 1 },
-
- /* arm_bootrom0 */
- { .dev = 0x27, .num_clks = 1 },
-
- /* dsp_bootrom0 */
- { .dev = 0x29, .num_clks = 1 },
-
- /* debugss0 */
- { .dev = 0x2b, .num_clks = 8 },
-
- /* uart0 */
- { .dev = 0x2c, .num_clks = 1 },
-
- /* uart1 */
- { .dev = 0x2d, .num_clks = 1 },
-
- /* uart2 */
- { .dev = 0x2e, .num_clks = 1 },
-
- /* ehrpwm0 */
- { .dev = 0x2f, .num_clks = 1 },
-
- /* ehrpwm1 */
- { .dev = 0x30, .num_clks = 1 },
-
- /* ehrpwm2 */
- { .dev = 0x31, .num_clks = 1 },
-
- /* ehrpwm3 */
- { .dev = 0x32, .num_clks = 1 },
-
- /* ehrpwm4 */
- { .dev = 0x33, .num_clks = 1 },
-
- /* ehrpwm5 */
- { .dev = 0x34, .num_clks = 1 },
-
- /* eqep0 */
- { .dev = 0x35, .num_clks = 1 },
-
- /* eqep1 */
- { .dev = 0x36, .num_clks = 1 },
-
- /* eqep2 */
- { .dev = 0x37, .num_clks = 1 },
-
- /* ecap0 */
- { .dev = 0x38, .num_clks = 1 },
-
- /* ecap1 */
- { .dev = 0x39, .num_clks = 1 },
-
- /* i2c0 */
- { .dev = 0x3a, .num_clks = 1 },
-
- /* i2c1 */
- { .dev = 0x3b, .num_clks = 1 },
-
- /* i2c2 */
- { .dev = 0x3c, .num_clks = 1 },
-
- /* edma0 */
- { .dev = 0x3f, .num_clks = 2 },
-
- /* semaphore0 */
- { .dev = 0x40, .num_clks = 1 },
-
- /* intc0 */
- { .dev = 0x41, .num_clks = 1 },
-
- /* gic0 */
- { .dev = 0x42, .num_clks = 1 },
-
- /* qspi0 */
- { .dev = 0x43, .num_clks = 5 },
-
- /* arm_64b_counter0 */
- { .dev = 0x44, .num_clks = 2 },
-
- /* tetris0 */
- { .dev = 0x45, .num_clks = 2 },
-
- /* cgem0 */
- { .dev = 0x46, .num_clks = 2 },
-
- /* msmc0 */
- { .dev = 0x47, .num_clks = 1 },
-
- /* cbass0 */
- { .dev = 0x49, .num_clks = 1 },
-
- /* board0 */
- { .dev = 0x4c, .num_clks = 36 },
-
- /* edma1 */
- { .dev = 0x4f, .num_clks = 2 },
- { .num_clks = 0 },
-};
-
static const struct of_device_id ti_sci_clk_of_match[] = {
- { .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data },
+ { .compatible = "ti,k2g-sci-clk" },
{ /* Sentinel */ },
};
MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
@@ -681,12 +420,16 @@ static int ti_sci_clk_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
struct sci_clk_provider *provider;
const struct ti_sci_handle *handle;
- const struct sci_clk_data *data;
int ret;
-
- data = of_device_get_match_data(dev);
- if (!data)
- return -EINVAL;
+ int num_clks = 0;
+ struct sci_clk **clks = NULL;
+ struct sci_clk **tmp_clks;
+ struct sci_clk *sci_clk;
+ int max_clks = 0;
+ int clk_id = 0;
+ int dev_id = 0;
+ u8 num_parents;
+ int gap_size = 0;
handle = devm_ti_sci_get_handle(dev);
if (IS_ERR(handle))
@@ -696,12 +439,69 @@ static int ti_sci_clk_probe(struct platform_device *pdev)
if (!provider)
return -ENOMEM;
- provider->clk_data = data;
-
provider->sci = handle;
provider->ops = &handle->ops.clk_ops;
provider->dev = dev;
+ while (1) {
+ ret = provider->ops->get_num_parents(provider->sci, dev_id,
+ clk_id, &num_parents);
+ if (ret) {
+ gap_size++;
+ if (!clk_id) {
+ if (gap_size >= 5)
+ break;
+ dev_id++;
+ } else {
+ if (gap_size >= 2) {
+ dev_id++;
+ clk_id = 0;
+ gap_size = 0;
+ } else {
+ clk_id++;
+ }
+ }
+ continue;
+ }
+
+ gap_size = 0;
+
+ if (num_clks == max_clks) {
+ tmp_clks = devm_kmalloc_array(dev, max_clks + 64,
+ sizeof(sci_clk),
+ GFP_KERNEL);
+ memcpy(tmp_clks, clks, max_clks * sizeof(sci_clk));
+ if (max_clks)
+ devm_kfree(dev, clks);
+ max_clks += 64;
+ clks = tmp_clks;
+ }
+
+ sci_clk = devm_kzalloc(dev, sizeof(*sci_clk), GFP_KERNEL);
+ if (!sci_clk)
+ return -ENOMEM;
+ sci_clk->dev_id = dev_id;
+ sci_clk->clk_id = clk_id;
+ sci_clk->provider = provider;
+ sci_clk->num_parents = num_parents;
+
+ clks[num_clks] = sci_clk;
+
+ clk_id++;
+ num_clks++;
+ }
+
+ provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk),
+ GFP_KERNEL);
+ if (!provider->clocks)
+ return -ENOMEM;
+
+ memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk));
+
+ provider->num_clocks = num_clks;
+
+ devm_kfree(dev, clks);
+
ret = ti_sci_init_clocks(provider);
if (ret) {
pr_err("ti-sci-init-clocks failed.\n");
diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c
index 498d13799388..991d4093726e 100644
--- a/drivers/clk/mediatek/clk-mt2712.c
+++ b/drivers/clk/mediatek/clk-mt2712.c
@@ -221,6 +221,8 @@ static const struct mtk_fixed_factor top_divs[] = {
4),
FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1,
4),
+ FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1_ck", 1,
+ 3),
};
static const char * const axi_parents[] = {
@@ -625,7 +627,7 @@ static const char * const ether_125m_parents[] = {
static const char * const ether_50m_parents[] = {
"clk26m",
"etherpll_50m",
- "univpll_d26",
+ "apll1_d3",
"univpll3_d4"
};
@@ -686,7 +688,7 @@ static const char * const i2c_parents[] = {
static const char * const msdc0p_aes_parents[] = {
"clk26m",
- "msdcpll_ck",
+ "syspll_d2",
"univpll_d3",
"vcodecpll_ck"
};
@@ -719,6 +721,17 @@ static const char * const aud_apll2_parents[] = {
"clkaud_ext_i_2"
};
+static const char * const apll1_ref_parents[] = {
+ "clkaud_ext_i_2",
+ "clkaud_ext_i_1",
+ "clki2si0_mck_i",
+ "clki2si1_mck_i",
+ "clki2si2_mck_i",
+ "clktdmin_mclk_i",
+ "clki2si2_mck_i",
+ "clktdmin_mclk_i"
+};
+
static const char * const audull_vtx_parents[] = {
"d2a_ulclk_6p5m",
"clkaud_ext_i_0"
@@ -886,6 +899,10 @@ static struct mtk_composite top_muxes[] = {
aud_apll2_parents, 0x134, 1, 1),
MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel",
audull_vtx_parents, 0x134, 31, 1),
+ MUX(CLK_TOP_APLL1_REF_SEL, "apll1_ref_sel",
+ apll1_ref_parents, 0x134, 4, 3),
+ MUX(CLK_TOP_APLL2_REF_SEL, "apll2_ref_sel",
+ apll1_ref_parents, 0x134, 7, 3),
};
static const char * const mcu_mp0_parents[] = {
@@ -932,36 +949,56 @@ static const struct mtk_clk_divider top_adj_divs[] = {
DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8),
};
-static const struct mtk_gate_regs top_cg_regs = {
+static const struct mtk_gate_regs top0_cg_regs = {
.set_ofs = 0x120,
.clr_ofs = 0x120,
.sta_ofs = 0x120,
};
-#define GATE_TOP(_id, _name, _parent, _shift) { \
+static const struct mtk_gate_regs top1_cg_regs = {
+ .set_ofs = 0x424,
+ .clr_ofs = 0x424,
+ .sta_ofs = 0x424,
+};
+
+#define GATE_TOP0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
- .regs = &top_cg_regs, \
+ .regs = &top0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
+#define GATE_TOP1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
static const struct mtk_gate top_clks[] = {
- GATE_TOP(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0),
- GATE_TOP(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1),
- GATE_TOP(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2),
- GATE_TOP(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3),
- GATE_TOP(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4),
- GATE_TOP(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5),
- GATE_TOP(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6),
- GATE_TOP(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7),
+ /* TOP0 */
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0),
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1),
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2),
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3),
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4),
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5),
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6),
+ GATE_TOP0(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7),
+ /* TOP1 */
+ GATE_TOP1(CLK_TOP_NFI2X_EN, "nfi2x_en", "nfi2x_sel", 0),
+ GATE_TOP1(CLK_TOP_NFIECC_EN, "nfiecc_en", "nfiecc_sel", 1),
+ GATE_TOP1(CLK_TOP_NFI1X_CK_EN, "nfi1x_ck_en", "nfi2x_sel", 2),
};
static const struct mtk_gate_regs infra_cg_regs = {
.set_ofs = 0x40,
.clr_ofs = 0x44,
- .sta_ofs = 0x40,
+ .sta_ofs = 0x48,
};
#define GATE_INFRA(_id, _name, _parent, _shift) { \
@@ -1120,6 +1157,10 @@ static const struct mtk_gate peri_clks[] = {
"msdc50_0_h_sel", 4),
GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h",
"msdc50_3_h_sel", 5),
+ GATE_PERI2(CLK_PERI_MSDC30_0_QTR_EN, "per_msdc30_0_q",
+ "axi_sel", 6),
+ GATE_PERI2(CLK_PERI_MSDC30_3_QTR_EN, "per_msdc30_3_q",
+ "mem_sel", 7),
};
#define MT2712_PLL_FMAX (3000UL * MHZ)
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 7694302c70a4..d5cbec522aec 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -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.
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 3c03ce583798..ffee82e60b7a 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -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
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 1294f3ad7cd5..5f5d468c1efe 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -11,125 +11,51 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
-#include <linux/init.h>
+#include <linux/regmap.h>
#include "clkc.h"
#include "axg.h"
static DEFINE_SPINLOCK(meson_clk_lock);
-static const struct pll_rate_table sys_pll_rate_table[] = {
- PLL_RATE(24000000, 56, 1, 2),
- PLL_RATE(48000000, 64, 1, 2),
- PLL_RATE(72000000, 72, 1, 2),
- PLL_RATE(96000000, 64, 1, 2),
- PLL_RATE(120000000, 80, 1, 2),
- PLL_RATE(144000000, 96, 1, 2),
- PLL_RATE(168000000, 56, 1, 1),
- PLL_RATE(192000000, 64, 1, 1),
- PLL_RATE(216000000, 72, 1, 1),
- PLL_RATE(240000000, 80, 1, 1),
- PLL_RATE(264000000, 88, 1, 1),
- PLL_RATE(288000000, 96, 1, 1),
- PLL_RATE(312000000, 52, 1, 2),
- PLL_RATE(336000000, 56, 1, 2),
- PLL_RATE(360000000, 60, 1, 2),
- PLL_RATE(384000000, 64, 1, 2),
- PLL_RATE(408000000, 68, 1, 2),
- PLL_RATE(432000000, 72, 1, 2),
- PLL_RATE(456000000, 76, 1, 2),
- PLL_RATE(480000000, 80, 1, 2),
- PLL_RATE(504000000, 84, 1, 2),
- PLL_RATE(528000000, 88, 1, 2),
- PLL_RATE(552000000, 92, 1, 2),
- PLL_RATE(576000000, 96, 1, 2),
- PLL_RATE(600000000, 50, 1, 1),
- PLL_RATE(624000000, 52, 1, 1),
- PLL_RATE(648000000, 54, 1, 1),
- PLL_RATE(672000000, 56, 1, 1),
- PLL_RATE(696000000, 58, 1, 1),
- PLL_RATE(720000000, 60, 1, 1),
- PLL_RATE(744000000, 62, 1, 1),
- PLL_RATE(768000000, 64, 1, 1),
- PLL_RATE(792000000, 66, 1, 1),
- PLL_RATE(816000000, 68, 1, 1),
- PLL_RATE(840000000, 70, 1, 1),
- PLL_RATE(864000000, 72, 1, 1),
- PLL_RATE(888000000, 74, 1, 1),
- PLL_RATE(912000000, 76, 1, 1),
- PLL_RATE(936000000, 78, 1, 1),
- PLL_RATE(960000000, 80, 1, 1),
- PLL_RATE(984000000, 82, 1, 1),
- PLL_RATE(1008000000, 84, 1, 1),
- PLL_RATE(1032000000, 86, 1, 1),
- PLL_RATE(1056000000, 88, 1, 1),
- PLL_RATE(1080000000, 90, 1, 1),
- PLL_RATE(1104000000, 92, 1, 1),
- PLL_RATE(1128000000, 94, 1, 1),
- PLL_RATE(1152000000, 96, 1, 1),
- PLL_RATE(1176000000, 98, 1, 1),
- PLL_RATE(1200000000, 50, 1, 0),
- PLL_RATE(1224000000, 51, 1, 0),
- PLL_RATE(1248000000, 52, 1, 0),
- PLL_RATE(1272000000, 53, 1, 0),
- PLL_RATE(1296000000, 54, 1, 0),
- PLL_RATE(1320000000, 55, 1, 0),
- PLL_RATE(1344000000, 56, 1, 0),
- PLL_RATE(1368000000, 57, 1, 0),
- PLL_RATE(1392000000, 58, 1, 0),
- PLL_RATE(1416000000, 59, 1, 0),
- PLL_RATE(1440000000, 60, 1, 0),
- PLL_RATE(1464000000, 61, 1, 0),
- PLL_RATE(1488000000, 62, 1, 0),
- PLL_RATE(1512000000, 63, 1, 0),
- PLL_RATE(1536000000, 64, 1, 0),
- PLL_RATE(1560000000, 65, 1, 0),
- PLL_RATE(1584000000, 66, 1, 0),
- PLL_RATE(1608000000, 67, 1, 0),
- PLL_RATE(1632000000, 68, 1, 0),
- PLL_RATE(1656000000, 68, 1, 0),
- PLL_RATE(1680000000, 68, 1, 0),
- PLL_RATE(1704000000, 68, 1, 0),
- PLL_RATE(1728000000, 69, 1, 0),
- PLL_RATE(1752000000, 69, 1, 0),
- PLL_RATE(1776000000, 69, 1, 0),
- PLL_RATE(1800000000, 69, 1, 0),
- PLL_RATE(1824000000, 70, 1, 0),
- PLL_RATE(1848000000, 70, 1, 0),
- PLL_RATE(1872000000, 70, 1, 0),
- PLL_RATE(1896000000, 70, 1, 0),
- PLL_RATE(1920000000, 71, 1, 0),
- PLL_RATE(1944000000, 71, 1, 0),
- PLL_RATE(1968000000, 71, 1, 0),
- PLL_RATE(1992000000, 71, 1, 0),
- PLL_RATE(2016000000, 72, 1, 0),
- PLL_RATE(2040000000, 72, 1, 0),
- PLL_RATE(2064000000, 72, 1, 0),
- PLL_RATE(2088000000, 72, 1, 0),
- PLL_RATE(2112000000, 73, 1, 0),
- { /* sentinel */ },
-};
-
-static struct meson_clk_pll axg_fixed_pll = {
- .m = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 16,
- .width = 2,
+static struct clk_regmap axg_fixed_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .frac = {
+ .reg_off = HHI_MPLL_CNTL2,
+ .shift = 0,
+ .width = 12,
+ },
+ .l = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &meson_clk_pll_ro_ops,
@@ -138,25 +64,34 @@ static struct meson_clk_pll axg_fixed_pll = {
},
};
-static struct meson_clk_pll axg_sys_pll = {
- .m = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 0,
- .width = 9,
+static struct clk_regmap axg_sys_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .l = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
},
- .n = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 10,
- .width = 2,
- },
- .rate_table = sys_pll_rate_table,
- .rate_count = ARRAY_SIZE(sys_pll_rate_table),
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &meson_clk_pll_ro_ops,
@@ -257,40 +192,51 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
{ /* sentinel */ },
};
-static struct pll_params_table axg_gp0_params_table[] = {
- PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250),
- PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000),
- PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be),
- PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288),
- PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d),
- PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000),
-};
-
-static struct meson_clk_pll axg_gp0_pll = {
- .m = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
- .params = {
- .params_table = axg_gp0_params_table,
- .params_count = ARRAY_SIZE(axg_gp0_params_table),
- .no_init_reset = true,
- .reset_lock_loop = true,
- },
- .rate_table = axg_gp0_pll_rate_table,
- .rate_count = ARRAY_SIZE(axg_gp0_pll_rate_table),
- .lock = &meson_clk_lock,
+static const struct reg_sequence axg_gp0_init_regs[] = {
+ { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 },
+ { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be },
+ { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
+ { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
+ { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
+ { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
+};
+
+static struct clk_regmap axg_gp0_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .frac = {
+ .reg_off = HHI_GP0_PLL_CNTL1,
+ .shift = 0,
+ .width = 10,
+ },
+ .l = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
+ .table = axg_gp0_pll_rate_table,
+ .init_regs = axg_gp0_init_regs,
+ .init_count = ARRAY_SIZE(axg_gp0_init_regs),
+ },
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &meson_clk_pll_ops,
@@ -299,234 +245,427 @@ static struct meson_clk_pll axg_gp0_pll = {
},
};
+static const struct reg_sequence axg_hifi_init_regs[] = {
+ { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 },
+ { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be },
+ { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 },
+ { .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d },
+ { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 },
+ { .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 },
+};
+
+static struct clk_regmap axg_hifi_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_HIFI_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_HIFI_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_HIFI_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .frac = {
+ .reg_off = HHI_HIFI_PLL_CNTL5,
+ .shift = 0,
+ .width = 13,
+ },
+ .l = {
+ .reg_off = HHI_HIFI_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_HIFI_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
+ .table = axg_gp0_pll_rate_table,
+ .init_regs = axg_hifi_init_regs,
+ .init_count = ARRAY_SIZE(axg_hifi_init_regs),
+ .flags = CLK_MESON_PLL_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hifi_pll",
+ .ops = &meson_clk_pll_ops,
+ .parent_names = (const char *[]){ "xtal" },
+ .num_parents = 1,
+ },
+};
-static struct clk_fixed_factor axg_fclk_div2 = {
+static struct clk_fixed_factor axg_fclk_div2_div = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div2",
+ .name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor axg_fclk_div3 = {
+static struct clk_regmap axg_fclk_div2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 27,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div2_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div3_div = {
.mult = 1,
.div = 3,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div3",
+ .name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor axg_fclk_div4 = {
+static struct clk_regmap axg_fclk_div3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 28,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div3_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div4_div = {
.mult = 1,
.div = 4,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div4",
+ .name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor axg_fclk_div5 = {
+static struct clk_regmap axg_fclk_div4 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div4",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div4_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div5_div = {
.mult = 1,
.div = 5,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div5",
+ .name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor axg_fclk_div7 = {
+static struct clk_regmap axg_fclk_div5 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div5_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div7_div = {
.mult = 1,
.div = 7,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div7",
+ .name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll axg_mpll0 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 0,
- .width = 14,
+static struct clk_regmap axg_fclk_div7 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 31,
},
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 15,
- .width = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div7_div" },
+ .num_parents = 1,
},
- .n2 = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 16,
- .width = 9,
+};
+
+static struct clk_regmap axg_mpll_prediv = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPLL_CNTL5,
+ .shift = 12,
+ .width = 1,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 14,
- .width = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll_prediv",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
},
- .ssen = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 25,
- .width = 1,
+};
+
+static struct clk_regmap axg_mpll0_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 16,
+ .width = 9,
+ },
+ .ssen = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 25,
+ .width = 1,
+ },
+ .misc = {
+ .reg_off = HHI_PLL_TOP_MISC,
+ .shift = 0,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll0",
+ .name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll axg_mpll1 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 0,
- .width = 14,
+static struct clk_regmap axg_mpll0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL7,
+ .bit_idx = 14,
},
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 15,
- .width = 1,
- },
- .n2 = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 16,
- .width = 9,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll0_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 14,
- .width = 1,
+};
+
+static struct clk_regmap axg_mpll1_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 16,
+ .width = 9,
+ },
+ .misc = {
+ .reg_off = HHI_PLL_TOP_MISC,
+ .shift = 1,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll1",
+ .name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll axg_mpll2 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 0,
- .width = 14,
+static struct clk_regmap axg_mpll1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL8,
+ .bit_idx = 14,
},
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 15,
- .width = 1,
- },
- .n2 = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 16,
- .width = 9,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll1_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 14,
- .width = 1,
+};
+
+static struct clk_regmap axg_mpll2_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 16,
+ .width = 9,
+ },
+ .misc = {
+ .reg_off = HHI_PLL_TOP_MISC,
+ .shift = 2,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll2",
+ .name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll axg_mpll3 = {
- .sdm = {
- .reg_off = HHI_MPLL3_CNTL0,
- .shift = 12,
- .width = 14,
+static struct clk_regmap axg_mpll2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL9,
+ .bit_idx = 14,
},
- .sdm_en = {
- .reg_off = HHI_MPLL3_CNTL0,
- .shift = 11,
- .width = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll2_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap axg_mpll3_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL3_CNTL0,
+ .shift = 12,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL3_CNTL0,
+ .shift = 11,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL3_CNTL0,
+ .shift = 2,
+ .width = 9,
+ },
+ .misc = {
+ .reg_off = HHI_PLL_TOP_MISC,
+ .shift = 3,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
},
- .n2 = {
- .reg_off = HHI_MPLL3_CNTL0,
- .shift = 2,
- .width = 9,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll3_div",
+ .ops = &meson_clk_mpll_ops,
+ .parent_names = (const char *[]){ "mpll_prediv" },
+ .num_parents = 1,
},
- .en = {
- .reg_off = HHI_MPLL3_CNTL0,
- .shift = 0,
- .width = 1,
+};
+
+static struct clk_regmap axg_mpll3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL3_CNTL0,
+ .bit_idx = 0,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpll3",
- .ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll3_div" },
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
-/*
- * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
- * and should be modeled with their respective PLLs via the forthcoming
- * coordinated clock rates feature
- */
static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
static const char * const clk81_parent_names[] = {
"xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
"fclk_div3", "fclk_div5"
};
-static struct clk_mux axg_mpeg_clk_sel = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .mask = 0x7,
- .shift = 12,
- .flags = CLK_MUX_READ_ONLY,
- .table = mux_table_clk81,
- .lock = &meson_clk_lock,
+static struct clk_regmap axg_mpeg_clk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 12,
+ .table = mux_table_clk81,
+ },
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
- .ops = &clk_mux_ro_ops,
+ .ops = &clk_regmap_mux_ro_ops,
.parent_names = clk81_parent_names,
.num_parents = ARRAY_SIZE(clk81_parent_names),
},
};
-static struct clk_divider axg_mpeg_clk_div = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap axg_mpeg_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "mpeg_clk_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate axg_clk81 = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .bit_idx = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap axg_clk81 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .bit_idx = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "clk81",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpeg_clk_div" },
.num_parents = 1,
.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
@@ -545,42 +684,45 @@ static const char * const axg_sd_emmc_clk0_parent_names[] = {
};
/* SDcard clock */
-static struct clk_mux axg_sd_emmc_b_clk0_sel = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .mask = 0x7,
- .shift = 25,
- .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_b_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 25,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = axg_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_divider axg_sd_emmc_b_clk0_div = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .shift = 16,
- .width = 7,
- .lock = &meson_clk_lock,
- .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap axg_sd_emmc_b_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .shift = 16,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate axg_sd_emmc_b_clk0 = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .bit_idx = 23,
- .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_b_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .bit_idx = 23,
+ },
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_b_clk0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -588,42 +730,45 @@ static struct clk_gate axg_sd_emmc_b_clk0 = {
};
/* EMMC/NAND clock */
-static struct clk_mux axg_sd_emmc_c_clk0_sel = {
- .reg = (void *)HHI_NAND_CLK_CNTL,
- .mask = 0x7,
- .shift = 9,
- .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_c_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_NAND_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 9,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = axg_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_divider axg_sd_emmc_c_clk0_div = {
- .reg = (void *)HHI_NAND_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
- .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap axg_sd_emmc_c_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_NAND_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate axg_sd_emmc_c_clk0 = {
- .reg = (void *)HHI_NAND_CLK_CNTL,
- .bit_idx = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_c_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_NAND_CLK_CNTL,
+ .bit_idx = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_c_clk0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -750,27 +895,24 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
[CLKID_SD_EMMC_C_CLK0_SEL] = &axg_sd_emmc_c_clk0_sel.hw,
[CLKID_SD_EMMC_C_CLK0_DIV] = &axg_sd_emmc_c_clk0_div.hw,
[CLKID_SD_EMMC_C_CLK0] = &axg_sd_emmc_c_clk0.hw,
+ [CLKID_MPLL0_DIV] = &axg_mpll0_div.hw,
+ [CLKID_MPLL1_DIV] = &axg_mpll1_div.hw,
+ [CLKID_MPLL2_DIV] = &axg_mpll2_div.hw,
+ [CLKID_MPLL3_DIV] = &axg_mpll3_div.hw,
+ [CLKID_HIFI_PLL] = &axg_hifi_pll.hw,
+ [CLKID_MPLL_PREDIV] = &axg_mpll_prediv.hw,
+ [CLKID_FCLK_DIV2_DIV] = &axg_fclk_div2_div.hw,
+ [CLKID_FCLK_DIV3_DIV] = &axg_fclk_div3_div.hw,
+ [CLKID_FCLK_DIV4_DIV] = &axg_fclk_div4_div.hw,
+ [CLKID_FCLK_DIV5_DIV] = &axg_fclk_div5_div.hw,
+ [CLKID_FCLK_DIV7_DIV] = &axg_fclk_div7_div.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
};
-/* Convenience tables to populate base addresses in .probe */
-
-static struct meson_clk_pll *const axg_clk_plls[] = {
- &axg_fixed_pll,
- &axg_sys_pll,
- &axg_gp0_pll,
-};
-
-static struct meson_clk_mpll *const axg_clk_mplls[] = {
- &axg_mpll0,
- &axg_mpll1,
- &axg_mpll2,
- &axg_mpll3,
-};
-
-static struct clk_gate *const axg_clk_gates[] = {
+/* Convenience table to populate regmap in .probe */
+static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_clk81,
&axg_ddr,
&axg_audio_locker,
@@ -818,113 +960,100 @@ static struct clk_gate *const axg_clk_gates[] = {
&axg_ao_i2c,
&axg_sd_emmc_b_clk0,
&axg_sd_emmc_c_clk0,
-};
-
-static struct clk_mux *const axg_clk_muxes[] = {
- &axg_mpeg_clk_sel,
- &axg_sd_emmc_b_clk0_sel,
- &axg_sd_emmc_c_clk0_sel,
-};
-
-static struct clk_divider *const axg_clk_dividers[] = {
&axg_mpeg_clk_div,
&axg_sd_emmc_b_clk0_div,
&axg_sd_emmc_c_clk0_div,
-};
-
-struct clkc_data {
- struct clk_gate *const *clk_gates;
- unsigned int clk_gates_count;
- struct meson_clk_mpll *const *clk_mplls;
- unsigned int clk_mplls_count;
- struct meson_clk_pll *const *clk_plls;
- unsigned int clk_plls_count;
- struct clk_mux *const *clk_muxes;
- unsigned int clk_muxes_count;
- struct clk_divider *const *clk_dividers;
- unsigned int clk_dividers_count;
- struct clk_hw_onecell_data *hw_onecell_data;
-};
-
-static const struct clkc_data axg_clkc_data = {
- .clk_gates = axg_clk_gates,
- .clk_gates_count = ARRAY_SIZE(axg_clk_gates),
- .clk_mplls = axg_clk_mplls,
- .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls),
- .clk_plls = axg_clk_plls,
- .clk_plls_count = ARRAY_SIZE(axg_clk_plls),
- .clk_muxes = axg_clk_muxes,
- .clk_muxes_count = ARRAY_SIZE(axg_clk_muxes),
- .clk_dividers = axg_clk_dividers,
- .clk_dividers_count = ARRAY_SIZE(axg_clk_dividers),
- .hw_onecell_data = &axg_hw_onecell_data,
+ &axg_mpeg_clk_sel,
+ &axg_sd_emmc_b_clk0_sel,
+ &axg_sd_emmc_c_clk0_sel,
+ &axg_mpll0,
+ &axg_mpll1,
+ &axg_mpll2,
+ &axg_mpll3,
+ &axg_mpll0_div,
+ &axg_mpll1_div,
+ &axg_mpll2_div,
+ &axg_mpll3_div,
+ &axg_fixed_pll,
+ &axg_sys_pll,
+ &axg_gp0_pll,
+ &axg_hifi_pll,
+ &axg_mpll_prediv,
+ &axg_fclk_div2,
+ &axg_fclk_div3,
+ &axg_fclk_div4,
+ &axg_fclk_div5,
+ &axg_fclk_div7,
};
static const struct of_device_id clkc_match_table[] = {
- { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data },
+ { .compatible = "amlogic,axg-clkc" },
{}
};
+static const struct regmap_config clkc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
static int axg_clkc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct clkc_data *clkc_data;
struct resource *res;
- void __iomem *clk_base;
- int ret, clkid, i;
-
- clkc_data = of_device_get_match_data(&pdev->dev);
- if (!clkc_data)
- return -EINVAL;
-
- /* Generic clocks and PLLs */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
- clk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!clk_base) {
- dev_err(&pdev->dev, "Unable to map clk base\n");
- return -ENXIO;
- }
+ void __iomem *clk_base = NULL;
+ struct regmap *map;
+ int ret, i;
- /* Populate base address for PLLs */
- for (i = 0; i < clkc_data->clk_plls_count; i++)
- clkc_data->clk_plls[i]->base = clk_base;
+ /* Get the hhi system controller node if available */
+ map = syscon_node_to_regmap(of_get_parent(dev->of_node));
+ if (IS_ERR(map)) {
+ dev_err(dev,
+ "failed to get HHI regmap - Trying obsolete regs\n");
- /* Populate base address for MPLLs */
- for (i = 0; i < clkc_data->clk_mplls_count; i++)
- clkc_data->clk_mplls[i]->base = clk_base;
+ /*
+ * FIXME: HHI registers should be accessed through
+ * the appropriate system controller. This is required because
+ * there is more than just clocks in this register space
+ *
+ * This fallback method is only provided temporarily until
+ * all the platform DTs are properly using the syscon node
+ */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
- /* Populate base address for gates */
- for (i = 0; i < clkc_data->clk_gates_count; i++)
- clkc_data->clk_gates[i]->reg = clk_base +
- (u64)clkc_data->clk_gates[i]->reg;
- /* Populate base address for muxes */
- for (i = 0; i < clkc_data->clk_muxes_count; i++)
- clkc_data->clk_muxes[i]->reg = clk_base +
- (u64)clkc_data->clk_muxes[i]->reg;
+ clk_base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!clk_base) {
+ dev_err(dev, "Unable to map clk base\n");
+ return -ENXIO;
+ }
+
+ map = devm_regmap_init_mmio(dev, clk_base,
+ &clkc_regmap_config);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+ }
- /* Populate base address for dividers */
- for (i = 0; i < clkc_data->clk_dividers_count; i++)
- clkc_data->clk_dividers[i]->reg = clk_base +
- (u64)clkc_data->clk_dividers[i]->reg;
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++)
+ axg_clk_regmaps[i]->map = map;
- for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
+ for (i = 0; i < axg_hw_onecell_data.num; i++) {
/* array might be sparse */
- if (!clkc_data->hw_onecell_data->hws[clkid])
+ if (!axg_hw_onecell_data.hws[i])
continue;
- ret = devm_clk_hw_register(dev,
- clkc_data->hw_onecell_data->hws[clkid]);
+ ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]);
if (ret) {
- dev_err(&pdev->dev, "Clock registration failed\n");
+ dev_err(dev, "Clock registration failed\n");
return ret;
}
}
- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
- clkc_data->hw_onecell_data);
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ &axg_hw_onecell_data);
}
static struct platform_driver axg_driver = {
diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
index ce0bafdb6b28..b421df6a7ea0 100644
--- a/drivers/clk/meson/axg.h
+++ b/drivers/clk/meson/axg.h
@@ -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>
diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c
index 6c07db06642d..f7ab5b1db342 100644
--- a/drivers/clk/meson/clk-audio-divider.c
+++ b/drivers/clk/meson/clk-audio-divider.c
@@ -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;
}
diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
deleted file mode 100644
index f8b2b7efd016..000000000000
--- a/drivers/clk/meson/clk-cpu.c
+++ /dev/null
@@ -1,178 +0,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,
-};
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 5144360e2c80..0df1227b65b3 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -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,
};
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 01341553f50b..65a7bd903551 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -2,6 +2,9 @@
* Copyright (c) 2015 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
+ * Copyright (c) 2018 Baylibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.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.
@@ -27,13 +30,14 @@
* | |
* FREF VCO
*
- * out = (in * M / N) >> OD
+ * out = in * (m + frac / frac_max) / (n << sum(ods))
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/math64.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/slab.h>
@@ -41,209 +45,213 @@
#include "clkc.h"
-#define MESON_PLL_RESET BIT(29)
-#define MESON_PLL_LOCK BIT(31)
-
-#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
-
-static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static inline struct meson_clk_pll_data *
+meson_clk_pll_data(struct clk_regmap *clk)
{
- struct meson_clk_pll *pll = to_meson_clk_pll(hw);
- struct parm *p;
- unsigned long parent_rate_mhz = parent_rate / 1000000;
- unsigned long rate_mhz;
- u16 n, m, frac = 0, od, od2 = 0;
- u32 reg;
-
- p = &pll->n;
- reg = readl(pll->base + p->reg_off);
- n = PARM_GET(p->width, p->shift, reg);
-
- p = &pll->m;
- reg = readl(pll->base + p->reg_off);
- m = PARM_GET(p->width, p->shift, reg);
-
- p = &pll->od;
- reg = readl(pll->base + p->reg_off);
- od = PARM_GET(p->width, p->shift, reg);
-
- p = &pll->od2;
- if (p->width) {
- reg = readl(pll->base + p->reg_off);
- od2 = PARM_GET(p->width, p->shift, reg);
- }
-
- p = &pll->frac;
- if (p->width) {
- reg = readl(pll->base + p->reg_off);
- frac = PARM_GET(p->width, p->shift, reg);
- rate_mhz = (parent_rate_mhz * m + \
- (parent_rate_mhz * frac >> 12)) * 2 / n;
- rate_mhz = rate_mhz >> od >> od2;
- } else
- rate_mhz = (parent_rate_mhz * m / n) >> od >> od2;
-
- return rate_mhz * 1000000;
+ return (struct meson_clk_pll_data *)clk->data;
}
-static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static unsigned long __pll_params_to_rate(unsigned long parent_rate,
+ const struct pll_rate_table *pllt,
+ u16 frac,
+ struct meson_clk_pll_data *pll)
{
- struct meson_clk_pll *pll = to_meson_clk_pll(hw);
- const struct pll_rate_table *rate_table = pll->rate_table;
- int i;
+ u64 rate = (u64)parent_rate * pllt->m;
+ unsigned int od = pllt->od + pllt->od2 + pllt->od3;
- for (i = 0; i < pll->rate_count; i++) {
- if (rate <= rate_table[i].rate)
- return rate_table[i].rate;
+ if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
+ u64 frac_rate = (u64)parent_rate * frac;
+
+ rate += DIV_ROUND_UP_ULL(frac_rate,
+ (1 << pll->frac.width));
}
- /* else return the smallest value */
- return rate_table[0].rate;
+ return DIV_ROUND_UP_ULL(rate, pllt->n << od);
}
-static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll,
- unsigned long rate)
+static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
{
- const struct pll_rate_table *rate_table = pll->rate_table;
- int i;
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+ struct pll_rate_table pllt;
+ u16 frac;
- for (i = 0; i < pll->rate_count; i++) {
- if (rate == rate_table[i].rate)
- return &rate_table[i];
- }
- return NULL;
+ pllt.n = meson_parm_read(clk->map, &pll->n);
+ 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) ?
+ meson_parm_read(clk->map, &pll->frac) :
+ 0;
+
+ return __pll_params_to_rate(parent_rate, &pllt, frac, pll);
}
-/* Specific wait loop for GXL/GXM GP0 PLL */
-static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll,
- struct parm *p_n)
+static u16 __pll_params_with_frac(unsigned long rate,
+ unsigned long parent_rate,
+ const struct pll_rate_table *pllt,
+ struct meson_clk_pll_data *pll)
{
- int delay = 100;
- u32 reg;
+ u16 frac_max = (1 << pll->frac.width);
+ u64 val = (u64)rate * pllt->n;
- while (delay > 0) {
- reg = readl(pll->base + p_n->reg_off);
- writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off);
- udelay(10);
- writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off);
+ val <<= pllt->od + pllt->od2 + pllt->od3;
- /* This delay comes from AMLogic tree clk-gp0-gxl driver */
- mdelay(1);
+ if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
+ val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
+ else
+ val = div_u64(val * frac_max, parent_rate);
- reg = readl(pll->base + p_n->reg_off);
- if (reg & MESON_PLL_LOCK)
- return 0;
- delay--;
+ val -= pllt->m * frac_max;
+
+ return min((u16)val, (u16)(frac_max - 1));
+}
+
+static const struct pll_rate_table *
+meson_clk_get_pll_settings(unsigned long rate,
+ struct meson_clk_pll_data *pll)
+{
+ const struct pll_rate_table *table = pll->table;
+ unsigned int i = 0;
+
+ if (!table)
+ return NULL;
+
+ /* Find the first table element exceeding rate */
+ while (table[i].rate && table[i].rate <= rate)
+ i++;
+
+ if (i != 0) {
+ if (MESON_PARM_APPLICABLE(&pll->frac) ||
+ !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
+ (abs(rate - table[i - 1].rate) <
+ abs(rate - table[i].rate)))
+ i--;
}
- return -ETIMEDOUT;
+
+ return (struct pll_rate_table *)&table[i];
}
-static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
- struct parm *p_n)
+static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
{
- int delay = 24000000;
- u32 reg;
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+ const struct pll_rate_table *pllt =
+ meson_clk_get_pll_settings(rate, pll);
+ u16 frac;
+
+ if (!pllt)
+ return meson_clk_pll_recalc_rate(hw, *parent_rate);
+
+ if (!MESON_PARM_APPLICABLE(&pll->frac)
+ || rate == pllt->rate)
+ return pllt->rate;
+
+ /*
+ * The rate provided by the setting is not an exact match, let's
+ * try to improve the result using the fractional parameter
+ */
+ frac = __pll_params_with_frac(rate, *parent_rate, pllt, pll);
+
+ return __pll_params_to_rate(*parent_rate, pllt, frac, pll);
+}
- while (delay > 0) {
- reg = readl(pll->base + p_n->reg_off);
+static int meson_clk_pll_wait_lock(struct clk_hw *hw)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+ int delay = 24000000;
- if (reg & MESON_PLL_LOCK)
+ do {
+ /* Is the clock locked now ? */
+ if (meson_parm_read(clk->map, &pll->l))
return 0;
+
delay--;
- }
+ } while (delay > 0);
+
return -ETIMEDOUT;
}
-static void meson_clk_pll_init_params(struct meson_clk_pll *pll)
+static void meson_clk_pll_init(struct clk_hw *hw)
{
- int i;
-
- for (i = 0 ; i < pll->params.params_count ; ++i)
- writel(pll->params.params_table[i].value,
- pll->base + pll->params.params_table[i].reg_off);
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+ if (pll->init_count) {
+ meson_parm_write(clk->map, &pll->rst, 1);
+ regmap_multi_reg_write(clk->map, pll->init_regs,
+ pll->init_count);
+ meson_parm_write(clk->map, &pll->rst, 0);
+ }
}
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct meson_clk_pll *pll = to_meson_clk_pll(hw);
- struct parm *p;
- const struct pll_rate_table *rate_set;
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+ const struct pll_rate_table *pllt;
unsigned long old_rate;
- int ret = 0;
- u32 reg;
+ u16 frac = 0;
if (parent_rate == 0 || rate == 0)
return -EINVAL;
old_rate = rate;
- rate_set = meson_clk_get_pll_settings(pll, rate);
- if (!rate_set)
+ pllt = meson_clk_get_pll_settings(rate, pll);
+ if (!pllt)
return -EINVAL;
- /* Initialize the PLL in a clean state if specified */
- if (pll->params.params_count)
- meson_clk_pll_init_params(pll);
-
- /* PLL reset */
- p = &pll->n;
- reg = readl(pll->base + p->reg_off);
- /* If no_init_reset is provided, avoid resetting at this point */
- if (!pll->params.no_init_reset)
- writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
-
- reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
- writel(reg, pll->base + p->reg_off);
-
- p = &pll->m;
- reg = readl(pll->base + p->reg_off);
- reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
- writel(reg, pll->base + p->reg_off);
-
- p = &pll->od;
- reg = readl(pll->base + p->reg_off);
- reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
- writel(reg, pll->base + p->reg_off);
-
- p = &pll->od2;
- if (p->width) {
- reg = readl(pll->base + p->reg_off);
- reg = PARM_SET(p->width, p->shift, reg, rate_set->od2);
- writel(reg, pll->base + p->reg_off);
- }
+ /* Put the pll in reset to write the params */
+ meson_parm_write(clk->map, &pll->rst, 1);
- p = &pll->frac;
- if (p->width) {
- reg = readl(pll->base + p->reg_off);
- reg = PARM_SET(p->width, p->shift, reg, rate_set->frac);
- writel(reg, pll->base + p->reg_off);
- }
+ meson_parm_write(clk->map, &pll->n, pllt->n);
+ 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);
- p = &pll->n;
- /* If clear_reset_for_lock is provided, remove the reset bit here */
- if (pll->params.clear_reset_for_lock) {
- reg = readl(pll->base + p->reg_off);
- writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
+ if (MESON_PARM_APPLICABLE(&pll->frac)) {
+ frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
+ meson_parm_write(clk->map, &pll->frac, frac);
}
- /* If reset_lock_loop, use a special loop including resetting */
- if (pll->params.reset_lock_loop)
- ret = meson_clk_pll_wait_lock_reset(pll, p);
- else
- ret = meson_clk_pll_wait_lock(pll, p);
- if (ret) {
+ /* make sure the reset is cleared at this point */
+ meson_parm_write(clk->map, &pll->rst, 0);
+
+ if (meson_clk_pll_wait_lock(hw)) {
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
__func__, old_rate);
+ /*
+ * FIXME: Do we really need/want this HACK ?
+ * It looks unsafe. what happens if the clock gets into a
+ * broken state and we can't lock back on the old_rate ? Looks
+ * like an infinite recursion is possible
+ */
meson_clk_pll_set_rate(hw, old_rate, parent_rate);
}
- return ret;
+ return 0;
}
const struct clk_ops meson_clk_pll_ops = {
+ .init = meson_clk_pll_init,
.recalc_rate = meson_clk_pll_recalc_rate,
.round_rate = meson_clk_pll_round_rate,
.set_rate = meson_clk_pll_set_rate,
diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c
new file mode 100644
index 000000000000..3645fdb62343
--- /dev/null
+++ b/drivers/clk/meson/clk-regmap.c
@@ -0,0 +1,166 @@
+// 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);
diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h
new file mode 100644
index 000000000000..627c888026d7
--- /dev/null
+++ b/drivers/clk/meson/clk-regmap.h
@@ -0,0 +1,111 @@
+// 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 */
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index c2ff0520ce53..8fe73c4edca8 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.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), \
}, \
};
diff --git a/drivers/clk/meson/gxbb-aoclk-regmap.c b/drivers/clk/meson/gxbb-aoclk-regmap.c
deleted file mode 100644
index 2515fbfa0467..000000000000
--- a/drivers/clk/meson/gxbb-aoclk-regmap.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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,
-};
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
index 6c161e0a8e59..9ec23ae9a219 100644
--- a/drivers/clk/meson/gxbb-aoclk.c
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -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;
}
diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h
index e8604c8f7eee..0be78383f257 100644
--- a/drivers/clk/meson/gxbb-aoclk.h
+++ b/drivers/clk/meson/gxbb-aoclk.h
@@ -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)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index af24455af5b4..b1e4d9557610 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -19,108 +19,19 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
-#include <linux/init.h>
+#include <linux/regmap.h>
#include "clkc.h"
#include "gxbb.h"
+#include "clk-regmap.h"
static DEFINE_SPINLOCK(meson_clk_lock);
-static const struct pll_rate_table sys_pll_rate_table[] = {
- PLL_RATE(24000000, 56, 1, 2),
- PLL_RATE(48000000, 64, 1, 2),
- PLL_RATE(72000000, 72, 1, 2),
- PLL_RATE(96000000, 64, 1, 2),
- PLL_RATE(120000000, 80, 1, 2),
- PLL_RATE(144000000, 96, 1, 2),
- PLL_RATE(168000000, 56, 1, 1),
- PLL_RATE(192000000, 64, 1, 1),
- PLL_RATE(216000000, 72, 1, 1),
- PLL_RATE(240000000, 80, 1, 1),
- PLL_RATE(264000000, 88, 1, 1),
- PLL_RATE(288000000, 96, 1, 1),
- PLL_RATE(312000000, 52, 1, 2),
- PLL_RATE(336000000, 56, 1, 2),
- PLL_RATE(360000000, 60, 1, 2),
- PLL_RATE(384000000, 64, 1, 2),
- PLL_RATE(408000000, 68, 1, 2),
- PLL_RATE(432000000, 72, 1, 2),
- PLL_RATE(456000000, 76, 1, 2),
- PLL_RATE(480000000, 80, 1, 2),
- PLL_RATE(504000000, 84, 1, 2),
- PLL_RATE(528000000, 88, 1, 2),
- PLL_RATE(552000000, 92, 1, 2),
- PLL_RATE(576000000, 96, 1, 2),
- PLL_RATE(600000000, 50, 1, 1),
- PLL_RATE(624000000, 52, 1, 1),
- PLL_RATE(648000000, 54, 1, 1),
- PLL_RATE(672000000, 56, 1, 1),
- PLL_RATE(696000000, 58, 1, 1),
- PLL_RATE(720000000, 60, 1, 1),
- PLL_RATE(744000000, 62, 1, 1),
- PLL_RATE(768000000, 64, 1, 1),
- PLL_RATE(792000000, 66, 1, 1),
- PLL_RATE(816000000, 68, 1, 1),
- PLL_RATE(840000000, 70, 1, 1),
- PLL_RATE(864000000, 72, 1, 1),
- PLL_RATE(888000000, 74, 1, 1),
- PLL_RATE(912000000, 76, 1, 1),
- PLL_RATE(936000000, 78, 1, 1),
- PLL_RATE(960000000, 80, 1, 1),
- PLL_RATE(984000000, 82, 1, 1),
- PLL_RATE(1008000000, 84, 1, 1),
- PLL_RATE(1032000000, 86, 1, 1),
- PLL_RATE(1056000000, 88, 1, 1),
- PLL_RATE(1080000000, 90, 1, 1),
- PLL_RATE(1104000000, 92, 1, 1),
- PLL_RATE(1128000000, 94, 1, 1),
- PLL_RATE(1152000000, 96, 1, 1),
- PLL_RATE(1176000000, 98, 1, 1),
- PLL_RATE(1200000000, 50, 1, 0),
- PLL_RATE(1224000000, 51, 1, 0),
- PLL_RATE(1248000000, 52, 1, 0),
- PLL_RATE(1272000000, 53, 1, 0),
- PLL_RATE(1296000000, 54, 1, 0),
- PLL_RATE(1320000000, 55, 1, 0),
- PLL_RATE(1344000000, 56, 1, 0),
- PLL_RATE(1368000000, 57, 1, 0),
- PLL_RATE(1392000000, 58, 1, 0),
- PLL_RATE(1416000000, 59, 1, 0),
- PLL_RATE(1440000000, 60, 1, 0),
- PLL_RATE(1464000000, 61, 1, 0),
- PLL_RATE(1488000000, 62, 1, 0),
- PLL_RATE(1512000000, 63, 1, 0),
- PLL_RATE(1536000000, 64, 1, 0),
- PLL_RATE(1560000000, 65, 1, 0),
- PLL_RATE(1584000000, 66, 1, 0),
- PLL_RATE(1608000000, 67, 1, 0),
- PLL_RATE(1632000000, 68, 1, 0),
- PLL_RATE(1656000000, 68, 1, 0),
- PLL_RATE(1680000000, 68, 1, 0),
- PLL_RATE(1704000000, 68, 1, 0),
- PLL_RATE(1728000000, 69, 1, 0),
- PLL_RATE(1752000000, 69, 1, 0),
- PLL_RATE(1776000000, 69, 1, 0),
- PLL_RATE(1800000000, 69, 1, 0),
- PLL_RATE(1824000000, 70, 1, 0),
- PLL_RATE(1848000000, 70, 1, 0),
- PLL_RATE(1872000000, 70, 1, 0),
- PLL_RATE(1896000000, 70, 1, 0),
- PLL_RATE(1920000000, 71, 1, 0),
- PLL_RATE(1944000000, 71, 1, 0),
- PLL_RATE(1968000000, 71, 1, 0),
- PLL_RATE(1992000000, 71, 1, 0),
- PLL_RATE(2016000000, 72, 1, 0),
- PLL_RATE(2040000000, 72, 1, 0),
- PLL_RATE(2064000000, 72, 1, 0),
- PLL_RATE(2088000000, 72, 1, 0),
- PLL_RATE(2112000000, 73, 1, 0),
- { /* sentinel */ },
-};
-
static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
PLL_RATE(96000000, 32, 1, 3),
PLL_RATE(99000000, 33, 1, 3),
@@ -278,23 +189,39 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
{ /* sentinel */ },
};
-static struct meson_clk_pll gxbb_fixed_pll = {
- .m = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 0,
- .width = 9,
+static struct clk_regmap gxbb_fixed_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .frac = {
+ .reg_off = HHI_MPLL_CNTL2,
+ .shift = 0,
+ .width = 12,
+ },
+ .l = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
},
- .n = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 16,
- .width = 2,
- },
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &meson_clk_pll_ro_ops,
@@ -304,33 +231,118 @@ static struct meson_clk_pll gxbb_fixed_pll = {
},
};
-static struct meson_clk_pll gxbb_hdmi_pll = {
- .m = {
- .reg_off = HHI_HDMI_PLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_HDMI_PLL_CNTL,
- .shift = 9,
- .width = 5,
+static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
+ .mult = 2,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll_pre_mult",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "xtal" },
+ .num_parents = 1,
},
- .frac = {
- .reg_off = HHI_HDMI_PLL_CNTL2,
- .shift = 0,
- .width = 12,
+};
+
+static struct clk_regmap gxbb_hdmi_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .frac = {
+ .reg_off = HHI_HDMI_PLL_CNTL2,
+ .shift = 0,
+ .width = 12,
+ },
+ .od = {
+ .reg_off = HHI_HDMI_PLL_CNTL2,
+ .shift = 16,
+ .width = 2,
+ },
+ .od2 = {
+ .reg_off = HHI_HDMI_PLL_CNTL2,
+ .shift = 22,
+ .width = 2,
+ },
+ .od3 = {
+ .reg_off = HHI_HDMI_PLL_CNTL2,
+ .shift = 18,
+ .width = 2,
+ },
+ .l = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 28,
+ .width = 1,
+ },
},
- .od = {
- .reg_off = HHI_HDMI_PLL_CNTL2,
- .shift = 16,
- .width = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
},
- .od2 = {
- .reg_off = HHI_HDMI_PLL_CNTL2,
- .shift = 22,
- .width = 2,
+};
+
+static struct clk_regmap gxl_hdmi_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .frac = {
+ /*
+ * On gxl, there is a register shift due to
+ * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
+ * so we compute the register offset based on the PLL
+ * base to get it right
+ */
+ .reg_off = HHI_HDMI_PLL_CNTL + 4,
+ .shift = 0,
+ .width = 12,
+ },
+ .od = {
+ .reg_off = HHI_HDMI_PLL_CNTL + 8,
+ .shift = 21,
+ .width = 2,
+ },
+ .od2 = {
+ .reg_off = HHI_HDMI_PLL_CNTL + 8,
+ .shift = 23,
+ .width = 2,
+ },
+ .od3 = {
+ .reg_off = HHI_HDMI_PLL_CNTL + 8,
+ .shift = 19,
+ .width = 2,
+ },
+ .l = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &meson_clk_pll_ro_ops,
@@ -340,25 +352,34 @@ static struct meson_clk_pll gxbb_hdmi_pll = {
},
};
-static struct meson_clk_pll gxbb_sys_pll = {
- .m = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 9,
- .width = 5,
+static struct clk_regmap gxbb_sys_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 10,
+ .width = 2,
+ },
+ .l = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
},
- .od = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 10,
- .width = 2,
- },
- .rate_table = sys_pll_rate_table,
- .rate_count = ARRAY_SIZE(sys_pll_rate_table),
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &meson_clk_pll_ro_ops,
@@ -368,38 +389,44 @@ static struct meson_clk_pll gxbb_sys_pll = {
},
};
-struct pll_params_table gxbb_gp0_params_table[] = {
- PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228),
- PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000),
- PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4),
- PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d),
-};
-
-static struct meson_clk_pll gxbb_gp0_pll = {
- .m = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
- .params = {
- .params_table = gxbb_gp0_params_table,
- .params_count = ARRAY_SIZE(gxbb_gp0_params_table),
- .no_init_reset = true,
- .clear_reset_for_lock = true,
+static const struct reg_sequence gxbb_gp0_init_regs[] = {
+ { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
+ { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
+ { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
+ { .reg = HHI_GP0_PLL_CNTL, .def = 0x4a000228 },
+};
+
+static struct clk_regmap gxbb_gp0_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .l = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
+ .table = gxbb_gp0_pll_rate_table,
+ .init_regs = gxbb_gp0_init_regs,
+ .init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
},
- .rate_table = gxbb_gp0_pll_rate_table,
- .rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table),
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &meson_clk_pll_ops,
@@ -409,40 +436,51 @@ static struct meson_clk_pll gxbb_gp0_pll = {
},
};
-struct pll_params_table gxl_gp0_params_table[] = {
- PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250),
- PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000),
- PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be),
- PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288),
- PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d),
- PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000),
-};
-
-static struct meson_clk_pll gxl_gp0_pll = {
- .m = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 16,
- .width = 2,
+static const struct reg_sequence gxl_gp0_init_regs[] = {
+ { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 },
+ { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be },
+ { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
+ { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
+ { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
+ { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
+};
+
+static struct clk_regmap gxl_gp0_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .frac = {
+ .reg_off = HHI_GP0_PLL_CNTL1,
+ .shift = 0,
+ .width = 10,
+ },
+ .l = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
+ .table = gxl_gp0_pll_rate_table,
+ .init_regs = gxl_gp0_init_regs,
+ .init_count = ARRAY_SIZE(gxl_gp0_init_regs),
},
- .params = {
- .params_table = gxl_gp0_params_table,
- .params_count = ARRAY_SIZE(gxl_gp0_params_table),
- .no_init_reset = true,
- .reset_lock_loop = true,
- },
- .rate_table = gxl_gp0_pll_rate_table,
- .rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table),
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &meson_clk_pll_ops,
@@ -452,161 +490,267 @@ static struct meson_clk_pll gxl_gp0_pll = {
},
};
-static struct clk_fixed_factor gxbb_fclk_div2 = {
+static struct clk_fixed_factor gxbb_fclk_div2_div = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div2",
+ .name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor gxbb_fclk_div3 = {
+static struct clk_regmap gxbb_fclk_div2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 27,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div2_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div3_div = {
.mult = 1,
.div = 3,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div3",
+ .name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor gxbb_fclk_div4 = {
+static struct clk_regmap gxbb_fclk_div3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 28,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div3_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div4_div = {
.mult = 1,
.div = 4,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div4",
+ .name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor gxbb_fclk_div5 = {
+static struct clk_regmap gxbb_fclk_div4 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div4",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div4_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div5_div = {
.mult = 1,
.div = 5,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div5",
+ .name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor gxbb_fclk_div7 = {
+static struct clk_regmap gxbb_fclk_div5 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div5_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div7_div = {
.mult = 1,
.div = 7,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div7",
+ .name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll gxbb_mpll0 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 0,
- .width = 14,
+static struct clk_regmap gxbb_fclk_div7 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 31,
},
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 15,
- .width = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div7_div" },
+ .num_parents = 1,
},
- .n2 = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 16,
- .width = 9,
+};
+
+static struct clk_regmap gxbb_mpll_prediv = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPLL_CNTL5,
+ .shift = 12,
+ .width = 1,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 14,
- .width = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll_prediv",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
},
- .ssen = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 25,
- .width = 1,
+};
+
+static struct clk_regmap gxbb_mpll0_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 16,
+ .width = 9,
+ },
+ .ssen = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 25,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll0",
+ .name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll gxbb_mpll1 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 0,
- .width = 14,
- },
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 15,
- .width = 1,
+static struct clk_regmap gxbb_mpll0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL7,
+ .bit_idx = 14,
},
- .n2 = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 16,
- .width = 9,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll0_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 14,
- .width = 1,
+};
+
+static struct clk_regmap gxbb_mpll1_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 16,
+ .width = 9,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll1",
+ .name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll gxbb_mpll2 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 0,
- .width = 14,
- },
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 15,
- .width = 1,
+static struct clk_regmap gxbb_mpll1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL8,
+ .bit_idx = 14,
},
- .n2 = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 16,
- .width = 9,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll1_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 14,
- .width = 1,
+};
+
+static struct clk_regmap gxbb_mpll2_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 16,
+ .width = 9,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll2",
+ .name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-/*
- * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
- * and should be modeled with their respective PLLs via the forthcoming
- * coordinated clock rates feature
- */
+static struct clk_regmap gxbb_mpll2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL9,
+ .bit_idx = 14,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll2_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
static const char * const clk81_parent_names[] = {
@@ -614,16 +758,16 @@ static const char * const clk81_parent_names[] = {
"fclk_div3", "fclk_div5"
};
-static struct clk_mux gxbb_mpeg_clk_sel = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .mask = 0x7,
- .shift = 12,
- .flags = CLK_MUX_READ_ONLY,
- .table = mux_table_clk81,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mpeg_clk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 12,
+ .table = mux_table_clk81,
+ },
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
- .ops = &clk_mux_ro_ops,
+ .ops = &clk_regmap_mux_ro_ops,
/*
* bits 14:12 selects from 8 possible parents:
* xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
@@ -631,72 +775,75 @@ static struct clk_mux gxbb_mpeg_clk_sel = {
*/
.parent_names = clk81_parent_names,
.num_parents = ARRAY_SIZE(clk81_parent_names),
- .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
},
};
-static struct clk_divider gxbb_mpeg_clk_div = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mpeg_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "mpeg_clk_sel" },
.num_parents = 1,
- .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
},
};
-/* the mother of dragons^W gates */
-static struct clk_gate gxbb_clk81 = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .bit_idx = 7,
- .lock = &meson_clk_lock,
+/* the mother of dragons gates */
+static struct clk_regmap gxbb_clk81 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .bit_idx = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "clk81",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpeg_clk_div" },
.num_parents = 1,
- .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+ .flags = CLK_IS_CRITICAL,
},
};
-static struct clk_mux gxbb_sar_adc_clk_sel = {
- .reg = (void *)HHI_SAR_CLK_CNTL,
- .mask = 0x3,
- .shift = 9,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sar_adc_clk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SAR_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 9,
+ },
.hw.init = &(struct clk_init_data){
.name = "sar_adc_clk_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/* NOTE: The datasheet doesn't list the parents for bit 10 */
.parent_names = (const char *[]){ "xtal", "clk81", },
.num_parents = 2,
},
};
-static struct clk_divider gxbb_sar_adc_clk_div = {
- .reg = (void *)HHI_SAR_CLK_CNTL,
- .shift = 0,
- .width = 8,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sar_adc_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SAR_CLK_CNTL,
+ .shift = 0,
+ .width = 8,
+ },
.hw.init = &(struct clk_init_data){
.name = "sar_adc_clk_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sar_adc_clk_sel" },
.num_parents = 1,
},
};
-static struct clk_gate gxbb_sar_adc_clk = {
- .reg = (void *)HHI_SAR_CLK_CNTL,
- .bit_idx = 8,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sar_adc_clk = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_SAR_CLK_CNTL,
+ .bit_idx = 8,
+ },
.hw.init = &(struct clk_init_data){
.name = "sar_adc_clk",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sar_adc_clk_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -708,21 +855,20 @@ static struct clk_gate gxbb_sar_adc_clk = {
* muxed by a glitch-free switch.
*/
-static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
static const char * const gxbb_mali_0_1_parent_names[] = {
"xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
"fclk_div4", "fclk_div3", "fclk_div5"
};
-static struct clk_mux gxbb_mali_0_sel = {
- .reg = (void *)HHI_MALI_CLK_CNTL,
- .mask = 0x7,
- .shift = 9,
- .table = mux_table_mali_0_1,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_MALI_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 9,
+ },
.hw.init = &(struct clk_init_data){
.name = "mali_0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bits 10:9 selects from 8 possible parents:
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
@@ -734,42 +880,44 @@ static struct clk_mux gxbb_mali_0_sel = {
},
};
-static struct clk_divider gxbb_mali_0_div = {
- .reg = (void *)HHI_MALI_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MALI_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "mali_0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "mali_0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
-static struct clk_gate gxbb_mali_0 = {
- .reg = (void *)HHI_MALI_CLK_CNTL,
- .bit_idx = 8,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MALI_CLK_CNTL,
+ .bit_idx = 8,
+ },
.hw.init = &(struct clk_init_data){
.name = "mali_0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mali_0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_mux gxbb_mali_1_sel = {
- .reg = (void *)HHI_MALI_CLK_CNTL,
- .mask = 0x7,
- .shift = 25,
- .table = mux_table_mali_0_1,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_1_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_MALI_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 25,
+ },
.hw.init = &(struct clk_init_data){
.name = "mali_1_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bits 10:9 selects from 8 possible parents:
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
@@ -781,77 +929,79 @@ static struct clk_mux gxbb_mali_1_sel = {
},
};
-static struct clk_divider gxbb_mali_1_div = {
- .reg = (void *)HHI_MALI_CLK_CNTL,
- .shift = 16,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MALI_CLK_CNTL,
+ .shift = 16,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "mali_1_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "mali_1_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
-static struct clk_gate gxbb_mali_1 = {
- .reg = (void *)HHI_MALI_CLK_CNTL,
- .bit_idx = 24,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MALI_CLK_CNTL,
+ .bit_idx = 24,
+ },
.hw.init = &(struct clk_init_data){
.name = "mali_1",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mali_1_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static u32 mux_table_mali[] = {0, 1};
static const char * const gxbb_mali_parent_names[] = {
"mali_0", "mali_1"
};
-static struct clk_mux gxbb_mali = {
- .reg = (void *)HHI_MALI_CLK_CNTL,
- .mask = 1,
- .shift = 31,
- .table = mux_table_mali,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_MALI_CLK_CNTL,
+ .mask = 1,
+ .shift = 31,
+ },
.hw.init = &(struct clk_init_data){
.name = "mali",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = gxbb_mali_parent_names,
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
-static struct clk_mux gxbb_cts_amclk_sel = {
- .reg = (void *) HHI_AUD_CLK_CNTL,
- .mask = 0x3,
- .shift = 9,
- /* Default parent unknown (register reset value: 0) */
- .table = (u32[]){ 1, 2, 3 },
- .lock = &meson_clk_lock,
- .hw.init = &(struct clk_init_data){
+static struct clk_regmap gxbb_cts_amclk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_AUD_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 9,
+ .table = (u32[]){ 1, 2, 3 },
+ },
+ .hw.init = &(struct clk_init_data){
.name = "cts_amclk_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
.num_parents = 3,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
- .div = {
- .reg_off = HHI_AUD_CLK_CNTL,
- .shift = 0,
- .width = 8,
+static struct clk_regmap gxbb_cts_amclk_div = {
+ .data = &(struct meson_clk_audio_div_data){
+ .div = {
+ .reg_off = HHI_AUD_CLK_CNTL,
+ .shift = 0,
+ .width = 8,
+ },
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
},
- .flags = CLK_DIVIDER_ROUND_CLOSEST,
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "cts_amclk_div",
.ops = &meson_clk_audio_divider_ops,
@@ -861,71 +1011,75 @@ static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
},
};
-static struct clk_gate gxbb_cts_amclk = {
- .reg = (void *) HHI_AUD_CLK_CNTL,
- .bit_idx = 8,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_cts_amclk = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_AUD_CLK_CNTL,
+ .bit_idx = 8,
+ },
.hw.init = &(struct clk_init_data){
.name = "cts_amclk",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_amclk_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_mux gxbb_cts_mclk_i958_sel = {
- .reg = (void *)HHI_AUD_CLK_CNTL2,
- .mask = 0x3,
- .shift = 25,
- /* Default parent unknown (register reset value: 0) */
- .table = (u32[]){ 1, 2, 3 },
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_cts_mclk_i958_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_AUD_CLK_CNTL2,
+ .mask = 0x3,
+ .shift = 25,
+ .table = (u32[]){ 1, 2, 3 },
+ },
.hw.init = &(struct clk_init_data) {
.name = "cts_mclk_i958_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
.num_parents = 3,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_divider gxbb_cts_mclk_i958_div = {
- .reg = (void *)HHI_AUD_CLK_CNTL2,
- .shift = 16,
- .width = 8,
- .lock = &meson_clk_lock,
- .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_cts_mclk_i958_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_AUD_CLK_CNTL2,
+ .shift = 16,
+ .width = 8,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
.hw.init = &(struct clk_init_data) {
.name = "cts_mclk_i958_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "cts_mclk_i958_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_cts_mclk_i958 = {
- .reg = (void *)HHI_AUD_CLK_CNTL2,
- .bit_idx = 24,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_cts_mclk_i958 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_AUD_CLK_CNTL2,
+ .bit_idx = 24,
+ },
.hw.init = &(struct clk_init_data){
.name = "cts_mclk_i958",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_mclk_i958_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_mux gxbb_cts_i958 = {
- .reg = (void *)HHI_AUD_CLK_CNTL2,
- .mask = 0x1,
- .shift = 27,
- .lock = &meson_clk_lock,
- .hw.init = &(struct clk_init_data){
+static struct clk_regmap gxbb_cts_i958 = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_AUD_CLK_CNTL2,
+ .mask = 0x1,
+ .shift = 27,
+ },
+ .hw.init = &(struct clk_init_data){
.name = "cts_i958",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" },
.num_parents = 2,
/*
@@ -936,27 +1090,29 @@ static struct clk_mux gxbb_cts_i958 = {
},
};
-static struct clk_divider gxbb_32k_clk_div = {
- .reg = (void *)HHI_32K_CLK_CNTL,
- .shift = 0,
- .width = 14,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_32k_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_32K_CLK_CNTL,
+ .shift = 0,
+ .width = 14,
+ },
.hw.init = &(struct clk_init_data){
.name = "32k_clk_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "32k_clk_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
},
};
-static struct clk_gate gxbb_32k_clk = {
- .reg = (void *)HHI_32K_CLK_CNTL,
- .bit_idx = 15,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_32k_clk = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_32K_CLK_CNTL,
+ .bit_idx = 15,
+ },
.hw.init = &(struct clk_init_data){
.name = "32k_clk",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "32k_clk_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -967,14 +1123,15 @@ static const char * const gxbb_32k_clk_parent_names[] = {
"xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
};
-static struct clk_mux gxbb_32k_clk_sel = {
- .reg = (void *)HHI_32K_CLK_CNTL,
- .mask = 0x3,
- .shift = 16,
- .lock = &meson_clk_lock,
- .hw.init = &(struct clk_init_data){
+static struct clk_regmap gxbb_32k_clk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_32K_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 16,
+ },
+ .hw.init = &(struct clk_init_data){
.name = "32k_clk_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = gxbb_32k_clk_parent_names,
.num_parents = 4,
.flags = CLK_SET_RATE_PARENT,
@@ -993,42 +1150,45 @@ static const char * const gxbb_sd_emmc_clk0_parent_names[] = {
};
/* SDIO clock */
-static struct clk_mux gxbb_sd_emmc_a_clk0_sel = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .mask = 0x7,
- .shift = 9,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_a_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 9,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_a_clk0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = gxbb_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_divider gxbb_sd_emmc_a_clk0_div = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
- .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_sd_emmc_a_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_a_clk0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_sd_emmc_a_clk0 = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .bit_idx = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_a_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .bit_idx = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_a_clk0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1036,42 +1196,45 @@ static struct clk_gate gxbb_sd_emmc_a_clk0 = {
};
/* SDcard clock */
-static struct clk_mux gxbb_sd_emmc_b_clk0_sel = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .mask = 0x7,
- .shift = 25,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_b_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 25,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = gxbb_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_divider gxbb_sd_emmc_b_clk0_div = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .shift = 16,
- .width = 7,
- .lock = &meson_clk_lock,
- .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_sd_emmc_b_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .shift = 16,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_sd_emmc_b_clk0 = {
- .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
- .bit_idx = 23,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_b_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_SD_EMMC_CLK_CNTL,
+ .bit_idx = 23,
+ },
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_b_clk0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1079,42 +1242,45 @@ static struct clk_gate gxbb_sd_emmc_b_clk0 = {
};
/* EMMC/NAND clock */
-static struct clk_mux gxbb_sd_emmc_c_clk0_sel = {
- .reg = (void *)HHI_NAND_CLK_CNTL,
- .mask = 0x7,
- .shift = 9,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_c_clk0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_NAND_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 9,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
.parent_names = gxbb_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_divider gxbb_sd_emmc_c_clk0_div = {
- .reg = (void *)HHI_NAND_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
- .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_sd_emmc_c_clk0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_NAND_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ },
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_sd_emmc_c_clk0 = {
- .reg = (void *)HHI_NAND_CLK_CNTL,
- .bit_idx = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_c_clk0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_NAND_CLK_CNTL,
+ .bit_idx = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_c_clk0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1123,20 +1289,19 @@ static struct clk_gate gxbb_sd_emmc_c_clk0 = {
/* VPU Clock */
-static u32 mux_table_vpu[] = {0, 1, 2, 3};
static const char * const gxbb_vpu_parent_names[] = {
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
};
-static struct clk_mux gxbb_vpu_0_sel = {
- .reg = (void *)HHI_VPU_CLK_CNTL,
- .mask = 0x3,
- .shift = 9,
- .lock = &meson_clk_lock,
- .table = mux_table_vpu,
+static struct clk_regmap gxbb_vpu_0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_VPU_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 9,
+ },
.hw.init = &(struct clk_init_data){
.name = "vpu_0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bits 9:10 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1147,42 +1312,44 @@ static struct clk_mux gxbb_vpu_0_sel = {
},
};
-static struct clk_divider gxbb_vpu_0_div = {
- .reg = (void *)HHI_VPU_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vpu_0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_VPU_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "vpu_0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "vpu_0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_vpu_0 = {
- .reg = (void *)HHI_VPU_CLK_CNTL,
- .bit_idx = 8,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vpu_0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_VPU_CLK_CNTL,
+ .bit_idx = 8,
+ },
.hw.init = &(struct clk_init_data) {
.name = "vpu_0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "vpu_0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
-static struct clk_mux gxbb_vpu_1_sel = {
- .reg = (void *)HHI_VPU_CLK_CNTL,
- .mask = 0x3,
- .shift = 25,
- .lock = &meson_clk_lock,
- .table = mux_table_vpu,
+static struct clk_regmap gxbb_vpu_1_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_VPU_CLK_CNTL,
+ .mask = 0x3,
+ .shift = 25,
+ },
.hw.init = &(struct clk_init_data){
.name = "vpu_1_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bits 25:26 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1193,41 +1360,44 @@ static struct clk_mux gxbb_vpu_1_sel = {
},
};
-static struct clk_divider gxbb_vpu_1_div = {
- .reg = (void *)HHI_VPU_CLK_CNTL,
- .shift = 16,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vpu_1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_VPU_CLK_CNTL,
+ .shift = 16,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "vpu_1_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "vpu_1_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_vpu_1 = {
- .reg = (void *)HHI_VPU_CLK_CNTL,
- .bit_idx = 24,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vpu_1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_VPU_CLK_CNTL,
+ .bit_idx = 24,
+ },
.hw.init = &(struct clk_init_data) {
.name = "vpu_1",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "vpu_1_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
-static struct clk_mux gxbb_vpu = {
- .reg = (void *)HHI_VPU_CLK_CNTL,
- .mask = 1,
- .shift = 31,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vpu = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_VPU_CLK_CNTL,
+ .mask = 1,
+ .shift = 31,
+ },
.hw.init = &(struct clk_init_data){
.name = "vpu",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bit 31 selects from 2 possible parents:
* vpu_0 or vpu_1
@@ -1240,20 +1410,19 @@ static struct clk_mux gxbb_vpu = {
/* VAPB Clock */
-static u32 mux_table_vapb[] = {0, 1, 2, 3};
static const char * const gxbb_vapb_parent_names[] = {
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
};
-static struct clk_mux gxbb_vapb_0_sel = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .mask = 0x3,
- .shift = 9,
- .lock = &meson_clk_lock,
- .table = mux_table_vapb,
+static struct clk_regmap gxbb_vapb_0_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .mask = 0x3,
+ .shift = 9,
+ },
.hw.init = &(struct clk_init_data){
.name = "vapb_0_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bits 9:10 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1264,42 +1433,44 @@ static struct clk_mux gxbb_vapb_0_sel = {
},
};
-static struct clk_divider gxbb_vapb_0_div = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_0_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "vapb_0_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "vapb_0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_vapb_0 = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .bit_idx = 8,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .bit_idx = 8,
+ },
.hw.init = &(struct clk_init_data) {
.name = "vapb_0",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "vapb_0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
-static struct clk_mux gxbb_vapb_1_sel = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .mask = 0x3,
- .shift = 25,
- .lock = &meson_clk_lock,
- .table = mux_table_vapb,
+static struct clk_regmap gxbb_vapb_1_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .mask = 0x3,
+ .shift = 25,
+ },
.hw.init = &(struct clk_init_data){
.name = "vapb_1_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bits 25:26 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1310,41 +1481,44 @@ static struct clk_mux gxbb_vapb_1_sel = {
},
};
-static struct clk_divider gxbb_vapb_1_div = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .shift = 16,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_1_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .shift = 16,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "vapb_1_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "vapb_1_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
-static struct clk_gate gxbb_vapb_1 = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .bit_idx = 24,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .bit_idx = 24,
+ },
.hw.init = &(struct clk_init_data) {
.name = "vapb_1",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "vapb_1_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
-static struct clk_mux gxbb_vapb_sel = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .mask = 1,
- .shift = 31,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .mask = 1,
+ .shift = 31,
+ },
.hw.init = &(struct clk_init_data){
.name = "vapb_sel",
- .ops = &clk_mux_ops,
+ .ops = &clk_regmap_mux_ops,
/*
* bit 31 selects from 2 possible parents:
* vapb_0 or vapb_1
@@ -1355,13 +1529,14 @@ static struct clk_mux gxbb_vapb_sel = {
},
};
-static struct clk_gate gxbb_vapb = {
- .reg = (void *)HHI_VAPBCLK_CNTL,
- .bit_idx = 30,
- .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_VAPBCLK_CNTL,
+ .bit_idx = 30,
+ },
.hw.init = &(struct clk_init_data) {
.name = "vapb",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "vapb_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
@@ -1601,6 +1776,16 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
[CLKID_VAPB] = &gxbb_vapb.hw,
+ [CLKID_HDMI_PLL_PRE_MULT] = &gxbb_hdmi_pll_pre_mult.hw,
+ [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw,
+ [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw,
+ [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw,
+ [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw,
+ [CLKID_FCLK_DIV2_DIV] = &gxbb_fclk_div2_div.hw,
+ [CLKID_FCLK_DIV3_DIV] = &gxbb_fclk_div3_div.hw,
+ [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw,
+ [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw,
+ [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
@@ -1609,7 +1794,7 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
static struct clk_hw_onecell_data gxl_hw_onecell_data = {
.hws = {
[CLKID_SYS_PLL] = &gxbb_sys_pll.hw,
- [CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw,
+ [CLKID_HDMI_PLL] = &gxl_hdmi_pll.hw,
[CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw,
[CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw,
[CLKID_FCLK_DIV3] = &gxbb_fclk_div3.hw,
@@ -1748,34 +1933,31 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
[CLKID_VAPB] = &gxbb_vapb.hw,
+ [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw,
+ [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw,
+ [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw,
+ [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw,
+ [CLKID_FCLK_DIV2_DIV] = &gxbb_fclk_div2_div.hw,
+ [CLKID_FCLK_DIV3_DIV] = &gxbb_fclk_div3_div.hw,
+ [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw,
+ [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw,
+ [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
};
-/* Convenience tables to populate base addresses in .probe */
-
-static struct meson_clk_pll *const gxbb_clk_plls[] = {
- &gxbb_fixed_pll,
- &gxbb_hdmi_pll,
- &gxbb_sys_pll,
+static struct clk_regmap *const gxbb_clk_regmaps[] = {
&gxbb_gp0_pll,
-};
-
-static struct meson_clk_pll *const gxl_clk_plls[] = {
- &gxbb_fixed_pll,
&gxbb_hdmi_pll,
- &gxbb_sys_pll,
- &gxl_gp0_pll,
};
-static struct meson_clk_mpll *const gxbb_clk_mplls[] = {
- &gxbb_mpll0,
- &gxbb_mpll1,
- &gxbb_mpll2,
+static struct clk_regmap *const gxl_clk_regmaps[] = {
+ &gxl_gp0_pll,
+ &gxl_hdmi_pll,
};
-static struct clk_gate *const gxbb_clk_gates[] = {
+static struct clk_regmap *const gx_clk_regmaps[] = {
&gxbb_clk81,
&gxbb_ddr,
&gxbb_dos,
@@ -1872,9 +2054,19 @@ static struct clk_gate *const gxbb_clk_gates[] = {
&gxbb_vapb_0,
&gxbb_vapb_1,
&gxbb_vapb,
-};
-
-static struct clk_mux *const gxbb_clk_muxes[] = {
+ &gxbb_mpeg_clk_div,
+ &gxbb_sar_adc_clk_div,
+ &gxbb_mali_0_div,
+ &gxbb_mali_1_div,
+ &gxbb_cts_mclk_i958_div,
+ &gxbb_32k_clk_div,
+ &gxbb_sd_emmc_a_clk0_div,
+ &gxbb_sd_emmc_b_clk0_div,
+ &gxbb_sd_emmc_c_clk0_div,
+ &gxbb_vpu_0_div,
+ &gxbb_vpu_1_div,
+ &gxbb_vapb_0_div,
+ &gxbb_vapb_1_div,
&gxbb_mpeg_clk_sel,
&gxbb_sar_adc_clk_sel,
&gxbb_mali_0_sel,
@@ -1893,73 +2085,38 @@ static struct clk_mux *const gxbb_clk_muxes[] = {
&gxbb_vapb_0_sel,
&gxbb_vapb_1_sel,
&gxbb_vapb_sel,
-};
-
-static struct clk_divider *const gxbb_clk_dividers[] = {
- &gxbb_mpeg_clk_div,
- &gxbb_sar_adc_clk_div,
- &gxbb_mali_0_div,
- &gxbb_mali_1_div,
- &gxbb_cts_mclk_i958_div,
- &gxbb_32k_clk_div,
- &gxbb_sd_emmc_a_clk0_div,
- &gxbb_sd_emmc_b_clk0_div,
- &gxbb_sd_emmc_c_clk0_div,
- &gxbb_vpu_0_div,
- &gxbb_vpu_1_div,
- &gxbb_vapb_0_div,
- &gxbb_vapb_1_div,
-};
-
-static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
+ &gxbb_mpll0,
+ &gxbb_mpll1,
+ &gxbb_mpll2,
+ &gxbb_mpll0_div,
+ &gxbb_mpll1_div,
+ &gxbb_mpll2_div,
&gxbb_cts_amclk_div,
+ &gxbb_fixed_pll,
+ &gxbb_sys_pll,
+ &gxbb_mpll_prediv,
+ &gxbb_fclk_div2,
+ &gxbb_fclk_div3,
+ &gxbb_fclk_div4,
+ &gxbb_fclk_div5,
+ &gxbb_fclk_div7,
};
struct clkc_data {
- struct clk_gate *const *clk_gates;
- unsigned int clk_gates_count;
- struct meson_clk_mpll *const *clk_mplls;
- unsigned int clk_mplls_count;
- struct meson_clk_pll *const *clk_plls;
- unsigned int clk_plls_count;
- struct clk_mux *const *clk_muxes;
- unsigned int clk_muxes_count;
- struct clk_divider *const *clk_dividers;
- unsigned int clk_dividers_count;
- struct meson_clk_audio_divider *const *clk_audio_dividers;
- unsigned int clk_audio_dividers_count;
+ struct clk_regmap *const *regmap_clks;
+ unsigned int regmap_clks_count;
struct clk_hw_onecell_data *hw_onecell_data;
};
static const struct clkc_data gxbb_clkc_data = {
- .clk_gates = gxbb_clk_gates,
- .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
- .clk_mplls = gxbb_clk_mplls,
- .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
- .clk_plls = gxbb_clk_plls,
- .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls),
- .clk_muxes = gxbb_clk_muxes,
- .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
- .clk_dividers = gxbb_clk_dividers,
- .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
- .clk_audio_dividers = gxbb_audio_dividers,
- .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
+ .regmap_clks = gxbb_clk_regmaps,
+ .regmap_clks_count = ARRAY_SIZE(gxbb_clk_regmaps),
.hw_onecell_data = &gxbb_hw_onecell_data,
};
static const struct clkc_data gxl_clkc_data = {
- .clk_gates = gxbb_clk_gates,
- .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
- .clk_mplls = gxbb_clk_mplls,
- .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
- .clk_plls = gxl_clk_plls,
- .clk_plls_count = ARRAY_SIZE(gxl_clk_plls),
- .clk_muxes = gxbb_clk_muxes,
- .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
- .clk_dividers = gxbb_clk_dividers,
- .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
- .clk_audio_dividers = gxbb_audio_dividers,
- .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
+ .regmap_clks = gxl_clk_regmaps,
+ .regmap_clks_count = ARRAY_SIZE(gxl_clk_regmaps),
.hw_onecell_data = &gxl_hw_onecell_data,
};
@@ -1969,71 +2126,79 @@ static const struct of_device_id clkc_match_table[] = {
{},
};
+static const struct regmap_config clkc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
static int gxbb_clkc_probe(struct platform_device *pdev)
{
const struct clkc_data *clkc_data;
+ struct resource *res;
void __iomem *clk_base;
- int ret, clkid, i;
+ struct regmap *map;
+ int ret, i;
struct device *dev = &pdev->dev;
- clkc_data = of_device_get_match_data(&pdev->dev);
+ clkc_data = of_device_get_match_data(dev);
if (!clkc_data)
return -EINVAL;
- /* Generic clocks and PLLs */
- clk_base = of_iomap(dev->of_node, 0);
- if (!clk_base) {
- pr_err("%s: Unable to map clk base\n", __func__);
- return -ENXIO;
- }
-
- /* Populate base address for PLLs */
- for (i = 0; i < clkc_data->clk_plls_count; i++)
- clkc_data->clk_plls[i]->base = clk_base;
-
- /* Populate base address for MPLLs */
- for (i = 0; i < clkc_data->clk_mplls_count; i++)
- clkc_data->clk_mplls[i]->base = clk_base;
+ /* Get the hhi system controller node if available */
+ map = syscon_node_to_regmap(of_get_parent(dev->of_node));
+ if (IS_ERR(map)) {
+ dev_err(dev,
+ "failed to get HHI regmap - Trying obsolete regs\n");
- /* Populate base address for gates */
- for (i = 0; i < clkc_data->clk_gates_count; i++)
- clkc_data->clk_gates[i]->reg = clk_base +
- (u64)clkc_data->clk_gates[i]->reg;
-
- /* Populate base address for muxes */
- for (i = 0; i < clkc_data->clk_muxes_count; i++)
- clkc_data->clk_muxes[i]->reg = clk_base +
- (u64)clkc_data->clk_muxes[i]->reg;
+ /*
+ * FIXME: HHI registers should be accessed through
+ * the appropriate system controller. This is required because
+ * there is more than just clocks in this register space
+ *
+ * This fallback method is only provided temporarily until
+ * all the platform DTs are properly using the syscon node
+ */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ clk_base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!clk_base) {
+ dev_err(dev, "Unable to map clk base\n");
+ return -ENXIO;
+ }
+
+ map = devm_regmap_init_mmio(dev, clk_base,
+ &clkc_regmap_config);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+ }
- /* Populate base address for dividers */
- for (i = 0; i < clkc_data->clk_dividers_count; i++)
- clkc_data->clk_dividers[i]->reg = clk_base +
- (u64)clkc_data->clk_dividers[i]->reg;
+ /* Populate regmap for the common regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++)
+ gx_clk_regmaps[i]->map = map;
- /* Populate base address for the audio dividers */
- for (i = 0; i < clkc_data->clk_audio_dividers_count; i++)
- clkc_data->clk_audio_dividers[i]->base = clk_base;
+ /* Populate regmap for soc specific clocks */
+ for (i = 0; i < clkc_data->regmap_clks_count; i++)
+ clkc_data->regmap_clks[i]->map = map;
- /*
- * register all clks
- */
- for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
+ /* Register all clks */
+ for (i = 0; i < clkc_data->hw_onecell_data->num; i++) {
/* array might be sparse */
- if (!clkc_data->hw_onecell_data->hws[clkid])
+ if (!clkc_data->hw_onecell_data->hws[i])
continue;
ret = devm_clk_hw_register(dev,
- clkc_data->hw_onecell_data->hws[clkid]);
- if (ret)
- goto iounmap;
+ clkc_data->hw_onecell_data->hws[i]);
+ if (ret) {
+ dev_err(dev, "Clock registration failed\n");
+ return ret;
+ }
}
- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
- clkc_data->hw_onecell_data);
-
-iounmap:
- iounmap(clk_base);
- return ret;
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ clkc_data->hw_onecell_data);
}
static struct platform_driver gxbb_driver = {
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index aee6fbba2004..9febf3f03739 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -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>
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 3ffea80c1308..cc2992493e0b 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -23,14 +23,16 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
-#include <linux/init.h>
+#include <linux/regmap.h>
#include "clkc.h"
#include "meson8b.h"
+#include "clk-regmap.h"
static DEFINE_SPINLOCK(meson_clk_lock);
@@ -97,20 +99,6 @@ static const struct pll_rate_table sys_pll_rate_table[] = {
{ /* sentinel */ },
};
-static const struct clk_div_table cpu_div_table[] = {
- { .val = 1, .div = 1 },
- { .val = 2, .div = 2 },
- { .val = 3, .div = 3 },
- { .val = 2, .div = 4 },
- { .val = 3, .div = 6 },
- { .val = 4, .div = 8 },
- { .val = 5, .div = 10 },
- { .val = 6, .div = 12 },
- { .val = 7, .div = 14 },
- { .val = 8, .div = 16 },
- { /* sentinel */ },
-};
-
static struct clk_fixed_rate meson8b_xtal = {
.fixed_rate = 24000000,
.hw.init = &(struct clk_init_data){
@@ -120,23 +108,39 @@ static struct clk_fixed_rate meson8b_xtal = {
},
};
-static struct meson_clk_pll meson8b_fixed_pll = {
- .m = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 16,
- .width = 2,
+static struct clk_regmap meson8b_fixed_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .frac = {
+ .reg_off = HHI_MPLL_CNTL2,
+ .shift = 0,
+ .width = 12,
+ },
+ .l = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &meson_clk_pll_ro_ops,
@@ -146,23 +150,34 @@ static struct meson_clk_pll meson8b_fixed_pll = {
},
};
-static struct meson_clk_pll meson8b_vid_pll = {
- .m = {
- .reg_off = HHI_VID_PLL_CNTL,
- .shift = 0,
- .width = 9,
+static struct clk_regmap meson8b_vid_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_VID_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_VID_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_VID_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .l = {
+ .reg_off = HHI_VID_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_VID_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
},
- .n = {
- .reg_off = HHI_VID_PLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .od = {
- .reg_off = HHI_VID_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vid_pll",
.ops = &meson_clk_pll_ro_ops,
@@ -172,213 +187,317 @@ static struct meson_clk_pll meson8b_vid_pll = {
},
};
-static struct meson_clk_pll meson8b_sys_pll = {
- .m = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 9,
- .width = 5,
+static struct clk_regmap meson8b_sys_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .m = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .l = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
+ .table = sys_pll_rate_table,
},
- .od = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
- .rate_table = sys_pll_rate_table,
- .rate_count = ARRAY_SIZE(sys_pll_rate_table),
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
- .ops = &meson_clk_pll_ops,
+ .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
};
-static struct clk_fixed_factor meson8b_fclk_div2 = {
+static struct clk_fixed_factor meson8b_fclk_div2_div = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div2",
+ .name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor meson8b_fclk_div3 = {
+static struct clk_regmap meson8b_fclk_div2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 27,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div2_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div3_div = {
.mult = 1,
.div = 3,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div3",
+ .name = "fclk_div_div3",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor meson8b_fclk_div4 = {
+static struct clk_regmap meson8b_fclk_div3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 28,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div3_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div4_div = {
.mult = 1,
.div = 4,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div4",
+ .name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor meson8b_fclk_div5 = {
+static struct clk_regmap meson8b_fclk_div4 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div4",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div4_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div5_div = {
.mult = 1,
.div = 5,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div5",
+ .name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct clk_fixed_factor meson8b_fclk_div7 = {
+static struct clk_regmap meson8b_fclk_div5 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div5_div" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div7_div = {
.mult = 1,
.div = 7,
.hw.init = &(struct clk_init_data){
- .name = "fclk_div7",
+ .name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll meson8b_mpll0 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 0,
- .width = 14,
+static struct clk_regmap meson8b_fclk_div7 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL6,
+ .bit_idx = 31,
},
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 15,
- .width = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "fclk_div7_div" },
+ .num_parents = 1,
},
- .n2 = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 16,
- .width = 9,
+};
+
+static struct clk_regmap meson8b_mpll_prediv = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPLL_CNTL5,
+ .shift = 12,
+ .width = 1,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL7,
- .shift = 14,
- .width = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll_prediv",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
},
- .ssen = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 25,
- .width = 1,
+};
+
+static struct clk_regmap meson8b_mpll0_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 16,
+ .width = 9,
+ },
+ .ssen = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 25,
+ .width = 1,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll0",
+ .name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll meson8b_mpll1 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 0,
- .width = 14,
+static struct clk_regmap meson8b_mpll0 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL7,
+ .bit_idx = 14,
},
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 15,
- .width = 1,
- },
- .n2 = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 16,
- .width = 9,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll0_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL8,
- .shift = 14,
- .width = 1,
+};
+
+static struct clk_regmap meson8b_mpll1_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 16,
+ .width = 9,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll1",
+ .name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-static struct meson_clk_mpll meson8b_mpll2 = {
- .sdm = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 0,
- .width = 14,
- },
- .sdm_en = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 15,
- .width = 1,
+static struct clk_regmap meson8b_mpll1 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL8,
+ .bit_idx = 14,
},
- .n2 = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 16,
- .width = 9,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll1_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
- .en = {
- .reg_off = HHI_MPLL_CNTL9,
- .shift = 14,
- .width = 1,
+};
+
+static struct clk_regmap meson8b_mpll2_div = {
+ .data = &(struct meson_clk_mpll_data){
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 16,
+ .width = 9,
+ },
+ .lock = &meson_clk_lock,
},
- .lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
- .name = "mpll2",
+ .name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
- .parent_names = (const char *[]){ "fixed_pll" },
+ .parent_names = (const char *[]){ "mpll_prediv" },
.num_parents = 1,
},
};
-/*
- * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
- * post-dividers and should be modeled with their respective PLLs via the
- * forthcoming coordinated clock rates feature
- */
-static struct meson_clk_cpu meson8b_cpu_clk = {
- .reg_off = HHI_SYS_CPU_CLK_CNTL1,
- .div_table = cpu_div_table,
- .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
+static struct clk_regmap meson8b_mpll2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPLL_CNTL9,
+ .bit_idx = 14,
+ },
.hw.init = &(struct clk_init_data){
- .name = "cpu_clk",
- .ops = &meson_clk_cpu_ops,
- .parent_names = (const char *[]){ "sys_pll" },
+ .name = "mpll2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_names = (const char *[]){ "mpll2_div" },
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
static u32 mux_table_clk81[] = { 6, 5, 7 };
-
-struct clk_mux meson8b_mpeg_clk_sel = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .mask = 0x7,
- .shift = 12,
- .flags = CLK_MUX_READ_ONLY,
- .table = mux_table_clk81,
- .lock = &meson_clk_lock,
+static struct clk_regmap meson8b_mpeg_clk_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 12,
+ .table = mux_table_clk81,
+ },
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
- .ops = &clk_mux_ro_ops,
+ .ops = &clk_regmap_mux_ro_ops,
/*
* FIXME bits 14:12 selects from 8 possible parents:
* xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
@@ -387,34 +506,136 @@ struct clk_mux meson8b_mpeg_clk_sel = {
.parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
"fclk_div5" },
.num_parents = 3,
- .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
},
};
-struct clk_divider meson8b_mpeg_clk_div = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .shift = 0,
- .width = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap meson8b_mpeg_clk_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
- .ops = &clk_divider_ops,
+ .ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "mpeg_clk_sel" },
.num_parents = 1,
- .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
},
};
-struct clk_gate meson8b_clk81 = {
- .reg = (void *)HHI_MPEG_CLK_CNTL,
- .bit_idx = 7,
- .lock = &meson_clk_lock,
+static struct clk_regmap meson8b_clk81 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = HHI_MPEG_CLK_CNTL,
+ .bit_idx = 7,
+ },
.hw.init = &(struct clk_init_data){
.name = "clk81",
- .ops = &clk_gate_ops,
+ .ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpeg_clk_div" },
.num_parents = 1,
- .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+ .flags = CLK_IS_CRITICAL,
+ },
+};
+
+static struct clk_regmap meson8b_cpu_in_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SYS_CPU_CLK_CNTL0,
+ .mask = 0x1,
+ .shift = 0,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cpu_in_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_names = (const char *[]){ "xtal", "sys_pll" },
+ .num_parents = 2,
+ .flags = (CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT),
+ },
+};
+
+static struct clk_fixed_factor meson8b_cpu_div2 = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "cpu_div2",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "cpu_in_sel" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_fixed_factor meson8b_cpu_div3 = {
+ .mult = 1,
+ .div = 3,
+ .hw.init = &(struct clk_init_data){
+ .name = "cpu_div3",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "cpu_in_sel" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_div_table cpu_scale_table[] = {
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 6 },
+ { .val = 4, .div = 8 },
+ { .val = 5, .div = 10 },
+ { .val = 6, .div = 12 },
+ { .val = 7, .div = 14 },
+ { .val = 8, .div = 16 },
+ { /* sentinel */ },
+};
+
+static struct clk_regmap meson8b_cpu_scale_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SYS_CPU_CLK_CNTL1,
+ .shift = 20,
+ .width = 9,
+ .table = cpu_scale_table,
+ .flags = CLK_DIVIDER_ALLOW_ZERO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cpu_scale_div",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "cpu_in_sel" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap meson8b_cpu_scale_out_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SYS_CPU_CLK_CNTL0,
+ .mask = 0x3,
+ .shift = 2,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cpu_scale_out_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_names = (const char *[]) { "cpu_in_sel",
+ "cpu_div2",
+ "cpu_div3",
+ "cpu_scale_div" },
+ .num_parents = 4,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap meson8b_cpu_clk = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = HHI_SYS_CPU_CLK_CNTL0,
+ .mask = 0x1,
+ .shift = 7,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cpu_clk",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_names = (const char *[]){ "xtal", "cpu_out_sel" },
+ .num_parents = 2,
+ .flags = (CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT),
},
};
@@ -599,24 +820,26 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_MPLL0] = &meson8b_mpll0.hw,
[CLKID_MPLL1] = &meson8b_mpll1.hw,
[CLKID_MPLL2] = &meson8b_mpll2.hw,
+ [CLKID_MPLL0_DIV] = &meson8b_mpll0_div.hw,
+ [CLKID_MPLL1_DIV] = &meson8b_mpll1_div.hw,
+ [CLKID_MPLL2_DIV] = &meson8b_mpll2_div.hw,
+ [CLKID_CPU_IN_SEL] = &meson8b_cpu_in_sel.hw,
+ [CLKID_CPU_DIV2] = &meson8b_cpu_div2.hw,
+ [CLKID_CPU_DIV3] = &meson8b_cpu_div3.hw,
+ [CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw,
+ [CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw,
+ [CLKID_MPLL_PREDIV] = &meson8b_mpll_prediv.hw,
+ [CLKID_FCLK_DIV2_DIV] = &meson8b_fclk_div2_div.hw,
+ [CLKID_FCLK_DIV3_DIV] = &meson8b_fclk_div3_div.hw,
+ [CLKID_FCLK_DIV4_DIV] = &meson8b_fclk_div4_div.hw,
+ [CLKID_FCLK_DIV5_DIV] = &meson8b_fclk_div5_div.hw,
+ [CLKID_FCLK_DIV7_DIV] = &meson8b_fclk_div7_div.hw,
[CLK_NR_CLKS] = NULL,
},
.num = CLK_NR_CLKS,
};
-static struct meson_clk_pll *const meson8b_clk_plls[] = {
- &meson8b_fixed_pll,
- &meson8b_vid_pll,
- &meson8b_sys_pll,
-};
-
-static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
- &meson8b_mpll0,
- &meson8b_mpll1,
- &meson8b_mpll2,
-};
-
-static struct clk_gate *const meson8b_clk_gates[] = {
+static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_clk81,
&meson8b_ddr,
&meson8b_dos,
@@ -695,14 +918,27 @@ static struct clk_gate *const meson8b_clk_gates[] = {
&meson8b_ao_ahb_sram,
&meson8b_ao_ahb_bus,
&meson8b_ao_iface,
-};
-
-static struct clk_mux *const meson8b_clk_muxes[] = {
- &meson8b_mpeg_clk_sel,
-};
-
-static struct clk_divider *const meson8b_clk_dividers[] = {
&meson8b_mpeg_clk_div,
+ &meson8b_mpeg_clk_sel,
+ &meson8b_mpll0,
+ &meson8b_mpll1,
+ &meson8b_mpll2,
+ &meson8b_mpll0_div,
+ &meson8b_mpll1_div,
+ &meson8b_mpll2_div,
+ &meson8b_fixed_pll,
+ &meson8b_vid_pll,
+ &meson8b_sys_pll,
+ &meson8b_cpu_in_sel,
+ &meson8b_cpu_scale_div,
+ &meson8b_cpu_scale_out_sel,
+ &meson8b_cpu_clk,
+ &meson8b_mpll_prediv,
+ &meson8b_fclk_div2,
+ &meson8b_fclk_div3,
+ &meson8b_fclk_div4,
+ &meson8b_fclk_div5,
+ &meson8b_fclk_div7,
};
static const struct meson8b_clk_reset_line {
@@ -804,82 +1040,45 @@ static const struct reset_control_ops meson8b_clk_reset_ops = {
.deassert = meson8b_clk_reset_deassert,
};
+static const struct regmap_config clkc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
static int meson8b_clkc_probe(struct platform_device *pdev)
{
- int ret, clkid, i;
- struct clk_hw *parent_hw;
- struct clk *parent_clk;
+ int ret, i;
struct device *dev = &pdev->dev;
+ struct regmap *map;
if (!clk_base)
return -ENXIO;
- /* Populate base address for PLLs */
- for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
- meson8b_clk_plls[i]->base = clk_base;
-
- /* Populate base address for MPLLs */
- for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
- meson8b_clk_mplls[i]->base = clk_base;
-
- /* Populate the base address for CPU clk */
- meson8b_cpu_clk.base = clk_base;
-
- /* Populate base address for gates */
- for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
- meson8b_clk_gates[i]->reg = clk_base +
- (u32)meson8b_clk_gates[i]->reg;
-
- /* Populate base address for muxes */
- for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
- meson8b_clk_muxes[i]->reg = clk_base +
- (u32)meson8b_clk_muxes[i]->reg;
+ map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
- /* Populate base address for dividers */
- for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++)
- meson8b_clk_dividers[i]->reg = clk_base +
- (u32)meson8b_clk_dividers[i]->reg;
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
+ meson8b_clk_regmaps[i]->map = map;
/*
* register all clks
* CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
*/
- for (clkid = CLKID_XTAL; clkid < CLK_NR_CLKS; clkid++) {
+ for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
/* array might be sparse */
- if (!meson8b_hw_onecell_data.hws[clkid])
+ if (!meson8b_hw_onecell_data.hws[i])
continue;
- /* FIXME convert to devm_clk_register */
- ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]);
+ ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]);
if (ret)
return ret;
}
- /*
- * Register CPU clk notifier
- *
- * FIXME this is wrong for a lot of reasons. First, the muxes should be
- * struct clk_hw objects. Second, we shouldn't program the muxes in
- * notifier handlers. The tricky programming sequence will be handled
- * by the forthcoming coordinated clock rates mechanism once that
- * feature is released.
- *
- * Furthermore, looking up the parent this way is terrible. At some
- * point we will stop allocating a default struct clk when registering
- * a new clk_hw, and this hack will no longer work. Releasing the ccr
- * feature before that time solves the problem :-)
- */
- parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw);
- parent_clk = parent_hw->clk;
- ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb);
- if (ret) {
- pr_err("%s: failed to register clock notifier for cpu_clk\n",
- __func__);
- return ret;
- }
-
- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
- &meson8b_hw_onecell_data);
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ &meson8b_hw_onecell_data);
}
static const struct of_device_id meson8b_clkc_match_table[] = {
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 2eaf8a52e7dd..6e414bd36981 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -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
diff --git a/drivers/clk/mvebu/armada-38x.c b/drivers/clk/mvebu/armada-38x.c
index 394aa6f03f01..9ff4ea63932d 100644
--- a/drivers/clk/mvebu/armada-38x.c
+++ b/drivers/clk/mvebu/armada-38x.c
@@ -46,11 +46,11 @@ static u32 __init armada_38x_get_tclk_freq(void __iomem *sar)
}
static const u32 armada_38x_cpu_frequencies[] __initconst = {
- 0, 0, 0, 0,
- 1066 * 1000 * 1000, 0, 0, 0,
+ 666 * 1000 * 1000, 0, 800 * 1000 * 1000, 0,
+ 1066 * 1000 * 1000, 0, 1200 * 1000 * 1000, 0,
1332 * 1000 * 1000, 0, 0, 0,
1600 * 1000 * 1000, 0, 0, 0,
- 1866 * 1000 * 1000,
+ 1866 * 1000 * 1000, 0, 0, 2000 * 1000 * 1000,
};
static u32 __init armada_38x_get_cpu_freq(void __iomem *sar)
@@ -76,11 +76,11 @@ static const struct coreclk_ratio armada_38x_coreclk_ratios[] __initconst = {
};
static const int armada_38x_cpu_l2_ratios[32][2] __initconst = {
- {0, 1}, {0, 1}, {0, 1}, {0, 1},
- {1, 2}, {0, 1}, {0, 1}, {0, 1},
- {1, 2}, {0, 1}, {0, 1}, {0, 1},
+ {1, 2}, {0, 1}, {1, 2}, {0, 1},
+ {1, 2}, {0, 1}, {1, 2}, {0, 1},
{1, 2}, {0, 1}, {0, 1}, {0, 1},
{1, 2}, {0, 1}, {0, 1}, {0, 1},
+ {1, 2}, {0, 1}, {0, 1}, {1, 2},
{0, 1}, {0, 1}, {0, 1}, {0, 1},
{0, 1}, {0, 1}, {0, 1}, {0, 1},
{0, 1}, {0, 1}, {0, 1}, {0, 1},
@@ -91,7 +91,7 @@ static const int armada_38x_cpu_ddr_ratios[32][2] __initconst = {
{1, 2}, {0, 1}, {0, 1}, {0, 1},
{1, 2}, {0, 1}, {0, 1}, {0, 1},
{1, 2}, {0, 1}, {0, 1}, {0, 1},
- {1, 2}, {0, 1}, {0, 1}, {0, 1},
+ {1, 2}, {0, 1}, {0, 1}, {7, 15},
{0, 1}, {0, 1}, {0, 1}, {0, 1},
{0, 1}, {0, 1}, {0, 1}, {0, 1},
{0, 1}, {0, 1}, {0, 1}, {0, 1},
diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c
index ca9a0a536174..75bf7b8f282f 100644
--- a/drivers/clk/mvebu/cp110-system-controller.c
+++ b/drivers/clk/mvebu/cp110-system-controller.c
@@ -13,18 +13,17 @@
/*
* CP110 has 6 core clocks:
*
- * - APLL (1 Ghz)
- * - PPv2 core (1/3 APLL)
- * - EIP (1/2 APLL)
- * - Core (1/2 EIP)
- * - SDIO (2/5 APLL)
+ * - PLL0 (1 Ghz)
+ * - PPv2 core (1/3 PLL0)
+ * - x2 Core (1/2 PLL0)
+ * - Core (1/2 x2 Core)
+ * - SDIO (2/5 PLL0)
*
* - NAND clock, which is either:
* - Equal to SDIO clock
- * - 2/5 APLL
+ * - 2/5 PLL0
*
- * CP110 has 32 gatable clocks, for the various peripherals in the
- * IP. They have fairly complicated parent/child relationships.
+ * CP110 has 32 gatable clocks, for the various peripherals in the IP.
*/
#define pr_fmt(fmt) "cp110-system-controller: " fmt
@@ -53,9 +52,9 @@ enum {
#define CP110_CLK_NUM \
(CP110_MAX_CORE_CLOCKS + CP110_MAX_GATABLE_CLOCKS)
-#define CP110_CORE_APLL 0
+#define CP110_CORE_PLL0 0
#define CP110_CORE_PPV2 1
-#define CP110_CORE_EIP 2
+#define CP110_CORE_X2CORE 2
#define CP110_CORE_CORE 3
#define CP110_CORE_NAND 4
#define CP110_CORE_SDIO 5
@@ -237,7 +236,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
struct regmap *regmap;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name,
+ const char *ppv2_name, *pll0_name, *core_name, *x2core_name, *nand_name,
*sdio_name;
struct clk_hw_onecell_data *cp110_clk_data;
struct clk_hw *hw, **cp110_clks;
@@ -263,20 +262,20 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks = cp110_clk_data->hws;
cp110_clk_data->num = CP110_CLK_NUM;
- /* Register the APLL which is the root of the hw tree */
- apll_name = cp110_unique_name(dev, syscon_node, "apll");
- hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0,
+ /* Register the PLL0 which is the root of the hw tree */
+ pll0_name = cp110_unique_name(dev, syscon_node, "pll0");
+ hw = clk_hw_register_fixed_rate(NULL, pll0_name, NULL, 0,
1000 * 1000 * 1000);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
- goto fail_apll;
+ goto fail_pll0;
}
- cp110_clks[CP110_CORE_APLL] = hw;
+ cp110_clks[CP110_CORE_PLL0] = hw;
- /* PPv2 is APLL/3 */
+ /* PPv2 is PLL0/3 */
ppv2_name = cp110_unique_name(dev, syscon_node, "ppv2-core");
- hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
+ hw = clk_hw_register_fixed_factor(NULL, ppv2_name, pll0_name, 0, 1, 3);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
goto fail_ppv2;
@@ -284,30 +283,32 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_PPV2] = hw;
- /* EIP clock is APLL/2 */
- eip_name = cp110_unique_name(dev, syscon_node, "eip");
- hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
+ /* X2CORE clock is PLL0/2 */
+ x2core_name = cp110_unique_name(dev, syscon_node, "x2core");
+ hw = clk_hw_register_fixed_factor(NULL, x2core_name, pll0_name,
+ 0, 1, 2);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
goto fail_eip;
}
- cp110_clks[CP110_CORE_EIP] = hw;
+ cp110_clks[CP110_CORE_X2CORE] = hw;
- /* Core clock is EIP/2 */
+ /* Core clock is X2CORE/2 */
core_name = cp110_unique_name(dev, syscon_node, "core");
- hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
+ hw = clk_hw_register_fixed_factor(NULL, core_name, x2core_name,
+ 0, 1, 2);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
goto fail_core;
}
cp110_clks[CP110_CORE_CORE] = hw;
- /* NAND can be either APLL/2.5 or core clock */
+ /* NAND can be either PLL0/2.5 or core clock */
nand_name = cp110_unique_name(dev, syscon_node, "nand-core");
if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
hw = clk_hw_register_fixed_factor(NULL, nand_name,
- apll_name, 0, 2, 5);
+ pll0_name, 0, 2, 5);
else
hw = clk_hw_register_fixed_factor(NULL, nand_name,
core_name, 0, 1, 1);
@@ -318,10 +319,10 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_NAND] = hw;
- /* SDIO clock is APLL/2.5 */
+ /* SDIO clock is PLL0/2.5 */
sdio_name = cp110_unique_name(dev, syscon_node, "sdio-core");
hw = clk_hw_register_fixed_factor(NULL, sdio_name,
- apll_name, 0, 2, 5);
+ pll0_name, 0, 2, 5);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
goto fail_sdio;
@@ -341,40 +342,23 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
continue;
switch (i) {
- case CP110_GATE_AUDIO:
- case CP110_GATE_COMM_UNIT:
- case CP110_GATE_EIP150:
- case CP110_GATE_EIP197:
- case CP110_GATE_SLOW_IO:
- parent = gate_name[CP110_GATE_MAIN];
- break;
- case CP110_GATE_MG:
- parent = gate_name[CP110_GATE_MG_CORE];
- break;
case CP110_GATE_NAND:
parent = nand_name;
break;
+ case CP110_GATE_MG:
+ case CP110_GATE_GOP_DP:
case CP110_GATE_PPV2:
parent = ppv2_name;
break;
case CP110_GATE_SDIO:
parent = sdio_name;
break;
- case CP110_GATE_GOP_DP:
- parent = gate_name[CP110_GATE_SDMMC_GOP];
- break;
- case CP110_GATE_XOR1:
- case CP110_GATE_XOR0:
- case CP110_GATE_PCIE_X1_0:
- case CP110_GATE_PCIE_X1_1:
+ case CP110_GATE_MAIN:
+ case CP110_GATE_PCIE_XOR:
case CP110_GATE_PCIE_X4:
- parent = gate_name[CP110_GATE_PCIE_XOR];
- break;
- case CP110_GATE_SATA:
- case CP110_GATE_USB3H0:
- case CP110_GATE_USB3H1:
- case CP110_GATE_USB3DEV:
- parent = gate_name[CP110_GATE_SATA_USB];
+ case CP110_GATE_EIP150:
+ case CP110_GATE_EIP197:
+ parent = x2core_name;
break;
default:
parent = core_name;
@@ -413,12 +397,12 @@ fail_sdio:
fail_nand:
clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
fail_core:
- clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
+ clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_X2CORE]);
fail_eip:
clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
fail_ppv2:
- clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
-fail_apll:
+ clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_PLL0]);
+fail_pll0:
return ret;
}
diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c
index 4e9b8c2c8980..1ee75a5e93f4 100644
--- a/drivers/clk/qcom/clk-regmap-divider.c
+++ b/drivers/clk/qcom/clk-regmap-divider.c
@@ -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,
diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c
index c60f61b10c7f..b94981447664 100644
--- a/drivers/clk/qcom/clk-rpm.c
+++ b/drivers/clk/qcom/clk-rpm.c
@@ -29,6 +29,7 @@
#define QCOM_RPM_MISC_CLK_TYPE 0x306b6c63
#define QCOM_RPM_SCALING_ENABLE_ID 0x2
+#define QCOM_RPM_XO_MODE_ON 0x2
#define DEFINE_CLK_RPM(_platform, _name, _active, r_id) \
static struct clk_rpm _platform##_##_active; \
@@ -56,6 +57,18 @@
}, \
}
+#define DEFINE_CLK_RPM_XO_BUFFER(_platform, _name, _active, offset) \
+ static struct clk_rpm _platform##_##_name = { \
+ .rpm_clk_id = QCOM_RPM_CXO_BUFFERS, \
+ .xo_offset = (offset), \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &clk_rpm_xo_ops, \
+ .name = #_name, \
+ .parent_names = (const char *[]){ "cxo_board" }, \
+ .num_parents = 1, \
+ }, \
+ }
+
#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \
static struct clk_rpm _platform##_##_name = { \
.rpm_clk_id = (r_id), \
@@ -126,8 +139,11 @@
#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
+struct rpm_cc;
+
struct clk_rpm {
const int rpm_clk_id;
+ const int xo_offset;
const bool active_only;
unsigned long rate;
bool enabled;
@@ -135,12 +151,15 @@ struct clk_rpm {
struct clk_rpm *peer;
struct clk_hw hw;
struct qcom_rpm *rpm;
+ struct rpm_cc *rpm_cc;
};
struct rpm_cc {
struct qcom_rpm *rpm;
struct clk_rpm **clks;
size_t num_clks;
+ u32 xo_buffer_value;
+ struct mutex xo_lock;
};
struct rpm_clk_desc {
@@ -159,7 +178,8 @@ static int clk_rpm_handoff(struct clk_rpm *r)
* The vendor tree simply reads the status for this
* RPM clock.
*/
- if (r->rpm_clk_id == QCOM_RPM_PLL_4)
+ if (r->rpm_clk_id == QCOM_RPM_PLL_4 ||
+ r->rpm_clk_id == QCOM_RPM_CXO_BUFFERS)
return 0;
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
@@ -288,6 +308,46 @@ out:
mutex_unlock(&rpm_clk_lock);
}
+static int clk_rpm_xo_prepare(struct clk_hw *hw)
+{
+ struct clk_rpm *r = to_clk_rpm(hw);
+ struct rpm_cc *rcc = r->rpm_cc;
+ int ret, clk_id = r->rpm_clk_id;
+ u32 value;
+
+ mutex_lock(&rcc->xo_lock);
+
+ value = rcc->xo_buffer_value | (QCOM_RPM_XO_MODE_ON << r->xo_offset);
+ ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1);
+ if (!ret) {
+ r->enabled = true;
+ rcc->xo_buffer_value = value;
+ }
+
+ mutex_unlock(&rcc->xo_lock);
+
+ return ret;
+}
+
+static void clk_rpm_xo_unprepare(struct clk_hw *hw)
+{
+ struct clk_rpm *r = to_clk_rpm(hw);
+ struct rpm_cc *rcc = r->rpm_cc;
+ int ret, clk_id = r->rpm_clk_id;
+ u32 value;
+
+ mutex_lock(&rcc->xo_lock);
+
+ value = rcc->xo_buffer_value & ~(QCOM_RPM_XO_MODE_ON << r->xo_offset);
+ ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1);
+ if (!ret) {
+ r->enabled = false;
+ rcc->xo_buffer_value = value;
+ }
+
+ mutex_unlock(&rcc->xo_lock);
+}
+
static int clk_rpm_fixed_prepare(struct clk_hw *hw)
{
struct clk_rpm *r = to_clk_rpm(hw);
@@ -378,6 +438,11 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
return r->rate;
}
+static const struct clk_ops clk_rpm_xo_ops = {
+ .prepare = clk_rpm_xo_prepare,
+ .unprepare = clk_rpm_xo_unprepare,
+};
+
static const struct clk_ops clk_rpm_fixed_ops = {
.prepare = clk_rpm_fixed_prepare,
.unprepare = clk_rpm_fixed_unprepare,
@@ -449,6 +514,11 @@ DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d0_clk, xo_d0_a_clk, 0);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d1_clk, xo_d1_a_clk, 8);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a0_clk, xo_a0_a_clk, 16);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a1_clk, xo_a1_a_clk, 24);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a2_clk, xo_a2_a_clk, 28);
static struct clk_rpm *apq8064_clks[] = {
[RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
@@ -469,6 +539,11 @@ static struct clk_rpm *apq8064_clks[] = {
[RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
[RPM_QDSS_CLK] = &apq8064_qdss_clk,
[RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
+ [RPM_XO_D0] = &apq8064_xo_d0_clk,
+ [RPM_XO_D1] = &apq8064_xo_d1_clk,
+ [RPM_XO_A0] = &apq8064_xo_a0_clk,
+ [RPM_XO_A1] = &apq8064_xo_a1_clk,
+ [RPM_XO_A2] = &apq8064_xo_a2_clk,
};
static const struct rpm_clk_desc rpm_clk_apq8064 = {
@@ -526,12 +601,14 @@ static int rpm_clk_probe(struct platform_device *pdev)
rcc->clks = rpm_clks;
rcc->num_clks = num_clks;
+ mutex_init(&rcc->xo_lock);
for (i = 0; i < num_clks; i++) {
if (!rpm_clks[i])
continue;
rpm_clks[i]->rpm = rpm;
+ rpm_clks[i]->rpm_cc = rcc;
ret = clk_rpm_handoff(rpm_clks[i]);
if (ret)
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index c26d9007bfc4..850c02a52248 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -686,7 +686,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
goto err;
}
- ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_smdrpm_clk_hw_get,
+ ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_smdrpm_clk_hw_get,
rcc);
if (ret)
goto err;
@@ -697,19 +697,12 @@ err:
return ret;
}
-static int rpm_smd_clk_remove(struct platform_device *pdev)
-{
- of_clk_del_provider(pdev->dev.of_node);
- return 0;
-}
-
static struct platform_driver rpm_smd_clk_driver = {
.driver = {
.name = "qcom-clk-smd-rpm",
.of_match_table = rpm_smd_clk_match_table,
},
.probe = rpm_smd_clk_probe,
- .remove = rpm_smd_clk_remove,
};
static int __init rpm_smd_clk_init(void)
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
index 5d7451209206..3d6452932797 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -2895,7 +2895,7 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = {
.name = "gcc_aggre0_snoc_axi_clk",
.parent_names = (const char *[]){ "system_noc_clk_src" },
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@@ -2910,7 +2910,7 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = {
.name = "gcc_aggre0_cnoc_ahb_clk",
.parent_names = (const char *[]){ "config_noc_clk_src" },
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@@ -2925,7 +2925,7 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = {
.name = "gcc_smmu_aggre0_axi_clk",
.parent_names = (const char *[]){ "system_noc_clk_src" },
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
@@ -2940,7 +2940,7 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = {
.name = "gcc_smmu_aggre0_ahb_clk",
.parent_names = (const char *[]){ "config_noc_clk_src" },
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
.ops = &clk_branch2_ops,
},
},
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index ef8900bc077f..513826393158 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -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
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index 5bfc92ee3129..b4b057c7301c 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -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);
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 1b81e283f605..27c9d23657b3 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -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 */ }
};
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 134f25f2a913..0421960eb963 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -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 */ }
};
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c
new file mode 100644
index 000000000000..93306283d764
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5-subcmu.c
@@ -0,0 +1,189 @@
+// 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);
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.h b/drivers/clk/samsung/clk-exynos5-subcmu.h
new file mode 100644
index 000000000000..755ee8aaa3de
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5-subcmu.h
@@ -0,0 +1,26 @@
+/* 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
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 9b073c98a891..347fd80c351b 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -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);
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index fd1d9bfc151b..2cc2583abd87 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -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 */
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index fc471a49e8f4..0a0b09591e6f 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -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 = {
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 45d34f601e9e..95e1bf69449b 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -19,6 +19,7 @@
#include "clk.h"
#include "clk-cpu.h"
+#include "clk-exynos5-subcmu.h"
#define APLL_LOCK 0x0
#define APLL_CON0 0x100
@@ -620,7 +621,8 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
mout_group5_5800_p, SRC_TOP7, 16, 2),
- MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2),
+ MUX_F(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2,
+ CLK_SET_RATE_PARENT, 0),
MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
};
@@ -863,7 +865,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
DIV(0, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8),
DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4),
DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4),
- DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2),
DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1",
"mout_aclk400_disp1", DIV_TOP2, 4, 3),
@@ -912,8 +913,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
DIV(0, "dout_spi1", "mout_spi1", DIV_PERIC1, 24, 4),
DIV(0, "dout_spi2", "mout_spi2", DIV_PERIC1, 28, 4),
- /* Mfc Block */
- DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2),
/* PCM */
DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC2, 16, 8),
@@ -932,8 +931,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
DIV(0, "dout_spi2_pre", "dout_spi2", DIV_PERIC4, 24, 8),
/* GSCL Block */
- DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl",
- DIV2_RATIO0, 4, 2),
DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
/* MSCL Block */
@@ -1190,8 +1187,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "mout_user_aclk333_432_gscl",
GATE_TOP_SCLK_GSCL, 7, 0, 0),
- GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0),
- GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0),
GATE(CLK_FIMC_3AA, "fimc_3aa", "aclk333_432_gscl",
GATE_IP_GSCL0, 4, 0, 0),
GATE(CLK_FIMC_LITE0, "fimc_lite0", "aclk333_432_gscl",
@@ -1205,10 +1200,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE_IP_GSCL1, 3, 0, 0),
GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333",
GATE_IP_GSCL1, 4, 0, 0),
- GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300",
- GATE_IP_GSCL1, 6, 0, 0),
- GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300",
- GATE_IP_GSCL1, 7, 0, 0),
GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0),
GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0),
GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333",
@@ -1227,18 +1218,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
GATE_IP_MSCL, 10, 0, 0),
- GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0),
- GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0),
- GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0),
- GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
- GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
- GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk",
- GATE_IP_DISP1, 7, 0, 0),
- GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk",
- GATE_IP_DISP1, 8, 0, 0),
- GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1",
- GATE_IP_DISP1, 9, 0, 0),
-
/* ISP */
GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0),
@@ -1255,48 +1234,138 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2",
GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
+};
+
+static const struct samsung_div_clock exynos5x_disp_div_clks[] __initconst = {
+ DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2),
+};
+
+static const struct samsung_gate_clock exynos5x_disp_gate_clks[] __initconst = {
+ GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0),
+ GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0),
+ GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0),
+ GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
+ GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
+ GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk",
+ GATE_IP_DISP1, 7, 0, 0),
+ GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk",
+ GATE_IP_DISP1, 8, 0, 0),
+ GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1",
+ GATE_IP_DISP1, 9, 0, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_disp_suspend_regs[] = {
+ { GATE_IP_DISP1, 0xffffffff, 0xffffffff }, /* DISP1 gates */
+ { SRC_TOP5, 0, BIT(0) }, /* MUX mout_user_aclk400_disp1 */
+ { SRC_TOP5, 0, BIT(24) }, /* MUX mout_user_aclk300_disp1 */
+ { SRC_TOP3, 0, BIT(8) }, /* MUX mout_user_aclk200_disp1 */
+ { DIV2_RATIO0, 0, 0x30000 }, /* DIV dout_disp1_blk */
+};
+
+static const struct samsung_div_clock exynos5x_gsc_div_clks[] __initconst = {
+ DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl",
+ DIV2_RATIO0, 4, 2),
+};
+
+static const struct samsung_gate_clock exynos5x_gsc_gate_clks[] __initconst = {
+ GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0),
+ GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0),
+ GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300",
+ GATE_IP_GSCL1, 6, 0, 0),
+ GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300",
+ GATE_IP_GSCL1, 7, 0, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_gsc_suspend_regs[] = {
+ { GATE_IP_GSCL0, 0x3, 0x3 }, /* GSC gates */
+ { GATE_IP_GSCL1, 0xc0, 0xc0 }, /* GSC gates */
+ { SRC_TOP5, 0, BIT(28) }, /* MUX mout_user_aclk300_gscl */
+ { DIV2_RATIO0, 0, 0x30 }, /* DIV dout_gscl_blk_300 */
+};
+
+static const struct samsung_div_clock exynos5x_mfc_div_clks[] __initconst = {
+ DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2),
+};
+
+static const struct samsung_gate_clock exynos5x_mfc_gate_clks[] __initconst = {
GATE(CLK_MFC, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
GATE(CLK_SMMU_MFCL, "smmu_mfcl", "dout_mfc_blk", GATE_IP_MFC, 1, 0, 0),
GATE(CLK_SMMU_MFCR, "smmu_mfcr", "dout_mfc_blk", GATE_IP_MFC, 2, 0, 0),
+};
- GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
+static struct exynos5_subcmu_reg_dump exynos5x_mfc_suspend_regs[] = {
+ { GATE_IP_MFC, 0xffffffff, 0xffffffff }, /* MFC gates */
+ { SRC_TOP4, 0, BIT(28) }, /* MUX mout_user_aclk333 */
+ { DIV4_RATIO, 0, 0x3 }, /* DIV dout_mfc_blk */
+};
+
+static const struct exynos5_subcmu_info exynos5x_subcmus[] = {
+ {
+ .div_clks = exynos5x_disp_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos5x_disp_div_clks),
+ .gate_clks = exynos5x_disp_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_disp_gate_clks),
+ .suspend_regs = exynos5x_disp_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
+ .pd_name = "DISP",
+ }, {
+ .div_clks = exynos5x_gsc_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos5x_gsc_div_clks),
+ .gate_clks = exynos5x_gsc_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_gsc_gate_clks),
+ .suspend_regs = exynos5x_gsc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
+ .pd_name = "GSC",
+ }, {
+ .div_clks = exynos5x_mfc_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos5x_mfc_div_clks),
+ .gate_clks = exynos5x_mfc_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_mfc_gate_clks),
+ .suspend_regs = exynos5x_mfc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
+ .pd_name = "MFC",
+ },
};
static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
- PLL_35XX_RATE(2000000000, 250, 3, 0),
- PLL_35XX_RATE(1900000000, 475, 6, 0),
- PLL_35XX_RATE(1800000000, 225, 3, 0),
- 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, 2, 1),
- PLL_35XX_RATE(1100000000, 275, 3, 1),
- PLL_35XX_RATE(1000000000, 250, 3, 1),
- PLL_35XX_RATE(900000000, 150, 2, 1),
- PLL_35XX_RATE(800000000, 200, 3, 1),
- PLL_35XX_RATE(700000000, 175, 3, 1),
- PLL_35XX_RATE(600000000, 200, 2, 2),
- PLL_35XX_RATE(500000000, 250, 3, 2),
- PLL_35XX_RATE(400000000, 200, 3, 2),
- PLL_35XX_RATE(300000000, 200, 2, 3),
- PLL_35XX_RATE(200000000, 200, 3, 3),
+ PLL_35XX_RATE(24 * MHZ, 2000000000, 250, 3, 0),
+ PLL_35XX_RATE(24 * MHZ, 1900000000, 475, 6, 0),
+ PLL_35XX_RATE(24 * MHZ, 1800000000, 225, 3, 0),
+ 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, 2, 1),
+ PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1),
+ PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1),
+ PLL_35XX_RATE(24 * MHZ, 900000000, 150, 2, 1),
+ PLL_35XX_RATE(24 * MHZ, 800000000, 200, 3, 1),
+ PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1),
+ PLL_35XX_RATE(24 * MHZ, 600000000, 200, 2, 2),
+ PLL_35XX_RATE(24 * MHZ, 500000000, 250, 3, 2),
+ PLL_35XX_RATE(24 * MHZ, 400000000, 200, 3, 2),
+ PLL_35XX_RATE(24 * MHZ, 300000000, 200, 2, 3),
+ PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3),
};
static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = {
- PLL_36XX_RATE(600000000U, 100, 2, 1, 0),
- PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
- PLL_36XX_RATE(393216003U, 197, 3, 2, -25690),
- PLL_36XX_RATE(361267218U, 301, 5, 2, 3671),
- PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
- PLL_36XX_RATE(196608001U, 197, 3, 3, -25690),
- PLL_36XX_RATE(180633609U, 301, 5, 3, 3671),
- PLL_36XX_RATE(131072006U, 131, 3, 3, 4719),
- PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
- PLL_36XX_RATE( 65536003U, 131, 3, 4, 4719),
- PLL_36XX_RATE( 49152000U, 197, 3, 5, -25690),
- PLL_36XX_RATE( 32768001U, 131, 3, 5, 4719),
+ PLL_36XX_RATE(24 * MHZ, 600000000U, 100, 2, 1, 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, 361267218U, 301, 5, 2, 3671),
+ PLL_36XX_RATE(24 * MHZ, 200000000U, 200, 3, 3, 0),
+ PLL_36XX_RATE(24 * MHZ, 196608001U, 197, 3, 3, -25690),
+ PLL_36XX_RATE(24 * MHZ, 180633609U, 301, 5, 3, 3671),
+ PLL_36XX_RATE(24 * MHZ, 131072006U, 131, 3, 3, 4719),
+ PLL_36XX_RATE(24 * MHZ, 100000000U, 200, 3, 4, 0),
+ PLL_36XX_RATE(24 * MHZ, 73728000U, 98, 2, 4, 19923),
+ PLL_36XX_RATE(24 * MHZ, 67737602U, 90, 2, 4, 20762),
+ PLL_36XX_RATE(24 * MHZ, 65536003U, 131, 3, 4, 4719),
+ PLL_36XX_RATE(24 * MHZ, 49152000U, 197, 3, 5, -25690),
+ PLL_36XX_RATE(24 * MHZ, 45158401U, 90, 3, 4, 20762),
+ PLL_36XX_RATE(24 * MHZ, 32768001U, 131, 3, 5, 4719),
};
static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
@@ -1472,6 +1541,8 @@ static void __init exynos5x_clk_init(struct device_node *np,
exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
exynos5420_clk_sleep_init();
+ exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
+ exynos5x_subcmus);
samsung_clk_of_add_provider(np, ctx);
}
@@ -1480,10 +1551,12 @@ static void __init exynos5420_clk_init(struct device_node *np)
{
exynos5x_clk_init(np, EXYNOS5420);
}
-CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init);
+CLK_OF_DECLARE_DRIVER(exynos5420_clk, "samsung,exynos5420-clock",
+ exynos5420_clk_init);
static void __init exynos5800_clk_init(struct device_node *np)
{
exynos5x_clk_init(np, EXYNOS5800);
}
-CLK_OF_DECLARE(exynos5800_clk, "samsung,exynos5800-clock", exynos5800_clk_init);
+CLK_OF_DECLARE_DRIVER(exynos5800_clk, "samsung,exynos5800-clock",
+ exynos5800_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index db270908037a..5305ace514b2 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -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);
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index 5931a4140c3d..492d51691080 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -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),
{},
};
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 61eb8abbfd9c..ca57b3dfa814 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -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), \
diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c
index e0650c33863b..a9c887475054 100644
--- a/drivers/clk/samsung/clk-s3c2410.c
+++ b/drivers/clk/samsung/clk-s3c2410.c
@@ -95,7 +95,7 @@ static void __init s3c2410_clk_sleep_init(void) {}
PNAME(fclk_p) = { "mpll", "div_slow" };
-struct samsung_mux_clock s3c2410_common_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2410_common_muxes[] __initdata = {
MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1),
};
@@ -111,12 +111,12 @@ static struct clk_div_table divslow_d[] = {
{ /* sentinel */ },
};
-struct samsung_div_clock s3c2410_common_dividers[] __initdata = {
+static struct samsung_div_clock s3c2410_common_dividers[] __initdata = {
DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d),
DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1),
};
-struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
+static struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0),
GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0),
GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0),
@@ -135,7 +135,7 @@ struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
};
/* should be added _after_ the soc-specific clocks are created */
-struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
ALIAS(PCLK_ADC, NULL, "adc"),
ALIAS(PCLK_RTC, NULL, "rtc"),
@@ -162,34 +162,34 @@ struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = {
/* sorted in descending order */
/* 2410A extras */
- PLL_35XX_RATE(270000000, 127, 1, 1),
- PLL_35XX_RATE(268000000, 126, 1, 1),
- PLL_35XX_RATE(266000000, 125, 1, 1),
- PLL_35XX_RATE(226000000, 105, 1, 1),
- PLL_35XX_RATE(210000000, 132, 2, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 270000000, 127, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 268000000, 126, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 266000000, 125, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 226000000, 105, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 210000000, 132, 2, 1),
/* 2410 common */
- PLL_35XX_RATE(203000000, 161, 3, 1),
- PLL_35XX_RATE(192000000, 88, 1, 1),
- PLL_35XX_RATE(186000000, 85, 1, 1),
- PLL_35XX_RATE(180000000, 82, 1, 1),
- PLL_35XX_RATE(170000000, 77, 1, 1),
- PLL_35XX_RATE(158000000, 71, 1, 1),
- PLL_35XX_RATE(152000000, 68, 1, 1),
- PLL_35XX_RATE(147000000, 90, 2, 1),
- PLL_35XX_RATE(135000000, 82, 2, 1),
- PLL_35XX_RATE(124000000, 116, 1, 2),
- PLL_35XX_RATE(118000000, 150, 2, 2),
- PLL_35XX_RATE(113000000, 105, 1, 2),
- PLL_35XX_RATE(101000000, 127, 2, 2),
- PLL_35XX_RATE(90000000, 112, 2, 2),
- PLL_35XX_RATE(85000000, 105, 2, 2),
- PLL_35XX_RATE(79000000, 71, 1, 2),
- PLL_35XX_RATE(68000000, 82, 2, 2),
- PLL_35XX_RATE(56000000, 142, 2, 3),
- PLL_35XX_RATE(48000000, 120, 2, 3),
- PLL_35XX_RATE(51000000, 161, 3, 3),
- PLL_35XX_RATE(45000000, 82, 1, 3),
- PLL_35XX_RATE(34000000, 82, 2, 3),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 202800000, 161, 3, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 192000000, 88, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 186000000, 85, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 180000000, 82, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 170000000, 77, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 158000000, 71, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 152000000, 68, 1, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 147000000, 90, 2, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 135000000, 82, 2, 1),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 124000000, 116, 1, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 118500000, 150, 2, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 113000000, 105, 1, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 101250000, 127, 2, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 90000000, 112, 2, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 84750000, 105, 2, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 79000000, 71, 1, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 67500000, 82, 2, 2),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 56250000, 142, 2, 3),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 48000000, 120, 2, 3),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 50700000, 161, 3, 3),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 45000000, 82, 1, 3),
+ PLL_S3C2410_MPLL_RATE(12 * MHZ, 33750000, 82, 2, 3),
{ /* sentinel */ },
};
@@ -200,11 +200,11 @@ static struct samsung_pll_clock s3c2410_plls[] __initdata = {
LOCKTIME, UPLLCON, NULL),
};
-struct samsung_div_clock s3c2410_dividers[] __initdata = {
+static struct samsung_div_clock s3c2410_dividers[] __initdata = {
DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1),
};
-struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
/*
* armclk is directly supplied by the fclk, without
* switching possibility like on the s3c244x below.
@@ -215,7 +215,7 @@ struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
FFACTOR(UCLK, "uclk", "upll", 1, 1, 0),
};
-struct samsung_clock_alias s3c2410_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2410_aliases[] __initdata = {
ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"),
ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"),
ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"),
@@ -229,33 +229,33 @@ struct samsung_clock_alias s3c2410_aliases[] __initdata = {
static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = {
/* sorted in descending order */
- PLL_35XX_RATE(400000000, 0x5c, 1, 1),
- PLL_35XX_RATE(390000000, 0x7a, 2, 1),
- PLL_35XX_RATE(380000000, 0x57, 1, 1),
- PLL_35XX_RATE(370000000, 0xb1, 4, 1),
- PLL_35XX_RATE(360000000, 0x70, 2, 1),
- PLL_35XX_RATE(350000000, 0xa7, 4, 1),
- PLL_35XX_RATE(340000000, 0x4d, 1, 1),
- PLL_35XX_RATE(330000000, 0x66, 2, 1),
- PLL_35XX_RATE(320000000, 0x98, 4, 1),
- PLL_35XX_RATE(310000000, 0x93, 4, 1),
- PLL_35XX_RATE(300000000, 0x75, 3, 1),
- PLL_35XX_RATE(240000000, 0x70, 1, 2),
- PLL_35XX_RATE(230000000, 0x6b, 1, 2),
- PLL_35XX_RATE(220000000, 0x66, 1, 2),
- PLL_35XX_RATE(210000000, 0x84, 2, 2),
- PLL_35XX_RATE(200000000, 0x5c, 1, 2),
- PLL_35XX_RATE(190000000, 0x57, 1, 2),
- PLL_35XX_RATE(180000000, 0x70, 2, 2),
- PLL_35XX_RATE(170000000, 0x4d, 1, 2),
- PLL_35XX_RATE(160000000, 0x98, 4, 2),
- PLL_35XX_RATE(150000000, 0x75, 3, 2),
- PLL_35XX_RATE(120000000, 0x70, 1, 3),
- PLL_35XX_RATE(110000000, 0x66, 1, 3),
- PLL_35XX_RATE(100000000, 0x5c, 1, 3),
- PLL_35XX_RATE(90000000, 0x70, 2, 3),
- PLL_35XX_RATE(80000000, 0x98, 4, 3),
- PLL_35XX_RATE(75000000, 0x75, 3, 3),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 400000000, 0x5c, 1, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 390000000, 0x7a, 2, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 380000000, 0x57, 1, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 370000000, 0xb1, 4, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 360000000, 0x70, 2, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 350000000, 0xa7, 4, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 340000000, 0x4d, 1, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 330000000, 0x66, 2, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 320000000, 0x98, 4, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 310000000, 0x93, 4, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 300000000, 0x75, 3, 1),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 240000000, 0x70, 1, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 230000000, 0x6b, 1, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 220000000, 0x66, 1, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 210000000, 0x84, 2, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 200000000, 0x5c, 1, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 190000000, 0x57, 1, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 180000000, 0x70, 2, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 170000000, 0x4d, 1, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 160000000, 0x98, 4, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 150000000, 0x75, 3, 2),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 120000000, 0x70, 1, 3),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 110000000, 0x66, 1, 3),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 100000000, 0x5c, 1, 3),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 90000000, 0x70, 2, 3),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 80000000, 0x98, 4, 3),
+ PLL_S3C2440_MPLL_RATE(12 * MHZ, 75000000, 0x75, 3, 3),
{ /* sentinel */ },
};
@@ -269,12 +269,12 @@ static struct samsung_pll_clock s3c244x_common_plls[] __initdata = {
PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" };
PNAME(armclk_p) = { "fclk", "hclk" };
-struct samsung_mux_clock s3c244x_common_muxes[] __initdata = {
+static struct samsung_mux_clock s3c244x_common_muxes[] __initdata = {
MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2),
MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1),
};
-struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = {
FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0),
FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT),
};
@@ -291,7 +291,7 @@ static struct clk_div_table div_hclk_3_d[] = {
{ /* sentinel */ },
};
-struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
+static struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1),
DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1),
DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d),
@@ -299,11 +299,11 @@ struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
DIV(0, "div_cam", "upll", CAMDIVN, 0, 3),
};
-struct samsung_gate_clock s3c244x_common_gates[] __initdata = {
+static struct samsung_gate_clock s3c244x_common_gates[] __initdata = {
GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0),
};
-struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
+static struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
@@ -318,23 +318,23 @@ struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
PNAME(s3c2440_camif_p) = { "upll", "ff_cam" };
-struct samsung_mux_clock s3c2440_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2440_muxes[] __initdata = {
MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1),
};
-struct samsung_gate_clock s3c2440_gates[] __initdata = {
+static struct samsung_gate_clock s3c2440_gates[] __initdata = {
GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0),
};
/* S3C2442 specific clocks */
-struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = {
FFACTOR(0, "upll_3", "upll", 1, 3, 0),
};
PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" };
-struct samsung_mux_clock s3c2442_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2442_muxes[] __initdata = {
MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2),
};
@@ -343,7 +343,7 @@ struct samsung_mux_clock s3c2442_muxes[] __initdata = {
* Only necessary until the devicetree-move is complete
*/
#define XTI 1
-struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
FRATE(XTI, "xti", NULL, 0, 0),
};
@@ -468,18 +468,18 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
static void __init s3c2410_clk_init(struct device_node *np)
{
- s3c2410_common_clk_init(np, 0, S3C2410, 0);
+ s3c2410_common_clk_init(np, 0, S3C2410, NULL);
}
CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init);
static void __init s3c2440_clk_init(struct device_node *np)
{
- s3c2410_common_clk_init(np, 0, S3C2440, 0);
+ s3c2410_common_clk_init(np, 0, S3C2440, NULL);
}
CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init);
static void __init s3c2442_clk_init(struct device_node *np)
{
- s3c2410_common_clk_init(np, 0, S3C2442, 0);
+ s3c2410_common_clk_init(np, 0, S3C2442, NULL);
}
CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
index b8340a49921b..6bc94d3aff78 100644
--- a/drivers/clk/samsung/clk-s3c2412.c
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -27,11 +27,6 @@
#define CLKSRC 0x1c
#define SWRST 0x30
-/* list of PLLs to be registered */
-enum s3c2412_plls {
- mpll, upll,
-};
-
static void __iomem *reg_base;
#ifdef CONFIG_PM_SLEEP
@@ -98,7 +93,7 @@ static struct clk_div_table divxti_d[] = {
{ /* sentinel */ },
};
-struct samsung_div_clock s3c2412_dividers[] __initdata = {
+static struct samsung_div_clock s3c2412_dividers[] __initdata = {
DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d),
DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4),
DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4),
@@ -110,7 +105,7 @@ struct samsung_div_clock s3c2412_dividers[] __initdata = {
DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2),
};
-struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT),
};
@@ -130,7 +125,7 @@ PNAME(msysclk_p) = { "mdivclk", "mpll" };
PNAME(mdivclk_p) = { "xti", "div_xti" };
PNAME(armclk_p) = { "armdiv", "hclk" };
-struct samsung_mux_clock s3c2412_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2412_muxes[] __initdata = {
MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2),
MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2),
MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1),
@@ -144,13 +139,11 @@ struct samsung_mux_clock s3c2412_muxes[] __initdata = {
};
static struct samsung_pll_clock s3c2412_plls[] __initdata = {
- [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
- LOCKTIME, MPLLCON, NULL),
- [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk",
- LOCKTIME, UPLLCON, NULL),
+ PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", LOCKTIME, MPLLCON, NULL),
+ PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", LOCKTIME, UPLLCON, NULL),
};
-struct samsung_gate_clock s3c2412_gates[] __initdata = {
+static struct samsung_gate_clock s3c2412_gates[] __initdata = {
GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0),
GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0),
GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0),
@@ -181,7 +174,7 @@ struct samsung_gate_clock s3c2412_gates[] __initdata = {
GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0),
};
-struct samsung_clock_alias s3c2412_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2412_aliases[] __initdata = {
ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"),
ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"),
ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"),
@@ -231,7 +224,7 @@ static struct notifier_block s3c2412_restart_handler = {
* Only necessary until the devicetree-move is complete
*/
#define XTI 1
-struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
FRATE(XTI, "xti", NULL, 0, 0),
FRATE(0, "ext", NULL, 0, 0),
};
@@ -296,6 +289,6 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
static void __init s3c2412_clk_init(struct device_node *np)
{
- s3c2412_common_clk_init(np, 0, 0, 0);
+ s3c2412_common_clk_init(np, 0, 0, NULL);
}
CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
index d94b85a42356..c46e6d5bc9bc 100644
--- a/drivers/clk/samsung/clk-s3c2443.c
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -41,11 +41,6 @@ enum supported_socs {
S3C2450,
};
-/* list of PLLs to be registered */
-enum s3c2443_plls {
- mpll, epll,
-};
-
static void __iomem *reg_base;
#ifdef CONFIG_PM_SLEEP
@@ -113,7 +108,7 @@ PNAME(msysclk_p) = { "mpllref", "mpll" };
PNAME(armclk_p) = { "armdiv" , "hclk" };
PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" };
-struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
MUX(0, "epllref", epllref_p, CLKSRC, 7, 2),
MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1),
MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1),
@@ -141,7 +136,7 @@ static struct clk_div_table mdivclk_d[] = {
{ /* sentinel */ },
};
-struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
+static struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d),
DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2),
DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d),
@@ -154,7 +149,7 @@ struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2),
};
-struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
+static struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0),
GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0),
GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0),
@@ -188,7 +183,7 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0),
};
-struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
ALIAS(MSYSCLK, NULL, "msysclk"),
ALIAS(ARMCLK, NULL, "armclk"),
ALIAS(MPLL, NULL, "mpll"),
@@ -225,10 +220,8 @@ struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
/* S3C2416 specific clocks */
static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = {
- [mpll] = PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref",
- LOCKCON0, MPLLCON, NULL),
- [epll] = PLL(pll_6553, EPLL, "epll", "epllref",
- LOCKCON1, EPLLCON, NULL),
+ PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL),
+ PLL(pll_6553, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL),
};
PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" };
@@ -245,19 +238,19 @@ static struct clk_div_table armdiv_s3c2416_d[] = {
{ /* sentinel */ },
};
-struct samsung_div_clock s3c2416_dividers[] __initdata = {
+static struct samsung_div_clock s3c2416_dividers[] __initdata = {
DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d),
DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4),
DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2),
};
-struct samsung_mux_clock s3c2416_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2416_muxes[] __initdata = {
MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1),
MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1),
MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1),
};
-struct samsung_gate_clock s3c2416_gates[] __initdata = {
+static struct samsung_gate_clock s3c2416_gates[] __initdata = {
GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0),
GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0),
@@ -267,7 +260,7 @@ struct samsung_gate_clock s3c2416_gates[] __initdata = {
GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0),
};
-struct samsung_clock_alias s3c2416_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2416_aliases[] __initdata = {
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"),
@@ -279,10 +272,8 @@ struct samsung_clock_alias s3c2416_aliases[] __initdata = {
/* S3C2443 specific clocks */
static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = {
- [mpll] = PLL(pll_3000, MPLL, "mpll", "mpllref",
- LOCKCON0, MPLLCON, NULL),
- [epll] = PLL(pll_2126, EPLL, "epll", "epllref",
- LOCKCON1, EPLLCON, NULL),
+ PLL(pll_3000, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL),
+ PLL(pll_2126, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL),
};
static struct clk_div_table armdiv_s3c2443_d[] = {
@@ -297,12 +288,12 @@ static struct clk_div_table armdiv_s3c2443_d[] = {
{ /* sentinel */ },
};
-struct samsung_div_clock s3c2443_dividers[] __initdata = {
+static struct samsung_div_clock s3c2443_dividers[] __initdata = {
DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d),
DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
};
-struct samsung_gate_clock s3c2443_gates[] __initdata = {
+static struct samsung_gate_clock s3c2443_gates[] __initdata = {
GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0),
GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0),
@@ -311,7 +302,7 @@ struct samsung_gate_clock s3c2443_gates[] __initdata = {
GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0),
};
-struct samsung_clock_alias s3c2443_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2443_aliases[] __initdata = {
ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
ALIAS(SCLK_CAM, NULL, "camif-upll"),
@@ -327,20 +318,20 @@ PNAME(s3c2450_cam_p) = { "div_cam", "hclk" };
PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" };
PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" };
-struct samsung_div_clock s3c2450_dividers[] __initdata = {
+static struct samsung_div_clock s3c2450_dividers[] __initdata = {
DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2),
DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4),
DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4),
};
-struct samsung_mux_clock s3c2450_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2450_muxes[] __initdata = {
MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1),
MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1),
MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2),
};
-struct samsung_gate_clock s3c2450_gates[] __initdata = {
+static struct samsung_gate_clock s3c2450_gates[] __initdata = {
GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0),
GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0),
GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
@@ -351,7 +342,7 @@ struct samsung_gate_clock s3c2450_gates[] __initdata = {
GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0),
};
-struct samsung_clock_alias s3c2450_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2450_aliases[] __initdata = {
ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"),
ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"),
ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"),
@@ -374,7 +365,7 @@ static struct notifier_block s3c2443_restart_handler = {
* fixed rate clocks generated outside the soc
* Only necessary until the devicetree-move is complete
*/
-struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
FRATE(0, "xti", NULL, 0, 0),
FRATE(0, "ext", NULL, 0, 0),
FRATE(0, "ext_i2s", NULL, 0, 0),
@@ -470,18 +461,18 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
static void __init s3c2416_clk_init(struct device_node *np)
{
- s3c2443_common_clk_init(np, 0, S3C2416, 0);
+ s3c2443_common_clk_init(np, 0, S3C2416, NULL);
}
CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init);
static void __init s3c2443_clk_init(struct device_node *np)
{
- s3c2443_common_clk_init(np, 0, S3C2443, 0);
+ s3c2443_common_clk_init(np, 0, S3C2443, NULL);
}
CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init);
static void __init s3c2450_clk_init(struct device_node *np)
{
- s3c2443_common_clk_init(np, 0, S3C2450, 0);
+ s3c2443_common_clk_init(np, 0, S3C2450, NULL);
}
CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 7306867a0ab8..6db01cf5ab83 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -56,11 +56,6 @@
#define GATE_ON(_id, cname, pname, o, b) \
GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
-/* list of PLLs to be registered */
-enum s3c64xx_plls {
- apll, mpll, epll,
-};
-
static void __iomem *reg_base;
static bool is_s3c6400;
@@ -364,12 +359,12 @@ GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
/* List of PLL clocks. */
static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = {
- [apll] = PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll",
- APLL_LOCK, APLL_CON, NULL),
- [mpll] = PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll",
- MPLL_LOCK, MPLL_CON, NULL),
- [epll] = PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll",
- EPLL_LOCK, EPLL_CON0, NULL),
+ PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON, NULL),
+ PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON, NULL),
+ PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, NULL),
};
/* Aliases for common s3c64xx clocks. */
diff --git a/drivers/clk/sprd/sc9860-clk.c b/drivers/clk/sprd/sc9860-clk.c
index ed5c027df0f4..9980ab55271b 100644
--- a/drivers/clk/sprd/sc9860-clk.c
+++ b/drivers/clk/sprd/sc9860-clk.c
@@ -959,6 +959,44 @@ static SPRD_SC_GATE_CLK(sdio2_2x_en, "sdio2-2x-en", "aon-apb", 0x13c,
0x1000, BIT(6), 0, 0);
static SPRD_SC_GATE_CLK(emmc_2x_en, "emmc-2x-en", "aon-apb", 0x13c,
0x1000, BIT(9), 0, 0);
+static SPRD_SC_GATE_CLK(arch_rtc_eb, "arch-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(kpb_rtc_eb, "kpb-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_syst_rtc_eb, "aon-syst-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_syst_rtc_eb, "ap-syst-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_tmr_rtc_eb, "aon-tmr-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr0_rtc_eb, "ap-tmr0-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(eic_rtc_eb, "eic-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(eic_rtcdv5_eb, "eic-rtcdv5-eb", "aon-apb", 0x10,
+ 0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_wdg_rtc_eb, "ap-wdg-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr1_rtc_eb, "ap-tmr1-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr2_rtc_eb, "ap-tmr2-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dcxo_tmr_rtc_eb, "dcxo-tmr-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(bb_cal_rtc_eb, "bb-cal-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_big_rtc_eb, "avs-big-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_lit_rtc_eb, "avs-lit-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(21), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_gpu0_rtc_eb, "avs-gpu0-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_gpu1_rtc_eb, "avs-gpu1-rtc-eb", "aon-apb", 0x10,
+ 0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu_ts_eb, "gpu-ts-eb", "aon-apb", 0x10,
+ 0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rtcdv10_eb, "rtcdv10-eb", "aon-apb", 0x10,
+ 0x1000, BIT(27), CLK_IGNORE_UNUSED, 0);
static struct sprd_clk_common *sc9860_aon_gate[] = {
/* address base is 0x402e0000 */
@@ -1030,6 +1068,25 @@ static struct sprd_clk_common *sc9860_aon_gate[] = {
&sdio1_2x_en.common,
&sdio2_2x_en.common,
&emmc_2x_en.common,
+ &arch_rtc_eb.common,
+ &kpb_rtc_eb.common,
+ &aon_syst_rtc_eb.common,
+ &ap_syst_rtc_eb.common,
+ &aon_tmr_rtc_eb.common,
+ &ap_tmr0_rtc_eb.common,
+ &eic_rtc_eb.common,
+ &eic_rtcdv5_eb.common,
+ &ap_wdg_rtc_eb.common,
+ &ap_tmr1_rtc_eb.common,
+ &ap_tmr2_rtc_eb.common,
+ &dcxo_tmr_rtc_eb.common,
+ &bb_cal_rtc_eb.common,
+ &avs_big_rtc_eb.common,
+ &avs_lit_rtc_eb.common,
+ &avs_gpu0_rtc_eb.common,
+ &avs_gpu1_rtc_eb.common,
+ &gpu_ts_eb.common,
+ &rtcdv10_eb.common,
};
static struct clk_hw_onecell_data sc9860_aon_gate_hws = {
@@ -1102,6 +1159,25 @@ static struct clk_hw_onecell_data sc9860_aon_gate_hws = {
[CLK_SDIO1_2X_EN] = &sdio1_2x_en.common.hw,
[CLK_SDIO2_2X_EN] = &sdio2_2x_en.common.hw,
[CLK_EMMC_2X_EN] = &emmc_2x_en.common.hw,
+ [CLK_ARCH_RTC_EB] = &arch_rtc_eb.common.hw,
+ [CLK_KPB_RTC_EB] = &kpb_rtc_eb.common.hw,
+ [CLK_AON_SYST_RTC_EB] = &aon_syst_rtc_eb.common.hw,
+ [CLK_AP_SYST_RTC_EB] = &ap_syst_rtc_eb.common.hw,
+ [CLK_AON_TMR_RTC_EB] = &aon_tmr_rtc_eb.common.hw,
+ [CLK_AP_TMR0_RTC_EB] = &ap_tmr0_rtc_eb.common.hw,
+ [CLK_EIC_RTC_EB] = &eic_rtc_eb.common.hw,
+ [CLK_EIC_RTCDV5_EB] = &eic_rtcdv5_eb.common.hw,
+ [CLK_AP_WDG_RTC_EB] = &ap_wdg_rtc_eb.common.hw,
+ [CLK_AP_TMR1_RTC_EB] = &ap_tmr1_rtc_eb.common.hw,
+ [CLK_AP_TMR2_RTC_EB] = &ap_tmr2_rtc_eb.common.hw,
+ [CLK_DCXO_TMR_RTC_EB] = &dcxo_tmr_rtc_eb.common.hw,
+ [CLK_BB_CAL_RTC_EB] = &bb_cal_rtc_eb.common.hw,
+ [CLK_AVS_BIG_RTC_EB] = &avs_big_rtc_eb.common.hw,
+ [CLK_AVS_LIT_RTC_EB] = &avs_lit_rtc_eb.common.hw,
+ [CLK_AVS_GPU0_RTC_EB] = &avs_gpu0_rtc_eb.common.hw,
+ [CLK_AVS_GPU1_RTC_EB] = &avs_gpu1_rtc_eb.common.hw,
+ [CLK_GPU_TS_EB] = &gpu_ts_eb.common.hw,
+ [CLK_RTCDV10_EB] = &rtcdv10_eb.common.hw,
},
.num = CLK_AON_GATE_NUM,
};
diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c
index 11a5066e5c27..5234acd30e89 100644
--- a/drivers/clk/tegra/clk-emc.c
+++ b/drivers/clk/tegra/clk-emc.c
@@ -515,7 +515,7 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
init.name = "emc";
init.ops = &tegra_clk_emc_ops;
- init.flags = 0;
+ init.flags = CLK_IS_CRITICAL;
init.parent_names = emc_parent_clk_names;
init.num_parents = ARRAY_SIZE(emc_parent_clk_names);
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 7c369e21c91c..830d1c87fa7c 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -1151,6 +1151,8 @@ static const struct clk_ops tegra_clk_pllu_ops = {
.enable = clk_pllu_enable,
.disable = clk_pll_disable,
.recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_round_rate,
+ .set_rate = clk_pll_set_rate,
};
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index c02711927d79..2acba2986bc6 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -830,7 +830,7 @@ static struct tegra_periph_init_data gate_clks[] = {
GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0),
GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0),
GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
- GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
+ GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IS_CRITICAL),
GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
GATE("ispa", "isp", 23, 0, tegra_clk_ispa, 0),
GATE("ispb", "isp", 3, 0, tegra_clk_ispb, 0),
diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c
index 10047107c1dc..89d6b47a27a8 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -125,7 +125,8 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
/* SCLK */
dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
if (dt_clk) {
- clk = clk_register_divider(NULL, "sclk", "sclk_mux", 0,
+ clk = clk_register_divider(NULL, "sclk", "sclk_mux",
+ CLK_IS_CRITICAL,
clk_base + SCLK_DIVIDER, 0, 8,
0, &sysrate_lock);
*dt_clk = clk;
@@ -137,7 +138,8 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
clk = tegra_clk_register_super_mux("sclk",
gen_info->sclk_parents,
gen_info->num_sclk_parents,
- CLK_SET_RATE_PARENT,
+ CLK_SET_RATE_PARENT |
+ CLK_IS_CRITICAL,
clk_base + SCLK_BURST_POLICY,
0, 4, 0, 0, NULL);
*dt_clk = clk;
@@ -151,7 +153,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
&sysrate_lock);
clk = clk_register_gate(NULL, "hclk", "hclk_div",
- CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
clk_base + SYSTEM_CLK_RATE,
7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
*dt_clk = clk;
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 63087d17c3e2..5d5a22d529f5 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -955,8 +955,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
/* PLLM */
clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
- &pll_m_params, NULL);
+ CLK_SET_RATE_GATE, &pll_m_params, NULL);
clks[TEGRA114_CLK_PLL_M] = clk;
/* PLLM_OUT1 */
@@ -1190,6 +1189,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0 },
{ TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0 },
{ TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0 },
+ { TEGRA114_CLK_VDE, TEGRA114_CLK_CLK_MAX, 600000000, 0 },
/* must be the last entry */
{ TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0 },
};
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index e81ea5b11577..50088e976611 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1089,8 +1089,7 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
/* PLLM */
clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
- &pll_m_params, NULL);
+ CLK_SET_RATE_GATE, &pll_m_params, NULL);
clk_register_clkdev(clk, "pll_m", NULL);
clks[TEGRA124_CLK_PLL_M] = clk;
@@ -1099,7 +1098,7 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
8, 8, 1, NULL);
clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
- clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+ clk_base + PLLM_OUT, 1, 0,
CLK_SET_RATE_PARENT, 0, NULL);
clk_register_clkdev(clk, "pll_m_out1", NULL);
clks[TEGRA124_CLK_PLL_M_OUT1] = clk;
@@ -1268,11 +1267,11 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
{ TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
- { TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0 },
+ { TEGRA124_CLK_VDE, TEGRA124_CLK_CLK_MAX, 600000000, 0 },
{ TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1 },
{ TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0 },
{ TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0 },
- { TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1 },
+ { TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 0 },
{ TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1 },
{ TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1 },
{ TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0 },
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index cbd5a2e5c569..0ee56dd04cec 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -576,6 +576,7 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
[tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true },
[tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true },
[tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true },
+ [tegra_clk_emc] = { .dt_id = TEGRA20_CLK_EMC, .present = true },
};
static unsigned long tegra20_clk_measure_input_freq(void)
@@ -651,8 +652,7 @@ static void tegra20_pll_init(void)
/* PLLM */
clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
- &pll_m_params, NULL);
+ CLK_SET_RATE_GATE, &pll_m_params, NULL);
clks[TEGRA20_CLK_PLL_M] = clk;
/* PLLM_OUT1 */
@@ -660,7 +660,7 @@ static void tegra20_pll_init(void)
clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
8, 8, 1, NULL);
clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
- clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+ clk_base + PLLM_OUT, 1, 0,
CLK_SET_RATE_PARENT, 0, NULL);
clks[TEGRA20_CLK_PLL_M_OUT1] = clk;
@@ -723,7 +723,8 @@ static void tegra20_super_clk_init(void)
/* SCLK */
clk = tegra_clk_register_super_mux("sclk", sclk_parents,
- ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT,
+ ARRAY_SIZE(sclk_parents),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
clks[TEGRA20_CLK_SCLK] = clk;
@@ -814,9 +815,6 @@ static void __init tegra20_periph_clk_init(void)
CLK_SET_RATE_NO_REPARENT,
clk_base + CLK_SOURCE_EMC,
30, 2, 0, &emc_lock);
- clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
- 57, periph_clk_enb_refcnt);
- clks[TEGRA20_CLK_EMC] = clk;
clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
&emc_lock);
@@ -1019,13 +1017,12 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1 },
{ TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 },
{ TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 },
- { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1 },
- { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 216000000, 1 },
- { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1 },
- { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1 },
- { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1 },
+ { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 0 },
+ { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 240000000, 0 },
+ { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 240000000, 0 },
+ { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 240000000, 0 },
+ { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 0 },
{ TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 },
- { TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1 },
{ TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 },
{ TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0 },
{ TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0 },
@@ -1051,6 +1048,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0 },
{ TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 },
{ TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 },
+ { TEGRA20_CLK_VDE, TEGRA20_CLK_CLK_MAX, 300000000, 0 },
/* must be the last entry */
{ TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 },
};
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 9e6260869eb9..9fb5d51ccce4 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -22,10 +22,12 @@
#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/export.h>
+#include <linux/mutex.h>
#include <linux/clk/tegra.h>
#include <dt-bindings/clock/tegra210-car.h>
#include <dt-bindings/reset/tegra210-car.h>
#include <linux/iopoll.h>
+#include <soc/tegra/pmc.h>
#include "clk.h"
#include "clk-id.h"
@@ -41,6 +43,7 @@
#define CLK_SOURCE_CSITE 0x1d4
#define CLK_SOURCE_EMC 0x19c
#define CLK_SOURCE_SOR1 0x410
+#define CLK_SOURCE_LA 0x1f8
#define PLLC_BASE 0x80
#define PLLC_OUT 0x84
@@ -231,6 +234,30 @@
#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
+#define LVL2_CLK_GATE_OVRA 0xf8
+#define LVL2_CLK_GATE_OVRC 0x3a0
+#define LVL2_CLK_GATE_OVRD 0x3a4
+#define LVL2_CLK_GATE_OVRE 0x554
+
+/* I2S registers to handle during APE MBIST WAR */
+#define TEGRA210_I2S_BASE 0x1000
+#define TEGRA210_I2S_SIZE 0x100
+#define TEGRA210_I2S_CTRLS 5
+#define TEGRA210_I2S_CG 0x88
+#define TEGRA210_I2S_CTRL 0xa0
+
+/* DISPA registers to handle during MBIST WAR */
+#define DC_CMD_DISPLAY_COMMAND 0xc8
+#define DC_COM_DSC_TOP_CTL 0xcf8
+
+/* VIC register to handle during MBIST WAR */
+#define NV_PVIC_THI_SLCG_OVERRIDE_LOW 0x8c
+
+/* APE, DISPA and VIC base addesses needed for MBIST WAR */
+#define TEGRA210_AHUB_BASE 0x702d0000
+#define TEGRA210_DISPA_BASE 0x54200000
+#define TEGRA210_VIC_BASE 0x54340000
+
/*
* SDM fractional divisor is 16-bit 2's complement signed number within
* (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned
@@ -255,8 +282,22 @@ static struct cpu_clk_suspend_context {
} tegra210_cpu_clk_sctx;
#endif
+struct tegra210_domain_mbist_war {
+ void (*handle_lvl2_ovr)(struct tegra210_domain_mbist_war *mbist);
+ const u32 lvl2_offset;
+ const u32 lvl2_mask;
+ const unsigned int num_clks;
+ const unsigned int *clk_init_data;
+ struct clk_bulk_data *clks;
+};
+
+static struct clk **clks;
+
static void __iomem *clk_base;
static void __iomem *pmc_base;
+static void __iomem *ahub_base;
+static void __iomem *dispa_base;
+static void __iomem *vic_base;
static unsigned long osc_freq;
static unsigned long pll_ref_freq;
@@ -267,6 +308,7 @@ static DEFINE_SPINLOCK(pll_re_lock);
static DEFINE_SPINLOCK(pll_u_lock);
static DEFINE_SPINLOCK(sor1_lock);
static DEFINE_SPINLOCK(emc_lock);
+static DEFINE_MUTEX(lvl2_ovr_lock);
/* possible OSC frequencies in Hz */
static unsigned long tegra210_input_freq[] = {
@@ -310,6 +352,8 @@ static const char *mux_pllmcp_clkm[] = {
#define PLLA_MISC2_WRITE_MASK 0x06ffffff
/* PLLD */
+#define PLLD_BASE_CSI_CLKSOURCE (1 << 23)
+
#define PLLD_MISC0_EN_SDM (1 << 16)
#define PLLD_MISC0_LOCK_OVERRIDE (1 << 17)
#define PLLD_MISC0_LOCK_ENABLE (1 << 18)
@@ -513,6 +557,115 @@ void tegra210_set_sata_pll_seq_sw(bool state)
}
EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw);
+static void tegra210_generic_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+ u32 val;
+
+ val = readl_relaxed(clk_base + mbist->lvl2_offset);
+ writel_relaxed(val | mbist->lvl2_mask, clk_base + mbist->lvl2_offset);
+ fence_udelay(1, clk_base);
+ writel_relaxed(val, clk_base + mbist->lvl2_offset);
+ fence_udelay(1, clk_base);
+}
+
+static void tegra210_venc_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+ u32 csi_src, ovra, ovre;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&pll_d_lock, flags);
+
+ csi_src = readl_relaxed(clk_base + PLLD_BASE);
+ writel_relaxed(csi_src | PLLD_BASE_CSI_CLKSOURCE, clk_base + PLLD_BASE);
+ fence_udelay(1, clk_base);
+
+ ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA);
+ writel_relaxed(ovra | BIT(15), clk_base + LVL2_CLK_GATE_OVRA);
+ ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE);
+ writel_relaxed(ovre | BIT(3), clk_base + LVL2_CLK_GATE_OVRE);
+ fence_udelay(1, clk_base);
+
+ writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA);
+ writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE);
+ writel_relaxed(csi_src, clk_base + PLLD_BASE);
+ fence_udelay(1, clk_base);
+
+ spin_unlock_irqrestore(&pll_d_lock, flags);
+}
+
+static void tegra210_disp_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+ u32 ovra, dsc_top_ctrl;
+
+ ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA);
+ writel_relaxed(ovra | BIT(1), clk_base + LVL2_CLK_GATE_OVRA);
+ fence_udelay(1, clk_base);
+
+ dsc_top_ctrl = readl_relaxed(dispa_base + DC_COM_DSC_TOP_CTL);
+ writel_relaxed(dsc_top_ctrl | BIT(2), dispa_base + DC_COM_DSC_TOP_CTL);
+ readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND);
+ writel_relaxed(dsc_top_ctrl, dispa_base + DC_COM_DSC_TOP_CTL);
+ readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND);
+
+ writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA);
+ fence_udelay(1, clk_base);
+}
+
+static void tegra210_vic_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+ u32 ovre, val;
+
+ ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE);
+ writel_relaxed(ovre | BIT(5), clk_base + LVL2_CLK_GATE_OVRE);
+ fence_udelay(1, clk_base);
+
+ val = readl_relaxed(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+ writel_relaxed(val | BIT(0) | GENMASK(7, 2) | BIT(24),
+ vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+ fence_udelay(1, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+
+ writel_relaxed(val, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+ readl(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+
+ writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE);
+ fence_udelay(1, clk_base);
+}
+
+static void tegra210_ape_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+ void __iomem *i2s_base;
+ unsigned int i;
+ u32 ovrc, ovre;
+
+ ovrc = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRC);
+ ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE);
+ writel_relaxed(ovrc | BIT(1), clk_base + LVL2_CLK_GATE_OVRC);
+ writel_relaxed(ovre | BIT(10) | BIT(11),
+ clk_base + LVL2_CLK_GATE_OVRE);
+ fence_udelay(1, clk_base);
+
+ i2s_base = ahub_base + TEGRA210_I2S_BASE;
+
+ for (i = 0; i < TEGRA210_I2S_CTRLS; i++) {
+ u32 i2s_ctrl;
+
+ i2s_ctrl = readl_relaxed(i2s_base + TEGRA210_I2S_CTRL);
+ writel_relaxed(i2s_ctrl | BIT(10),
+ i2s_base + TEGRA210_I2S_CTRL);
+ writel_relaxed(0, i2s_base + TEGRA210_I2S_CG);
+ readl(i2s_base + TEGRA210_I2S_CG);
+ writel_relaxed(1, i2s_base + TEGRA210_I2S_CG);
+ writel_relaxed(i2s_ctrl, i2s_base + TEGRA210_I2S_CTRL);
+ readl(i2s_base + TEGRA210_I2S_CTRL);
+
+ i2s_base += TEGRA210_I2S_SIZE;
+ }
+
+ writel_relaxed(ovrc, clk_base + LVL2_CLK_GATE_OVRC);
+ writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE);
+ fence_udelay(1, clk_base);
+}
+
static inline void _pll_misc_chk_default(void __iomem *base,
struct tegra_clk_pll_params *params,
u8 misc_num, u32 default_val, u32 mask)
@@ -2411,13 +2564,150 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = {
{ "pll_a1", &pll_a1_params, tegra_clk_pll_a1, "pll_ref" },
};
-static struct clk **clks;
-
static const char * const aclk_parents[] = {
"pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3",
"clk_m"
};
+static const unsigned int nvjpg_slcg_clkids[] = { TEGRA210_CLK_NVDEC };
+static const unsigned int nvdec_slcg_clkids[] = { TEGRA210_CLK_NVJPG };
+static const unsigned int sor_slcg_clkids[] = { TEGRA210_CLK_HDA2CODEC_2X,
+ TEGRA210_CLK_HDA2HDMI, TEGRA210_CLK_DISP1, TEGRA210_CLK_DISP2 };
+static const unsigned int disp_slcg_clkids[] = { TEGRA210_CLK_LA,
+ TEGRA210_CLK_HOST1X};
+static const unsigned int xusba_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST,
+ TEGRA210_CLK_XUSB_DEV };
+static const unsigned int xusbb_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST,
+ TEGRA210_CLK_XUSB_SS };
+static const unsigned int xusbc_slcg_clkids[] = { TEGRA210_CLK_XUSB_DEV,
+ TEGRA210_CLK_XUSB_SS };
+static const unsigned int venc_slcg_clkids[] = { TEGRA210_CLK_HOST1X,
+ TEGRA210_CLK_PLL_D };
+static const unsigned int ape_slcg_clkids[] = { TEGRA210_CLK_ACLK,
+ TEGRA210_CLK_I2S0, TEGRA210_CLK_I2S1, TEGRA210_CLK_I2S2,
+ TEGRA210_CLK_I2S3, TEGRA210_CLK_I2S4, TEGRA210_CLK_SPDIF_OUT,
+ TEGRA210_CLK_D_AUDIO };
+static const unsigned int vic_slcg_clkids[] = { TEGRA210_CLK_HOST1X };
+
+static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = {
+ [TEGRA_POWERGATE_VENC] = {
+ .handle_lvl2_ovr = tegra210_venc_mbist_war,
+ .num_clks = ARRAY_SIZE(venc_slcg_clkids),
+ .clk_init_data = venc_slcg_clkids,
+ },
+ [TEGRA_POWERGATE_SATA] = {
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRC,
+ .lvl2_mask = BIT(0) | BIT(17) | BIT(19),
+ },
+ [TEGRA_POWERGATE_MPE] = {
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRE,
+ .lvl2_mask = BIT(2),
+ },
+ [TEGRA_POWERGATE_SOR] = {
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .num_clks = ARRAY_SIZE(sor_slcg_clkids),
+ .clk_init_data = sor_slcg_clkids,
+ .lvl2_offset = LVL2_CLK_GATE_OVRA,
+ .lvl2_mask = BIT(1) | BIT(2),
+ },
+ [TEGRA_POWERGATE_DIS] = {
+ .handle_lvl2_ovr = tegra210_disp_mbist_war,
+ .num_clks = ARRAY_SIZE(disp_slcg_clkids),
+ .clk_init_data = disp_slcg_clkids,
+ },
+ [TEGRA_POWERGATE_DISB] = {
+ .num_clks = ARRAY_SIZE(disp_slcg_clkids),
+ .clk_init_data = disp_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRA,
+ .lvl2_mask = BIT(2),
+ },
+ [TEGRA_POWERGATE_XUSBA] = {
+ .num_clks = ARRAY_SIZE(xusba_slcg_clkids),
+ .clk_init_data = xusba_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRC,
+ .lvl2_mask = BIT(30) | BIT(31),
+ },
+ [TEGRA_POWERGATE_XUSBB] = {
+ .num_clks = ARRAY_SIZE(xusbb_slcg_clkids),
+ .clk_init_data = xusbb_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRC,
+ .lvl2_mask = BIT(30) | BIT(31),
+ },
+ [TEGRA_POWERGATE_XUSBC] = {
+ .num_clks = ARRAY_SIZE(xusbc_slcg_clkids),
+ .clk_init_data = xusbc_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRC,
+ .lvl2_mask = BIT(30) | BIT(31),
+ },
+ [TEGRA_POWERGATE_VIC] = {
+ .num_clks = ARRAY_SIZE(vic_slcg_clkids),
+ .clk_init_data = vic_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_vic_mbist_war,
+ },
+ [TEGRA_POWERGATE_NVDEC] = {
+ .num_clks = ARRAY_SIZE(nvdec_slcg_clkids),
+ .clk_init_data = nvdec_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRC,
+ .lvl2_mask = BIT(9) | BIT(31),
+ },
+ [TEGRA_POWERGATE_NVJPG] = {
+ .num_clks = ARRAY_SIZE(nvjpg_slcg_clkids),
+ .clk_init_data = nvjpg_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRC,
+ .lvl2_mask = BIT(9) | BIT(31),
+ },
+ [TEGRA_POWERGATE_AUD] = {
+ .num_clks = ARRAY_SIZE(ape_slcg_clkids),
+ .clk_init_data = ape_slcg_clkids,
+ .handle_lvl2_ovr = tegra210_ape_mbist_war,
+ },
+ [TEGRA_POWERGATE_VE2] = {
+ .handle_lvl2_ovr = tegra210_generic_mbist_war,
+ .lvl2_offset = LVL2_CLK_GATE_OVRD,
+ .lvl2_mask = BIT(22),
+ },
+};
+
+int tegra210_clk_handle_mbist_war(unsigned int id)
+{
+ int err;
+ struct tegra210_domain_mbist_war *mbist_war;
+
+ if (id >= ARRAY_SIZE(tegra210_pg_mbist_war)) {
+ WARN(1, "unknown domain id in MBIST WAR handler\n");
+ return -EINVAL;
+ }
+
+ mbist_war = &tegra210_pg_mbist_war[id];
+ if (!mbist_war->handle_lvl2_ovr)
+ return 0;
+
+ if (mbist_war->num_clks && !mbist_war->clks)
+ return -ENODEV;
+
+ err = clk_bulk_prepare_enable(mbist_war->num_clks, mbist_war->clks);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&lvl2_ovr_lock);
+
+ mbist_war->handle_lvl2_ovr(mbist_war);
+
+ mutex_unlock(&lvl2_ovr_lock);
+
+ clk_bulk_disable_unprepare(mbist_war->num_clks, mbist_war->clks);
+
+ return 0;
+}
+
void tegra210_put_utmipll_in_iddq(void)
{
u32 reg;
@@ -2654,6 +2944,13 @@ static struct tegra_periph_init_data tegra210_periph[] = {
sor1_parents_idx, 0, &sor1_lock),
};
+static const char * const la_parents[] = {
+ "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_re_out1", "pll_a1", "clk_m", "pll_c4_out0"
+};
+
+static struct tegra_clk_periph tegra210_la =
+ TEGRA_CLK_PERIPH(29, 7, 9, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, 76, 0, NULL, 0);
+
static __init void tegra210_periph_clk_init(void __iomem *clk_base,
void __iomem *pmc_base)
{
@@ -2700,6 +2997,12 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
periph_clk_enb_refcnt);
clks[TEGRA210_CLK_DSIB] = clk;
+ /* la */
+ clk = tegra_clk_register_periph("la", la_parents,
+ ARRAY_SIZE(la_parents), &tegra210_la, clk_base,
+ CLK_SOURCE_LA, 0);
+ clks[TEGRA210_CLK_LA] = clk;
+
/* emc mux */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm), 0,
@@ -3025,7 +3328,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA210_CLK_I2S4, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA210_CLK_HOST1X, TEGRA210_CLK_PLL_P, 136000000, 1 },
{ TEGRA210_CLK_SCLK_MUX, TEGRA210_CLK_PLL_P, 0, 1 },
- { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 1 },
+ { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 0 },
{ TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 },
{ TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 },
{ TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 },
@@ -3040,7 +3343,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA210_CLK_XUSB_DEV_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 },
{ TEGRA210_CLK_SATA, TEGRA210_CLK_PLL_P, 104000000, 0 },
{ TEGRA210_CLK_SATA_OOB, TEGRA210_CLK_PLL_P, 204000000, 0 },
- { TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 },
{ TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 },
{ TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 },
/* TODO find a way to enable this on-demand */
@@ -3149,6 +3451,37 @@ static int tegra210_reset_deassert(unsigned long id)
return 0;
}
+static void tegra210_mbist_clk_init(void)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(tegra210_pg_mbist_war); i++) {
+ unsigned int num_clks = tegra210_pg_mbist_war[i].num_clks;
+ struct clk_bulk_data *clk_data;
+
+ if (!num_clks)
+ continue;
+
+ clk_data = kmalloc_array(num_clks, sizeof(*clk_data),
+ GFP_KERNEL);
+ if (WARN_ON(!clk_data))
+ return;
+
+ tegra210_pg_mbist_war[i].clks = clk_data;
+ for (j = 0; j < num_clks; j++) {
+ int clk_id = tegra210_pg_mbist_war[i].clk_init_data[j];
+ struct clk *clk = clks[clk_id];
+
+ if (WARN(IS_ERR(clk), "clk_id: %d\n", clk_id)) {
+ kfree(clk_data);
+ tegra210_pg_mbist_war[i].clks = NULL;
+ break;
+ }
+ clk_data[j].clk = clk;
+ }
+ }
+}
+
/**
* tegra210_clock_init - Tegra210-specific clock initialization
* @np: struct device_node * of the DT node for the SoC CAR IP block
@@ -3183,6 +3516,24 @@ static void __init tegra210_clock_init(struct device_node *np)
return;
}
+ ahub_base = ioremap(TEGRA210_AHUB_BASE, SZ_64K);
+ if (!ahub_base) {
+ pr_err("ioremap tegra210 APE failed\n");
+ return;
+ }
+
+ dispa_base = ioremap(TEGRA210_DISPA_BASE, SZ_256K);
+ if (!dispa_base) {
+ pr_err("ioremap tegra210 DISPA failed\n");
+ return;
+ }
+
+ vic_base = ioremap(TEGRA210_VIC_BASE, SZ_256K);
+ if (!vic_base) {
+ pr_err("ioremap tegra210 VIC failed\n");
+ return;
+ }
+
clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX,
TEGRA210_CAR_BANK_COUNT);
if (!clks)
@@ -3219,6 +3570,8 @@ static void __init tegra210_clock_init(struct device_node *np)
tegra_add_of_provider(np);
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
+ tegra210_mbist_clk_init();
+
tegra_cpu_car_ops = &tegra210_cpu_car_ops;
}
CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init);
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index bee84c554932..b316dfb6f6c7 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -819,6 +819,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
[tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true },
[tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true },
[tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true },
+ [tegra_clk_emc] = { .dt_id = TEGRA30_CLK_EMC, .present = true },
};
static const char *pll_e_parents[] = { "pll_ref", "pll_p" };
@@ -843,8 +844,7 @@ static void __init tegra30_pll_init(void)
/* PLLM */
clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base,
- CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
- &pll_m_params, NULL);
+ CLK_SET_RATE_GATE, &pll_m_params, NULL);
clks[TEGRA30_CLK_PLL_M] = clk;
/* PLLM_OUT1 */
@@ -852,7 +852,7 @@ static void __init tegra30_pll_init(void)
clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
8, 8, 1, NULL);
clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
- clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+ clk_base + PLLM_OUT, 1, 0,
CLK_SET_RATE_PARENT, 0, NULL);
clks[TEGRA30_CLK_PLL_M_OUT1] = clk;
@@ -990,7 +990,7 @@ static void __init tegra30_super_clk_init(void)
/* SCLK */
clk = tegra_clk_register_super_mux("sclk", sclk_parents,
ARRAY_SIZE(sclk_parents),
- CLK_SET_RATE_PARENT,
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
clk_base + SCLK_BURST_POLICY,
0, 4, 0, 0, NULL);
clks[TEGRA30_CLK_SCLK] = clk;
@@ -1060,9 +1060,6 @@ static void __init tegra30_periph_clk_init(void)
CLK_SET_RATE_NO_REPARENT,
clk_base + CLK_SOURCE_EMC,
30, 2, 0, &emc_lock);
- clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
- 57, periph_clk_enb_refcnt);
- clks[TEGRA30_CLK_EMC] = clk;
clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
&emc_lock);
@@ -1252,10 +1249,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0 },
{ TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0 },
{ TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0 },
- { TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1 },
- { TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1 },
{ TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1 },
- { TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1 },
{ TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1 },
{ TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0 },
{ TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0 },
@@ -1272,6 +1266,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
{ TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
{ TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 },
+ { TEGRA30_CLK_VDE, TEGRA30_CLK_CLK_MAX, 600000000, 0 },
/* must be the last entry */
{ TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
};
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 3b2763df51c2..ba7e20e6a82b 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -812,4 +812,11 @@ int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll);
u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate);
int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div);
+/* Combined read fence with delay */
+#define fence_udelay(delay, reg) \
+ do { \
+ readl(reg); \
+ udelay(delay); \
+ } while (0)
+
#endif /* TEGRA_CLK_H */
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index f4d6802a8544..7d22e1af2247 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -55,6 +55,29 @@ static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg)
writel_relaxed(val, io->mem + reg->offset);
}
+static void _clk_rmw(u32 val, u32 mask, void __iomem *ptr)
+{
+ u32 v;
+
+ v = readl_relaxed(ptr);
+ v &= ~mask;
+ v |= val;
+ writel_relaxed(v, ptr);
+}
+
+static void clk_memmap_rmw(u32 val, u32 mask, const struct clk_omap_reg *reg)
+{
+ struct clk_iomap *io = clk_memmaps[reg->index];
+
+ if (reg->ptr) {
+ _clk_rmw(val, mask, reg->ptr);
+ } else if (io->regmap) {
+ regmap_update_bits(io->regmap, reg->offset, mask, val);
+ } else {
+ _clk_rmw(val, mask, io->mem + reg->offset);
+ }
+}
+
static u32 clk_memmap_readl(const struct clk_omap_reg *reg)
{
u32 val;
@@ -89,6 +112,7 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
ti_clk_ll_ops = ops;
ops->clk_readl = clk_memmap_readl;
ops->clk_writel = clk_memmap_writel;
+ ops->clk_rmw = clk_memmap_rmw;
return 0;
}
@@ -251,6 +275,20 @@ int ti_clk_get_reg_addr(struct device_node *node, int index,
return 0;
}
+void ti_clk_latch(struct clk_omap_reg *reg, s8 shift)
+{
+ u32 latch;
+
+ if (shift < 0)
+ return;
+
+ latch = 1 << shift;
+
+ ti_clk_ll_ops->clk_rmw(latch, latch, reg);
+ ti_clk_ll_ops->clk_rmw(0, latch, reg);
+ ti_clk_ll_ops->clk_readl(reg); /* OCP barrier */
+}
+
/**
* omap2_clk_provider_init - init master clock provider
* @parent: master node
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index d9b43bfc2532..90b86aadfda7 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -22,6 +22,7 @@ struct clk_omap_divider {
u8 shift;
u8 width;
u8 flags;
+ s8 latch;
const struct clk_div_table *table;
};
@@ -33,6 +34,7 @@ struct clk_omap_mux {
u32 *table;
u32 mask;
u8 shift;
+ s8 latch;
u8 flags;
};
@@ -194,6 +196,8 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
void ti_clk_add_aliases(void);
+void ti_clk_latch(struct clk_omap_reg *reg, s8 shift);
+
struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index 77f93f6d2806..aaa277dd6d99 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -263,6 +263,8 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
val |= value << divider->shift;
ti_clk_ll_ops->clk_writel(val, &divider->reg);
+ ti_clk_latch(&divider->reg, divider->latch);
+
return 0;
}
@@ -276,7 +278,8 @@ static struct clk *_register_divider(struct device *dev, const char *name,
const char *parent_name,
unsigned long flags,
struct clk_omap_reg *reg,
- u8 shift, u8 width, u8 clk_divider_flags,
+ u8 shift, u8 width, s8 latch,
+ u8 clk_divider_flags,
const struct clk_div_table *table)
{
struct clk_omap_divider *div;
@@ -305,6 +308,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
memcpy(&div->reg, reg, sizeof(*reg));
div->shift = shift;
div->width = width;
+ div->latch = latch;
div->flags = clk_divider_flags;
div->hw.init = &init;
div->table = table;
@@ -420,6 +424,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
div->table = _get_div_table_from_setup(setup, &div->width);
div->shift = setup->bit_shift;
+ div->latch = -EINVAL;
return &div->hw;
}
@@ -452,7 +457,7 @@ struct clk *ti_clk_register_divider(struct ti_clk *setup)
clk = _register_divider(NULL, setup->name, div->parent,
flags, &reg, div->bit_shift,
- width, div_flags, table);
+ width, -EINVAL, div_flags, table);
if (IS_ERR(clk))
kfree(table);
@@ -556,7 +561,7 @@ static int _get_divider_width(struct device_node *node,
static int __init ti_clk_divider_populate(struct device_node *node,
struct clk_omap_reg *reg, const struct clk_div_table **table,
- u32 *flags, u8 *div_flags, u8 *width, u8 *shift)
+ u32 *flags, u8 *div_flags, u8 *width, u8 *shift, s8 *latch)
{
u32 val;
int ret;
@@ -570,6 +575,13 @@ static int __init ti_clk_divider_populate(struct device_node *node,
else
*shift = 0;
+ if (latch) {
+ if (!of_property_read_u32(node, "ti,latch-bit", &val))
+ *latch = val;
+ else
+ *latch = -EINVAL;
+ }
+
*flags = 0;
*div_flags = 0;
@@ -606,17 +618,18 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
u8 clk_divider_flags = 0;
u8 width = 0;
u8 shift = 0;
+ s8 latch = -EINVAL;
const struct clk_div_table *table = NULL;
u32 flags = 0;
parent_name = of_clk_get_parent_name(node, 0);
if (ti_clk_divider_populate(node, &reg, &table, &flags,
- &clk_divider_flags, &width, &shift))
+ &clk_divider_flags, &width, &shift, &latch))
goto cleanup;
clk = _register_divider(NULL, node->name, parent_name, flags, &reg,
- shift, width, clk_divider_flags, table);
+ shift, width, latch, clk_divider_flags, table);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -639,7 +652,8 @@ static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
return;
if (ti_clk_divider_populate(node, &div->reg, &div->table, &val,
- &div->flags, &div->width, &div->shift) < 0)
+ &div->flags, &div->width, &div->shift,
+ NULL) < 0)
goto cleanup;
if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index d4705803f3d3..69a4308a5a98 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -86,6 +86,7 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
}
val |= index << mux->shift;
ti_clk_ll_ops->clk_writel(val, &mux->reg);
+ ti_clk_latch(&mux->reg, mux->latch);
return 0;
}
@@ -100,7 +101,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
const char * const *parent_names,
u8 num_parents, unsigned long flags,
struct clk_omap_reg *reg, u8 shift, u32 mask,
- u8 clk_mux_flags, u32 *table)
+ s8 latch, u8 clk_mux_flags, u32 *table)
{
struct clk_omap_mux *mux;
struct clk *clk;
@@ -121,6 +122,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
memcpy(&mux->reg, reg, sizeof(*reg));
mux->shift = shift;
mux->mask = mask;
+ mux->latch = latch;
mux->flags = clk_mux_flags;
mux->table = table;
mux->hw.init = &init;
@@ -160,7 +162,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup)
flags |= CLK_SET_RATE_PARENT;
return _register_mux(NULL, setup->name, mux->parents, mux->num_parents,
- flags, &reg, mux->bit_shift, mask,
+ flags, &reg, mux->bit_shift, mask, -EINVAL,
mux_flags, NULL);
}
@@ -179,6 +181,7 @@ static void of_mux_clk_setup(struct device_node *node)
u8 clk_mux_flags = 0;
u32 mask = 0;
u32 shift = 0;
+ s32 latch = -EINVAL;
u32 flags = CLK_SET_RATE_NO_REPARENT;
num_parents = of_clk_get_parent_count(node);
@@ -197,6 +200,8 @@ static void of_mux_clk_setup(struct device_node *node)
of_property_read_u32(node, "ti,bit-shift", &shift);
+ of_property_read_u32(node, "ti,latch-bit", &latch);
+
if (of_property_read_bool(node, "ti,index-starts-at-one"))
clk_mux_flags |= CLK_MUX_INDEX_ONE;
@@ -211,7 +216,8 @@ static void of_mux_clk_setup(struct device_node *node)
mask = (1 << fls(mask)) - 1;
clk = _register_mux(NULL, node->name, parent_names, num_parents,
- flags, &reg, shift, mask, clk_mux_flags, NULL);
+ flags, &reg, shift, mask, latch, clk_mux_flags,
+ NULL);
if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -234,6 +240,7 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
return ERR_PTR(-ENOMEM);
mux->shift = setup->bit_shift;
+ mux->latch = -EINVAL;
mux->reg.index = setup->module;
mux->reg.offset = setup->reg;
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
index e7a868b83fe5..dd08ecb498be 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -44,10 +44,10 @@ static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate,
{
struct vexpress_osc *osc = to_vexpress_osc(hw);
- if (WARN_ON(osc->rate_min && rate < osc->rate_min))
+ if (osc->rate_min && rate < osc->rate_min)
rate = osc->rate_min;
- if (WARN_ON(osc->rate_max && rate > osc->rate_max))
+ if (osc->rate_max && rate > osc->rate_max)
rate = osc->rate_max;
return rate;
@@ -104,6 +104,7 @@ static int vexpress_osc_probe(struct platform_device *pdev)
return PTR_ERR(clk);
of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
+ clk_hw_set_rate_range(&osc->hw, osc->rate_min, osc->rate_max);
dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);