Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: keystone: Add sci-clk driver support

In K2G, the clock handling is done through firmware executing on a
separate core. Linux kernel needs to communicate to the firmware
through TI system control interface to access any power management
related resources, including clocks.

The keystone sci-clk driver does this, by communicating to the
firmware through the TI SCI driver. The driver adds support for
registering clocks through DT, and basic required clock operations
like prepare/get_rate, etc.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
[sboyd@codeaurora.org: Make ti_sci_init_clocks() static]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

authored by

Tero Kristo and committed by
Stephen Boyd
b745c079 8f306cfe

+744 -9
+1
MAINTAINERS
··· 12631 12631 F: include/dt-bindings/genpd/k2g.h 12632 12632 F: drivers/soc/ti/ti_sci_pm_domains.c 12633 12633 F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt 12634 + F: drivers/clk/keystone/sci-clk.c 12634 12635 12635 12636 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER 12636 12637 M: Hans Verkuil <hverkuil@xs4all.nl>
+1 -7
drivers/clk/Kconfig
··· 164 164 ---help--- 165 165 Sypport for the APM X-Gene SoC reference, PLL, and device clocks. 166 166 167 - config COMMON_CLK_KEYSTONE 168 - tristate "Clock drivers for Keystone based SOCs" 169 - depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF 170 - ---help--- 171 - Supports clock drivers for Keystone based SOCs. These SOCs have local 172 - a power sleep control module that gate the clock to the IPs and PLLs. 173 - 174 167 config COMMON_CLK_NXP 175 168 def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX) 176 169 select REGMAP_MMIO if ARCH_LPC32XX ··· 212 219 213 220 source "drivers/clk/bcm/Kconfig" 214 221 source "drivers/clk/hisilicon/Kconfig" 222 + source "drivers/clk/keystone/Kconfig" 215 223 source "drivers/clk/mediatek/Kconfig" 216 224 source "drivers/clk/meson/Kconfig" 217 225 source "drivers/clk/mvebu/Kconfig"
+1 -1
drivers/clk/Makefile
··· 61 61 obj-$(CONFIG_ARCH_HISI) += hisilicon/ 62 62 obj-$(CONFIG_ARCH_MXC) += imx/ 63 63 obj-$(CONFIG_MACH_INGENIC) += ingenic/ 64 - obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ 64 + obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ 65 65 obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ 66 66 obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ 67 67 obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/
+15
drivers/clk/keystone/Kconfig
··· 1 + config COMMON_CLK_KEYSTONE 2 + tristate "Clock drivers for Keystone based SOCs" 3 + depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF 4 + ---help--- 5 + Supports clock drivers for Keystone based SOCs. These SOCs have local 6 + a power sleep control module that gate the clock to the IPs and PLLs. 7 + 8 + config TI_SCI_CLK 9 + tristate "TI System Control Interface clock drivers" 10 + depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF 11 + default TI_SCI_PROTOCOL 12 + ---help--- 13 + This adds the clock driver support over TI System Control Interface. 14 + If you wish to use clock resources from the PMMC firmware, say Y. 15 + Otherwise, say N.
+2 -1
drivers/clk/keystone/Makefile
··· 1 - obj-y += pll.o gate.o 1 + obj-$(CONFIG_COMMON_CLK_KEYSTONE) += pll.o gate.o 2 + obj-$(CONFIG_TI_SCI_CLK) += sci-clk.o
+724
drivers/clk/keystone/sci-clk.c
··· 1 + /* 2 + * SCI Clock driver for keystone based devices 3 + * 4 + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ 5 + * Tero Kristo <t-kristo@ti.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 + * kind, whether express or implied; without even the implied warranty 13 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + #include <linux/clk-provider.h> 17 + #include <linux/err.h> 18 + #include <linux/io.h> 19 + #include <linux/module.h> 20 + #include <linux/of_address.h> 21 + #include <linux/of_device.h> 22 + #include <linux/platform_device.h> 23 + #include <linux/slab.h> 24 + #include <linux/soc/ti/ti_sci_protocol.h> 25 + 26 + #define SCI_CLK_SSC_ENABLE BIT(0) 27 + #define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1) 28 + #define SCI_CLK_INPUT_TERMINATION BIT(2) 29 + 30 + /** 31 + * struct sci_clk_data - TI SCI clock data 32 + * @dev: device index 33 + * @num_clks: number of clocks for this device 34 + */ 35 + struct sci_clk_data { 36 + u16 dev; 37 + u16 num_clks; 38 + }; 39 + 40 + /** 41 + * struct sci_clk_provider - TI SCI clock provider representation 42 + * @sci: Handle to the System Control Interface protocol handler 43 + * @ops: Pointer to the SCI ops to be used by the clocks 44 + * @dev: Device pointer for the clock provider 45 + * @clk_data: Clock data 46 + * @clocks: Clocks array for this device 47 + */ 48 + struct sci_clk_provider { 49 + const struct ti_sci_handle *sci; 50 + const struct ti_sci_clk_ops *ops; 51 + struct device *dev; 52 + const struct sci_clk_data *clk_data; 53 + struct clk_hw **clocks; 54 + }; 55 + 56 + /** 57 + * struct sci_clk - TI SCI clock representation 58 + * @hw: Hardware clock cookie for common clock framework 59 + * @dev_id: Device index 60 + * @clk_id: Clock index 61 + * @node: Clocks list link 62 + * @provider: Master clock provider 63 + * @flags: Flags for the clock 64 + */ 65 + struct sci_clk { 66 + struct clk_hw hw; 67 + u16 dev_id; 68 + u8 clk_id; 69 + struct list_head node; 70 + struct sci_clk_provider *provider; 71 + u8 flags; 72 + }; 73 + 74 + #define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw) 75 + 76 + /** 77 + * sci_clk_prepare - Prepare (enable) a TI SCI clock 78 + * @hw: clock to prepare 79 + * 80 + * Prepares a clock to be actively used. Returns the SCI protocol status. 81 + */ 82 + static int sci_clk_prepare(struct clk_hw *hw) 83 + { 84 + struct sci_clk *clk = to_sci_clk(hw); 85 + bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE; 86 + bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE; 87 + bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION; 88 + 89 + return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id, 90 + clk->clk_id, enable_ssc, 91 + allow_freq_change, 92 + input_termination); 93 + } 94 + 95 + /** 96 + * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock 97 + * @hw: clock to unprepare 98 + * 99 + * Un-prepares a clock from active state. 100 + */ 101 + static void sci_clk_unprepare(struct clk_hw *hw) 102 + { 103 + struct sci_clk *clk = to_sci_clk(hw); 104 + int ret; 105 + 106 + ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id, 107 + clk->clk_id); 108 + if (ret) 109 + dev_err(clk->provider->dev, 110 + "unprepare failed for dev=%d, clk=%d, ret=%d\n", 111 + clk->dev_id, clk->clk_id, ret); 112 + } 113 + 114 + /** 115 + * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not 116 + * @hw: clock to check status for 117 + * 118 + * Checks if a clock is prepared (enabled) in hardware. Returns non-zero 119 + * value if clock is enabled, zero otherwise. 120 + */ 121 + static int sci_clk_is_prepared(struct clk_hw *hw) 122 + { 123 + struct sci_clk *clk = to_sci_clk(hw); 124 + bool req_state, current_state; 125 + int ret; 126 + 127 + ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id, 128 + clk->clk_id, &req_state, 129 + &current_state); 130 + if (ret) { 131 + dev_err(clk->provider->dev, 132 + "is_prepared failed for dev=%d, clk=%d, ret=%d\n", 133 + clk->dev_id, clk->clk_id, ret); 134 + return 0; 135 + } 136 + 137 + return req_state; 138 + } 139 + 140 + /** 141 + * sci_clk_recalc_rate - Get clock rate for a TI SCI clock 142 + * @hw: clock to get rate for 143 + * @parent_rate: parent rate provided by common clock framework, not used 144 + * 145 + * Gets the current clock rate of a TI SCI clock. Returns the current 146 + * clock rate, or zero in failure. 147 + */ 148 + static unsigned long sci_clk_recalc_rate(struct clk_hw *hw, 149 + unsigned long parent_rate) 150 + { 151 + struct sci_clk *clk = to_sci_clk(hw); 152 + u64 freq; 153 + int ret; 154 + 155 + ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id, 156 + clk->clk_id, &freq); 157 + if (ret) { 158 + dev_err(clk->provider->dev, 159 + "recalc-rate failed for dev=%d, clk=%d, ret=%d\n", 160 + clk->dev_id, clk->clk_id, ret); 161 + return 0; 162 + } 163 + 164 + return freq; 165 + } 166 + 167 + /** 168 + * sci_clk_determine_rate - Determines a clock rate a clock can be set to 169 + * @hw: clock to change rate for 170 + * @req: requested rate configuration for the clock 171 + * 172 + * Determines a suitable clock rate and parent for a TI SCI clock. 173 + * The parent handling is un-used, as generally the parent clock rates 174 + * are not known by the kernel; instead these are internally handled 175 + * by the firmware. Returns 0 on success, negative error value on failure. 176 + */ 177 + static int sci_clk_determine_rate(struct clk_hw *hw, 178 + struct clk_rate_request *req) 179 + { 180 + struct sci_clk *clk = to_sci_clk(hw); 181 + int ret; 182 + u64 new_rate; 183 + 184 + ret = clk->provider->ops->get_best_match_freq(clk->provider->sci, 185 + clk->dev_id, 186 + clk->clk_id, 187 + req->min_rate, 188 + req->rate, 189 + req->max_rate, 190 + &new_rate); 191 + if (ret) { 192 + dev_err(clk->provider->dev, 193 + "determine-rate failed for dev=%d, clk=%d, ret=%d\n", 194 + clk->dev_id, clk->clk_id, ret); 195 + return ret; 196 + } 197 + 198 + req->rate = new_rate; 199 + 200 + return 0; 201 + } 202 + 203 + /** 204 + * sci_clk_set_rate - Set rate for a TI SCI clock 205 + * @hw: clock to change rate for 206 + * @rate: target rate for the clock 207 + * @parent_rate: rate of the clock parent, not used for TI SCI clocks 208 + * 209 + * Sets a clock frequency for a TI SCI clock. Returns the TI SCI 210 + * protocol status. 211 + */ 212 + static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate, 213 + unsigned long parent_rate) 214 + { 215 + struct sci_clk *clk = to_sci_clk(hw); 216 + 217 + return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, 218 + clk->clk_id, rate, rate, rate); 219 + } 220 + 221 + /** 222 + * sci_clk_get_parent - Get the current parent of a TI SCI clock 223 + * @hw: clock to get parent for 224 + * 225 + * Returns the index of the currently selected parent for a TI SCI clock. 226 + */ 227 + static u8 sci_clk_get_parent(struct clk_hw *hw) 228 + { 229 + struct sci_clk *clk = to_sci_clk(hw); 230 + u8 parent_id; 231 + int ret; 232 + 233 + ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id, 234 + clk->clk_id, &parent_id); 235 + if (ret) { 236 + dev_err(clk->provider->dev, 237 + "get-parent failed for dev=%d, clk=%d, ret=%d\n", 238 + clk->dev_id, clk->clk_id, ret); 239 + return 0; 240 + } 241 + 242 + return parent_id - clk->clk_id - 1; 243 + } 244 + 245 + /** 246 + * sci_clk_set_parent - Set the parent of a TI SCI clock 247 + * @hw: clock to set parent for 248 + * @index: new parent index for the clock 249 + * 250 + * Sets the parent of a TI SCI clock. Return TI SCI protocol status. 251 + */ 252 + static int sci_clk_set_parent(struct clk_hw *hw, u8 index) 253 + { 254 + struct sci_clk *clk = to_sci_clk(hw); 255 + 256 + return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, 257 + clk->clk_id, 258 + index + 1 + clk->clk_id); 259 + } 260 + 261 + static const struct clk_ops sci_clk_ops = { 262 + .prepare = sci_clk_prepare, 263 + .unprepare = sci_clk_unprepare, 264 + .is_prepared = sci_clk_is_prepared, 265 + .recalc_rate = sci_clk_recalc_rate, 266 + .determine_rate = sci_clk_determine_rate, 267 + .set_rate = sci_clk_set_rate, 268 + .get_parent = sci_clk_get_parent, 269 + .set_parent = sci_clk_set_parent, 270 + }; 271 + 272 + /** 273 + * _sci_clk_get - Gets a handle for an SCI clock 274 + * @provider: Handle to SCI clock provider 275 + * @dev_id: device ID for the clock to register 276 + * @clk_id: clock ID for the clock to register 277 + * 278 + * Gets a handle to an existing TI SCI hw clock, or builds a new clock 279 + * entry and registers it with the common clock framework. Called from 280 + * the common clock framework, when a corresponding of_clk_get call is 281 + * executed, or recursively from itself when parsing parent clocks. 282 + * Returns a pointer to the hw clock struct, or ERR_PTR value in failure. 283 + */ 284 + static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider, 285 + u16 dev_id, u8 clk_id) 286 + { 287 + struct clk_init_data init = { NULL }; 288 + struct sci_clk *sci_clk = NULL; 289 + char *name = NULL; 290 + char **parent_names = NULL; 291 + int i; 292 + int ret; 293 + 294 + sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL); 295 + if (!sci_clk) 296 + return ERR_PTR(-ENOMEM); 297 + 298 + sci_clk->dev_id = dev_id; 299 + sci_clk->clk_id = clk_id; 300 + sci_clk->provider = provider; 301 + 302 + ret = provider->ops->get_num_parents(provider->sci, dev_id, 303 + clk_id, 304 + &init.num_parents); 305 + if (ret) 306 + goto err; 307 + 308 + name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev), 309 + sci_clk->dev_id, sci_clk->clk_id); 310 + 311 + init.name = name; 312 + 313 + /* 314 + * From kernel point of view, we only care about a clocks parents, 315 + * if it has more than 1 possible parent. In this case, it is going 316 + * to have mux functionality. Otherwise it is going to act as a root 317 + * clock. 318 + */ 319 + if (init.num_parents < 2) 320 + init.num_parents = 0; 321 + 322 + if (init.num_parents) { 323 + parent_names = kcalloc(init.num_parents, sizeof(char *), 324 + GFP_KERNEL); 325 + 326 + if (!parent_names) { 327 + ret = -ENOMEM; 328 + goto err; 329 + } 330 + 331 + for (i = 0; i < init.num_parents; i++) { 332 + char *parent_name; 333 + 334 + parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d", 335 + dev_name(provider->dev), 336 + sci_clk->dev_id, 337 + sci_clk->clk_id + 1 + i); 338 + if (!parent_name) { 339 + ret = -ENOMEM; 340 + goto err; 341 + } 342 + parent_names[i] = parent_name; 343 + } 344 + init.parent_names = (void *)parent_names; 345 + } 346 + 347 + init.ops = &sci_clk_ops; 348 + sci_clk->hw.init = &init; 349 + 350 + ret = devm_clk_hw_register(provider->dev, &sci_clk->hw); 351 + if (ret) 352 + dev_err(provider->dev, "failed clk register with %d\n", ret); 353 + 354 + err: 355 + if (parent_names) { 356 + for (i = 0; i < init.num_parents; i++) 357 + kfree(parent_names[i]); 358 + 359 + kfree(parent_names); 360 + } 361 + 362 + kfree(name); 363 + 364 + if (ret) 365 + return ERR_PTR(ret); 366 + 367 + return &sci_clk->hw; 368 + } 369 + 370 + /** 371 + * sci_clk_get - Xlate function for getting clock handles 372 + * @clkspec: device tree clock specifier 373 + * @data: pointer to the clock provider 374 + * 375 + * Xlate function for retrieving clock TI SCI hw clock handles based on 376 + * device tree clock specifier. Called from the common clock framework, 377 + * when a corresponding of_clk_get call is executed. Returns a pointer 378 + * to the TI SCI hw clock struct, or ERR_PTR value in failure. 379 + */ 380 + static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data) 381 + { 382 + struct sci_clk_provider *provider = data; 383 + u16 dev_id; 384 + u8 clk_id; 385 + const struct sci_clk_data *clks = provider->clk_data; 386 + struct clk_hw **clocks = provider->clocks; 387 + 388 + if (clkspec->args_count != 2) 389 + return ERR_PTR(-EINVAL); 390 + 391 + dev_id = clkspec->args[0]; 392 + clk_id = clkspec->args[1]; 393 + 394 + while (clks->num_clks) { 395 + if (clks->dev == dev_id) { 396 + if (clk_id >= clks->num_clks) 397 + return ERR_PTR(-EINVAL); 398 + 399 + return clocks[clk_id]; 400 + } 401 + 402 + clks++; 403 + } 404 + 405 + return ERR_PTR(-ENODEV); 406 + } 407 + 408 + static int ti_sci_init_clocks(struct sci_clk_provider *p) 409 + { 410 + const struct sci_clk_data *data = p->clk_data; 411 + struct clk_hw *hw; 412 + int i; 413 + 414 + while (data->num_clks) { 415 + p->clocks = devm_kcalloc(p->dev, data->num_clks, 416 + sizeof(struct sci_clk), 417 + GFP_KERNEL); 418 + if (!p->clocks) 419 + return -ENOMEM; 420 + 421 + for (i = 0; i < data->num_clks; i++) { 422 + hw = _sci_clk_build(p, data->dev, i); 423 + if (!IS_ERR(hw)) { 424 + p->clocks[i] = hw; 425 + continue; 426 + } 427 + 428 + /* Skip any holes in the clock lists */ 429 + if (PTR_ERR(hw) == -ENODEV) 430 + continue; 431 + 432 + return PTR_ERR(hw); 433 + } 434 + data++; 435 + } 436 + 437 + return 0; 438 + } 439 + 440 + static const struct sci_clk_data k2g_clk_data[] = { 441 + /* pmmc */ 442 + { .dev = 0x0, .num_clks = 4 }, 443 + 444 + /* mlb0 */ 445 + { .dev = 0x1, .num_clks = 5 }, 446 + 447 + /* dss0 */ 448 + { .dev = 0x2, .num_clks = 2 }, 449 + 450 + /* mcbsp0 */ 451 + { .dev = 0x3, .num_clks = 8 }, 452 + 453 + /* mcasp0 */ 454 + { .dev = 0x4, .num_clks = 8 }, 455 + 456 + /* mcasp1 */ 457 + { .dev = 0x5, .num_clks = 8 }, 458 + 459 + /* mcasp2 */ 460 + { .dev = 0x6, .num_clks = 8 }, 461 + 462 + /* dcan0 */ 463 + { .dev = 0x8, .num_clks = 2 }, 464 + 465 + /* dcan1 */ 466 + { .dev = 0x9, .num_clks = 2 }, 467 + 468 + /* emif0 */ 469 + { .dev = 0xa, .num_clks = 6 }, 470 + 471 + /* mmchs0 */ 472 + { .dev = 0xb, .num_clks = 3 }, 473 + 474 + /* mmchs1 */ 475 + { .dev = 0xc, .num_clks = 3 }, 476 + 477 + /* gpmc0 */ 478 + { .dev = 0xd, .num_clks = 1 }, 479 + 480 + /* elm0 */ 481 + { .dev = 0xe, .num_clks = 1 }, 482 + 483 + /* spi0 */ 484 + { .dev = 0x10, .num_clks = 1 }, 485 + 486 + /* spi1 */ 487 + { .dev = 0x11, .num_clks = 1 }, 488 + 489 + /* spi2 */ 490 + { .dev = 0x12, .num_clks = 1 }, 491 + 492 + /* spi3 */ 493 + { .dev = 0x13, .num_clks = 1 }, 494 + 495 + /* icss0 */ 496 + { .dev = 0x14, .num_clks = 6 }, 497 + 498 + /* icss1 */ 499 + { .dev = 0x15, .num_clks = 6 }, 500 + 501 + /* usb0 */ 502 + { .dev = 0x16, .num_clks = 7 }, 503 + 504 + /* usb1 */ 505 + { .dev = 0x17, .num_clks = 7 }, 506 + 507 + /* nss0 */ 508 + { .dev = 0x18, .num_clks = 14 }, 509 + 510 + /* pcie0 */ 511 + { .dev = 0x19, .num_clks = 1 }, 512 + 513 + /* gpio0 */ 514 + { .dev = 0x1b, .num_clks = 1 }, 515 + 516 + /* gpio1 */ 517 + { .dev = 0x1c, .num_clks = 1 }, 518 + 519 + /* timer64_0 */ 520 + { .dev = 0x1d, .num_clks = 9 }, 521 + 522 + /* timer64_1 */ 523 + { .dev = 0x1e, .num_clks = 9 }, 524 + 525 + /* timer64_2 */ 526 + { .dev = 0x1f, .num_clks = 9 }, 527 + 528 + /* timer64_3 */ 529 + { .dev = 0x20, .num_clks = 9 }, 530 + 531 + /* timer64_4 */ 532 + { .dev = 0x21, .num_clks = 9 }, 533 + 534 + /* timer64_5 */ 535 + { .dev = 0x22, .num_clks = 9 }, 536 + 537 + /* timer64_6 */ 538 + { .dev = 0x23, .num_clks = 9 }, 539 + 540 + /* msgmgr0 */ 541 + { .dev = 0x25, .num_clks = 1 }, 542 + 543 + /* bootcfg0 */ 544 + { .dev = 0x26, .num_clks = 1 }, 545 + 546 + /* arm_bootrom0 */ 547 + { .dev = 0x27, .num_clks = 1 }, 548 + 549 + /* dsp_bootrom0 */ 550 + { .dev = 0x29, .num_clks = 1 }, 551 + 552 + /* debugss0 */ 553 + { .dev = 0x2b, .num_clks = 8 }, 554 + 555 + /* uart0 */ 556 + { .dev = 0x2c, .num_clks = 1 }, 557 + 558 + /* uart1 */ 559 + { .dev = 0x2d, .num_clks = 1 }, 560 + 561 + /* uart2 */ 562 + { .dev = 0x2e, .num_clks = 1 }, 563 + 564 + /* ehrpwm0 */ 565 + { .dev = 0x2f, .num_clks = 1 }, 566 + 567 + /* ehrpwm1 */ 568 + { .dev = 0x30, .num_clks = 1 }, 569 + 570 + /* ehrpwm2 */ 571 + { .dev = 0x31, .num_clks = 1 }, 572 + 573 + /* ehrpwm3 */ 574 + { .dev = 0x32, .num_clks = 1 }, 575 + 576 + /* ehrpwm4 */ 577 + { .dev = 0x33, .num_clks = 1 }, 578 + 579 + /* ehrpwm5 */ 580 + { .dev = 0x34, .num_clks = 1 }, 581 + 582 + /* eqep0 */ 583 + { .dev = 0x35, .num_clks = 1 }, 584 + 585 + /* eqep1 */ 586 + { .dev = 0x36, .num_clks = 1 }, 587 + 588 + /* eqep2 */ 589 + { .dev = 0x37, .num_clks = 1 }, 590 + 591 + /* ecap0 */ 592 + { .dev = 0x38, .num_clks = 1 }, 593 + 594 + /* ecap1 */ 595 + { .dev = 0x39, .num_clks = 1 }, 596 + 597 + /* i2c0 */ 598 + { .dev = 0x3a, .num_clks = 1 }, 599 + 600 + /* i2c1 */ 601 + { .dev = 0x3b, .num_clks = 1 }, 602 + 603 + /* i2c2 */ 604 + { .dev = 0x3c, .num_clks = 1 }, 605 + 606 + /* edma0 */ 607 + { .dev = 0x3f, .num_clks = 2 }, 608 + 609 + /* semaphore0 */ 610 + { .dev = 0x40, .num_clks = 1 }, 611 + 612 + /* intc0 */ 613 + { .dev = 0x41, .num_clks = 1 }, 614 + 615 + /* gic0 */ 616 + { .dev = 0x42, .num_clks = 1 }, 617 + 618 + /* qspi0 */ 619 + { .dev = 0x43, .num_clks = 5 }, 620 + 621 + /* arm_64b_counter0 */ 622 + { .dev = 0x44, .num_clks = 2 }, 623 + 624 + /* tetris0 */ 625 + { .dev = 0x45, .num_clks = 2 }, 626 + 627 + /* cgem0 */ 628 + { .dev = 0x46, .num_clks = 2 }, 629 + 630 + /* msmc0 */ 631 + { .dev = 0x47, .num_clks = 1 }, 632 + 633 + /* cbass0 */ 634 + { .dev = 0x49, .num_clks = 1 }, 635 + 636 + /* board0 */ 637 + { .dev = 0x4c, .num_clks = 36 }, 638 + 639 + /* edma1 */ 640 + { .dev = 0x4f, .num_clks = 2 }, 641 + { .num_clks = 0 }, 642 + }; 643 + 644 + static const struct of_device_id ti_sci_clk_of_match[] = { 645 + { .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data }, 646 + { /* Sentinel */ }, 647 + }; 648 + MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match); 649 + 650 + /** 651 + * ti_sci_clk_probe - Probe function for the TI SCI clock driver 652 + * @pdev: platform device pointer to be probed 653 + * 654 + * Probes the TI SCI clock device. Allocates a new clock provider 655 + * and registers this to the common clock framework. Also applies 656 + * any required flags to the identified clocks via clock lists 657 + * supplied from DT. Returns 0 for success, negative error value 658 + * for failure. 659 + */ 660 + static int ti_sci_clk_probe(struct platform_device *pdev) 661 + { 662 + struct device *dev = &pdev->dev; 663 + struct device_node *np = dev->of_node; 664 + struct sci_clk_provider *provider; 665 + const struct ti_sci_handle *handle; 666 + const struct sci_clk_data *data; 667 + int ret; 668 + 669 + data = of_device_get_match_data(dev); 670 + if (!data) 671 + return -EINVAL; 672 + 673 + handle = devm_ti_sci_get_handle(dev); 674 + if (IS_ERR(handle)) 675 + return PTR_ERR(handle); 676 + 677 + provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL); 678 + if (!provider) 679 + return -ENOMEM; 680 + 681 + provider->clk_data = data; 682 + 683 + provider->sci = handle; 684 + provider->ops = &handle->ops.clk_ops; 685 + provider->dev = dev; 686 + 687 + ret = ti_sci_init_clocks(provider); 688 + if (ret) { 689 + pr_err("ti-sci-init-clocks failed.\n"); 690 + return ret; 691 + } 692 + 693 + return of_clk_add_hw_provider(np, sci_clk_get, provider); 694 + } 695 + 696 + /** 697 + * ti_sci_clk_remove - Remove TI SCI clock device 698 + * @pdev: platform device pointer for the device to be removed 699 + * 700 + * Removes the TI SCI device. Unregisters the clock provider registered 701 + * via common clock framework. Any memory allocated for the device will 702 + * be free'd silently via the devm framework. Returns 0 always. 703 + */ 704 + static int ti_sci_clk_remove(struct platform_device *pdev) 705 + { 706 + of_clk_del_provider(pdev->dev.of_node); 707 + 708 + return 0; 709 + } 710 + 711 + static struct platform_driver ti_sci_clk_driver = { 712 + .probe = ti_sci_clk_probe, 713 + .remove = ti_sci_clk_remove, 714 + .driver = { 715 + .name = "ti-sci-clk", 716 + .of_match_table = of_match_ptr(ti_sci_clk_of_match), 717 + }, 718 + }; 719 + module_platform_driver(ti_sci_clk_driver); 720 + 721 + MODULE_LICENSE("GPL v2"); 722 + MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver"); 723 + MODULE_AUTHOR("Tero Kristo"); 724 + MODULE_ALIAS("platform:ti-sci-clk");