Commit 498e1652 authored by Stephen Boyd's avatar Stephen Boyd

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

Merge tag 'imx-clk-5.6' 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 series from Abel Vesa to do some trivial cleanups which will be
   helpful for i.MX clock driver switching to clk_hw based API
 - A series from Anson Huang to add i.MX8MP clock driver support
 - Disable non-functional divider between pll4_audio_div and
   pll4_post_div on imx6q
 - Fix watchdog2 clock name typo in imx7ulp clock driver
 - A couple of patches from Leonard Crestez to set CLK_GET_RATE_NOCACHE
   flag for DRAM related clocks on i.MX8M SoCs
 - Suppress bind attrs for i.MX8M clock driver to avoid the possibility
   of reloading the driver at runtime
 - Add a big comment in imx8qxp-lpcg driver to tell why
   devm_platform_ioremap_resource() shouldn't be used for the driver
 - A correction on i.MX8MN usb1_ctrl parent clock setting
 - A couple of trivial cleanup on clk-divider-gate driver
 - A series from Peng Fan to convert i.MX8M clock drivers to clk_hw
   based API

* tag 'imx-clk-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: (32 commits)
  clk: imx: Add support for i.MX8MP clock driver
  dt-bindings: imx: Add clock binding doc for i.MX8MP
  clk: imx: gate4: Switch imx_clk_gate4_flags() to clk_hw based API
  clk: imx: imx8mq: Switch to clk_hw based API
  clk: imx: imx8mm: Switch to clk_hw based API
  clk: imx: imx8mn: Switch to clk_hw based API
  clk: imx: Remove __init for imx_obtain_fixed_clk_hw() API
  clk: imx: gate3: Switch to clk_hw based API
  clk: imx: add hw API imx_clk_hw_mux2_flags
  clk: imx: add imx_unregister_hw_clocks
  clk: imx: clk-composite-8m: Switch to clk_hw based API
  clk: imx: clk-pll14xx: Switch to clk_hw based API
  clk: imx7up: Rename the clks to hws
  clk: imx: Rename the imx_clk_divider_gate to imply it's clk_hw based
  clk: imx: Rename the imx_clk_pfdv2 to imply it's clk_hw based
  clk: imx: Rename the imx_clk_pllv4 to imply it's clk_hw based
  clk: imx: Rename sccg and frac pll register to suggest clk_hw
  clk: imx: imx7ulp composite: Rename to show is clk_hw based
  clk: imx: pllv2: Switch to clk_hw based API
  clk: imx: pllv1: Switch to clk_hw based API
  ...
parents e42617b8 9c140d99
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/bindings/clock/imx8mp-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP i.MX8M Plus Clock Control Module Binding
maintainers:
- Anson Huang <Anson.Huang@nxp.com>
description:
NXP i.MX8M Plus clock control module is an integrated clock controller, which
generates and supplies to all modules.
properties:
compatible:
const: fsl,imx8mp-ccm
reg:
maxItems: 1
clocks:
items:
- description: 32k osc
- description: 24m osc
- description: ext1 clock input
- description: ext2 clock input
- description: ext3 clock input
- description: ext4 clock input
clock-names:
items:
- const: osc_32k
- const: osc_24m
- const: clk_ext1
- const: clk_ext2
- const: clk_ext3
- const: clk_ext4
'#clock-cells':
const: 1
description:
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mp-clock.h
for the full list of i.MX8M Plus clock IDs.
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
examples:
# Clock Control Module node:
- |
clk: clock-controller@30380000 {
compatible = "fsl,imx8mp-ccm";
reg = <0x30380000 0x10000>;
#clock-cells = <1>;
clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>,
<&clk_ext2>, <&clk_ext3>, <&clk_ext4>;
clock-names = "osc_32k", "osc_24m", "clk_ext1",
"clk_ext2", "clk_ext3", "clk_ext4";
};
...
......@@ -20,6 +20,12 @@ config CLK_IMX8MN
help
Build the driver for i.MX8MN CCM Clock Driver
config CLK_IMX8MP
bool "IMX8MP CCM Clock Driver"
depends on ARCH_MXC && ARM64
help
Build the driver for i.MX8MP CCM Clock Driver
config CLK_IMX8MQ
bool "IMX8MQ CCM Clock Driver"
depends on ARCH_MXC && ARM64
......
......@@ -18,7 +18,7 @@ obj-$(CONFIG_MXC_CLK) += \
clk-pllv2.o \
clk-pllv3.o \
clk-pllv4.o \
clk-sccg-pll.o \
clk-sscg-pll.o \
clk-pll14xx.o
obj-$(CONFIG_MXC_CLK_SCU) += \
......@@ -27,6 +27,7 @@ obj-$(CONFIG_MXC_CLK_SCU) += \
obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o
obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
......
......@@ -21,7 +21,7 @@
#define PCG_PCD_WIDTH 3
#define PCG_PCD_MASK 0x7
struct clk_hw *imx7ulp_clk_composite(const char *name,
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,
......
......@@ -123,7 +123,7 @@ static const struct clk_ops imx8m_clk_composite_divider_ops = {
.set_rate = imx8m_clk_composite_divider_set_rate,
};
struct clk *imx8m_clk_composite_flags(const char *name,
struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
const char * const *parent_names,
int num_parents, void __iomem *reg,
unsigned long flags)
......@@ -169,7 +169,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
if (IS_ERR(hw))
goto fail;
return hw->clk;
return hw;
fail:
kfree(gate);
......
......@@ -43,7 +43,7 @@ static unsigned long clk_divider_gate_recalc_rate(struct clk_hw *hw,
{
struct clk_divider_gate *div_gate = to_clk_divider_gate(hw);
struct clk_divider *div = to_clk_divider(hw);
unsigned long flags = 0;
unsigned long flags;
unsigned int val;
spin_lock_irqsave(div->lock, flags);
......@@ -75,7 +75,7 @@ static int clk_divider_gate_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_divider_gate *div_gate = to_clk_divider_gate(hw);
struct clk_divider *div = to_clk_divider(hw);
unsigned long flags = 0;
unsigned long flags;
int value;
u32 val;
......@@ -104,7 +104,7 @@ static int clk_divider_enable(struct clk_hw *hw)
{
struct clk_divider_gate *div_gate = to_clk_divider_gate(hw);
struct clk_divider *div = to_clk_divider(hw);
unsigned long flags = 0;
unsigned long flags;
u32 val;
if (!div_gate->cached_val) {
......@@ -127,7 +127,7 @@ static void clk_divider_disable(struct clk_hw *hw)
{
struct clk_divider_gate *div_gate = to_clk_divider_gate(hw);
struct clk_divider *div = to_clk_divider(hw);
unsigned long flags = 0;
unsigned long flags;
u32 val;
spin_lock_irqsave(div->lock, flags);
......@@ -167,13 +167,13 @@ static const struct clk_ops clk_divider_gate_ops = {
};
/*
* NOTE: In order to resue the most code from the common divider,
* NOTE: In order to reuse the most code from the common divider,
* we also design our divider following the way that provids an extra
* clk_divider_flags, however it's fixed to CLK_DIVIDER_ONE_BASED by
* default as our HW is. Besides that it supports only CLK_DIVIDER_READ_ONLY
* flag which can be specified by user flexibly.
*/
struct clk_hw *imx_clk_divider_gate(const char *name, const char *parent_name,
struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name,
unsigned long flags, void __iomem *reg,
u8 shift, u8 width, u8 clk_divider_flags,
const struct clk_div_table *table,
......
......@@ -201,8 +201,9 @@ static const struct clk_ops clk_frac_pll_ops = {
.set_rate = clk_pll_set_rate,
};
struct clk *imx_clk_frac_pll(const char *name, const char *parent_name,
void __iomem *base)
struct clk_hw *imx_clk_hw_frac_pll(const char *name,
const char *parent_name,
void __iomem *base)
{
struct clk_init_data init;
struct clk_frac_pll *pll;
......@@ -230,5 +231,5 @@ struct clk *imx_clk_frac_pll(const char *name, const char *parent_name,
return ERR_PTR(ret);
}
return hw->clk;
return hw;
}
......@@ -598,7 +598,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
}
hws[IMX6QDL_CLK_PLL4_POST_DIV] = clk_hw_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
hws[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_hw_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
if (clk_on_imx6q() || clk_on_imx6qp())
hws[IMX6QDL_CLK_PLL4_AUDIO_DIV] = imx_clk_hw_fixed_factor("pll4_audio_div", "pll4_post_div", 1, 1);
else
hws[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_hw_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
hws[IMX6QDL_CLK_PLL5_POST_DIV] = clk_hw_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
hws[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_hw_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -173,6 +173,17 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
if (!ss_lpcg)
return -ENODEV;
/*
* Please don't replace this with devm_platform_ioremap_resource.
*
* devm_platform_ioremap_resource calls devm_ioremap_resource which
* differs from devm_ioremap by also calling devm_request_mem_region
* and preventing other mappings in the same area.
*
* On imx8 the LPCG nodes map entire subsystems and overlap
* peripherals, this means that using devm_platform_ioremap_resource
* will cause many devices to fail to probe including serial ports.
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
......
......@@ -166,7 +166,7 @@ static const struct clk_ops clk_pfdv2_ops = {
.is_enabled = clk_pfdv2_is_enabled,
};
struct clk_hw *imx_clk_pfdv2(const char *name, const char *parent_name,
struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name,
void __iomem *reg, u8 idx)
{
struct clk_init_data init;
......
......@@ -67,6 +67,13 @@ struct imx_pll14xx_clk imx_1443x_pll = {
.rate_count = ARRAY_SIZE(imx_pll1443x_tbl),
};
struct imx_pll14xx_clk imx_1443x_dram_pll = {
.type = PLL_1443X,
.rate_table = imx_pll1443x_tbl,
.rate_count = ARRAY_SIZE(imx_pll1443x_tbl),
.flags = CLK_GET_RATE_NOCACHE,
};
struct imx_pll14xx_clk imx_1416x_pll = {
.type = PLL_1416X,
.rate_table = imx_pll1416x_tbl,
......@@ -369,13 +376,14 @@ static const struct clk_ops clk_pll1443x_ops = {
.set_rate = clk_pll1443x_set_rate,
};
struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
void __iomem *base,
const struct imx_pll14xx_clk *pll_clk)
struct clk_hw *imx_clk_hw_pll14xx(const char *name, const char *parent_name,
void __iomem *base,
const struct imx_pll14xx_clk *pll_clk)
{
struct clk_pll14xx *pll;
struct clk *clk;
struct clk_hw *hw;
struct clk_init_data init;
int ret;
u32 val;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
......@@ -412,12 +420,15 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
val &= ~BYPASS_MASK;
writel_relaxed(val, pll->base + GNRL_CTL);
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll %s %lu\n",
__func__, name, PTR_ERR(clk));
hw = &pll->hw;
ret = clk_hw_register(NULL, hw);
if (ret) {
pr_err("%s: failed to register pll %s %d\n",
__func__, name, ret);
kfree(pll);
return ERR_PTR(ret);
}
return clk;
return hw;
}
......@@ -111,12 +111,13 @@ static const struct clk_ops clk_pllv1_ops = {
.recalc_rate = clk_pllv1_recalc_rate,
};
struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
struct clk_hw *imx_clk_hw_pllv1(enum imx_pllv1_type type, const char *name,
const char *parent, void __iomem *base)
{
struct clk_pllv1 *pll;
struct clk *clk;
struct clk_hw *hw;
struct clk_init_data init;
int ret;
pll = kmalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
......@@ -132,10 +133,13 @@ struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
init.num_parents = 1;
pll->hw.init = &init;
hw = &pll->hw;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk))
ret = clk_hw_register(NULL, hw);
if (ret) {
kfree(pll);
return ERR_PTR(ret);
}
return clk;
return hw;
}
......@@ -239,12 +239,13 @@ static const struct clk_ops clk_pllv2_ops = {
.set_rate = clk_pllv2_set_rate,
};
struct clk *imx_clk_pllv2(const char *name, const char *parent,
struct clk_hw *imx_clk_hw_pllv2(const char *name, const char *parent,
void __iomem *base)
{
struct clk_pllv2 *pll;
struct clk *clk;
struct clk_hw *hw;
struct clk_init_data init;
int ret;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
......@@ -259,10 +260,13 @@ struct clk *imx_clk_pllv2(const char *name, const char *parent,
init.num_parents = 1;
pll->hw.init = &init;
hw = &pll->hw;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk))
ret = clk_hw_register(NULL, hw);
if (ret) {
kfree(pll);
return ERR_PTR(ret);
}
return clk;
return hw;
}
......@@ -206,7 +206,7 @@ static const struct clk_ops clk_pllv4_ops = {
.is_enabled = clk_pllv4_is_enabled,
};
struct clk_hw *imx_clk_pllv4(const char *name, const char *parent_name,
struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name,
void __iomem *base)
{
struct clk_pllv4 *pll;
......
......@@ -22,6 +22,14 @@ void imx_unregister_clocks(struct clk *clks[], unsigned int count)
clk_unregister(clks[i]);
}
void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count)
{
unsigned int i;
for (i = 0; i < count; i++)
clk_hw_unregister(hws[i]);
}
void __init imx_mmdc_mask_handshake(void __iomem *ccm_base,
unsigned int chn)
{
......@@ -94,8 +102,8 @@ struct clk_hw * __init imx_obtain_fixed_clock_hw(
return __clk_get_hw(clk);
}
struct clk_hw * __init imx_obtain_fixed_clk_hw(struct device_node *np,
const char *name)
struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
const char *name)
{
struct clk *clk;
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment