Lines Matching +full:parent +full:- +full:clk

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
44 #include <dev/clk/clk.h>
45 #include <dev/clk/clk_fixed.h>
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>
85 #define CLK_ID_TO_ZYNQMP(x) ((x) - 1)
98 device_t parent; member
113 struct zynqmp_clk *clk; member
119 zynqmp_clk_init(struct clknode *clk, device_t dev) in zynqmp_clk_init() argument
122 clknode_init_parent_idx(clk, 0); in zynqmp_clk_init()
147 if (ZYNQMP_GET_NODE_TYPE(clkdef->topology[i]) == CLK_NODE_TYPE_NULL) in zynqmp_clk_register()
150 zynqclk->id = clkdef->clkdef.id; in zynqmp_clk_register()
153 zynqclk->parent_cnt = clkdef->clkdef.parent_cnt; in zynqmp_clk_register()
154 zynqclk->parent_names = clkdef->clkdef.parent_names; in zynqmp_clk_register()
156 zynqclk->parent_cnt = 1; in zynqmp_clk_register()
157 … zynqclk->parent_names = malloc(sizeof(char *) * zynqclk->parent_cnt, M_DEVBUF, M_ZERO | M_WAITOK); in zynqmp_clk_register()
159 zynqclk->parent_names[0] = (const char *)parent_name; in zynqmp_clk_register()
162 switch (ZYNQMP_GET_NODE_TYPE(clkdef->topology[i])) { in zynqmp_clk_register()
164 asprintf(&clkname, M_DEVBUF, "%s_mux", clkdef->clkdef.name); in zynqmp_clk_register()
165 zynqclk->name = (const char *)clkname; in zynqmp_clk_register()
169 asprintf(&clkname, M_DEVBUF, "%s_pll", clkdef->clkdef.name); in zynqmp_clk_register()
170 zynqclk->name = (const char *)clkname; in zynqmp_clk_register()
174 asprintf(&clkname, M_DEVBUF, "%s_fixed", clkdef->clkdef.name); in zynqmp_clk_register()
175 zynqclk->name = (const char *)clkname; in zynqmp_clk_register()
179 asprintf(&clkname, M_DEVBUF, "%s_div0", clkdef->clkdef.name); in zynqmp_clk_register()
180 zynqclk->name = (const char *)clkname; in zynqmp_clk_register()
184 asprintf(&clkname, M_DEVBUF, "%s_div1", clkdef->clkdef.name); in zynqmp_clk_register()
185 zynqclk->name = (const char *)clkname; in zynqmp_clk_register()
189 asprintf(&clkname, M_DEVBUF, "%s_gate", clkdef->clkdef.name); in zynqmp_clk_register()
190 zynqclk->name = (const char *)clkname; in zynqmp_clk_register()
200 free(zynqclk->parent_names, M_DEVBUF); in zynqmp_clk_register()
209 clkdef->clkdef.name = clkdef->clkdef.name; in zynqmp_clk_register()
210 clkdef->clkdef.parent_cnt = 1; in zynqmp_clk_register()
211 …clkdef->clkdef.parent_names = malloc(sizeof(char *) * clkdef->clkdef.parent_cnt, M_DEVBUF, M_ZERO … in zynqmp_clk_register()
212 clkdef->clkdef.parent_names[0] = strdup(prev_clock_name, M_DEVBUF); in zynqmp_clk_register()
213 clknode = clknode_create(clkdom, &zynqmp_clk_clknode_class, &clkdef->clkdef); in zynqmp_clk_register()
217 sc->id = clkdef->clkdef.id - 1; in zynqmp_clk_register()
218 sc->firmware = fw; in zynqmp_clk_register()
219 sc->clk = clkdef; in zynqmp_clk_register()
225 zynqmp_fw_clk_get_name(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) in zynqmp_fw_clk_get_name() argument
231 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_NAME, id, 0, 0, query_data); in zynqmp_fw_clk_get_name()
238 clk->clkdef.name = clkname; in zynqmp_fw_clk_get_name()
243 zynqmp_fw_clk_get_attributes(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) in zynqmp_fw_clk_get_attributes() argument
248 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_ATTRIBUTES, id, 0, 0, query_data); in zynqmp_fw_clk_get_attributes()
251 clk->attributes = query_data[1]; in zynqmp_fw_clk_get_attributes()
256 zynqmp_fw_clk_get_parents(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) in zynqmp_fw_clk_get_parents() argument
262 clk->parentids[i] = -1; in zynqmp_fw_clk_get_parents()
263 clk->parentids[i + 1] = -1; in zynqmp_fw_clk_get_parents()
264 clk->parentids[i + 2] = -1; in zynqmp_fw_clk_get_parents()
265 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_PARENTS, id, i, 0, query_data); in zynqmp_fw_clk_get_parents()
266 clk->parentids[i] = query_data[1] & 0xFFFF; in zynqmp_fw_clk_get_parents()
267 clk->parentids[i + 1] = query_data[2] & 0xFFFF; in zynqmp_fw_clk_get_parents()
268 clk->parentids[i + 2] = query_data[3] & 0xFFFF; in zynqmp_fw_clk_get_parents()
269 if ((int32_t)query_data[1] == -1) { in zynqmp_fw_clk_get_parents()
270 clk->parentids[i] = -1; in zynqmp_fw_clk_get_parents()
273 clk->parentids[i] += 1; in zynqmp_fw_clk_get_parents()
274 clk->clkdef.parent_cnt++; in zynqmp_fw_clk_get_parents()
275 if ((int32_t)query_data[2] == -1) { in zynqmp_fw_clk_get_parents()
276 clk->parentids[i + 1] = -1; in zynqmp_fw_clk_get_parents()
279 clk->parentids[i + 1] += 1; in zynqmp_fw_clk_get_parents()
280 clk->clkdef.parent_cnt++; in zynqmp_fw_clk_get_parents()
281 if ((int32_t)query_data[3] == -1) { in zynqmp_fw_clk_get_parents()
282 clk->parentids[i + 2] = -1; in zynqmp_fw_clk_get_parents()
285 clk->parentids[i + 2] += 1; in zynqmp_fw_clk_get_parents()
286 clk->clkdef.parent_cnt++; in zynqmp_fw_clk_get_parents()
287 if ((int32_t)query_data[1] == -2) in zynqmp_fw_clk_get_parents()
288 clk->parentids[i] = -2; in zynqmp_fw_clk_get_parents()
289 if ((int32_t)query_data[2] == -2) in zynqmp_fw_clk_get_parents()
290 clk->parentids[i + 1] = -2; in zynqmp_fw_clk_get_parents()
291 if ((int32_t)query_data[3] == -2) in zynqmp_fw_clk_get_parents()
292 clk->parentids[i + 2] = -2; in zynqmp_fw_clk_get_parents()
300 zynqmp_fw_clk_get_topology(struct zynqmp_clock_softc *sc, struct zynqmp_clk *clk, uint32_t id) in zynqmp_fw_clk_get_topology() argument
305 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_TOPOLOGY, id, 0, 0, query_data); in zynqmp_fw_clk_get_topology()
308 clk->topology[0] = query_data[1]; in zynqmp_fw_clk_get_topology()
309 clk->topology[1] = query_data[2]; in zynqmp_fw_clk_get_topology()
310 clk->topology[2] = query_data[3]; in zynqmp_fw_clk_get_topology()
313 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, PM_QID_CLOCK_GET_TOPOLOGY, id, 3, 0, query_data); in zynqmp_fw_clk_get_topology()
316 clk->topology[3] = query_data[1]; in zynqmp_fw_clk_get_topology()
317 clk->topology[4] = query_data[2]; in zynqmp_fw_clk_get_topology()
318 clk->topology[5] = query_data[3]; in zynqmp_fw_clk_get_topology()
326 phandle_t *cells, struct clknode **clk) in zynqmp_clock_ofw_map() argument
331 *clk = clknode_find_by_id(clkdom, ZYNQMP_ID_TO_CLK(cells[0])); in zynqmp_clock_ofw_map()
332 if (*clk == NULL) in zynqmp_clock_ofw_map()
341 struct zynqmp_clk *clk, *tmp, *tmp2; in zynqmp_fw_clk_get_all() local
347 rv = ZYNQMP_FIRMWARE_QUERY_DATA(sc->parent, in zynqmp_fw_clk_get_all()
354 device_printf(sc->dev, "Cannot get clock details from the firmware\n"); in zynqmp_fw_clk_get_all()
360 clk = malloc(sizeof(*clk), M_DEVBUF, M_WAITOK | M_ZERO); in zynqmp_fw_clk_get_all()
361 clk->clkdef.id = ZYNQMP_ID_TO_CLK(i); in zynqmp_fw_clk_get_all()
362 zynqmp_fw_clk_get_name(sc, clk, i); in zynqmp_fw_clk_get_all()
363 zynqmp_fw_clk_get_attributes(sc, clk, i); in zynqmp_fw_clk_get_all()
364 if ((clk->attributes & ZYNQMP_CLK_IS_VALID) == 0) { in zynqmp_fw_clk_get_all()
365 free(clk, M_DEVBUF); in zynqmp_fw_clk_get_all()
368 if (clk->attributes & ZYNQMP_CLK_IS_EXT) in zynqmp_fw_clk_get_all()
371 rv = zynqmp_fw_clk_get_parents(sc, clk, i); in zynqmp_fw_clk_get_all()
373 device_printf(sc->dev, "Cannot get parent for %s\n", clk->clkdef.name); in zynqmp_fw_clk_get_all()
374 free(clk, M_DEVBUF); in zynqmp_fw_clk_get_all()
378 rv = zynqmp_fw_clk_get_topology(sc, clk, i); in zynqmp_fw_clk_get_all()
380 device_printf(sc->dev, "Cannot get topology for %s\n", clk->clkdef.name); in zynqmp_fw_clk_get_all()
381 free(clk, M_DEVBUF); in zynqmp_fw_clk_get_all()
385 TAILQ_INSERT_TAIL(&clk_list, clk, next); in zynqmp_fw_clk_get_all()
389 clk = malloc(sizeof(*clk), M_DEVBUF, M_WAITOK | M_ZERO); in zynqmp_fw_clk_get_all()
391 clk->clkdef.name = (const char *)clkname; in zynqmp_fw_clk_get_all()
392 clk->clkdef.id = i; in zynqmp_fw_clk_get_all()
393 clk->attributes = ZYNQMP_CLK_IS_EXT; in zynqmp_fw_clk_get_all()
394 TAILQ_INSERT_TAIL(&clk_list, clk, next); in zynqmp_fw_clk_get_all()
397 TAILQ_FOREACH_SAFE(clk, &clk_list, next, tmp) { in zynqmp_fw_clk_get_all()
398 if (clk->attributes & ZYNQMP_CLK_IS_EXT) in zynqmp_fw_clk_get_all()
400clk->clkdef.parent_names = malloc(sizeof(char *) * clk->clkdef.parent_cnt, M_DEVBUF, M_ZERO | M_WA… in zynqmp_fw_clk_get_all()
402 if (clk->parentids[i] == -1) in zynqmp_fw_clk_get_all()
404 if (clk->parentids[i] == -2) { in zynqmp_fw_clk_get_all()
405 clk->clkdef.parent_names[i] = strdup("dummy", M_DEVBUF); in zynqmp_fw_clk_get_all()
409 if (tmp2->clkdef.id == clk->parentids[i]) { in zynqmp_fw_clk_get_all()
410 if (tmp2->attributes & ZYNQMP_CLK_IS_EXT) { in zynqmp_fw_clk_get_all()
413 if (ofw_bus_find_string_index( sc->node, in zynqmp_fw_clk_get_all()
414 "clock-names", tmp2->clkdef.name, &idx) == ENOENT) in zynqmp_fw_clk_get_all()
415 clk->clkdef.parent_names[i] = strdup("dummy", M_DEVBUF); in zynqmp_fw_clk_get_all()
417 clk->clkdef.parent_names[i] = strdup(tmp2->clkdef.name, M_DEVBUF); in zynqmp_fw_clk_get_all()
420 clk->clkdef.parent_names[i] = strdup(tmp2->clkdef.name, M_DEVBUF); in zynqmp_fw_clk_get_all()
427 sc->clkdom = clkdom_create(sc->dev); in zynqmp_fw_clk_get_all()
428 if (sc->clkdom == NULL) in zynqmp_fw_clk_get_all()
430 clkdom_set_ofw_mapper(sc->clkdom, zynqmp_clock_ofw_map); in zynqmp_fw_clk_get_all()
433 TAILQ_FOREACH_SAFE(clk, &clk_list, next, tmp) { in zynqmp_fw_clk_get_all()
434 if (clk->attributes & ZYNQMP_CLK_IS_EXT) { in zynqmp_fw_clk_get_all()
435 if (strcmp(clk->clkdef.name, "dummy") == 0) { in zynqmp_fw_clk_get_all()
439 dummy.clkdef.id = clk->clkdef.id; in zynqmp_fw_clk_get_all()
441 clknode_fixed_register(sc->clkdom, &dummy); in zynqmp_fw_clk_get_all()
445 zynqmp_clk_register(sc->clkdom, sc->parent, clk); in zynqmp_fw_clk_get_all()
447 TAILQ_REMOVE(&clk_list, clk, next); in zynqmp_fw_clk_get_all()
448 for (i = 0; i < clk->clkdef.parent_cnt; i++) in zynqmp_fw_clk_get_all()
449 free(__DECONST(char *, clk->clkdef.parent_names[i]), M_DEVBUF); in zynqmp_fw_clk_get_all()
450 free(clk->clkdef.parent_names, M_DEVBUF); in zynqmp_fw_clk_get_all()
451 free(__DECONST(char *, clk->clkdef.name), M_DEVBUF); in zynqmp_fw_clk_get_all()
452 free(clk, M_DEVBUF); in zynqmp_fw_clk_get_all()
455 if (clkdom_finit(sc->clkdom) != 0) in zynqmp_fw_clk_get_all()
459 clkdom_dump(sc->clkdom); in zynqmp_fw_clk_get_all()
470 if (!ofw_bus_is_compatible(dev, "xlnx,zynqmp-clk")) in zynqmp_clock_probe()
484 sc->dev = dev; in zynqmp_clock_attach()
485 sc->parent = device_get_parent(dev); in zynqmp_clock_attach()
486 sc->node = ofw_bus_get_node(dev); in zynqmp_clock_attach()
489 if (clk_get_by_ofw_name(dev, 0, "pss_ref_clk", &sc->clk_pss_ref) != 0) { in zynqmp_clock_attach()
493 rv = clk_enable(sc->clk_pss_ref); in zynqmp_clock_attach()
498 if (clk_get_by_ofw_name(dev, 0, "video_clk", &sc->clk_video) != 0) { in zynqmp_clock_attach()
502 rv = clk_enable(sc->clk_video); in zynqmp_clock_attach()
507 if (clk_get_by_ofw_name(dev, 0, "pss_alt_ref_clk", &sc->clk_pss_alt_ref) != 0) { in zynqmp_clock_attach()
511 rv = clk_enable(sc->clk_pss_alt_ref); in zynqmp_clock_attach()
516 if (clk_get_by_ofw_name(dev, 0, "aux_ref_clk", &sc->clk_aux_ref) != 0) { in zynqmp_clock_attach()
520 rv = clk_enable(sc->clk_aux_ref); in zynqmp_clock_attach()
525 if (clk_get_by_ofw_name(dev, 0, "gt_crx_ref_clk", &sc->clk_gt_crx_ref) != 0) { in zynqmp_clock_attach()
529 rv = clk_enable(sc->clk_gt_crx_ref); in zynqmp_clock_attach()
537 clk_disable(sc->clk_gt_crx_ref); in zynqmp_clock_attach()
538 clk_disable(sc->clk_aux_ref); in zynqmp_clock_attach()
539 clk_disable(sc->clk_pss_alt_ref); in zynqmp_clock_attach()
540 clk_disable(sc->clk_video); in zynqmp_clock_attach()
541 clk_disable(sc->clk_pss_ref); in zynqmp_clock_attach()