Commit 897a54f9 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'clk-imx-5.16' of...

Merge tag 'clk-imx-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux into clk-imx

Pull i.MX clk driver changes from Abel Vesa:

 - Remove unused helpers from i.MX specific clock header
 - Rework all clk based helpers to use clk_hw based ones
 - Rework gate/mux/divider wrappers
 - Rework imx_clk_hw_composite and imx_clk_hw_pll14xx wrappers
 - Add i.MX8ULP clock driver and related bindings
 - Update i.MX pllv4 and composite clocks to support i.MX8ULP
 - Disable i.MX7ULP composite clock during initialization
 - Add CLK_SET_RATE_NO_REPARENT flag to the i.MX7ULP composite
 - Disable the pfd when set pfdv2 clock rate
 - Add support for i.MX8ULP in pfdv2
 - Add the pcc reset controller support on i.MX8ULP
 - Fix the build break when clk-imx8ulp is built as module
 - Move csi_sel mux to correct base register in i.MX6UL clock drivr
 - Fix csi clk gate register in i.MX6UL clock driver
 - Fix build bug making CLK_IMX8ULP select MXC_CLK

* tag 'clk-imx-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux: (21 commits)
  clk: imx: Make CLK_IMX8ULP select MXC_CLK
  clk: imx: imx6ul: Fix csi clk gate register
  clk: imx: imx6ul: Move csi_sel mux to correct base register
  clk: imx: Fix the build break when clk-imx8ulp build as module
  clk: imx: Add the pcc reset controller support on imx8ulp
  clk: imx: Add clock driver for imx8ulp
  clk: imx: Update the pfdv2 for 8ulp specific support
  clk: imx: disable the pfd when set pfdv2 clock rate
  clk: imx: Add 'CLK_SET_RATE_NO_REPARENT' for composite-7ulp
  clk: imx: disable i.mx7ulp composite clock during initialization
  clk: imx: Update the compsite driver to support imx8ulp
  clk: imx: Update the pllv4 to support imx8ulp
  dt-bindings: clock: Add imx8ulp clock support
  clk: imx: Rework imx_clk_hw_pll14xx wrapper
  clk: imx: Rework all imx_clk_hw_composite wrappers
  clk: imx: Rework all clk_hw_register_divider wrappers
  clk: imx: Rework all clk_hw_register_mux wrappers
  clk: imx: Rework all clk_hw_register_gate2 wrappers
  clk: imx: Rework all clk_hw_register_gate wrappers
  clk: imx: Make mux/mux2 clk based helpers use clk_hw based ones
  ...
parents 6880fa6c e8271eff
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/imx8ulp-cgc-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: NXP i.MX8ULP Clock Generation & Control(CGC) Module Binding

maintainers:
  - Jacky Bai <ping.bai@nxp.com>

description: |
  On i.MX8ULP, The clock sources generation, distribution and management is
  under the control of several CGCs & PCCs modules. The CGC modules generate
  and distribute clocks on the device.

properties:
  compatible:
    enum:
      - fsl,imx8ulp-cgc1
      - fsl,imx8ulp-cgc2

  reg:
    maxItems: 1

  '#clock-cells':
    const: 1

required:
  - compatible
  - reg
  - '#clock-cells'

additionalProperties: false

examples:
  # Clock Generation & Control Module node:
  - |
    clock-controller@292c0000 {
        compatible = "fsl,imx8ulp-cgc1";
        reg = <0x292c0000 0x10000>;
        #clock-cells = <1>;
    };
+50 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/imx8ulp-pcc-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: NXP i.MX8ULP Peripheral Clock Controller(PCC) Module Binding

maintainers:
  - Jacky Bai <ping.bai@nxp.com>

description: |
  On i.MX8ULP, The clock sources generation, distribution and management is
  under the control of several CGCs & PCCs modules. The PCC modules control
  software reset, clock selection, optional division and clock gating mode
  for peripherals.

properties:
  compatible:
    enum:
      - fsl,imx8ulp-pcc3
      - fsl,imx8ulp-pcc4
      - fsl,imx8ulp-pcc5

  reg:
    maxItems: 1

  '#clock-cells':
    const: 1

  '#reset-cells':
    const: 1

required:
  - compatible
  - reg
  - '#clock-cells'
  - '#reset-cells'

additionalProperties: false

examples:
  # Peripheral Clock Control Module node:
  - |
    clock-controller@292d0000 {
        compatible = "fsl,imx8ulp-pcc3";
        reg = <0x292d0000 0x10000>;
        #clock-cells = <1>;
        #reset-cells = <1>;
    };
+7 −0
Original line number Diff line number Diff line
@@ -98,3 +98,10 @@ config CLK_IMX8QXP
	select MXC_CLK_SCU
	help
	  Build the driver for IMX8QXP SCU based clocks.

config CLK_IMX8ULP
	tristate "IMX8ULP CCM Clock Driver"
	depends on ARCH_MXC || COMPILE_TEST
	select MXC_CLK
	help
	    Build the driver for i.MX8ULP CCM Clock Driver
+2 −0
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \
				     clk-imx8qxp-rsrc.o clk-imx8qm-rsrc.o
clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o

obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp.o

obj-$(CONFIG_CLK_IMX1)   += clk-imx1.o
obj-$(CONFIG_CLK_IMX25)  += clk-imx25.o
obj-$(CONFIG_CLK_IMX27)  += clk-imx27.o
+84 −4
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/slab.h>

#include "../clk-fractional-divider.h"
@@ -23,17 +24,61 @@
#define PCG_PCD_WIDTH	3
#define PCG_PCD_MASK	0x7

struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
#define SW_RST		BIT(28)

static int pcc_gate_enable(struct clk_hw *hw)
{
	struct clk_gate *gate = to_clk_gate(hw);
	unsigned long flags;
	u32 val;
	int ret;

	ret = clk_gate_ops.enable(hw);
	if (ret)
		return ret;

	spin_lock_irqsave(gate->lock, flags);
	/*
	 * release the sw reset for peripherals associated with
	 * with this pcc clock.
	 */
	val = readl(gate->reg);
	val |= SW_RST;
	writel(val, gate->reg);

	spin_unlock_irqrestore(gate->lock, flags);

	return 0;
}

static void pcc_gate_disable(struct clk_hw *hw)
{
	clk_gate_ops.disable(hw);
}

static int pcc_gate_is_enabled(struct clk_hw *hw)
{
	return clk_gate_ops.is_enabled(hw);
}

static const struct clk_ops pcc_gate_ops = {
	.enable = pcc_gate_enable,
	.disable = pcc_gate_disable,
	.is_enabled = pcc_gate_is_enabled,
};

static struct clk_hw *imx_ulp_clk_hw_composite(const char *name,
				     const char * const *parent_names,
				     int num_parents, bool mux_present,
				     bool rate_present, bool gate_present,
				     void __iomem *reg)
				     void __iomem *reg, bool has_swrst)
{
	struct clk_hw *mux_hw = NULL, *fd_hw = NULL, *gate_hw = NULL;
	struct clk_fractional_divider *fd = NULL;
	struct clk_gate *gate = NULL;
	struct clk_mux *mux = NULL;
	struct clk_hw *hw;
	u32 val;

	if (mux_present) {
		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
@@ -43,6 +88,8 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
		mux->reg = reg;
		mux->shift = PCG_PCS_SHIFT;
		mux->mask = PCG_PCS_MASK;
		if (has_swrst)
			mux->lock = &imx_ccm_lock;
	}

	if (rate_present) {
@@ -60,6 +107,8 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
		fd->nwidth = PCG_PCD_WIDTH;
		fd->nmask = PCG_PCD_MASK;
		fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED;
		if (has_swrst)
			fd->lock = &imx_ccm_lock;
	}

	if (gate_present) {
@@ -72,13 +121,27 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,
		gate_hw = &gate->hw;
		gate->reg = reg;
		gate->bit_idx = PCG_CGC_SHIFT;
		if (has_swrst)
			gate->lock = &imx_ccm_lock;
		/*
		 * make sure clock is gated during clock tree initialization,
		 * the HW ONLY allow clock parent/rate changed with clock gated,
		 * during clock tree initialization, clocks could be enabled
		 * by bootloader, so the HW status will mismatch with clock tree
		 * prepare count, then clock core driver will allow parent/rate
		 * change since the prepare count is zero, but HW actually
		 * prevent the parent/rate change due to the clock is enabled.
		 */
		val = readl_relaxed(reg);
		val &= ~(1 << PCG_CGC_SHIFT);
		writel_relaxed(val, reg);
	}

	hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
				       mux_hw, &clk_mux_ops, fd_hw,
				       &clk_fractional_divider_ops, gate_hw,
				       &clk_gate_ops, CLK_SET_RATE_GATE |
				       CLK_SET_PARENT_GATE);
				       has_swrst ? &pcc_gate_ops : &clk_gate_ops, CLK_SET_RATE_GATE |
				       CLK_SET_PARENT_GATE | CLK_SET_RATE_NO_REPARENT);
	if (IS_ERR(hw)) {
		kfree(mux);
		kfree(fd);
@@ -87,3 +150,20 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name,

	return hw;
}

struct clk_hw *imx7ulp_clk_hw_composite(const char *name, const char * const *parent_names,
				int num_parents, bool mux_present, bool rate_present,
				bool gate_present, void __iomem *reg)
{
	return imx_ulp_clk_hw_composite(name, parent_names, num_parents, mux_present, rate_present,
					gate_present, reg, false);
}

struct clk_hw *imx8ulp_clk_hw_composite(const char *name, const char * const *parent_names,
				int num_parents, bool mux_present, bool rate_present,
				bool gate_present, void __iomem *reg, bool has_swrst)
{
	return imx_ulp_clk_hw_composite(name, parent_names, num_parents, mux_present, rate_present,
					gate_present, reg, has_swrst);
}
EXPORT_SYMBOL_GPL(imx8ulp_clk_hw_composite);
Loading