1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2018 NXP 4 * Dong Aisheng <aisheng.dong@nxp.com> 5 */ 6 7 #include <linux/bits.h> 8 #include <linux/clk-provider.h> 9 #include <linux/delay.h> 10 #include <linux/err.h> 11 #include <linux/io.h> 12 #include <linux/slab.h> 13 #include <linux/spinlock.h> 14 #include <linux/units.h> 15 16 #include "clk-scu.h" 17 18 static DEFINE_SPINLOCK(imx_lpcg_scu_lock); 19 20 #define CLK_GATE_SCU_LPCG_MASK 0x3 21 #define CLK_GATE_SCU_LPCG_HW_SEL BIT(0) 22 #define CLK_GATE_SCU_LPCG_SW_SEL BIT(1) 23 24 /* 25 * struct clk_lpcg_scu - Description of LPCG clock 26 * 27 * @hw: clk_hw of this LPCG 28 * @reg: register of this LPCG clock 29 * @bit_idx: bit index of this LPCG clock 30 * @hw_gate: HW auto gate enable 31 * 32 * This structure describes one LPCG clock 33 */ 34 struct clk_lpcg_scu { 35 struct clk_hw hw; 36 void __iomem *reg; 37 u8 bit_idx; 38 bool hw_gate; 39 40 /* for state save&restore */ 41 u32 state; 42 }; 43 44 #define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw) 45 46 /* e10858 -LPCG clock gating register synchronization errata */ 47 static void lpcg_e10858_writel(unsigned long rate, void __iomem *reg, u32 val) 48 { 49 writel(val, reg); 50 51 if (rate >= 24 * HZ_PER_MHZ || rate == 0) { 52 /* 53 * The time taken to access the LPCG registers from the AP core 54 * through the interconnect is longer than the minimum delay 55 * of 4 clock cycles required by the errata. 56 * Adding a readl will provide sufficient delay to prevent 57 * back-to-back writes. 58 */ 59 readl(reg); 60 } else { 61 /* 62 * For clocks running below 24MHz, wait a minimum of 63 * 4 clock cycles. 64 */ 65 ndelay(4 * (DIV_ROUND_UP(1000 * HZ_PER_MHZ, rate))); 66 } 67 } 68 69 static int clk_lpcg_scu_enable(struct clk_hw *hw) 70 { 71 struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw); 72 unsigned long flags; 73 u32 reg, val; 74 75 spin_lock_irqsave(&imx_lpcg_scu_lock, flags); 76 77 reg = readl_relaxed(clk->reg); 78 reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx); 79 80 val = CLK_GATE_SCU_LPCG_SW_SEL; 81 if (clk->hw_gate) 82 val |= CLK_GATE_SCU_LPCG_HW_SEL; 83 84 reg |= val << clk->bit_idx; 85 86 lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg); 87 88 spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); 89 90 return 0; 91 } 92 93 static void clk_lpcg_scu_disable(struct clk_hw *hw) 94 { 95 struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw); 96 unsigned long flags; 97 u32 reg; 98 99 spin_lock_irqsave(&imx_lpcg_scu_lock, flags); 100 101 reg = readl_relaxed(clk->reg); 102 reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx); 103 lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg); 104 105 spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); 106 } 107 108 static const struct clk_ops clk_lpcg_scu_ops = { 109 .enable = clk_lpcg_scu_enable, 110 .disable = clk_lpcg_scu_disable, 111 }; 112 113 struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, 114 const char *parent_name, unsigned long flags, 115 void __iomem *reg, u8 bit_idx, bool hw_gate) 116 { 117 struct clk_lpcg_scu *clk; 118 struct clk_init_data init; 119 struct clk_hw *hw; 120 int ret; 121 122 clk = kzalloc(sizeof(*clk), GFP_KERNEL); 123 if (!clk) 124 return ERR_PTR(-ENOMEM); 125 126 clk->reg = reg; 127 clk->bit_idx = bit_idx; 128 clk->hw_gate = hw_gate; 129 130 init.name = name; 131 init.ops = &clk_lpcg_scu_ops; 132 init.flags = CLK_SET_RATE_PARENT | flags; 133 init.parent_names = parent_name ? &parent_name : NULL; 134 init.num_parents = parent_name ? 1 : 0; 135 136 clk->hw.init = &init; 137 138 hw = &clk->hw; 139 ret = clk_hw_register(dev, hw); 140 if (ret) { 141 kfree(clk); 142 hw = ERR_PTR(ret); 143 return hw; 144 } 145 146 if (dev) 147 dev_set_drvdata(dev, clk); 148 149 return hw; 150 } 151 152 void imx_clk_lpcg_scu_unregister(struct clk_hw *hw) 153 { 154 struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw); 155 156 clk_hw_unregister(&clk->hw); 157 kfree(clk); 158 } 159 160 static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev) 161 { 162 struct clk_lpcg_scu *clk = dev_get_drvdata(dev); 163 164 if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg"))) 165 return 0; 166 167 clk->state = readl_relaxed(clk->reg); 168 dev_dbg(dev, "save lpcg state 0x%x\n", clk->state); 169 170 return 0; 171 } 172 173 static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev) 174 { 175 struct clk_lpcg_scu *clk = dev_get_drvdata(dev); 176 177 if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg"))) 178 return 0; 179 180 writel(clk->state, clk->reg); 181 lpcg_e10858_writel(0, clk->reg, clk->state); 182 dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state); 183 184 return 0; 185 } 186 187 const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = { 188 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend, 189 imx_clk_lpcg_scu_resume) 190 }; 191