1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2021 NXP 4 * 5 * Peng Fan <peng.fan@nxp.com> 6 */ 7 8 #include <linux/clk-provider.h> 9 #include <linux/errno.h> 10 #include <linux/export.h> 11 #include <linux/io.h> 12 #include <linux/slab.h> 13 14 #include "clk.h" 15 16 #define CCM_DIV_SHIFT 0 17 #define CCM_DIV_WIDTH 8 18 #define CCM_MUX_SHIFT 8 19 #define CCM_MUX_MASK 3 20 #define CCM_OFF_SHIFT 24 21 22 #define AUTHEN_OFFSET 0x30 23 #define TZ_NS_SHIFT 9 24 #define TZ_NS_MASK BIT(9) 25 26 struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names, 27 int num_parents, void __iomem *reg, 28 unsigned long flags) 29 { 30 struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw; 31 struct clk_hw *div_hw, *gate_hw; 32 struct clk_divider *div = NULL; 33 struct clk_gate *gate = NULL; 34 struct clk_mux *mux = NULL; 35 bool clk_ro = false; 36 37 mux = kzalloc(sizeof(*mux), GFP_KERNEL); 38 if (!mux) 39 goto fail; 40 41 mux_hw = &mux->hw; 42 mux->reg = reg; 43 mux->shift = CCM_MUX_SHIFT; 44 mux->mask = CCM_MUX_MASK; 45 mux->lock = &imx_ccm_lock; 46 47 div = kzalloc(sizeof(*div), GFP_KERNEL); 48 if (!div) 49 goto fail; 50 51 div_hw = &div->hw; 52 div->reg = reg; 53 div->shift = CCM_DIV_SHIFT; 54 div->width = CCM_DIV_WIDTH; 55 div->lock = &imx_ccm_lock; 56 div->flags = CLK_DIVIDER_ROUND_CLOSEST; 57 58 if (!(readl(reg + AUTHEN_OFFSET) & TZ_NS_MASK)) 59 clk_ro = true; 60 61 if (clk_ro) { 62 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, 63 mux_hw, &clk_mux_ro_ops, div_hw, 64 &clk_divider_ro_ops, NULL, NULL, flags); 65 } else { 66 gate = kzalloc(sizeof(*gate), GFP_KERNEL); 67 if (!gate) 68 goto fail; 69 70 gate_hw = &gate->hw; 71 gate->reg = reg; 72 gate->bit_idx = CCM_OFF_SHIFT; 73 gate->lock = &imx_ccm_lock; 74 gate->flags = CLK_GATE_SET_TO_DISABLE; 75 76 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, 77 mux_hw, &clk_mux_ops, div_hw, 78 &clk_divider_ops, gate_hw, 79 &clk_gate_ops, flags | CLK_SET_RATE_NO_REPARENT); 80 } 81 82 if (IS_ERR(hw)) 83 goto fail; 84 85 return hw; 86 87 fail: 88 kfree(gate); 89 kfree(div); 90 kfree(mux); 91 return ERR_CAST(hw); 92 } 93 EXPORT_SYMBOL_GPL(imx93_clk_composite_flags); 94