Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright 2021 NXP
0004  *
0005  * Peng Fan <peng.fan@nxp.com>
0006  */
0007 
0008 #include <linux/clk-provider.h>
0009 #include <linux/errno.h>
0010 #include <linux/export.h>
0011 #include <linux/io.h>
0012 #include <linux/slab.h>
0013 
0014 #include "clk.h"
0015 
0016 #define CCM_DIV_SHIFT   0
0017 #define CCM_DIV_WIDTH   8
0018 #define CCM_MUX_SHIFT   8
0019 #define CCM_MUX_MASK    3
0020 #define CCM_OFF_SHIFT   24
0021 
0022 #define AUTHEN_OFFSET   0x30
0023 #define TZ_NS_SHIFT 9
0024 #define TZ_NS_MASK  BIT(9)
0025 
0026 struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names,
0027                      int num_parents, void __iomem *reg,
0028                      unsigned long flags)
0029 {
0030     struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw;
0031     struct clk_hw *div_hw, *gate_hw;
0032     struct clk_divider *div = NULL;
0033     struct clk_gate *gate = NULL;
0034     struct clk_mux *mux = NULL;
0035     bool clk_ro = false;
0036 
0037     mux = kzalloc(sizeof(*mux), GFP_KERNEL);
0038     if (!mux)
0039         goto fail;
0040 
0041     mux_hw = &mux->hw;
0042     mux->reg = reg;
0043     mux->shift = CCM_MUX_SHIFT;
0044     mux->mask = CCM_MUX_MASK;
0045     mux->lock = &imx_ccm_lock;
0046 
0047     div = kzalloc(sizeof(*div), GFP_KERNEL);
0048     if (!div)
0049         goto fail;
0050 
0051     div_hw = &div->hw;
0052     div->reg = reg;
0053     div->shift = CCM_DIV_SHIFT;
0054     div->width = CCM_DIV_WIDTH;
0055     div->lock = &imx_ccm_lock;
0056     div->flags = CLK_DIVIDER_ROUND_CLOSEST;
0057 
0058     if (!(readl(reg + AUTHEN_OFFSET) & TZ_NS_MASK))
0059         clk_ro = true;
0060 
0061     if (clk_ro) {
0062         hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
0063                            mux_hw, &clk_mux_ro_ops, div_hw,
0064                            &clk_divider_ro_ops, NULL, NULL, flags);
0065     } else {
0066         gate = kzalloc(sizeof(*gate), GFP_KERNEL);
0067         if (!gate)
0068             goto fail;
0069 
0070         gate_hw = &gate->hw;
0071         gate->reg = reg;
0072         gate->bit_idx = CCM_OFF_SHIFT;
0073         gate->lock = &imx_ccm_lock;
0074         gate->flags = CLK_GATE_SET_TO_DISABLE;
0075 
0076         hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
0077                            mux_hw, &clk_mux_ops, div_hw,
0078                            &clk_divider_ops, gate_hw,
0079                            &clk_gate_ops, flags | CLK_SET_RATE_NO_REPARENT);
0080     }
0081 
0082     if (IS_ERR(hw))
0083         goto fail;
0084 
0085     return hw;
0086 
0087 fail:
0088     kfree(gate);
0089     kfree(div);
0090     kfree(mux);
0091     return ERR_CAST(hw);
0092 }
0093 EXPORT_SYMBOL_GPL(imx93_clk_composite_flags);