Commit 5484bb83 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

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

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

Pull i.MX clk driver updates from Shawn Guo:

- A few patches from Abel Vesa as preparation of adding audiomix clock
  support
- A couple of cleanups from Anson Huang on clk-sscg-pll and clk-pllv3
  driver
- Update imx7ulp clock driver to use imx_clk_hw_cpu() for making the
  change of ARM core clock easier
- Drop dependency on ARM64 for i.MX8M clock driver, as there is a move
  to support aarch32 mode on aarch64 hardware
- A series from Peng Fan to improve i.MX8M clock drivers, using
  composite clock for core and bus clk slice
- Set a better parent clock for flexcan on i.MX6UL to support CiA102
  defined bit rates

* tag 'clk-imx-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux:
  clk: imx: use imx8m_clk_hw_composite_bus for i.MX8M bus clk slice
  clk: imx: add imx8m_clk_hw_composite_bus
  clk: imx: add mux ops for i.MX8M composite clk
  clk: imx8m: migrate A53 clk root to use composite core
  clk: imx8mp: use imx8m_clk_hw_composite_core to simplify code
  clk: imx8mp: Define gates for pll1/2 fixed dividers
  clk: imx: imx8mp: fix pll mux bit
  clk: imx8m: drop clk_hw_set_parent for A53
  dt-bindings: clocks: imx8mp: Add ids for audiomix clocks
  clk: imx: Add helpers for passing the device as argument
  clk: imx: pll14xx: Add the device as argument when registering
  clk: imx: gate2: Allow single bit gating clock
  clk: imx: clk-pllv3: Use readl_relaxed_poll_timeout() for PLL lock wait
  clk: imx: clk-sscg-pll: Remove unnecessary blank lines
  clk: imx: drop the dependency on ARM64 for i.MX8M
  clk: imx7ulp: make it easy to change ARM core clk
  clk: imx: imx6ul: change flexcan clock to support CiA bitrates
parents 8f3d9f35 b1657ad7
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -10,25 +10,25 @@ config MXC_CLK_SCU

config CLK_IMX8MM
	bool "IMX8MM CCM Clock Driver"
	depends on ARCH_MXC && ARM64
	depends on ARCH_MXC
	help
	    Build the driver for i.MX8MM CCM Clock Driver

config CLK_IMX8MN
	bool "IMX8MN CCM Clock Driver"
	depends on ARCH_MXC && ARM64
	depends on ARCH_MXC
	help
	    Build the driver for i.MX8MN CCM Clock Driver

config CLK_IMX8MP
	bool "IMX8MP CCM Clock Driver"
	depends on ARCH_MXC && ARM64
	depends on ARCH_MXC
	help
	    Build the driver for i.MX8MP CCM Clock Driver

config CLK_IMX8MQ
	bool "IMX8MQ CCM Clock Driver"
	depends on ARCH_MXC && ARM64
	depends on ARCH_MXC
	help
	    Build the driver for i.MX8MQ CCM Clock Driver

+55 −1
Original line number Diff line number Diff line
@@ -124,6 +124,52 @@ static const struct clk_ops imx8m_clk_composite_divider_ops = {
	.set_rate = imx8m_clk_composite_divider_set_rate,
};

static u8 imx8m_clk_composite_mux_get_parent(struct clk_hw *hw)
{
	return clk_mux_ops.get_parent(hw);
}

static int imx8m_clk_composite_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);

	reg = readl(mux->reg);
	reg &= ~(mux->mask << mux->shift);
	val = val << mux->shift;
	reg |= val;
	/*
	 * write twice to make sure non-target interface
	 * SEL_A/B point the same clk input.
	 */
	writel(reg, mux->reg);
	writel(reg, mux->reg);

	if (mux->lock)
		spin_unlock_irqrestore(mux->lock, flags);

	return 0;
}

static int
imx8m_clk_composite_mux_determine_rate(struct clk_hw *hw,
				       struct clk_rate_request *req)
{
	return clk_mux_ops.determine_rate(hw, req);
}


static const struct clk_ops imx8m_clk_composite_mux_ops = {
	.get_parent = imx8m_clk_composite_mux_get_parent,
	.set_parent = imx8m_clk_composite_mux_set_parent,
	.determine_rate = imx8m_clk_composite_mux_determine_rate,
};

struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
					const char * const *parent_names,
					int num_parents, void __iomem *reg,
@@ -136,6 +182,7 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
	struct clk_gate *gate = NULL;
	struct clk_mux *mux = NULL;
	const struct clk_ops *divider_ops;
	const struct clk_ops *mux_ops;

	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
	if (!mux)
@@ -157,10 +204,17 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
		div->shift = PCG_DIV_SHIFT;
		div->width = PCG_CORE_DIV_WIDTH;
		divider_ops = &clk_divider_ops;
		mux_ops = &imx8m_clk_composite_mux_ops;
	} else if (composite_flags & IMX_COMPOSITE_BUS) {
		div->shift = PCG_PREDIV_SHIFT;
		div->width = PCG_PREDIV_WIDTH;
		divider_ops = &imx8m_clk_composite_divider_ops;
		mux_ops = &imx8m_clk_composite_mux_ops;
	} else {
		div->shift = PCG_PREDIV_SHIFT;
		div->width = PCG_PREDIV_WIDTH;
		divider_ops = &imx8m_clk_composite_divider_ops;
		mux_ops = &clk_mux_ops;
	}

	div->lock = &imx_ccm_lock;
@@ -176,7 +230,7 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
	gate->lock = &imx_ccm_lock;

	hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
			mux_hw, &clk_mux_ops, div_hw,
			mux_hw, mux_ops, div_hw,
			divider_ops, gate_hw, &clk_gate_ops, flags);
	if (IS_ERR(hw))
		goto fail;
+23 −8
Original line number Diff line number Diff line
@@ -41,21 +41,26 @@ static int clk_gate2_enable(struct clk_hw *hw)
	struct clk_gate2 *gate = to_clk_gate2(hw);
	u32 reg;
	unsigned long flags;
	int ret = 0;

	spin_lock_irqsave(gate->lock, flags);

	if (gate->share_count && (*gate->share_count)++ > 0)
		goto out;

	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
		ret = clk_gate_ops.enable(hw);
	} else {
		reg = readl(gate->reg);
		reg &= ~(3 << gate->bit_idx);
		reg |= gate->cgr_val << gate->bit_idx;
		writel(reg, gate->reg);
	}

out:
	spin_unlock_irqrestore(gate->lock, flags);

	return 0;
	return ret;
}

static void clk_gate2_disable(struct clk_hw *hw)
@@ -73,9 +78,13 @@ static void clk_gate2_disable(struct clk_hw *hw)
			goto out;
	}

	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
		clk_gate_ops.disable(hw);
	} else {
		reg = readl(gate->reg);
		reg &= ~(3 << gate->bit_idx);
		writel(reg, gate->reg);
	}

out:
	spin_unlock_irqrestore(gate->lock, flags);
@@ -95,6 +104,9 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)
{
	struct clk_gate2 *gate = to_clk_gate2(hw);

	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
		return clk_gate_ops.is_enabled(hw);

	return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
}

@@ -104,6 +116,9 @@ static void clk_gate2_disable_unused(struct clk_hw *hw)
	unsigned long flags;
	u32 reg;

	if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
		return;

	spin_lock_irqsave(gate->lock, flags);

	if (!gate->share_count || *gate->share_count == 0) {
+1 −1
Original line number Diff line number Diff line
@@ -503,7 +503,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
		clk_prepare_enable(hws[IMX6UL_CLK_USBPHY2_GATE]->clk);
	}

	clk_set_parent(hws[IMX6UL_CLK_CAN_SEL]->clk, hws[IMX6UL_CLK_PLL3_60M]->clk);
	clk_set_parent(hws[IMX6UL_CLK_CAN_SEL]->clk, hws[IMX6UL_CLK_PLL3_80M]->clk);
	if (clk_on_imx6ul())
		clk_set_parent(hws[IMX6UL_CLK_SIM_PRE_SEL]->clk, hws[IMX6UL_CLK_PLL3_USB_OTG]->clk);
	else if (clk_on_imx6ull())
+4 −2
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ static const char * const ddr_sels[] = { "apll_pfd_sel", "dummy", "dummy", "dum
static const char * const nic_sels[]		= { "firc", "ddr_clk", };
static const char * const periph_plat_sels[]	= { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
static const char * const periph_bus_sels[]	= { "dummy", "sosc_bus_clk", "dummy", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
static const char * const arm_sels[]		= { "divcore", "dummy", "dummy", "hsrun_divcore", };
static const char * const arm_sels[]		= { "core", "dummy", "dummy", "hsrun_core", };

/* used by sosc/sirc/firc/ddr/spll/apll dividers */
static const struct clk_div_table ulp_div_table[] = {
@@ -121,7 +121,9 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
	hws[IMX7ULP_CLK_DDR_SEL]	= imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 2, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);

	hws[IMX7ULP_CLK_CORE_DIV]	= imx_clk_hw_divider_flags("divcore",	"scs_sel",  base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
	hws[IMX7ULP_CLK_CORE]		= imx_clk_hw_cpu("core", "divcore", hws[IMX7ULP_CLK_CORE_DIV]->clk, hws[IMX7ULP_CLK_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
	hws[IMX7ULP_CLK_HSRUN_CORE_DIV] = imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
	hws[IMX7ULP_CLK_HSRUN_CORE] = imx_clk_hw_cpu("hsrun_core", "hsrun_divcore", hws[IMX7ULP_CLK_HSRUN_CORE_DIV]->clk, hws[IMX7ULP_CLK_HSRUN_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);

	hws[IMX7ULP_CLK_DDR_DIV]	= imx_clk_hw_divider_gate("ddr_clk", "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3,
							       0, ulp_div_table, &imx_ccm_lock);
@@ -270,7 +272,7 @@ static void __init imx7ulp_clk_smc1_init(struct device_node *np)
	base = of_iomap(np, 0);
	WARN_ON(!base);

	hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_IS_CRITICAL);
	hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_SET_RATE_PARENT);

	imx_check_clk_hws(hws, clk_data->num);

Loading