0001
0002
0003
0004
0005
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);