1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2018 NXP 4 * Dong Aisheng <aisheng.dong@nxp.com> 5 */ 6 7 #include <linux/clk-provider.h> 8 #include <linux/err.h> 9 #include <linux/slab.h> 10 11 #include "clk-scu.h" 12 13 static struct imx_sc_ipc *ccm_ipc_handle; 14 15 /* 16 * struct clk_scu - Description of one SCU clock 17 * @hw: the common clk_hw 18 * @rsrc_id: resource ID of this SCU clock 19 * @clk_type: type of this clock resource 20 */ 21 struct clk_scu { 22 struct clk_hw hw; 23 u16 rsrc_id; 24 u8 clk_type; 25 }; 26 27 /* 28 * struct imx_sc_msg_req_set_clock_rate - clock set rate protocol 29 * @hdr: SCU protocol header 30 * @rate: rate to set 31 * @resource: clock resource to set rate 32 * @clk: clk type of this resource 33 * 34 * This structure describes the SCU protocol of clock rate set 35 */ 36 struct imx_sc_msg_req_set_clock_rate { 37 struct imx_sc_rpc_msg hdr; 38 __le32 rate; 39 __le16 resource; 40 u8 clk; 41 } __packed; 42 43 struct req_get_clock_rate { 44 __le16 resource; 45 u8 clk; 46 } __packed; 47 48 struct resp_get_clock_rate { 49 __le32 rate; 50 }; 51 52 /* 53 * struct imx_sc_msg_get_clock_rate - clock get rate protocol 54 * @hdr: SCU protocol header 55 * @req: get rate request protocol 56 * @resp: get rate response protocol 57 * 58 * This structure describes the SCU protocol of clock rate get 59 */ 60 struct imx_sc_msg_get_clock_rate { 61 struct imx_sc_rpc_msg hdr; 62 union { 63 struct req_get_clock_rate req; 64 struct resp_get_clock_rate resp; 65 } data; 66 }; 67 68 /* 69 * struct imx_sc_msg_req_clock_enable - clock gate protocol 70 * @hdr: SCU protocol header 71 * @resource: clock resource to gate 72 * @clk: clk type of this resource 73 * @enable: whether gate off the clock 74 * @autog: HW auto gate enable 75 * 76 * This structure describes the SCU protocol of clock gate 77 */ 78 struct imx_sc_msg_req_clock_enable { 79 struct imx_sc_rpc_msg hdr; 80 __le16 resource; 81 u8 clk; 82 u8 enable; 83 u8 autog; 84 } __packed; 85 86 static inline struct clk_scu *to_clk_scu(struct clk_hw *hw) 87 { 88 return container_of(hw, struct clk_scu, hw); 89 } 90 91 int imx_clk_scu_init(void) 92 { 93 return imx_scu_get_handle(&ccm_ipc_handle); 94 } 95 96 /* 97 * clk_scu_recalc_rate - Get clock rate for a SCU clock 98 * @hw: clock to get rate for 99 * @parent_rate: parent rate provided by common clock framework, not used 100 * 101 * Gets the current clock rate of a SCU clock. Returns the current 102 * clock rate, or zero in failure. 103 */ 104 static unsigned long clk_scu_recalc_rate(struct clk_hw *hw, 105 unsigned long parent_rate) 106 { 107 struct clk_scu *clk = to_clk_scu(hw); 108 struct imx_sc_msg_get_clock_rate msg; 109 struct imx_sc_rpc_msg *hdr = &msg.hdr; 110 int ret; 111 112 hdr->ver = IMX_SC_RPC_VERSION; 113 hdr->svc = IMX_SC_RPC_SVC_PM; 114 hdr->func = IMX_SC_PM_FUNC_GET_CLOCK_RATE; 115 hdr->size = 2; 116 117 msg.data.req.resource = cpu_to_le16(clk->rsrc_id); 118 msg.data.req.clk = clk->clk_type; 119 120 ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true); 121 if (ret) { 122 pr_err("%s: failed to get clock rate %d\n", 123 clk_hw_get_name(hw), ret); 124 return 0; 125 } 126 127 return le32_to_cpu(msg.data.resp.rate); 128 } 129 130 /* 131 * clk_scu_round_rate - Round clock rate for a SCU clock 132 * @hw: clock to round rate for 133 * @rate: rate to round 134 * @parent_rate: parent rate provided by common clock framework, not used 135 * 136 * Returns the current clock rate, or zero in failure. 137 */ 138 static long clk_scu_round_rate(struct clk_hw *hw, unsigned long rate, 139 unsigned long *parent_rate) 140 { 141 /* 142 * Assume we support all the requested rate and let the SCU firmware 143 * to handle the left work 144 */ 145 return rate; 146 } 147 148 /* 149 * clk_scu_set_rate - Set rate for a SCU clock 150 * @hw: clock to change rate for 151 * @rate: target rate for the clock 152 * @parent_rate: rate of the clock parent, not used for SCU clocks 153 * 154 * Sets a clock frequency for a SCU clock. Returns the SCU 155 * protocol status. 156 */ 157 static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate, 158 unsigned long parent_rate) 159 { 160 struct clk_scu *clk = to_clk_scu(hw); 161 struct imx_sc_msg_req_set_clock_rate msg; 162 struct imx_sc_rpc_msg *hdr = &msg.hdr; 163 164 hdr->ver = IMX_SC_RPC_VERSION; 165 hdr->svc = IMX_SC_RPC_SVC_PM; 166 hdr->func = IMX_SC_PM_FUNC_SET_CLOCK_RATE; 167 hdr->size = 3; 168 169 msg.rate = cpu_to_le32(rate); 170 msg.resource = cpu_to_le16(clk->rsrc_id); 171 msg.clk = clk->clk_type; 172 173 return imx_scu_call_rpc(ccm_ipc_handle, &msg, true); 174 } 175 176 static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource, 177 u8 clk, bool enable, bool autog) 178 { 179 struct imx_sc_msg_req_clock_enable msg; 180 struct imx_sc_rpc_msg *hdr = &msg.hdr; 181 182 hdr->ver = IMX_SC_RPC_VERSION; 183 hdr->svc = IMX_SC_RPC_SVC_PM; 184 hdr->func = IMX_SC_PM_FUNC_CLOCK_ENABLE; 185 hdr->size = 3; 186 187 msg.resource = cpu_to_le16(resource); 188 msg.clk = clk; 189 msg.enable = enable; 190 msg.autog = autog; 191 192 return imx_scu_call_rpc(ccm_ipc_handle, &msg, true); 193 } 194 195 /* 196 * clk_scu_prepare - Enable a SCU clock 197 * @hw: clock to enable 198 * 199 * Enable the clock at the DSC slice level 200 */ 201 static int clk_scu_prepare(struct clk_hw *hw) 202 { 203 struct clk_scu *clk = to_clk_scu(hw); 204 205 return sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id, 206 clk->clk_type, true, false); 207 } 208 209 /* 210 * clk_scu_unprepare - Disable a SCU clock 211 * @hw: clock to enable 212 * 213 * Disable the clock at the DSC slice level 214 */ 215 static void clk_scu_unprepare(struct clk_hw *hw) 216 { 217 struct clk_scu *clk = to_clk_scu(hw); 218 int ret; 219 220 ret = sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id, 221 clk->clk_type, false, false); 222 if (ret) 223 pr_warn("%s: clk unprepare failed %d\n", clk_hw_get_name(hw), 224 ret); 225 } 226 227 static const struct clk_ops clk_scu_ops = { 228 .recalc_rate = clk_scu_recalc_rate, 229 .round_rate = clk_scu_round_rate, 230 .set_rate = clk_scu_set_rate, 231 .prepare = clk_scu_prepare, 232 .unprepare = clk_scu_unprepare, 233 }; 234 235 struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type) 236 { 237 struct clk_init_data init; 238 struct clk_scu *clk; 239 struct clk_hw *hw; 240 int ret; 241 242 clk = kzalloc(sizeof(*clk), GFP_KERNEL); 243 if (!clk) 244 return ERR_PTR(-ENOMEM); 245 246 clk->rsrc_id = rsrc_id; 247 clk->clk_type = clk_type; 248 249 init.name = name; 250 init.ops = &clk_scu_ops; 251 init.num_parents = 0; 252 /* 253 * Note on MX8, the clocks are tightly coupled with power domain 254 * that once the power domain is off, the clock status may be 255 * lost. So we make it NOCACHE to let user to retrieve the real 256 * clock status from HW instead of using the possible invalid 257 * cached rate. 258 */ 259 init.flags = CLK_GET_RATE_NOCACHE; 260 clk->hw.init = &init; 261 262 hw = &clk->hw; 263 ret = clk_hw_register(NULL, hw); 264 if (ret) { 265 kfree(clk); 266 hw = ERR_PTR(ret); 267 } 268 269 return hw; 270 } 271