1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Sophgo SG2042 RP clock Driver 4 * 5 * Copyright (C) 2024 Sophgo Technology Inc. 6 * Copyright (C) 2024 Chen Wang <unicorn_wang@outlook.com> 7 */ 8 9 #include <linux/array_size.h> 10 #include <linux/clk-provider.h> 11 #include <linux/platform_device.h> 12 13 #include <dt-bindings/clock/sophgo,sg2042-rpgate.h> 14 15 #include "clk-sg2042.h" 16 17 #define R_SYSGATE_BEGIN 0x0368 18 #define R_RP_RXU_CLK_ENABLE (0x0368 - R_SYSGATE_BEGIN) 19 #define R_MP0_STATUS_REG (0x0380 - R_SYSGATE_BEGIN) 20 #define R_MP0_CONTROL_REG (0x0384 - R_SYSGATE_BEGIN) 21 #define R_MP1_STATUS_REG (0x0388 - R_SYSGATE_BEGIN) 22 #define R_MP1_CONTROL_REG (0x038C - R_SYSGATE_BEGIN) 23 #define R_MP2_STATUS_REG (0x0390 - R_SYSGATE_BEGIN) 24 #define R_MP2_CONTROL_REG (0x0394 - R_SYSGATE_BEGIN) 25 #define R_MP3_STATUS_REG (0x0398 - R_SYSGATE_BEGIN) 26 #define R_MP3_CONTROL_REG (0x039C - R_SYSGATE_BEGIN) 27 #define R_MP4_STATUS_REG (0x03A0 - R_SYSGATE_BEGIN) 28 #define R_MP4_CONTROL_REG (0x03A4 - R_SYSGATE_BEGIN) 29 #define R_MP5_STATUS_REG (0x03A8 - R_SYSGATE_BEGIN) 30 #define R_MP5_CONTROL_REG (0x03AC - R_SYSGATE_BEGIN) 31 #define R_MP6_STATUS_REG (0x03B0 - R_SYSGATE_BEGIN) 32 #define R_MP6_CONTROL_REG (0x03B4 - R_SYSGATE_BEGIN) 33 #define R_MP7_STATUS_REG (0x03B8 - R_SYSGATE_BEGIN) 34 #define R_MP7_CONTROL_REG (0x03BC - R_SYSGATE_BEGIN) 35 #define R_MP8_STATUS_REG (0x03C0 - R_SYSGATE_BEGIN) 36 #define R_MP8_CONTROL_REG (0x03C4 - R_SYSGATE_BEGIN) 37 #define R_MP9_STATUS_REG (0x03C8 - R_SYSGATE_BEGIN) 38 #define R_MP9_CONTROL_REG (0x03CC - R_SYSGATE_BEGIN) 39 #define R_MP10_STATUS_REG (0x03D0 - R_SYSGATE_BEGIN) 40 #define R_MP10_CONTROL_REG (0x03D4 - R_SYSGATE_BEGIN) 41 #define R_MP11_STATUS_REG (0x03D8 - R_SYSGATE_BEGIN) 42 #define R_MP11_CONTROL_REG (0x03DC - R_SYSGATE_BEGIN) 43 #define R_MP12_STATUS_REG (0x03E0 - R_SYSGATE_BEGIN) 44 #define R_MP12_CONTROL_REG (0x03E4 - R_SYSGATE_BEGIN) 45 #define R_MP13_STATUS_REG (0x03E8 - R_SYSGATE_BEGIN) 46 #define R_MP13_CONTROL_REG (0x03EC - R_SYSGATE_BEGIN) 47 #define R_MP14_STATUS_REG (0x03F0 - R_SYSGATE_BEGIN) 48 #define R_MP14_CONTROL_REG (0x03F4 - R_SYSGATE_BEGIN) 49 #define R_MP15_STATUS_REG (0x03F8 - R_SYSGATE_BEGIN) 50 #define R_MP15_CONTROL_REG (0x03FC - R_SYSGATE_BEGIN) 51 52 /** 53 * struct sg2042_rpgate_clock - Gate clock for RP(riscv processors) subsystem 54 * @hw: clk_hw for initialization 55 * @id: used to map clk_onecell_data 56 * @offset_enable: offset of gate enable registers 57 * @bit_idx: which bit in the register controls gating of this clock 58 */ 59 struct sg2042_rpgate_clock { 60 struct clk_hw hw; 61 62 unsigned int id; 63 64 u32 offset_enable; 65 u8 bit_idx; 66 }; 67 68 /* 69 * Clock initialization macro naming rules: 70 * FW: use CLK_HW_INIT_FW_NAME 71 */ 72 #define SG2042_GATE_FW(_id, _name, _parent, _flags, \ 73 _r_enable, _bit_idx) { \ 74 .hw.init = CLK_HW_INIT_FW_NAME( \ 75 _name, \ 76 _parent, \ 77 NULL, \ 78 _flags), \ 79 .id = _id, \ 80 .offset_enable = _r_enable, \ 81 .bit_idx = _bit_idx, \ 82 } 83 84 /* 85 * Gate clocks for RP subsystem (including the MP subsystem), which control 86 * registers are defined in SYS_CTRL. 87 */ 88 static const struct sg2042_rpgate_clock sg2042_gate_rp[] = { 89 /* downstream of clk_gate_rp_cpu_normal about rxu */ 90 SG2042_GATE_FW(GATE_CLK_RXU0, "clk_gate_rxu0", "rpgate", 91 0, R_RP_RXU_CLK_ENABLE, 0), 92 SG2042_GATE_FW(GATE_CLK_RXU1, "clk_gate_rxu1", "rpgate", 93 0, R_RP_RXU_CLK_ENABLE, 1), 94 SG2042_GATE_FW(GATE_CLK_RXU2, "clk_gate_rxu2", "rpgate", 95 0, R_RP_RXU_CLK_ENABLE, 2), 96 SG2042_GATE_FW(GATE_CLK_RXU3, "clk_gate_rxu3", "rpgate", 97 0, R_RP_RXU_CLK_ENABLE, 3), 98 SG2042_GATE_FW(GATE_CLK_RXU4, "clk_gate_rxu4", "rpgate", 99 0, R_RP_RXU_CLK_ENABLE, 4), 100 SG2042_GATE_FW(GATE_CLK_RXU5, "clk_gate_rxu5", "rpgate", 101 0, R_RP_RXU_CLK_ENABLE, 5), 102 SG2042_GATE_FW(GATE_CLK_RXU6, "clk_gate_rxu6", "rpgate", 103 0, R_RP_RXU_CLK_ENABLE, 6), 104 SG2042_GATE_FW(GATE_CLK_RXU7, "clk_gate_rxu7", "rpgate", 105 0, R_RP_RXU_CLK_ENABLE, 7), 106 SG2042_GATE_FW(GATE_CLK_RXU8, "clk_gate_rxu8", "rpgate", 107 0, R_RP_RXU_CLK_ENABLE, 8), 108 SG2042_GATE_FW(GATE_CLK_RXU9, "clk_gate_rxu9", "rpgate", 109 0, R_RP_RXU_CLK_ENABLE, 9), 110 SG2042_GATE_FW(GATE_CLK_RXU10, "clk_gate_rxu10", "rpgate", 111 0, R_RP_RXU_CLK_ENABLE, 10), 112 SG2042_GATE_FW(GATE_CLK_RXU11, "clk_gate_rxu11", "rpgate", 113 0, R_RP_RXU_CLK_ENABLE, 11), 114 SG2042_GATE_FW(GATE_CLK_RXU12, "clk_gate_rxu12", "rpgate", 115 0, R_RP_RXU_CLK_ENABLE, 12), 116 SG2042_GATE_FW(GATE_CLK_RXU13, "clk_gate_rxu13", "rpgate", 117 0, R_RP_RXU_CLK_ENABLE, 13), 118 SG2042_GATE_FW(GATE_CLK_RXU14, "clk_gate_rxu14", "rpgate", 119 0, R_RP_RXU_CLK_ENABLE, 14), 120 SG2042_GATE_FW(GATE_CLK_RXU15, "clk_gate_rxu15", "rpgate", 121 0, R_RP_RXU_CLK_ENABLE, 15), 122 SG2042_GATE_FW(GATE_CLK_RXU16, "clk_gate_rxu16", "rpgate", 123 0, R_RP_RXU_CLK_ENABLE, 16), 124 SG2042_GATE_FW(GATE_CLK_RXU17, "clk_gate_rxu17", "rpgate", 125 0, R_RP_RXU_CLK_ENABLE, 17), 126 SG2042_GATE_FW(GATE_CLK_RXU18, "clk_gate_rxu18", "rpgate", 127 0, R_RP_RXU_CLK_ENABLE, 18), 128 SG2042_GATE_FW(GATE_CLK_RXU19, "clk_gate_rxu19", "rpgate", 129 0, R_RP_RXU_CLK_ENABLE, 19), 130 SG2042_GATE_FW(GATE_CLK_RXU20, "clk_gate_rxu20", "rpgate", 131 0, R_RP_RXU_CLK_ENABLE, 20), 132 SG2042_GATE_FW(GATE_CLK_RXU21, "clk_gate_rxu21", "rpgate", 133 0, R_RP_RXU_CLK_ENABLE, 21), 134 SG2042_GATE_FW(GATE_CLK_RXU22, "clk_gate_rxu22", "rpgate", 135 0, R_RP_RXU_CLK_ENABLE, 22), 136 SG2042_GATE_FW(GATE_CLK_RXU23, "clk_gate_rxu23", "rpgate", 137 0, R_RP_RXU_CLK_ENABLE, 23), 138 SG2042_GATE_FW(GATE_CLK_RXU24, "clk_gate_rxu24", "rpgate", 139 0, R_RP_RXU_CLK_ENABLE, 24), 140 SG2042_GATE_FW(GATE_CLK_RXU25, "clk_gate_rxu25", "rpgate", 141 0, R_RP_RXU_CLK_ENABLE, 25), 142 SG2042_GATE_FW(GATE_CLK_RXU26, "clk_gate_rxu26", "rpgate", 143 0, R_RP_RXU_CLK_ENABLE, 26), 144 SG2042_GATE_FW(GATE_CLK_RXU27, "clk_gate_rxu27", "rpgate", 145 0, R_RP_RXU_CLK_ENABLE, 27), 146 SG2042_GATE_FW(GATE_CLK_RXU28, "clk_gate_rxu28", "rpgate", 147 0, R_RP_RXU_CLK_ENABLE, 28), 148 SG2042_GATE_FW(GATE_CLK_RXU29, "clk_gate_rxu29", "rpgate", 149 0, R_RP_RXU_CLK_ENABLE, 29), 150 SG2042_GATE_FW(GATE_CLK_RXU30, "clk_gate_rxu30", "rpgate", 151 0, R_RP_RXU_CLK_ENABLE, 30), 152 SG2042_GATE_FW(GATE_CLK_RXU31, "clk_gate_rxu31", "rpgate", 153 0, R_RP_RXU_CLK_ENABLE, 31), 154 155 /* downstream of clk_gate_rp_cpu_normal about mp */ 156 SG2042_GATE_FW(GATE_CLK_MP0, "clk_gate_mp0", "rpgate", 157 CLK_IS_CRITICAL, R_MP0_CONTROL_REG, 0), 158 SG2042_GATE_FW(GATE_CLK_MP1, "clk_gate_mp1", "rpgate", 159 CLK_IS_CRITICAL, R_MP1_CONTROL_REG, 0), 160 SG2042_GATE_FW(GATE_CLK_MP2, "clk_gate_mp2", "rpgate", 161 CLK_IS_CRITICAL, R_MP2_CONTROL_REG, 0), 162 SG2042_GATE_FW(GATE_CLK_MP3, "clk_gate_mp3", "rpgate", 163 CLK_IS_CRITICAL, R_MP3_CONTROL_REG, 0), 164 SG2042_GATE_FW(GATE_CLK_MP4, "clk_gate_mp4", "rpgate", 165 CLK_IS_CRITICAL, R_MP4_CONTROL_REG, 0), 166 SG2042_GATE_FW(GATE_CLK_MP5, "clk_gate_mp5", "rpgate", 167 CLK_IS_CRITICAL, R_MP5_CONTROL_REG, 0), 168 SG2042_GATE_FW(GATE_CLK_MP6, "clk_gate_mp6", "rpgate", 169 CLK_IS_CRITICAL, R_MP6_CONTROL_REG, 0), 170 SG2042_GATE_FW(GATE_CLK_MP7, "clk_gate_mp7", "rpgate", 171 CLK_IS_CRITICAL, R_MP7_CONTROL_REG, 0), 172 SG2042_GATE_FW(GATE_CLK_MP8, "clk_gate_mp8", "rpgate", 173 CLK_IS_CRITICAL, R_MP8_CONTROL_REG, 0), 174 SG2042_GATE_FW(GATE_CLK_MP9, "clk_gate_mp9", "rpgate", 175 CLK_IS_CRITICAL, R_MP9_CONTROL_REG, 0), 176 SG2042_GATE_FW(GATE_CLK_MP10, "clk_gate_mp10", "rpgate", 177 CLK_IS_CRITICAL, R_MP10_CONTROL_REG, 0), 178 SG2042_GATE_FW(GATE_CLK_MP11, "clk_gate_mp11", "rpgate", 179 CLK_IS_CRITICAL, R_MP11_CONTROL_REG, 0), 180 SG2042_GATE_FW(GATE_CLK_MP12, "clk_gate_mp12", "rpgate", 181 CLK_IS_CRITICAL, R_MP12_CONTROL_REG, 0), 182 SG2042_GATE_FW(GATE_CLK_MP13, "clk_gate_mp13", "rpgate", 183 CLK_IS_CRITICAL, R_MP13_CONTROL_REG, 0), 184 SG2042_GATE_FW(GATE_CLK_MP14, "clk_gate_mp14", "rpgate", 185 CLK_IS_CRITICAL, R_MP14_CONTROL_REG, 0), 186 SG2042_GATE_FW(GATE_CLK_MP15, "clk_gate_mp15", "rpgate", 187 CLK_IS_CRITICAL, R_MP15_CONTROL_REG, 0), 188 }; 189 190 static DEFINE_SPINLOCK(sg2042_clk_lock); 191 192 static int sg2042_clk_register_rpgates(struct device *dev, 193 struct sg2042_clk_data *clk_data, 194 const struct sg2042_rpgate_clock gate_clks[], 195 int num_gate_clks) 196 { 197 const struct sg2042_rpgate_clock *gate; 198 struct clk_hw *hw; 199 int i, ret = 0; 200 201 for (i = 0; i < num_gate_clks; i++) { 202 gate = &gate_clks[i]; 203 hw = devm_clk_hw_register_gate_parent_data 204 (dev, 205 gate->hw.init->name, 206 gate->hw.init->parent_data, 207 gate->hw.init->flags, 208 clk_data->iobase + gate->offset_enable, 209 gate->bit_idx, 210 0, 211 &sg2042_clk_lock); 212 if (IS_ERR(hw)) { 213 pr_err("failed to register clock %s\n", gate->hw.init->name); 214 ret = PTR_ERR(hw); 215 break; 216 } 217 218 clk_data->onecell_data.hws[gate->id] = hw; 219 } 220 221 return ret; 222 } 223 224 static int sg2042_init_clkdata(struct platform_device *pdev, 225 int num_clks, 226 struct sg2042_clk_data **pp_clk_data) 227 { 228 struct sg2042_clk_data *clk_data; 229 230 clk_data = devm_kzalloc(&pdev->dev, 231 struct_size(clk_data, onecell_data.hws, num_clks), 232 GFP_KERNEL); 233 if (!clk_data) 234 return -ENOMEM; 235 236 clk_data->iobase = devm_platform_ioremap_resource(pdev, 0); 237 if (WARN_ON(IS_ERR(clk_data->iobase))) 238 return PTR_ERR(clk_data->iobase); 239 240 clk_data->onecell_data.num = num_clks; 241 242 *pp_clk_data = clk_data; 243 244 return 0; 245 } 246 247 static int sg2042_rpgate_probe(struct platform_device *pdev) 248 { 249 struct sg2042_clk_data *clk_data = NULL; 250 int num_clks; 251 int ret; 252 253 num_clks = ARRAY_SIZE(sg2042_gate_rp); 254 255 ret = sg2042_init_clkdata(pdev, num_clks, &clk_data); 256 if (ret) 257 goto error_out; 258 259 ret = sg2042_clk_register_rpgates(&pdev->dev, clk_data, sg2042_gate_rp, 260 num_clks); 261 if (ret) 262 goto error_out; 263 264 return devm_of_clk_add_hw_provider(&pdev->dev, 265 of_clk_hw_onecell_get, 266 &clk_data->onecell_data); 267 268 error_out: 269 pr_err("%s failed error number %d\n", __func__, ret); 270 return ret; 271 } 272 273 static const struct of_device_id sg2042_rpgate_match[] = { 274 { .compatible = "sophgo,sg2042-rpgate" }, 275 { /* sentinel */ } 276 }; 277 MODULE_DEVICE_TABLE(of, sg2042_rpgate_match); 278 279 static struct platform_driver sg2042_rpgate_driver = { 280 .probe = sg2042_rpgate_probe, 281 .driver = { 282 .name = "clk-sophgo-sg2042-rpgate", 283 .of_match_table = sg2042_rpgate_match, 284 .suppress_bind_attrs = true, 285 }, 286 }; 287 module_platform_driver(sg2042_rpgate_driver); 288 289 MODULE_AUTHOR("Chen Wang"); 290 MODULE_DESCRIPTION("Sophgo SG2042 rp subsystem clock driver"); 291 MODULE_LICENSE("GPL"); 292