Merge branches 'clk-spreadtrum', 'clk-stm32f', 'clk-stm32mp1', 'clk-hi655x' and ...
authorStephen Boyd <sboyd@kernel.org>
Fri, 6 Apr 2018 20:21:45 +0000 (13:21 -0700)
committerStephen Boyd <sboyd@kernel.org>
Fri, 6 Apr 2018 20:21:45 +0000 (13:21 -0700)
* clk-spreadtrum:
  clk: sprd: add RTC gate for SC9860
  dt-bindings: clocks: add APB RTC gate for SC9860

* clk-stm32f:
  clk: stm32: Add clk entry for SDMMC2 on stm32F769
  clk: stm32: Add DSI clock for STM32F469 Board
  clk: stm32: END_PRIMARY_CLK should be declare after CLK_SYSCLK

* clk-stm32mp1:
  clk: stm32: add configuration flags for each of the stm32 drivers
  clk: stm32mp1: add Debug clocks
  clk: stm32mp1: add MCO clocks
  clk: stm32mp1: add RTC clock
  clk: stm32mp1: add Peripheral & Kernel Clocks
  clk: stm32mp1: add Kernel timers
  clk: stm32mp1: add Sub System clocks
  clk: stm32mp1: add Post-dividers for PLL
  clk: stm32mp1: add PLL clocks
  clk: stm32mp1: add Source Clocks for PLLs
  clk: stm32mp1: add MP1 gate for hse/hsi/csi oscillators
  clk: stm32mp1: Introduce STM32MP1 clock driver
  dt-bindings: Document STM32MP1 Reset Clock Controller (RCC) bindings

* clk-hi655x:
  clk: enable hi655x common clk automatically

* clk-gpio:
  clk: clk-gpio: Allow GPIO to sleep in set/get_parent

77 files changed:
Documentation/clk.txt
Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/divider.txt
Documentation/devicetree/bindings/clock/ti/mux.txt
MAINTAINERS
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-divider.c
drivers/clk/clk-mux.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-stm32mp1.c [new file with mode: 0644]
drivers/clk/clk.c
drivers/clk/keystone/sci-clk.c
drivers/clk/meson/Kconfig
drivers/clk/meson/Makefile
drivers/clk/meson/axg.c
drivers/clk/meson/axg.h
drivers/clk/meson/clk-audio-divider.c
drivers/clk/meson/clk-cpu.c [deleted file]
drivers/clk/meson/clk-mpll.c
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clk-regmap.c [new file with mode: 0644]
drivers/clk/meson/clk-regmap.h [new file with mode: 0644]
drivers/clk/meson/clkc.h
drivers/clk/meson/gxbb-aoclk-regmap.c [deleted file]
drivers/clk/meson/gxbb-aoclk.c
drivers/clk/meson/gxbb-aoclk.h
drivers/clk/meson/gxbb.c
drivers/clk/meson/gxbb.h
drivers/clk/meson/meson8b.c
drivers/clk/meson/meson8b.h
drivers/clk/qcom/clk-regmap-divider.c
drivers/clk/qcom/clk-smd-rpm.c
drivers/clk/qcom/gcc-msm8996.c
drivers/clk/samsung/Makefile
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5-subcmu.c [new file with mode: 0644]
drivers/clk/samsung/clk-exynos5-subcmu.h [new file with mode: 0644]
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5260.c
drivers/clk/samsung/clk-exynos5410.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/samsung/clk-exynos7.c
drivers/clk/samsung/clk-pll.h
drivers/clk/samsung/clk-s3c2410.c
drivers/clk/samsung/clk-s3c2412.c
drivers/clk/samsung/clk-s3c2443.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clk/sprd/sc9860-clk.c
drivers/clk/tegra/clk-emc.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra-super-gen4.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra210.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.h
drivers/clk/ti/clk.c
drivers/clk/ti/clock.h
drivers/clk/ti/divider.c
drivers/clk/ti/mux.c
drivers/clk/versatile/clk-vexpress-osc.c
drivers/soc/samsung/pm_domains.c
include/dt-bindings/clock/axg-clkc.h
include/dt-bindings/clock/sprd,sc9860-clk.h
include/dt-bindings/clock/stm32fx-clock.h
include/dt-bindings/clock/stm32mp1-clks.h [new file with mode: 0644]
include/dt-bindings/clock/tegra210-car.h
include/linux/clk-provider.h
include/linux/clk.h
include/linux/clk/tegra.h
include/linux/clk/ti.h

index be909ed..511628b 100644 (file)
@@ -268,9 +268,19 @@ The common clock framework uses two global locks, the prepare lock and the
 enable lock.
 
 The enable lock is a spinlock and is held across calls to the .enable,
-.disable and .is_enabled operations. Those operations are thus not allowed to
-sleep, and calls to the clk_enable(), clk_disable() and clk_is_enabled() API
-functions are allowed in atomic context.
+.disable operations. Those operations are thus not allowed to sleep,
+and calls to the clk_enable(), clk_disable() API functions are allowed in
+atomic context.
+
+For clk_is_enabled() API, it is also designed to be allowed to be used in
+atomic context. However, it doesn't really make any sense to hold the enable
+lock in core, unless you want to do something else with the information of
+the enable state with that lock held. Otherwise, seeing if a clk is enabled is
+a one-shot read of the enabled state, which could just as easily change after
+the function returns because the lock is released. Thus the user of this API
+needs to handle synchronizing the read of the state with whatever they're
+using it for to make sure that the enable state doesn't change during that
+time.
 
 The prepare lock is a mutex and is held across calls to all other operations.
 All those operations are allowed to sleep, and calls to the corresponding API
diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt
new file mode 100644 (file)
index 0000000..fb9495e
--- /dev/null
@@ -0,0 +1,60 @@
+STMicroelectronics STM32 Peripheral Reset Clock Controller
+==========================================================
+
+The RCC IP is both a reset and a clock controller.
+
+RCC makes also power management (resume/supend and wakeup interrupt).
+
+Please also refer to reset.txt for common reset controller binding usage.
+
+Please also refer to clock-bindings.txt for common clock controller
+binding usage.
+
+
+Required properties:
+- compatible: "st,stm32mp1-rcc", "syscon"
+- reg: should be register base and length as documented in the datasheet
+- #clock-cells: 1, device nodes should specify the clock in their
+  "clocks" property, containing a phandle to the clock device node,
+  an index specifying the clock to use.
+- #reset-cells: Shall be 1
+- interrupts: Should contain a general interrupt line and a interrupt line
+  to the wake-up of processor (CSTOP).
+
+Example:
+       rcc: rcc@50000000 {
+               compatible = "st,stm32mp1-rcc", "syscon";
+               reg = <0x50000000 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+               interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>,
+                            <GIC_SPI 145 IRQ_TYPE_NONE>;
+       };
+
+Specifying clocks
+=================
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/stm32mp1-clks.h header and can be used in device
+tree sources.
+
+Specifying softreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the reset device node and an index specifying
+which channel to use.
+The index is the bit number within the RCC registers bank, starting from RCC
+base address.
+It is calculated as: index = register_offset / 4 * 32 + bit_offset.
+Where bit_offset is the bit offset within the register.
+
+For example on STM32MP1, for LTDC reset:
+ ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset
+      = 0x180 / 4 * 32 + 0 = 3072
+
+The list of valid indices for STM32MP1 is available in:
+include/dt-bindings/reset-controller/stm32mp1-resets.h
+
+This file implements defines like:
+#define LTDC_R 3072
index 35a6f5c..9b13b32 100644 (file)
@@ -75,6 +75,9 @@ Optional properties:
 - ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0,
   see [2]
 - ti,set-rate-parent : clk_set_rate is propagated to parent
+- ti,latch-bit : latch the divider value to HW, only needed if the register
+  access requires this. As an example dra76x DPLL_GMAC H14 divider implements
+  such behavior.
 
 Examples:
 dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 {
index 2d0d170..eec8994 100644 (file)
@@ -48,6 +48,9 @@ Optional properties:
   zero
 - ti,set-rate-parent : clk_set_rate is propagated to parent clock,
   not supported by the composite-mux-clock subtype
+- ti,latch-bit : latch the mux value to HW, only needed if the register
+  access requires this. As an example, dra7x DPLL_GMAC H14 muxing
+  implements such behavior.
 
 Examples:
 
index 3bdc260..395ea06 100644 (file)
@@ -12189,6 +12189,7 @@ M:      Tomasz Figa <tomasz.figa@gmail.com>
 M:     Chanwoo Choi <cw00.choi@samsung.com>
 S:     Supported
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
 F:     drivers/clk/samsung/
 F:     include/dt-bindings/clock/exynos*.h
 F:     Documentation/devicetree/bindings/clock/exynos*.txt
index 98ce9fc..ede9cb0 100644 (file)
@@ -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"
index 71ec41e..e0c106e 100644 (file)
@@ -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
index b49942b..b6234a5 100644 (file)
  * 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);
index 39cabe1..ac4a042 100644 (file)
  * 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);
index da44f8d..294850b 100644 (file)
@@ -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 (file)
index 0000000..f1d5967
--- /dev/null
@@ -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);
index 0f686a9..037035a 100644 (file)
@@ -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);
 
@@ -2486,19 +2488,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 +2522,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 +2545,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 +2567,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 +2586,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 +2600,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 +2884,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 +2935,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);
index 9cdf9d5..4cb70be 100644 (file)
 #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");
index 7694302..d5cbec5 100644 (file)
@@ -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.
index 3c03ce5..ffee82e 100644 (file)
@@ -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
index 1294f3a..5f5d468 100644 (file)
 
 #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 = {
index ce0bafd..b421df6 100644 (file)
 #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>
index 6c07db0..f7ab5b1 100644 (file)
 #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 (file)
index f8b2b7e..0000000
+++ /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,
-};
index 5144360..0df1227 100644 (file)
 #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,
 };
index 0134155..65a7bd9 100644 (file)
@@ -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.
  *                |        |
  *               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>
 
 #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 (file)
index 0000000..3645fdb
--- /dev/null
@@ -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 (file)
index 0000000..627c888
--- /dev/null
@@ -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 */
index c2ff052..8fe73c4 100644 (file)
@@ -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 (file)
index 2515fbf..0000000
+++ /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,
-};
index 6c161e0..9ec23ae 100644 (file)
 #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;
        }
index e8604c8..0be7838 100644 (file)
 #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)
index af24455..b1e4d95 100644 (file)
 
 #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 = {
index aee6fbb..9febf3f 100644 (file)
 #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>
index 3ffea80..cc29924 100644 (file)
 
 #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[] = {
index 2eaf8a5..6e414bd 100644 (file)
  * 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
index 4e9b8c2..1ee75a5 100644 (file)
@@ -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,
index c26d900..850c02a 100644 (file)
@@ -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)
index 5d74512..3d64529 100644 (file)
@@ -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,
                },
        },
index ef8900b..5138263 100644 (file)
@@ -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
index 5bfc92e..b4b057c 100644 (file)
@@ -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);
 
index 1b81e28..27c9d23 100644 (file)
@@ -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 */ }
 };
 
index 134f25f..0421960 100644 (file)
@@ -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 (file)
index 0000000..9330628
--- /dev/null
@@ -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 (file)
index 0000000..755ee8a
--- /dev/null
@@ -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
index 9b073c9..347fd80 100644 (file)
@@ -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);
index fd1d9bf..2cc2583 100644 (file)
  * 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 */
index fc471a4..0a0b095 100644 (file)
@@ -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 = {
index 45d34f6..95e1bf6 100644 (file)
@@ -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);
index db27090..5305ace 100644 (file)
@@ -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);
index 5931a41..492d516 100644 (file)
@@ -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),
        {},
 };
 
index 61eb8ab..ca57b3d 100644 (file)
@@ -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),                           \
index e0650c3..a9c8874 100644 (file)
@@ -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);
index b8340a4..6bc94d3 100644 (file)
 #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);
index d94b85a..c46e6d5 100644 (file)
@@ -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);
index 7306867..6db01cf 100644 (file)
 #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. */
index ed5c027..9980ab5 100644 (file)
@@ -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,
 };
index 11a5066..5234acd 100644 (file)
@@ -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);
 
index 7c369e2..830d1c8 100644 (file)
@@ -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,
index c027119..2acba29 100644 (file)
@@ -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),
index 1004710..89d6b47 100644 (file)
@@ -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;
index 63087d1..5d5a22d 100644 (file)
@@ -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 },
 };
index e81ea5b..50088e9 100644 (file)
@@ -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 },
index cbd5a2e..0ee56dd 100644 (file)
@@ -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 },
 };
index 9e62608..9fb5d51 100644 (file)
 #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
 #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);
index bee84c5..b316dfb 100644 (file)
@@ -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 },
 };
index 3b2763d..ba7e20e 100644 (file)
@@ -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 */
index f4d6802..7d22e1a 100644 (file)
@@ -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
index d9b43bf..90b86aa 100644 (file)
@@ -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,
index 77f93f6..aaa277d 100644 (file)
@@ -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))
index d470580..69a4308 100644 (file)
@@ -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;
index e7a868b..dd08ecb 100644 (file)
@@ -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);
 
index b6a4365..caf45cf 100644 (file)
@@ -147,6 +147,12 @@ static __init const char *exynos_get_domain_name(struct device_node *node)
        return kstrdup_const(name, GFP_KERNEL);
 }
 
+static const char *soc_force_no_clk[] = {
+       "samsung,exynos5250-clock",
+       "samsung,exynos5420-clock",
+       "samsung,exynos5800-clock",
+};
+
 static __init int exynos4_pm_init_power_domain(void)
 {
        struct device_node *np;
@@ -183,6 +189,11 @@ static __init int exynos4_pm_init_power_domain(void)
                pd->pd.power_on = exynos_pd_power_on;
                pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
 
+               for (i = 0; i < ARRAY_SIZE(soc_force_no_clk); i++)
+                       if (of_find_compatible_node(NULL, NULL,
+                                                   soc_force_no_clk[i]))
+                               goto no_clk;
+
                for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
                        char clk_name[8];
 
index 941ac70..555937a 100644 (file)
@@ -67,5 +67,6 @@
 #define CLKID_AO_I2C                           58
 #define CLKID_SD_EMMC_B_CLK0                   59
 #define CLKID_SD_EMMC_C_CLK0                   60
+#define CLKID_HIFI_PLL                         69
 
 #endif /* __AXG_CLKC_H */
index 4cb202f..f2ab463 100644 (file)
 #define        CLK_SDIO1_2X_EN         65
 #define        CLK_SDIO2_2X_EN         66
 #define        CLK_EMMC_2X_EN          67
-#define CLK_AON_GATE_NUM       (CLK_EMMC_2X_EN + 1)
+#define        CLK_ARCH_RTC_EB         68
+#define        CLK_KPB_RTC_EB          69
+#define        CLK_AON_SYST_RTC_EB     70
+#define        CLK_AP_SYST_RTC_EB      71
+#define        CLK_AON_TMR_RTC_EB      72
+#define        CLK_AP_TMR0_RTC_EB      73
+#define        CLK_EIC_RTC_EB          74
+#define        CLK_EIC_RTCDV5_EB       75
+#define        CLK_AP_WDG_RTC_EB       76
+#define        CLK_AP_TMR1_RTC_EB      77
+#define        CLK_AP_TMR2_RTC_EB      78
+#define        CLK_DCXO_TMR_RTC_EB     79
+#define        CLK_BB_CAL_RTC_EB       80
+#define        CLK_AVS_BIG_RTC_EB      81
+#define        CLK_AVS_LIT_RTC_EB      82
+#define        CLK_AVS_GPU0_RTC_EB     83
+#define        CLK_AVS_GPU1_RTC_EB     84
+#define        CLK_GPU_TS_EB           85
+#define        CLK_RTCDV10_EB          86
+#define        CLK_AON_GATE_NUM        (CLK_RTCDV10_EB + 1)
 
 #define        CLK_LIT_MCU             0
 #define        CLK_BIG_MCU             1
index 49bb3c2..58d8b51 100644 (file)
 #define CLK_SAI2               11
 #define CLK_I2SQ_PDIV          12
 #define CLK_SAIQ_PDIV          13
-
-#define END_PRIMARY_CLK                14
-
 #define CLK_HSI                        14
 #define CLK_SYSCLK             15
+#define CLK_F469_DSI           16
+
+#define END_PRIMARY_CLK                17
+
 #define CLK_HDMI_CEC           16
 #define CLK_SPDIF              17
 #define CLK_USART1             18
diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h
new file mode 100644 (file)
index 0000000..86e3ec6
--- /dev/null
@@ -0,0 +1,254 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
+ */
+
+#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_
+#define _DT_BINDINGS_STM32MP1_CLKS_H_
+
+/* OSCILLATOR clocks */
+#define CK_HSE         0
+#define CK_CSI         1
+#define CK_LSI         2
+#define CK_LSE         3
+#define CK_HSI         4
+#define CK_HSE_DIV2    5
+
+/* Bus clocks */
+#define TIM2           6
+#define TIM3           7
+#define TIM4           8
+#define TIM5           9
+#define TIM6           10
+#define TIM7           11
+#define TIM12          12
+#define TIM13          13
+#define TIM14          14
+#define LPTIM1         15
+#define SPI2           16
+#define SPI3           17
+#define USART2         18
+#define USART3         19
+#define UART4          20
+#define UART5          21
+#define UART7          22
+#define UART8          23
+#define I2C1           24
+#define I2C2           25
+#define I2C3           26
+#define I2C5           27
+#define SPDIF          28
+#define CEC            29
+#define DAC12          30
+#define MDIO           31
+#define TIM1           32
+#define TIM8           33
+#define TIM15          34
+#define TIM16          35
+#define TIM17          36
+#define SPI1           37
+#define SPI4           38
+#define SPI5           39
+#define USART6         40
+#define SAI1           41
+#define SAI2           42
+#define SAI3           43
+#define DFSDM          44
+#define FDCAN          45
+#define LPTIM2         46
+#define LPTIM3         47
+#define LPTIM4         48
+#define LPTIM5         49
+#define SAI4           50
+#define SYSCFG         51
+#define VREF           52
+#define TMPSENS                53
+#define PMBCTRL                54
+#define HDP            55
+#define LTDC           56
+#define DSI            57
+#define IWDG2          58
+#define USBPHY         59
+#define STGENRO                60
+#define SPI6           61
+#define I2C4           62
+#define I2C6           63
+#define USART1         64
+#define RTCAPB         65
+#define TZC            66
+#define TZPC           67
+#define IWDG1          68
+#define BSEC           69
+#define STGEN          70
+#define DMA1           71
+#define DMA2           72
+#define DMAMUX         73
+#define ADC12          74
+#define USBO           75
+#define SDMMC3         76
+#define DCMI           77
+#define CRYP2          78
+#define HASH2          79
+#define RNG2           80
+#define CRC2           81
+#define HSEM           82
+#define IPCC           83
+#define GPIOA          84
+#define GPIOB          85
+#define GPIOC          86
+#define GPIOD          87
+#define GPIOE          88
+#define GPIOF          89
+#define GPIOG          90
+#define GPIOH          91
+#define GPIOI          92
+#define GPIOJ          93
+#define GPIOK          94
+#define GPIOZ          95
+#define CRYP1          96
+#define HASH1          97
+#define RNG1           98
+#define BKPSRAM                99
+#define MDMA           100
+#define GPU            101
+#define ETHCK          102
+#define ETHTX          103
+#define ETHRX          104
+#define ETHMAC         105
+#define FMC            106
+#define QSPI           107
+#define SDMMC1         108
+#define SDMMC2         109
+#define CRC1           110
+#define USBH           111
+#define ETHSTP         112
+
+/* Kernel clocks */
+#define SDMMC1_K       118
+#define SDMMC2_K       119
+#define SDMMC3_K       120
+#define FMC_K          121
+#define QSPI_K         122
+#define ETHCK_K                123
+#define RNG1_K         124
+#define RNG2_K         125
+#define GPU_K          126
+#define USBPHY_K       127
+#define STGEN_K                128
+#define SPDIF_K                129
+#define SPI1_K         130
+#define SPI2_K         131
+#define SPI3_K         132
+#define SPI4_K         133
+#define SPI5_K         134
+#define SPI6_K         135
+#define CEC_K          136
+#define I2C1_K         137
+#define I2C2_K         138
+#define I2C3_K         139
+#define I2C4_K         140
+#define I2C5_K         141
+#define I2C6_K         142
+#define LPTIM1_K       143
+#define LPTIM2_K       144
+#define LPTIM3_K       145
+#define LPTIM4_K       146
+#define LPTIM5_K       147
+#define USART1_K       148
+#define USART2_K       149
+#define USART3_K       150
+#define UART4_K                151
+#define UART5_K                152
+#define USART6_K       153
+#define UART7_K                154
+#define UART8_K                155
+#define DFSDM_K                156
+#define FDCAN_K                157
+#define SAI1_K         158
+#define SAI2_K         159
+#define SAI3_K         160
+#define SAI4_K         161
+#define ADC12_K                162
+#define DSI_K          163
+#define DSI_PX         164
+#define ADFSDM_K       165
+#define USBO_K         166
+#define LTDC_PX                167
+#define DAC12_K                168
+#define ETHPTP_K       169
+
+/* PLL */
+#define PLL1           176
+#define PLL2           177
+#define PLL3           178
+#define PLL4           179
+
+/* ODF */
+#define PLL1_P         180
+#define PLL1_Q         181
+#define PLL1_R         182
+#define PLL2_P         183
+#define PLL2_Q         184
+#define PLL2_R         185
+#define PLL3_P         186
+#define PLL3_Q         187
+#define PLL3_R         188
+#define PLL4_P         189
+#define PLL4_Q         190
+#define PLL4_R         191
+
+/* AUX */
+#define RTC            192
+
+/* MCLK */
+#define CK_PER         193
+#define CK_MPU         194
+#define CK_AXI         195
+#define CK_MCU         196
+
+/* Time base */
+#define TIM2_K         197
+#define TIM3_K         198
+#define TIM4_K         199
+#define TIM5_K         200
+#define TIM6_K         201
+#define TIM7_K         202
+#define TIM12_K                203
+#define TIM13_K                204
+#define TIM14_K                205
+#define TIM1_K         206
+#define TIM8_K         207
+#define TIM15_K                208
+#define TIM16_K                209
+#define TIM17_K                210
+
+/* MCO clocks */
+#define CK_MCO1                211
+#define CK_MCO2                212
+
+/* TRACE & DEBUG clocks */
+#define DBG            213
+#define CK_DBG         214
+#define CK_TRACE       215
+
+/* DDR */
+#define DDRC1          220
+#define DDRC1LP                221
+#define DDRC2          222
+#define DDRC2LP                223
+#define DDRPHYC                224
+#define DDRPHYCLP      225
+#define DDRCAPB                226
+#define DDRCAPBLP      227
+#define AXIDCG         228
+#define DDRPHYCAPB     229
+#define DDRPHYCAPBLP   230
+#define DDRPERFM       231
+
+#define STM32MP1_LAST_CLK 232
+
+#define LTDC_K         LTDC_PX
+#define ETHMAC_K       ETHCK_K
+
+#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
index 6422314..6b77e72 100644 (file)
@@ -95,7 +95,7 @@
 #define TEGRA210_CLK_CSITE 73
 /* 74 */
 /* 75 */
-/* 76 */
+#define TEGRA210_CLK_LA 76
 /* 77 */
 #define TEGRA210_CLK_SOC_THERM 78
 #define TEGRA210_CLK_DTV 79
index f711be6..210a890 100644 (file)
@@ -399,6 +399,7 @@ struct clk_divider {
        spinlock_t      *lock;
 };
 
+#define clk_div_mask(width)    ((1 << (width)) - 1)
 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
 
 #define CLK_DIVIDER_ONE_BASED          BIT(0)
@@ -419,6 +420,10 @@ long divider_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);
+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 divider_get_val(unsigned long rate, unsigned long parent_rate,
                const struct clk_div_table *table, u8 width,
                unsigned long flags);
@@ -449,8 +454,9 @@ void clk_hw_unregister_divider(struct clk_hw *hw);
  *
  * @hw:                handle between common and hardware-specific interfaces
  * @reg:       register controlling multiplexer
+ * @table:     array of register values corresponding to the parent index
  * @shift:     shift to multiplexer bit field
- * @width:     width of mutliplexer bit field
+ * @mask:      mask of mutliplexer bit field
  * @flags:     hardware-specific flags
  * @lock:      register lock
  *
@@ -510,6 +516,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
                void __iomem *reg, u8 shift, u32 mask,
                u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
+int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
+                        unsigned int val);
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
+
 void clk_unregister_mux(struct clk *clk);
 void clk_hw_unregister_mux(struct clk_hw *hw);
 
@@ -774,6 +784,17 @@ static inline long divider_round_rate(struct clk_hw *hw, unsigned long rate,
                                         rate, prate, table, width, flags);
 }
 
+static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate,
+                                        unsigned long *prate,
+                                        const struct clk_div_table *table,
+                                        u8 width, unsigned long flags,
+                                        unsigned int val)
+{
+       return divider_ro_round_rate_parent(hw, clk_hw_get_parent(hw),
+                                           rate, prate, table, width, flags,
+                                           val);
+}
+
 /*
  * FIXME clock api without lock protection
  */
index 4c4ef9f..0dbd088 100644 (file)
@@ -209,7 +209,7 @@ static inline int clk_prepare(struct clk *clk)
        return 0;
 }
 
-static inline int clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks)
 {
        might_sleep();
        return 0;
@@ -603,8 +603,8 @@ static inline struct clk *clk_get(struct device *dev, const char *id)
        return NULL;
 }
 
-static inline int clk_bulk_get(struct device *dev, int num_clks,
-                              struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
+                                           struct clk_bulk_data *clks)
 {
        return 0;
 }
@@ -614,8 +614,8 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
        return NULL;
 }
 
-static inline int devm_clk_bulk_get(struct device *dev, int num_clks,
-                                   struct clk_bulk_data *clks)
+static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
+                                                struct clk_bulk_data *clks)
 {
        return 0;
 }
@@ -645,7 +645,7 @@ static inline int clk_enable(struct clk *clk)
        return 0;
 }
 
-static inline int clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
 {
        return 0;
 }
@@ -719,8 +719,8 @@ static inline void clk_disable_unprepare(struct clk *clk)
        clk_unprepare(clk);
 }
 
-static inline int clk_bulk_prepare_enable(int num_clks,
-                                         struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_prepare_enable(int num_clks,
+                                       struct clk_bulk_data *clks)
 {
        int ret;
 
index d23c9cf..afb9edf 100644 (file)
@@ -128,5 +128,6 @@ extern void tegra210_sata_pll_hw_sequence_start(void);
 extern void tegra210_set_sata_pll_seq_sw(bool state);
 extern void tegra210_put_utmipll_in_iddq(void);
 extern void tegra210_put_utmipll_out_iddq(void);
+extern int tegra210_clk_handle_mbist_war(unsigned int id);
 
 #endif /* __LINUX_CLK_TEGRA_H_ */
index d18da83..9e86114 100644 (file)
@@ -211,6 +211,7 @@ enum {
  * struct ti_clk_ll_ops - low-level ops for clocks
  * @clk_readl: pointer to register read function
  * @clk_writel: pointer to register write function
+ * @clk_rmw: pointer to register read-modify-write function
  * @clkdm_clk_enable: pointer to clockdomain enable function
  * @clkdm_clk_disable: pointer to clockdomain disable function
  * @clkdm_lookup: pointer to clockdomain lookup function
@@ -226,6 +227,7 @@ enum {
 struct ti_clk_ll_ops {
        u32     (*clk_readl)(const struct clk_omap_reg *reg);
        void    (*clk_writel)(u32 val, const struct clk_omap_reg *reg);
+       void    (*clk_rmw)(u32 val, u32 mask, const struct clk_omap_reg *reg);
        int     (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
        int     (*clkdm_clk_disable)(struct clockdomain *clkdm,
                                     struct clk *clk);