1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2023 Beckhoff Automation GmbH & Co. KG 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/malloc.h> 35 #include <sys/bus.h> 36 #include <sys/cpu.h> 37 #include <machine/bus.h> 38 #include <sys/queue.h> 39 40 #include <dev/ofw/openfirm.h> 41 #include <dev/ofw/ofw_bus.h> 42 #include <dev/ofw/ofw_bus_subr.h> 43 44 #include <dev/extres/clk/clk.h> 45 #include <dev/extres/clk/clk_fixed.h> 46 47 #include <dev/clk/xilinx/zynqmp_clk_mux.h> 48 #include <dev/clk/xilinx/zynqmp_clk_pll.h> 49 #include <dev/clk/xilinx/zynqmp_clk_fixed.h> 50 #include <dev/clk/xilinx/zynqmp_clk_div.h> 51 #include <dev/clk/xilinx/zynqmp_clk_gate.h> 52 53 #include <dev/firmware/xilinx/pm_defs.h> 54 55 #include "clkdev_if.h" 56 #include "zynqmp_firmware_if.h" 57 58 #define ZYNQMP_MAX_NAME_LEN 16 59 #define ZYNQMP_MAX_NODES 6 60 #define ZYNQMP_MAX_PARENTS 100 61 62 #define ZYNQMP_CLK_IS_VALID (1 << 0) 63 #define ZYNQMP_CLK_IS_EXT (1 << 2) 64 65 #define ZYNQMP_GET_NODE_TYPE(x) (x & 0x7) 66 #define ZYNQMP_GET_NODE_CLKFLAGS(x) ((x >> 8) & 0xFF) 67 #define ZYNQMP_GET_NODE_TYPEFLAGS(x) ((x >> 24) & 0xF) 68 69 enum ZYNQMP_NODE_TYPE { 70 CLK_NODE_TYPE_NULL = 0, 71 CLK_NODE_TYPE_MUX, 72 CLK_NODE_TYPE_PLL, 73 CLK_NODE_TYPE_FIXED, 74 CLK_NODE_TYPE_DIV0, 75 CLK_NODE_TYPE_DIV1, 76 CLK_NODE_TYPE_GATE, 77 }; 78 79 /* 80 * Clock IDs in the firmware starts at 0 but 81 * exported clocks (and so clock exposed by the clock framework) 82 * starts at 1 83 */ 84 #define ZYNQMP_ID_TO_CLK(x) ((x) + 1) 85 #define CLK_ID_TO_ZYNQMP(x) ((x) - 1) 86 87 struct zynqmp_clk { 88 TAILQ_ENTRY(zynqmp_clk) next; 89 struct clknode_init_def clkdef; 90 uint32_t id; 91 uint32_t parentids[ZYNQMP_MAX_PARENTS]; 92 uint32_t topology[ZYNQMP_MAX_NODES]; 93 uint32_t attributes; 94 }; 95 96 struct zynqmp_clock_softc { 97 device_t dev; 98 device_t parent; 99 phandle_t node; 100 clk_t clk_pss_ref; 101 clk_t clk_video; 102 clk_t clk_pss_alt_ref; 103 clk_t clk_aux_ref; 104 clk_t clk_gt_crx_ref; 105 struct clkdom *clkdom; 106 }; 107 108 struct name_resp { 109 char name[16]; 110 }; 111 112 struct zynqmp_clk_softc { 113 struct zynqmp_clk *clk; 114 device_t firmware; 115 uint32_t id; 116 }; 117 118 static int 119 zynqmp_clk_init(struct clknode *clk, device_t dev) 120 { 121 122 clknode_init_parent_idx(clk, 0); 123 return (0); 124 } 125 126 static clknode_method_t zynqmp_clk_clknode_methods[] = { 127 /* Device interface */ 128 CLKNODEMETHOD(clknode_init, zynqmp_clk_init), 129 CLKNODEMETHOD_END 130 }; 131 132 DEFINE_CLASS_1(zynqmp_clk_clknode, zynqmp_clk_clknode_class, 133 zynqmp_clk_clknode_methods, sizeof(struct zynqmp_clk_softc), clknode_class); 134 135 static int 136 zynqmp_clk_register(struct clkdom *clkdom, device_t fw, struct zynqmp_clk *clkdef) 137 { 138 struct clknode *clknode; 139 struct zynqmp_clk_softc *sc; 140 char *prev_clock_name = NULL; 141 char *clkname, *parent_name; 142 struct clknode_init_def *zynqclk; 143 int i; 144 145 for (i = 0; i < ZYNQMP_MAX_NODES; i++) { 146 /* Bail early if we have no node */ 147 if (ZYNQMP_GET_NODE_TYPE(clkdef->topology[i]) == CLK_NODE_TYPE_NULL) 148 break; 149 zynqclk = malloc(sizeof(*zynqclk), M_DEVBUF, M_WAITOK | M_ZERO); 150 zynqclk->id = clkdef->clkdef.id; 151 /* For the first node in the topology we use the main clock parents */ 152 if (i == 0) { 153 zynqclk->parent_cnt = clkdef->clkdef.parent_cnt; 154 zynqclk->parent_names = clkdef->clkdef.parent_names; 155 } else { 156 zynqclk->parent_cnt = 1; 157 zynqclk->parent_names = malloc(sizeof(char *) * zynqclk->parent_cnt, M_DEVBUF, M_ZERO | M_WAITOK); 158 parent_name = strdup(prev_clock_name, M_DEVBUF); 159 zynqclk->parent_names[0] = (const char *)parent_name; 160 } 161 /* Register the clock node based on the topology type */ 162 switch (ZYNQMP_GET_NODE_TYPE(clkdef->topology[i])) { 163 case CLK_NODE_TYPE_MUX: 164 asprintf(&clkname, M_DEVBUF, "%s_mux", clkdef->clkdef.name); 165 zynqclk->name = (const char *)clkname; 166 zynqmp_clk_mux_register(clkdom, fw, zynqclk); 167 break; 168 case CLK_NODE_TYPE_PLL: 169 asprintf(&clkname, M_DEVBUF, "%s_pll", clkdef->clkdef.name); 170 zynqclk->name = (const char *)clkname; 171 zynqmp_clk_pll_register(clkdom, fw, zynqclk); 172 break; 173 case CLK_NODE_TYPE_FIXED: 174 asprintf(&clkname, M_DEVBUF, "%s_fixed", clkdef->clkdef.name); 175 zynqclk->name = (const char *)clkname; 176 zynqmp_clk_fixed_register(clkdom, fw, zynqclk); 177 break; 178 case CLK_NODE_TYPE_DIV0: 179 asprintf(&clkname, M_DEVBUF, "%s_div0", clkdef->clkdef.name); 180 zynqclk->name = (const char *)clkname; 181 zynqmp_clk_div_register(clkdom, fw, zynqclk, CLK_DIV_TYPE_DIV0); 182 break; 183 case CLK_NODE_TYPE_DIV1: 184 asprintf(&clkname, M_DEVBUF, "%s_div1", clkdef->clkdef.name); 185 zynqclk->name = (const char *)clkname; 186 zynqmp_clk_div_register(clkdom, fw, zynqclk, CLK_DIV_TYPE_DIV1); 187 break; 188 case CLK_NODE_TYPE_GATE: 189 asprintf(&clkname, M_DEVBUF, "%s_gate", clkdef->clkdef.name); 190 zynqclk->name = (const char *)clkname; 191 zynqmp_clk_gate_register(clkdom, fw, zynqclk); 192 break; 193 case CLK_NODE_TYPE_NULL: 194 default: 195 clkname = NULL; 196 break; 197 } 198 if (i != 0) { 199 free(parent_name, M_DEVBUF); 200 free(zynqclk->parent_names, M_DEVBUF); 201 } 202 if (clkname != NULL) 203 prev_clock_name = strdup(clkname, M_DEVBUF); 204 free(clkname, M_DEVBUF); 205 free(zynqclk, M_DEVBUF); 206 } 207 208 /* Register main clock */ 209 clkdef->clkdef.name = clkdef->clkdef.name; 210 clkdef->clkdef.parent_cnt = 1; 211 clkdef->clkdef.parent_names = malloc(sizeof(char *) * clkdef->clkdef.parent_cnt, M_DEVBUF, M_ZERO | M_WAITOK); 212 clkdef->clkdef.parent_names[0] = strdup(prev_clock_name, M_DEVBUF); 213 clknode = clknode_create(clkdom, &zynqmp_clk_clknode_class, &clkdef->clkdef); 214 if (clknode == NULL) 215 return (1); 216 sc = clknode_get_softc(clknode); 217 sc->id = clkdef->clkdef.id - 1; 218 sc->firmware = fw; 219 sc->clk = clkdef; 220 clknode_register(clkdom, clknode); 221 return (0); 222 } 223 224 static int 225 zynqmp_fw_clk_get_name(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) 226 { 227 char *clkname; 228 uint32_t query_data[4]; 229 int rv; 230 231 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_NAME, id, 0, 0, query_data); 232 if (rv != 0) 233 return (rv); 234 if (query_data[0] == '\0') 235 return (EINVAL); 236 clkname = malloc(ZYNQMP_MAX_NAME_LEN, M_DEVBUF, M_ZERO | M_WAITOK); 237 memcpy(clkname, query_data, ZYNQMP_MAX_NAME_LEN); 238 clk->clkdef.name = clkname; 239 return (0); 240 } 241 242 static int 243 zynqmp_fw_clk_get_attributes(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) 244 { 245 uint32_t query_data[4]; 246 int rv; 247 248 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_ATTRIBUTES, id, 0, 0, query_data); 249 if (rv != 0) 250 return (rv); 251 clk->attributes = query_data[1]; 252 return (0); 253 } 254 255 static int 256 zynqmp_fw_clk_get_parents(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) 257 { 258 int rv, i; 259 uint32_t query_data[4]; 260 261 for (i = 0; i < ZYNQMP_MAX_PARENTS; i += 3) { 262 clk->parentids[i] = -1; 263 clk->parentids[i + 1] = -1; 264 clk->parentids[i + 2] = -1; 265 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_PARENTS, id, i, 0, query_data); 266 clk->parentids[i] = query_data[1] & 0xFFFF; 267 clk->parentids[i + 1] = query_data[2] & 0xFFFF; 268 clk->parentids[i + 2] = query_data[3] & 0xFFFF; 269 if ((int32_t)query_data[1] == -1) { 270 clk->parentids[i] = -1; 271 break; 272 } 273 clk->parentids[i] += 1; 274 clk->clkdef.parent_cnt++; 275 if ((int32_t)query_data[2] == -1) { 276 clk->parentids[i + 1] = -1; 277 break; 278 } 279 clk->parentids[i + 1] += 1; 280 clk->clkdef.parent_cnt++; 281 if ((int32_t)query_data[3] == -1) { 282 clk->parentids[i + 2] = -1; 283 break; 284 } 285 clk->parentids[i + 2] += 1; 286 clk->clkdef.parent_cnt++; 287 if ((int32_t)query_data[1] == -2) 288 clk->parentids[i] = -2; 289 if ((int32_t)query_data[2] == -2) 290 clk->parentids[i + 1] = -2; 291 if ((int32_t)query_data[3] == -2) 292 clk->parentids[i + 2] = -2; 293 if (rv != 0) 294 break; 295 } 296 return (0); 297 } 298 299 static int 300 zynqmp_fw_clk_get_topology(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) 301 { 302 uint32_t query_data[4]; 303 int rv; 304 305 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_TOPOLOGY, id, 0, 0, query_data); 306 if (rv != 0) 307 return (rv); 308 clk->topology[0] = query_data[1]; 309 clk->topology[1] = query_data[2]; 310 clk->topology[2] = query_data[3]; 311 if (query_data[3] == '\0') 312 goto out; 313 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_TOPOLOGY, id, 3, 0, query_data); 314 if (rv != 0) 315 return (rv); 316 clk->topology[3] = query_data[1]; 317 clk->topology[4] = query_data[2]; 318 clk->topology[5] = query_data[3]; 319 320 out: 321 return (0); 322 } 323 324 static int 325 zynqmp_clock_ofw_map(struct clkdom *clkdom, uint32_t ncells, 326 phandle_t *cells, struct clknode **clk) 327 { 328 329 if (ncells != 1) 330 return (ERANGE); 331 *clk = clknode_find_by_id(clkdom, ZYNQMP_ID_TO_CLK(cells[0])); 332 if (*clk == NULL) 333 return (ENXIO); 334 return (0); 335 } 336 337 static int 338 zynqmp_fw_clk_get_all(struct zynqmp_clock_softc *sc) 339 { 340 TAILQ_HEAD(tailhead, zynqmp_clk) clk_list; 341 struct zynqmp_clk *clk, *tmp, *tmp2; 342 char *clkname; 343 int rv, i; 344 uint32_t query_data[4], num_clock; 345 346 TAILQ_INIT(&clk_list); 347 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, 348 PM_QID_CLOCK_GET_NUM_CLOCKS, 349 0, 350 0, 351 0, 352 query_data); 353 if (rv != 0) { 354 device_printf(sc->dev, "Cannot get clock details from the firmware\n"); 355 return (ENXIO); 356 } 357 358 num_clock = query_data[1]; 359 for (i = 0; i < num_clock; i++) { 360 clk = malloc(sizeof(*clk), M_DEVBUF, M_WAITOK | M_ZERO); 361 clk->clkdef.id = ZYNQMP_ID_TO_CLK(i); 362 zynqmp_fw_clk_get_name(sc, clk, i); 363 zynqmp_fw_clk_get_attributes(sc, clk, i); 364 if ((clk->attributes & ZYNQMP_CLK_IS_VALID) == 0) { 365 free(clk, M_DEVBUF); 366 continue; 367 } 368 if (clk->attributes & ZYNQMP_CLK_IS_EXT) 369 goto skip_ext; 370 /* Get parents id */ 371 rv = zynqmp_fw_clk_get_parents(sc, clk, i); 372 if (rv != 0) { 373 device_printf(sc->dev, "Cannot get parent for %s\n", clk->clkdef.name); 374 free(clk, M_DEVBUF); 375 continue; 376 } 377 /* Get topology */ 378 rv = zynqmp_fw_clk_get_topology(sc, clk, i); 379 if (rv != 0) { 380 device_printf(sc->dev, "Cannot get topology for %s\n", clk->clkdef.name); 381 free(clk, M_DEVBUF); 382 continue; 383 } 384 skip_ext: 385 TAILQ_INSERT_TAIL(&clk_list, clk, next); 386 } 387 388 /* Add a dummy clock */ 389 clk = malloc(sizeof(*clk), M_DEVBUF, M_WAITOK | M_ZERO); 390 clkname = strdup("dummy", M_DEVBUF); 391 clk->clkdef.name = (const char *)clkname; 392 clk->clkdef.id = i; 393 clk->attributes = ZYNQMP_CLK_IS_EXT; 394 TAILQ_INSERT_TAIL(&clk_list, clk, next); 395 396 /* Map parents id to name */ 397 TAILQ_FOREACH_SAFE(clk, &clk_list, next, tmp) { 398 if (clk->attributes & ZYNQMP_CLK_IS_EXT) 399 continue; 400 clk->clkdef.parent_names = malloc(sizeof(char *) * clk->clkdef.parent_cnt, M_DEVBUF, M_ZERO | M_WAITOK); 401 for (i = 0; i < ZYNQMP_MAX_PARENTS; i++) { 402 if (clk->parentids[i] == -1) 403 break; 404 if (clk->parentids[i] == -2) { 405 clk->clkdef.parent_names[i] = strdup("dummy", M_DEVBUF); 406 continue; 407 } 408 TAILQ_FOREACH(tmp2, &clk_list, next) { 409 if (tmp2->clkdef.id == clk->parentids[i]) { 410 if (tmp2->attributes & ZYNQMP_CLK_IS_EXT) { 411 int idx; 412 413 if (ofw_bus_find_string_index( sc->node, 414 "clock-names", tmp2->clkdef.name, &idx) == ENOENT) 415 clk->clkdef.parent_names[i] = strdup("dummy", M_DEVBUF); 416 else 417 clk->clkdef.parent_names[i] = strdup(tmp2->clkdef.name, M_DEVBUF); 418 } 419 else 420 clk->clkdef.parent_names[i] = strdup(tmp2->clkdef.name, M_DEVBUF); 421 break; 422 } 423 } 424 } 425 } 426 427 sc->clkdom = clkdom_create(sc->dev); 428 if (sc->clkdom == NULL) 429 panic("Cannot create clkdom\n"); 430 clkdom_set_ofw_mapper(sc->clkdom, zynqmp_clock_ofw_map); 431 432 /* Register the clocks */ 433 TAILQ_FOREACH_SAFE(clk, &clk_list, next, tmp) { 434 if (clk->attributes & ZYNQMP_CLK_IS_EXT) { 435 if (strcmp(clk->clkdef.name, "dummy") == 0) { 436 struct clk_fixed_def dummy; 437 438 bzero(&dummy, sizeof(dummy)); 439 dummy.clkdef.id = clk->clkdef.id; 440 dummy.clkdef.name = strdup("dummy", M_DEVBUF); 441 clknode_fixed_register(sc->clkdom, &dummy); 442 free(__DECONST(char *, dummy.clkdef.name), M_DEVBUF); 443 } 444 } else 445 zynqmp_clk_register(sc->clkdom, sc->parent, clk); 446 447 TAILQ_REMOVE(&clk_list, clk, next); 448 for (i = 0; i < clk->clkdef.parent_cnt; i++) 449 free(__DECONST(char *, clk->clkdef.parent_names[i]), M_DEVBUF); 450 free(clk->clkdef.parent_names, M_DEVBUF); 451 free(__DECONST(char *, clk->clkdef.name), M_DEVBUF); 452 free(clk, M_DEVBUF); 453 } 454 455 if (clkdom_finit(sc->clkdom) != 0) 456 panic("cannot finalize clkdom initialization\n"); 457 458 if (bootverbose) 459 clkdom_dump(sc->clkdom); 460 461 return (0); 462 } 463 464 static int 465 zynqmp_clock_probe(device_t dev) 466 { 467 468 if (!ofw_bus_status_okay(dev)) 469 return (ENXIO); 470 if (!ofw_bus_is_compatible(dev, "xlnx,zynqmp-clk")) 471 return (ENXIO); 472 device_set_desc(dev, "ZynqMP Clock Controller"); 473 474 return (BUS_PROBE_DEFAULT); 475 } 476 477 static int 478 zynqmp_clock_attach(device_t dev) 479 { 480 struct zynqmp_clock_softc *sc; 481 int rv; 482 483 sc = device_get_softc(dev); 484 sc->dev = dev; 485 sc->parent = device_get_parent(dev); 486 sc->node = ofw_bus_get_node(dev); 487 488 /* Enable all clocks */ 489 if (clk_get_by_ofw_name(dev, 0, "pss_ref_clk", &sc->clk_pss_ref) != 0) { 490 device_printf(dev, "Cannot get pss_ref_clk clock\n"); 491 return (ENXIO); 492 } 493 rv = clk_enable(sc->clk_pss_ref); 494 if (rv != 0) { 495 device_printf(dev, "Could not enable clock pss_ref_clk\n"); 496 return (ENXIO); 497 } 498 if (clk_get_by_ofw_name(dev, 0, "video_clk", &sc->clk_video) != 0) { 499 device_printf(dev, "Cannot get video_clk clock\n"); 500 return (ENXIO); 501 } 502 rv = clk_enable(sc->clk_video); 503 if (rv != 0) { 504 device_printf(dev, "Could not enable clock video_clk\n"); 505 return (ENXIO); 506 } 507 if (clk_get_by_ofw_name(dev, 0, "pss_alt_ref_clk", &sc->clk_pss_alt_ref) != 0) { 508 device_printf(dev, "Cannot get pss_alt_ref_clk clock\n"); 509 return (ENXIO); 510 } 511 rv = clk_enable(sc->clk_pss_alt_ref); 512 if (rv != 0) { 513 device_printf(dev, "Could not enable clock pss_alt_ref_clk\n"); 514 return (ENXIO); 515 } 516 if (clk_get_by_ofw_name(dev, 0, "aux_ref_clk", &sc->clk_aux_ref) != 0) { 517 device_printf(dev, "Cannot get pss_aux_clk clock\n"); 518 return (ENXIO); 519 } 520 rv = clk_enable(sc->clk_aux_ref); 521 if (rv != 0) { 522 device_printf(dev, "Could not enable clock pss_aux_clk\n"); 523 return (ENXIO); 524 } 525 if (clk_get_by_ofw_name(dev, 0, "gt_crx_ref_clk", &sc->clk_gt_crx_ref) != 0) { 526 device_printf(dev, "Cannot get gt_crx_ref_clk clock\n"); 527 return (ENXIO); 528 } 529 rv = clk_enable(sc->clk_gt_crx_ref); 530 if (rv != 0) { 531 device_printf(dev, "Could not enable clock gt_crx_ref_clk\n"); 532 return (ENXIO); 533 } 534 535 rv = zynqmp_fw_clk_get_all(sc); 536 if (rv != 0) { 537 clk_disable(sc->clk_gt_crx_ref); 538 clk_disable(sc->clk_aux_ref); 539 clk_disable(sc->clk_pss_alt_ref); 540 clk_disable(sc->clk_video); 541 clk_disable(sc->clk_pss_ref); 542 return (rv); 543 } 544 return (0); 545 } 546 547 static device_method_t zynqmp_clock_methods[] = { 548 /* device_if */ 549 DEVMETHOD(device_probe, zynqmp_clock_probe), 550 DEVMETHOD(device_attach, zynqmp_clock_attach), 551 552 DEVMETHOD_END 553 }; 554 555 static driver_t zynqmp_clock_driver = { 556 "zynqmp_clock", 557 zynqmp_clock_methods, 558 sizeof(struct zynqmp_clock_softc), 559 }; 560 561 EARLY_DRIVER_MODULE(zynqmp_clock, simplebus, zynqmp_clock_driver, 0, 0, 562 BUS_PASS_BUS + BUS_PASS_ORDER_LAST); 563