Commit 989e4659 authored by Stephen Boyd's avatar Stephen Boyd

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

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

Pull i.MX clk driver updates from Abel Vesa:

 - Remove CLK_SET_RATE_PARENT flag from LDB clocks on i.MX6SX
 - Keep UART clocks enabled during kernel boot if earlycon is set
 - Drop the imx_unregister_clocks as there are no users for it
 - Switch to _safe iterator on imx_clk_scu_unregister to avoid use after free
 - Add determine_rate op to the imx8m composite clock
 - Use device managed API for iomap and kzalloc for i.MXRT1050,
   i.MX8MN, i.MX8MP and i.MX93 clock controller drivers
 - Add missing interrupt DT property for the i.MX8M clock controller

* tag 'clk-imx-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux:
  clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
  clk: imx93: fix memory leak and missing unwind goto in imx93_clocks_probe
  clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
  dt-bindings: clock: imx8m: Add missing interrupt property
  clk: imx: clk-imxrt1050: fix memory leak in imxrt1050_clocks_probe
  clk: imx: composite-8m: Add imx8m_divider_determine_rate
  clk: imx: scu: use _safe list iterator to avoid a use after free
  clk: imx: drop imx_unregister_clocks
  clk: imx6ul: retain early UART clocks during kernel init
  clk: imx: imx6sx: Remove CLK_SET_RATE_PARENT from the LDB clocks
parents ac9a7868 878b02d5
......@@ -24,6 +24,9 @@ properties:
reg:
maxItems: 1
interrupts:
maxItems: 2
clocks:
minItems: 6
maxItems: 7
......
......@@ -119,10 +119,41 @@ static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
return ret;
}
static int imx8m_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_divider *divider = to_clk_divider(hw);
int prediv_value;
int div_value;
/* if read only, just return current value */
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
u32 val;
val = readl(divider->reg);
prediv_value = val >> divider->shift;
prediv_value &= clk_div_mask(divider->width);
prediv_value++;
div_value = val >> PCG_DIV_SHIFT;
div_value &= clk_div_mask(PCG_DIV_WIDTH);
div_value++;
return divider_ro_determine_rate(hw, req, divider->table,
PCG_PREDIV_WIDTH + PCG_DIV_WIDTH,
divider->flags, prediv_value * div_value);
}
return divider_determine_rate(hw, req, divider->table,
PCG_PREDIV_WIDTH + PCG_DIV_WIDTH,
divider->flags);
}
static const struct clk_ops imx8m_clk_composite_divider_ops = {
.recalc_rate = imx8m_clk_composite_divider_recalc_rate,
.round_rate = imx8m_clk_composite_divider_round_rate,
.set_rate = imx8m_clk_composite_divider_set_rate,
.determine_rate = imx8m_divider_determine_rate,
};
static u8 imx8m_clk_composite_mux_get_parent(struct clk_hw *hw)
......
......@@ -302,10 +302,10 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
hws[IMX6SX_CLK_CKO2_SEL] = imx_clk_hw_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
hws[IMX6SX_CLK_CKO] = imx_clk_hw_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels));
hws[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
hws[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
hws[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_hw_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels), CLK_SET_RATE_PARENT);
hws[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_hw_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels), CLK_SET_RATE_PARENT);
hws[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
hws[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
hws[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_hw_mux("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels));
hws[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_hw_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
hws[IMX6SX_CLK_LCDIF1_PRE_SEL] = imx_clk_hw_mux_flags("lcdif1_pre_sel", base + 0x38, 15, 3, lcdif1_pre_sels, ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT);
hws[IMX6SX_CLK_LCDIF1_SEL] = imx_clk_hw_mux_flags("lcdif1_sel", base + 0x38, 9, 3, lcdif1_sels, ARRAY_SIZE(lcdif1_sels), CLK_SET_RATE_PARENT);
......
......@@ -544,6 +544,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clk_set_parent(hws[IMX6UL_CLK_ENET1_REF_SEL]->clk, hws[IMX6UL_CLK_ENET_REF]->clk);
clk_set_parent(hws[IMX6UL_CLK_ENET2_REF_SEL]->clk, hws[IMX6UL_CLK_ENET2_REF]->clk);
imx_register_uart_clocks();
}
CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init);
......@@ -323,7 +323,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
void __iomem *base;
int ret;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
IMX8MN_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
......@@ -340,10 +340,10 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws[IMX8MN_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop");
base = of_iomap(np, 0);
base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
if (WARN_ON(!base)) {
ret = -ENOMEM;
if (WARN_ON(IS_ERR(base))) {
ret = PTR_ERR(base);
goto unregister_hws;
}
......
......@@ -414,25 +414,22 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np;
void __iomem *anatop_base, *ccm_base;
int err;
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
anatop_base = of_iomap(np, 0);
anatop_base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
if (WARN_ON(!anatop_base))
return -ENOMEM;
if (WARN_ON(IS_ERR(anatop_base)))
return PTR_ERR(anatop_base);
np = dev->of_node;
ccm_base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(ccm_base))) {
iounmap(anatop_base);
if (WARN_ON(IS_ERR(ccm_base)))
return PTR_ERR(ccm_base);
}
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data)) {
iounmap(anatop_base);
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
}
clk_hw_data->num = IMX8MP_CLK_END;
hws = clk_hw_data->hws;
......@@ -722,7 +719,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
imx_check_clk_hws(hws, IMX8MP_CLK_END);
of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
if (err < 0) {
dev_err(dev, "failed to register hws for i.MX8MP\n");
imx_unregister_hw_clocks(hws, IMX8MP_CLK_END);
return err;
}
imx_register_uart_clocks();
......
......@@ -264,7 +264,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
void __iomem *base, *anatop_base;
int i, ret;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
IMX93_CLK_END), GFP_KERNEL);
if (!clk_hw_data)
return -ENOMEM;
......@@ -288,10 +288,12 @@ static int imx93_clocks_probe(struct platform_device *pdev)
"sys_pll_pfd2", 1, 2);
np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop");
anatop_base = of_iomap(np, 0);
anatop_base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
if (WARN_ON(!anatop_base))
return -ENOMEM;
if (WARN_ON(IS_ERR(anatop_base))) {
ret = PTR_ERR(base);
goto unregister_hws;
}
clks[IMX93_CLK_ARM_PLL] = imx_clk_fracn_gppll_integer("arm_pll", "osc_24m",
anatop_base + 0x1000,
......@@ -304,8 +306,8 @@ static int imx93_clocks_probe(struct platform_device *pdev)
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base))) {
iounmap(anatop_base);
return PTR_ERR(base);
ret = PTR_ERR(base);
goto unregister_hws;
}
for (i = 0; i < ARRAY_SIZE(root_array); i++) {
......@@ -345,7 +347,6 @@ static int imx93_clocks_probe(struct platform_device *pdev)
unregister_hws:
imx_unregister_hw_clocks(clks, IMX93_CLK_END);
iounmap(anatop_base);
return ret;
}
......
......@@ -42,7 +42,7 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
struct device_node *anp;
int ret;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
IMXRT1050_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
......@@ -53,10 +53,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
hws[IMXRT1050_CLK_OSC] = imx_get_clk_hw_by_name(np, "osc");
anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop");
pll_base = of_iomap(anp, 0);
pll_base = devm_of_iomap(dev, anp, 0, NULL);
of_node_put(anp);
if (WARN_ON(!pll_base))
return -ENOMEM;
if (WARN_ON(IS_ERR(pll_base))) {
ret = PTR_ERR(pll_base);
goto unregister_hws;
}
/* Anatop clocks */
hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL);
......@@ -104,8 +106,10 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
/* CCM clocks */
ccm_base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(ccm_base)))
return PTR_ERR(ccm_base);
if (WARN_ON(IS_ERR(ccm_base))) {
ret = PTR_ERR(ccm_base);
goto unregister_hws;
}
hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3);
hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2,
......@@ -149,8 +153,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
if (ret < 0) {
dev_err(dev, "Failed to register clks for i.MXRT1050.\n");
imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END);
goto unregister_hws;
}
return 0;
unregister_hws:
imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END);
return ret;
}
static const struct of_device_id imxrt1050_clk_of_match[] = {
......
......@@ -707,11 +707,11 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
void imx_clk_scu_unregister(void)
{
struct imx_scu_clk_node *clk;
struct imx_scu_clk_node *clk, *n;
int i;
for (i = 0; i < IMX_SC_R_LAST; i++) {
list_for_each_entry(clk, &imx_scu_clks[i], node) {
list_for_each_entry_safe(clk, n, &imx_scu_clks[i], node) {
clk_hw_unregister(clk->hw);
kfree(clk);
}
......
......@@ -20,14 +20,6 @@ EXPORT_SYMBOL_GPL(imx_ccm_lock);
bool mcore_booted;
EXPORT_SYMBOL_GPL(mcore_booted);
void imx_unregister_clocks(struct clk *clks[], unsigned int count)
{
unsigned int i;
for (i = 0; i < count; i++)
clk_unregister(clks[i]);
}
void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count)
{
unsigned int i;
......
......@@ -19,7 +19,6 @@ static inline void imx_register_uart_clocks(void)
}
#endif
void imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn);
void imx_unregister_clocks(struct clk *clks[], unsigned int count);
void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count);
extern void imx_cscmr1_fixup(u32 *val);
......
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