1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Toshiba Visconti clock controller 4 * 5 * Copyright (c) 2021 TOSHIBA CORPORATION 6 * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation 7 * 8 * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> 9 */ 10 11 #include <linux/clk-provider.h> 12 #include <linux/platform_device.h> 13 14 #include <dt-bindings/clock/toshiba,tmpv770x.h> 15 #include <dt-bindings/reset/toshiba,tmpv770x.h> 16 17 #include "clkc.h" 18 #include "reset.h" 19 20 static DEFINE_SPINLOCK(tmpv770x_clk_lock); 21 static DEFINE_SPINLOCK(tmpv770x_rst_lock); 22 23 static const struct clk_parent_data clks_parent_data[] = { 24 { .fw_name = "pipll1", .name = "pipll1", }, 25 }; 26 27 static const struct clk_parent_data pietherplls_parent_data[] = { 28 { .fw_name = "pietherpll", .name = "pietherpll", }, 29 }; 30 31 static const struct visconti_fixed_clk fixed_clk_tables[] = { 32 /* PLL1 */ 33 /* PICMPT0/1, PITSC, PIUWDT, PISWDT, PISBUS, PIPMU, PIGPMU, PITMU */ 34 /* PIEMM, PIMISC, PIGCOMM, PIDCOMM, PIMBUS, PIGPIO, PIPGM */ 35 { TMPV770X_CLK_PIPLL1_DIV4, "pipll1_div4", "pipll1", 0, 1, 4, }, 36 /* PISBUS */ 37 { TMPV770X_CLK_PIPLL1_DIV2, "pipll1_div2", "pipll1", 0, 1, 2, }, 38 /* PICOBUS_CLK */ 39 { TMPV770X_CLK_PIPLL1_DIV1, "pipll1_div1", "pipll1", 0, 1, 1, }, 40 /* PIDNNPLL */ 41 /* CONN_CLK, PIMBUS, PICRC0/1 */ 42 { TMPV770X_CLK_PIDNNPLL_DIV1, "pidnnpll_div1", "pidnnpll", 0, 1, 1, }, 43 { TMPV770X_CLK_PIREFCLK, "pirefclk", "osc2-clk", 0, 1, 1, }, 44 { TMPV770X_CLK_WDTCLK, "wdtclk", "osc2-clk", 0, 1, 1, }, 45 }; 46 47 static const struct visconti_clk_gate_table pietherpll_clk_gate_tables[] = { 48 /* pietherpll */ 49 { TMPV770X_CLK_PIETHER_2P5M, "piether_2p5m", 50 pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data), 51 CLK_SET_RATE_PARENT, 0x34, 0x134, 4, 200, 52 TMPV770X_RESET_PIETHER_2P5M, }, 53 { TMPV770X_CLK_PIETHER_25M, "piether_25m", 54 pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data), 55 CLK_SET_RATE_PARENT, 0x34, 0x134, 5, 20, 56 TMPV770X_RESET_PIETHER_25M, }, 57 { TMPV770X_CLK_PIETHER_50M, "piether_50m", 58 pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data), 59 CLK_SET_RATE_PARENT, 0x34, 0x134, 6, 10, 60 TMPV770X_RESET_PIETHER_50M, }, 61 { TMPV770X_CLK_PIETHER_125M, "piether_125m", 62 pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data), 63 CLK_SET_RATE_PARENT, 0x34, 0x134, 7, 4, 64 TMPV770X_RESET_PIETHER_125M, }, 65 }; 66 67 static const struct visconti_clk_gate_table clk_gate_tables[] = { 68 { TMPV770X_CLK_HOX, "hox", 69 clks_parent_data, ARRAY_SIZE(clks_parent_data), 70 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x4c, 0x14c, 0, 1, 71 TMPV770X_RESET_HOX, }, 72 { TMPV770X_CLK_PCIE_MSTR, "pcie_mstr", 73 clks_parent_data, ARRAY_SIZE(clks_parent_data), 74 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x38, 0x138, 0, 1, 75 TMPV770X_RESET_PCIE_MSTR, }, 76 { TMPV770X_CLK_PCIE_AUX, "pcie_aux", 77 clks_parent_data, ARRAY_SIZE(clks_parent_data), 78 CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x38, 0x138, 1, 24, 79 TMPV770X_RESET_PCIE_AUX, }, 80 { TMPV770X_CLK_PIINTC, "piintc", 81 clks_parent_data, ARRAY_SIZE(clks_parent_data), 82 CLK_IGNORE_UNUSED, 0x8, 0x108, 0, 2, //FIX!! 83 TMPV770X_RESET_PIINTC,}, 84 { TMPV770X_CLK_PIETHER_BUS, "piether_bus", 85 clks_parent_data, ARRAY_SIZE(clks_parent_data), 86 0, 0x34, 0x134, 0, 2, 87 TMPV770X_RESET_PIETHER_BUS, }, /* BUS_CLK */ 88 { TMPV770X_CLK_PISPI0, "pispi0", 89 clks_parent_data, ARRAY_SIZE(clks_parent_data), 90 0, 0x28, 0x128, 0, 2, 91 TMPV770X_RESET_PISPI0, }, 92 { TMPV770X_CLK_PISPI1, "pispi1", 93 clks_parent_data, ARRAY_SIZE(clks_parent_data), 94 0, 0x28, 0x128, 1, 2, 95 TMPV770X_RESET_PISPI1, }, 96 { TMPV770X_CLK_PISPI2, "pispi2", 97 clks_parent_data, ARRAY_SIZE(clks_parent_data), 98 0, 0x28, 0x128, 2, 2, 99 TMPV770X_RESET_PISPI2, }, 100 { TMPV770X_CLK_PISPI3, "pispi3", 101 clks_parent_data, ARRAY_SIZE(clks_parent_data), 102 0, 0x28, 0x128, 3, 2, 103 TMPV770X_RESET_PISPI3,}, 104 { TMPV770X_CLK_PISPI4, "pispi4", 105 clks_parent_data, ARRAY_SIZE(clks_parent_data), 106 0, 0x28, 0x128, 4, 2, 107 TMPV770X_RESET_PISPI4, }, 108 { TMPV770X_CLK_PISPI5, "pispi5", 109 clks_parent_data, ARRAY_SIZE(clks_parent_data), 110 0, 0x28, 0x128, 5, 2, 111 TMPV770X_RESET_PISPI5}, 112 { TMPV770X_CLK_PISPI6, "pispi6", 113 clks_parent_data, ARRAY_SIZE(clks_parent_data), 114 0, 0x28, 0x128, 6, 2, 115 TMPV770X_RESET_PISPI6,}, 116 { TMPV770X_CLK_PIUART0, "piuart0", 117 clks_parent_data, ARRAY_SIZE(clks_parent_data), 118 //CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x2c, 0x12c, 0, 4, 119 0, 0x2c, 0x12c, 0, 4, 120 TMPV770X_RESET_PIUART0,}, 121 { TMPV770X_CLK_PIUART1, "piuart1", 122 clks_parent_data, ARRAY_SIZE(clks_parent_data), 123 //CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x2c, 0x12c, 1, 4, 124 0, 0x2c, 0x12c, 1, 4, 125 TMPV770X_RESET_PIUART1, }, 126 { TMPV770X_CLK_PIUART2, "piuart2", 127 clks_parent_data, ARRAY_SIZE(clks_parent_data), 128 0, 0x2c, 0x12c, 2, 4, 129 TMPV770X_RESET_PIUART2, }, 130 { TMPV770X_CLK_PIUART3, "piuart3", 131 clks_parent_data, ARRAY_SIZE(clks_parent_data), 132 0, 0x2c, 0x12c, 3, 4, 133 TMPV770X_RESET_PIUART3, }, 134 { TMPV770X_CLK_PII2C0, "pii2c0", 135 clks_parent_data, ARRAY_SIZE(clks_parent_data), 136 0, 0x30, 0x130, 0, 4, 137 TMPV770X_RESET_PII2C0, }, 138 { TMPV770X_CLK_PII2C1, "pii2c1", 139 clks_parent_data, ARRAY_SIZE(clks_parent_data), 140 0, 0x30, 0x130, 1, 4, 141 TMPV770X_RESET_PII2C1, }, 142 { TMPV770X_CLK_PII2C2, "pii2c2", 143 clks_parent_data, ARRAY_SIZE(clks_parent_data), 144 0, 0x30, 0x130, 2, 4, 145 TMPV770X_RESET_PII2C2, }, 146 { TMPV770X_CLK_PII2C3, "pii2c3", 147 clks_parent_data, ARRAY_SIZE(clks_parent_data), 148 0, 0x30, 0x130, 3, 4, 149 TMPV770X_RESET_PII2C3,}, 150 { TMPV770X_CLK_PII2C4, "pii2c4", 151 clks_parent_data, ARRAY_SIZE(clks_parent_data), 152 0, 0x30, 0x130, 4, 4, 153 TMPV770X_RESET_PII2C4, }, 154 { TMPV770X_CLK_PII2C5, "pii2c5", 155 clks_parent_data, ARRAY_SIZE(clks_parent_data), 156 0, 0x30, 0x130, 5, 4, 157 TMPV770X_RESET_PII2C5, }, 158 { TMPV770X_CLK_PII2C6, "pii2c6", 159 clks_parent_data, ARRAY_SIZE(clks_parent_data), 160 0, 0x30, 0x130, 6, 4, 161 TMPV770X_RESET_PII2C6, }, 162 { TMPV770X_CLK_PII2C7, "pii2c7", 163 clks_parent_data, ARRAY_SIZE(clks_parent_data), 164 0, 0x30, 0x130, 7, 4, 165 TMPV770X_RESET_PII2C7, }, 166 { TMPV770X_CLK_PII2C8, "pii2c8", 167 clks_parent_data, ARRAY_SIZE(clks_parent_data), 168 0, 0x30, 0x130, 8, 4, 169 TMPV770X_RESET_PII2C8, }, 170 /* PIPCMIF */ 171 { TMPV770X_CLK_PIPCMIF, "pipcmif", 172 clks_parent_data, ARRAY_SIZE(clks_parent_data), 173 0, 0x64, 0x164, 0, 4, 174 TMPV770X_RESET_PIPCMIF, }, 175 /* PISYSTEM */ 176 { TMPV770X_CLK_WRCK, "wrck", 177 clks_parent_data, ARRAY_SIZE(clks_parent_data), 178 0, 0x68, 0x168, 9, 32, 179 -1, }, /* No reset */ 180 { TMPV770X_CLK_PICKMON, "pickmon", 181 clks_parent_data, ARRAY_SIZE(clks_parent_data), 182 0, 0x10, 0x110, 8, 4, 183 TMPV770X_RESET_PICKMON, }, 184 { TMPV770X_CLK_SBUSCLK, "sbusclk", 185 clks_parent_data, ARRAY_SIZE(clks_parent_data), 186 0, 0x14, 0x114, 0, 4, 187 TMPV770X_RESET_SBUSCLK, }, 188 }; 189 190 static const struct visconti_reset_data clk_reset_data[] = { 191 [TMPV770X_RESET_PIETHER_2P5M] = { 0x434, 0x534, 4, }, 192 [TMPV770X_RESET_PIETHER_25M] = { 0x434, 0x534, 5, }, 193 [TMPV770X_RESET_PIETHER_50M] = { 0x434, 0x534, 6, }, 194 [TMPV770X_RESET_PIETHER_125M] = { 0x434, 0x534, 7, }, 195 [TMPV770X_RESET_HOX] = { 0x44c, 0x54c, 0, }, 196 [TMPV770X_RESET_PCIE_MSTR] = { 0x438, 0x538, 0, }, 197 [TMPV770X_RESET_PCIE_AUX] = { 0x438, 0x538, 1, }, 198 [TMPV770X_RESET_PIINTC] = { 0x408, 0x508, 0, }, 199 [TMPV770X_RESET_PIETHER_BUS] = { 0x434, 0x534, 0, }, 200 [TMPV770X_RESET_PISPI0] = { 0x428, 0x528, 0, }, 201 [TMPV770X_RESET_PISPI1] = { 0x428, 0x528, 1, }, 202 [TMPV770X_RESET_PISPI2] = { 0x428, 0x528, 2, }, 203 [TMPV770X_RESET_PISPI3] = { 0x428, 0x528, 3, }, 204 [TMPV770X_RESET_PISPI4] = { 0x428, 0x528, 4, }, 205 [TMPV770X_RESET_PISPI5] = { 0x428, 0x528, 5, }, 206 [TMPV770X_RESET_PISPI6] = { 0x428, 0x528, 6, }, 207 [TMPV770X_RESET_PIUART0] = { 0x42c, 0x52c, 0, }, 208 [TMPV770X_RESET_PIUART1] = { 0x42c, 0x52c, 1, }, 209 [TMPV770X_RESET_PIUART2] = { 0x42c, 0x52c, 2, }, 210 [TMPV770X_RESET_PIUART3] = { 0x42c, 0x52c, 3, }, 211 [TMPV770X_RESET_PII2C0] = { 0x430, 0x530, 0, }, 212 [TMPV770X_RESET_PII2C1] = { 0x430, 0x530, 1, }, 213 [TMPV770X_RESET_PII2C2] = { 0x430, 0x530, 2, }, 214 [TMPV770X_RESET_PII2C3] = { 0x430, 0x530, 3, }, 215 [TMPV770X_RESET_PII2C4] = { 0x430, 0x530, 4, }, 216 [TMPV770X_RESET_PII2C5] = { 0x430, 0x530, 5, }, 217 [TMPV770X_RESET_PII2C6] = { 0x430, 0x530, 6, }, 218 [TMPV770X_RESET_PII2C7] = { 0x430, 0x530, 7, }, 219 [TMPV770X_RESET_PII2C8] = { 0x430, 0x530, 8, }, 220 [TMPV770X_RESET_PIPCMIF] = { 0x464, 0x564, 0, }, 221 [TMPV770X_RESET_PICKMON] = { 0x410, 0x510, 8, }, 222 [TMPV770X_RESET_SBUSCLK] = { 0x414, 0x514, 0, }, 223 }; 224 225 static int visconti_clk_probe(struct platform_device *pdev) 226 { 227 struct device_node *np = pdev->dev.of_node; 228 struct visconti_clk_provider *ctx; 229 struct device *dev = &pdev->dev; 230 struct regmap *regmap; 231 int ret, i; 232 233 regmap = syscon_node_to_regmap(np); 234 if (IS_ERR(regmap)) 235 return PTR_ERR(regmap); 236 237 ctx = visconti_init_clk(dev, regmap, TMPV770X_NR_CLK); 238 if (IS_ERR(ctx)) 239 return PTR_ERR(ctx); 240 241 ret = visconti_register_reset_controller(dev, regmap, clk_reset_data, 242 TMPV770X_NR_RESET, 243 &visconti_reset_ops, 244 &tmpv770x_rst_lock); 245 if (ret) { 246 dev_err(dev, "Failed to register reset controller: %d\n", ret); 247 return ret; 248 } 249 250 for (i = 0; i < (ARRAY_SIZE(fixed_clk_tables)); i++) 251 ctx->clk_data.hws[fixed_clk_tables[i].id] = 252 clk_hw_register_fixed_factor(NULL, 253 fixed_clk_tables[i].name, 254 fixed_clk_tables[i].parent, 255 fixed_clk_tables[i].flag, 256 fixed_clk_tables[i].mult, 257 fixed_clk_tables[i].div); 258 259 ret = visconti_clk_register_gates(ctx, clk_gate_tables, 260 ARRAY_SIZE(clk_gate_tables), clk_reset_data, 261 &tmpv770x_clk_lock); 262 if (ret) { 263 dev_err(dev, "Failed to register main clock gate: %d\n", ret); 264 return ret; 265 } 266 267 ret = visconti_clk_register_gates(ctx, pietherpll_clk_gate_tables, 268 ARRAY_SIZE(pietherpll_clk_gate_tables), 269 clk_reset_data, &tmpv770x_clk_lock); 270 if (ret) { 271 dev_err(dev, "Failed to register pietherpll clock gate: %d\n", ret); 272 return ret; 273 } 274 275 return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &ctx->clk_data); 276 } 277 278 static const struct of_device_id visconti_clk_ids[] = { 279 { .compatible = "toshiba,tmpv7708-pismu", }, 280 { } 281 }; 282 283 static struct platform_driver visconti_clk_driver = { 284 .probe = visconti_clk_probe, 285 .driver = { 286 .name = "visconti-clk", 287 .of_match_table = visconti_clk_ids, 288 }, 289 }; 290 291 builtin_platform_driver(visconti_clk_driver); 292