154b96380SRuslan Bukin /*- 254b96380SRuslan Bukin * SPDX-License-Identifier: BSD-2-Clause 354b96380SRuslan Bukin * 454b96380SRuslan Bukin * Copyright (c) 2022 Ruslan Bukin <br@bsdpad.com> 554b96380SRuslan Bukin * 654b96380SRuslan Bukin * This work was supported by Innovate UK project 105694, "Digital Security 754b96380SRuslan Bukin * by Design (DSbD) Technology Platform Prototype". 854b96380SRuslan Bukin * 954b96380SRuslan Bukin * Redistribution and use in source and binary forms, with or without 1054b96380SRuslan Bukin * modification, are permitted provided that the following conditions 1154b96380SRuslan Bukin * are met: 1254b96380SRuslan Bukin * 1. Redistributions of source code must retain the above copyright 1354b96380SRuslan Bukin * notice, this list of conditions and the following disclaimer. 1454b96380SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 1554b96380SRuslan Bukin * notice, this list of conditions and the following disclaimer in the 1654b96380SRuslan Bukin * documentation and/or other materials provided with the distribution. 1754b96380SRuslan Bukin * 1854b96380SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1954b96380SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2054b96380SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2154b96380SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2254b96380SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2354b96380SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2454b96380SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2554b96380SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2654b96380SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2754b96380SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2854b96380SRuslan Bukin * SUCH DAMAGE. 2954b96380SRuslan Bukin */ 3054b96380SRuslan Bukin 3154b96380SRuslan Bukin #include <sys/param.h> 3254b96380SRuslan Bukin #include <sys/systm.h> 3354b96380SRuslan Bukin #include <sys/bus.h> 3454b96380SRuslan Bukin #include <sys/cpu.h> 3554b96380SRuslan Bukin #include <sys/kernel.h> 3654b96380SRuslan Bukin #include <sys/module.h> 3754b96380SRuslan Bukin 38*be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h> 3954b96380SRuslan Bukin #include <dev/fdt/simplebus.h> 4054b96380SRuslan Bukin #include <dev/fdt/fdt_common.h> 4154b96380SRuslan Bukin #include <dev/ofw/ofw_bus_subr.h> 4254b96380SRuslan Bukin 4354b96380SRuslan Bukin #include "scmi.h" 4454b96380SRuslan Bukin #include "scmi_protocols.h" 4554b96380SRuslan Bukin #include "scmi_clk.h" 4654b96380SRuslan Bukin 4754b96380SRuslan Bukin struct scmi_clk_softc { 4854b96380SRuslan Bukin device_t dev; 4954b96380SRuslan Bukin device_t scmi; 5054b96380SRuslan Bukin struct clkdom *clkdom; 5154b96380SRuslan Bukin }; 5254b96380SRuslan Bukin 5354b96380SRuslan Bukin struct scmi_clknode_softc { 5454b96380SRuslan Bukin device_t dev; 5554b96380SRuslan Bukin int clock_id; 5654b96380SRuslan Bukin }; 5754b96380SRuslan Bukin 5819a7cf0cSMark Johnston static int __unused 5954b96380SRuslan Bukin scmi_clk_get_rate(struct scmi_clk_softc *sc, int clk_id, uint64_t *rate) 6054b96380SRuslan Bukin { 6154b96380SRuslan Bukin struct scmi_clk_rate_get_out out; 6254b96380SRuslan Bukin struct scmi_clk_rate_get_in in; 6354b96380SRuslan Bukin struct scmi_req req; 6454b96380SRuslan Bukin int error; 6554b96380SRuslan Bukin 6654b96380SRuslan Bukin req.protocol_id = SCMI_PROTOCOL_ID_CLOCK; 6754b96380SRuslan Bukin req.message_id = SCMI_CLOCK_RATE_GET; 6854b96380SRuslan Bukin req.in_buf = ∈ 6954b96380SRuslan Bukin req.in_size = sizeof(struct scmi_clk_rate_get_in); 7054b96380SRuslan Bukin req.out_buf = &out; 7154b96380SRuslan Bukin req.out_size = sizeof(struct scmi_clk_rate_get_out); 7254b96380SRuslan Bukin 7354b96380SRuslan Bukin in.clock_id = clk_id; 7454b96380SRuslan Bukin 7554b96380SRuslan Bukin error = scmi_request(sc->scmi, &req); 7654b96380SRuslan Bukin if (error != 0) 7754b96380SRuslan Bukin return (error); 7854b96380SRuslan Bukin 7954b96380SRuslan Bukin if (out.status != 0) 8054b96380SRuslan Bukin return (ENXIO); 8154b96380SRuslan Bukin 8254b96380SRuslan Bukin *rate = out.rate_lsb | ((uint64_t)out.rate_msb << 32); 8354b96380SRuslan Bukin 8454b96380SRuslan Bukin return (0); 8554b96380SRuslan Bukin } 8654b96380SRuslan Bukin 8754b96380SRuslan Bukin static int 8854b96380SRuslan Bukin scmi_clk_set_rate(struct scmi_clk_softc *sc, int clk_id, uint64_t rate) 8954b96380SRuslan Bukin { 9054b96380SRuslan Bukin struct scmi_clk_rate_set_out out; 9154b96380SRuslan Bukin struct scmi_clk_rate_set_in in; 9254b96380SRuslan Bukin struct scmi_req req; 9354b96380SRuslan Bukin int error; 9454b96380SRuslan Bukin 9554b96380SRuslan Bukin req.protocol_id = SCMI_PROTOCOL_ID_CLOCK; 9654b96380SRuslan Bukin req.message_id = SCMI_CLOCK_RATE_SET; 9754b96380SRuslan Bukin req.in_buf = ∈ 9854b96380SRuslan Bukin req.in_size = sizeof(struct scmi_clk_rate_set_in); 9954b96380SRuslan Bukin req.out_buf = &out; 10054b96380SRuslan Bukin req.out_size = sizeof(struct scmi_clk_rate_set_out); 10154b96380SRuslan Bukin 10254b96380SRuslan Bukin in.clock_id = clk_id; 10354b96380SRuslan Bukin in.flags = SCMI_CLK_RATE_ROUND_CLOSEST; 10454b96380SRuslan Bukin in.rate_lsb = (uint32_t)rate; 10554b96380SRuslan Bukin in.rate_msb = (uint32_t)(rate >> 32); 10654b96380SRuslan Bukin 10754b96380SRuslan Bukin error = scmi_request(sc->scmi, &req); 10854b96380SRuslan Bukin if (error != 0) 10954b96380SRuslan Bukin return (error); 11054b96380SRuslan Bukin 11154b96380SRuslan Bukin if (out.status != 0) 11254b96380SRuslan Bukin return (ENXIO); 11354b96380SRuslan Bukin 11454b96380SRuslan Bukin return (0); 11554b96380SRuslan Bukin } 11654b96380SRuslan Bukin 11719a7cf0cSMark Johnston static int __unused 11854b96380SRuslan Bukin scmi_clk_gate(struct scmi_clk_softc *sc, int clk_id, int enable) 11954b96380SRuslan Bukin { 12054b96380SRuslan Bukin struct scmi_clk_state_out out; 12154b96380SRuslan Bukin struct scmi_clk_state_in in; 12254b96380SRuslan Bukin struct scmi_req req; 12354b96380SRuslan Bukin int error; 12454b96380SRuslan Bukin 12554b96380SRuslan Bukin req.protocol_id = SCMI_PROTOCOL_ID_CLOCK; 12654b96380SRuslan Bukin req.message_id = SCMI_CLOCK_CONFIG_SET; 12754b96380SRuslan Bukin req.in_buf = ∈ 12854b96380SRuslan Bukin req.in_size = sizeof(struct scmi_clk_state_in); 12954b96380SRuslan Bukin req.out_buf = &out; 13054b96380SRuslan Bukin req.out_size = sizeof(struct scmi_clk_state_out); 13154b96380SRuslan Bukin 13254b96380SRuslan Bukin in.clock_id = clk_id; 13354b96380SRuslan Bukin in.attributes = enable; 13454b96380SRuslan Bukin 13554b96380SRuslan Bukin error = scmi_request(sc->scmi, &req); 13654b96380SRuslan Bukin if (error != 0) 13754b96380SRuslan Bukin return (error); 13854b96380SRuslan Bukin 13954b96380SRuslan Bukin if (out.status != 0) 14054b96380SRuslan Bukin return (ENXIO); 14154b96380SRuslan Bukin 14254b96380SRuslan Bukin return (0); 14354b96380SRuslan Bukin } 14454b96380SRuslan Bukin 14554b96380SRuslan Bukin static int 14654b96380SRuslan Bukin scmi_clknode_init(struct clknode *clk, device_t dev) 14754b96380SRuslan Bukin { 14854b96380SRuslan Bukin 14954b96380SRuslan Bukin clknode_init_parent_idx(clk, 0); 15054b96380SRuslan Bukin 15154b96380SRuslan Bukin return (0); 15254b96380SRuslan Bukin } 15354b96380SRuslan Bukin 15454b96380SRuslan Bukin static int 15554b96380SRuslan Bukin scmi_clknode_recalc_freq(struct clknode *clk, uint64_t *freq) 15654b96380SRuslan Bukin { 15754b96380SRuslan Bukin 15854b96380SRuslan Bukin return (0); 15954b96380SRuslan Bukin } 16054b96380SRuslan Bukin 16154b96380SRuslan Bukin static int 16254b96380SRuslan Bukin scmi_clknode_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, 16354b96380SRuslan Bukin int flags, int *stop) 16454b96380SRuslan Bukin { 16554b96380SRuslan Bukin struct scmi_clknode_softc *clk_sc; 16654b96380SRuslan Bukin struct scmi_clk_softc *sc; 16754b96380SRuslan Bukin 16854b96380SRuslan Bukin clk_sc = clknode_get_softc(clk); 16954b96380SRuslan Bukin sc = device_get_softc(clk_sc->dev); 17054b96380SRuslan Bukin 17154b96380SRuslan Bukin dprintf("%s: %ld\n", __func__, *fout); 17254b96380SRuslan Bukin 17354b96380SRuslan Bukin scmi_clk_set_rate(sc, clk_sc->clock_id, *fout); 17454b96380SRuslan Bukin 17554b96380SRuslan Bukin *stop = 1; 17654b96380SRuslan Bukin 17754b96380SRuslan Bukin return (0); 17854b96380SRuslan Bukin } 17954b96380SRuslan Bukin 18054b96380SRuslan Bukin static clknode_method_t scmi_clknode_methods[] = { 18154b96380SRuslan Bukin /* Device interface */ 18254b96380SRuslan Bukin CLKNODEMETHOD(clknode_init, scmi_clknode_init), 18354b96380SRuslan Bukin CLKNODEMETHOD(clknode_recalc_freq, scmi_clknode_recalc_freq), 18454b96380SRuslan Bukin CLKNODEMETHOD(clknode_set_freq, scmi_clknode_set_freq), 18554b96380SRuslan Bukin CLKNODEMETHOD_END 18654b96380SRuslan Bukin }; 18754b96380SRuslan Bukin 18854b96380SRuslan Bukin DEFINE_CLASS_1(scmi_clknode, scmi_clknode_class, scmi_clknode_methods, 18954b96380SRuslan Bukin sizeof(struct scmi_clknode_softc), clknode_class); 19054b96380SRuslan Bukin 19154b96380SRuslan Bukin static int 19254b96380SRuslan Bukin scmi_clk_add_node(struct scmi_clk_softc *sc, int index, char *clock_name) 19354b96380SRuslan Bukin { 19454b96380SRuslan Bukin struct scmi_clknode_softc *clk_sc; 19554b96380SRuslan Bukin struct clknode_init_def def; 19654b96380SRuslan Bukin struct clknode *clk; 19754b96380SRuslan Bukin 19854b96380SRuslan Bukin memset(&def, 0, sizeof(def)); 19954b96380SRuslan Bukin def.id = index; 20054b96380SRuslan Bukin def.name = clock_name; 20154b96380SRuslan Bukin def.parent_names = NULL; 20254b96380SRuslan Bukin def.parent_cnt = 0; 20354b96380SRuslan Bukin 20454b96380SRuslan Bukin clk = clknode_create(sc->clkdom, &scmi_clknode_class, &def); 20554b96380SRuslan Bukin if (clk == NULL) { 20654b96380SRuslan Bukin device_printf(sc->dev, "Cannot create clknode.\n"); 20754b96380SRuslan Bukin return (ENXIO); 20854b96380SRuslan Bukin } 20954b96380SRuslan Bukin 21054b96380SRuslan Bukin clk_sc = clknode_get_softc(clk); 21154b96380SRuslan Bukin clk_sc->dev = sc->dev; 21254b96380SRuslan Bukin clk_sc->clock_id = index; 21354b96380SRuslan Bukin 21454b96380SRuslan Bukin if (clknode_register(sc->clkdom, clk) == NULL) { 21554b96380SRuslan Bukin device_printf(sc->dev, "Could not register clock '%s'.\n", 21654b96380SRuslan Bukin def.name); 21754b96380SRuslan Bukin return (ENXIO); 21854b96380SRuslan Bukin } 21954b96380SRuslan Bukin 22054b96380SRuslan Bukin device_printf(sc->dev, "Clock '%s' registered.\n", def.name); 22154b96380SRuslan Bukin 22254b96380SRuslan Bukin return (0); 22354b96380SRuslan Bukin } 22454b96380SRuslan Bukin 22554b96380SRuslan Bukin static int 22654b96380SRuslan Bukin scmi_clk_get_name(struct scmi_clk_softc *sc, int index, char **result) 22754b96380SRuslan Bukin { 22854b96380SRuslan Bukin struct scmi_clk_name_get_out out; 22954b96380SRuslan Bukin struct scmi_clk_name_get_in in; 23054b96380SRuslan Bukin struct scmi_req req; 23154b96380SRuslan Bukin char *clock_name; 23254b96380SRuslan Bukin int error; 23354b96380SRuslan Bukin 23454b96380SRuslan Bukin req.protocol_id = SCMI_PROTOCOL_ID_CLOCK; 23554b96380SRuslan Bukin req.message_id = SCMI_CLOCK_NAME_GET; 23654b96380SRuslan Bukin req.in_buf = ∈ 23754b96380SRuslan Bukin req.in_size = sizeof(struct scmi_clk_name_get_in); 23854b96380SRuslan Bukin req.out_buf = &out; 23954b96380SRuslan Bukin req.out_size = sizeof(struct scmi_clk_name_get_out); 24054b96380SRuslan Bukin 24154b96380SRuslan Bukin in.clock_id = index; 24254b96380SRuslan Bukin 24354b96380SRuslan Bukin error = scmi_request(sc->scmi, &req); 24454b96380SRuslan Bukin if (error != 0) 24554b96380SRuslan Bukin return (error); 24654b96380SRuslan Bukin 24754b96380SRuslan Bukin if (out.status != 0) 24854b96380SRuslan Bukin return (ENXIO); 24954b96380SRuslan Bukin 25054b96380SRuslan Bukin clock_name = malloc(sizeof(out.name), M_DEVBUF, M_WAITOK); 25154b96380SRuslan Bukin strncpy(clock_name, out.name, sizeof(out.name)); 25254b96380SRuslan Bukin 25354b96380SRuslan Bukin *result = clock_name; 25454b96380SRuslan Bukin 25554b96380SRuslan Bukin return (0); 25654b96380SRuslan Bukin } 25754b96380SRuslan Bukin 25854b96380SRuslan Bukin static int 25954b96380SRuslan Bukin scmi_clk_attrs(struct scmi_clk_softc *sc, int index) 26054b96380SRuslan Bukin { 26154b96380SRuslan Bukin struct scmi_clk_attrs_out out; 26254b96380SRuslan Bukin struct scmi_clk_attrs_in in; 26354b96380SRuslan Bukin struct scmi_req req; 26454b96380SRuslan Bukin int error; 26554b96380SRuslan Bukin char *clock_name; 26654b96380SRuslan Bukin 26754b96380SRuslan Bukin req.protocol_id = SCMI_PROTOCOL_ID_CLOCK; 26854b96380SRuslan Bukin req.message_id = SCMI_CLOCK_ATTRIBUTES; 26954b96380SRuslan Bukin req.in_buf = ∈ 27054b96380SRuslan Bukin req.in_size = sizeof(struct scmi_clk_attrs_in); 27154b96380SRuslan Bukin req.out_buf = &out; 27254b96380SRuslan Bukin req.out_size = sizeof(struct scmi_clk_attrs_out); 27354b96380SRuslan Bukin 27454b96380SRuslan Bukin in.clock_id = index; 27554b96380SRuslan Bukin 27654b96380SRuslan Bukin error = scmi_request(sc->scmi, &req); 27754b96380SRuslan Bukin if (error != 0) 27854b96380SRuslan Bukin return (error); 27954b96380SRuslan Bukin 28054b96380SRuslan Bukin if (out.status != 0) 28154b96380SRuslan Bukin return (ENXIO); 28254b96380SRuslan Bukin 28354b96380SRuslan Bukin if (out.attributes & CLK_ATTRS_EXT_CLK_NAME) { 28454b96380SRuslan Bukin error = scmi_clk_get_name(sc, index, &clock_name); 28554b96380SRuslan Bukin if (error) 28654b96380SRuslan Bukin return (error); 28754b96380SRuslan Bukin } else { 28854b96380SRuslan Bukin clock_name = malloc(sizeof(out.clock_name), M_DEVBUF, M_WAITOK); 28954b96380SRuslan Bukin strncpy(clock_name, out.clock_name, sizeof(out.clock_name)); 29054b96380SRuslan Bukin } 29154b96380SRuslan Bukin 29254b96380SRuslan Bukin error = scmi_clk_add_node(sc, index, clock_name); 29354b96380SRuslan Bukin 29454b96380SRuslan Bukin return (error); 29554b96380SRuslan Bukin } 29654b96380SRuslan Bukin 29754b96380SRuslan Bukin static int 29854b96380SRuslan Bukin scmi_clk_discover(struct scmi_clk_softc *sc) 29954b96380SRuslan Bukin { 30054b96380SRuslan Bukin struct scmi_clk_protocol_attrs_out out; 30154b96380SRuslan Bukin struct scmi_req req; 30254b96380SRuslan Bukin int nclocks; 30354b96380SRuslan Bukin int failing; 30454b96380SRuslan Bukin int error; 30554b96380SRuslan Bukin int i; 30654b96380SRuslan Bukin 30754b96380SRuslan Bukin req.protocol_id = SCMI_PROTOCOL_ID_CLOCK; 30854b96380SRuslan Bukin req.message_id = SCMI_PROTOCOL_ATTRIBUTES; 30954b96380SRuslan Bukin req.in_buf = NULL; 31054b96380SRuslan Bukin req.in_size = 0; 31154b96380SRuslan Bukin req.out_buf = &out; 31254b96380SRuslan Bukin req.out_size = sizeof(struct scmi_clk_protocol_attrs_out); 31354b96380SRuslan Bukin 31454b96380SRuslan Bukin error = scmi_request(sc->scmi, &req); 31554b96380SRuslan Bukin if (error != 0) 31654b96380SRuslan Bukin return (error); 31754b96380SRuslan Bukin 31854b96380SRuslan Bukin if (out.status != 0) 31954b96380SRuslan Bukin return (ENXIO); 32054b96380SRuslan Bukin 32154b96380SRuslan Bukin nclocks = (out.attributes & CLK_ATTRS_NCLOCKS_M) >> 32254b96380SRuslan Bukin CLK_ATTRS_NCLOCKS_S; 32354b96380SRuslan Bukin 32454b96380SRuslan Bukin device_printf(sc->dev, "Found %d clocks.\n", nclocks); 32554b96380SRuslan Bukin 32654b96380SRuslan Bukin failing = 0; 32754b96380SRuslan Bukin 32854b96380SRuslan Bukin for (i = 0; i < nclocks; i++) { 32954b96380SRuslan Bukin error = scmi_clk_attrs(sc, i); 33054b96380SRuslan Bukin if (error) { 33154b96380SRuslan Bukin device_printf(sc->dev, 33254b96380SRuslan Bukin "Could not process clock index %d.\n", i); 33354b96380SRuslan Bukin failing++; 33454b96380SRuslan Bukin } 33554b96380SRuslan Bukin } 33654b96380SRuslan Bukin 33754b96380SRuslan Bukin if (failing == nclocks) 33854b96380SRuslan Bukin return (ENXIO); 33954b96380SRuslan Bukin 34054b96380SRuslan Bukin return (0); 34154b96380SRuslan Bukin } 34254b96380SRuslan Bukin 34354b96380SRuslan Bukin static int 34454b96380SRuslan Bukin scmi_clk_init(struct scmi_clk_softc *sc) 34554b96380SRuslan Bukin { 34654b96380SRuslan Bukin int error; 34754b96380SRuslan Bukin 34854b96380SRuslan Bukin /* Create clock domain */ 34954b96380SRuslan Bukin sc->clkdom = clkdom_create(sc->dev); 35054b96380SRuslan Bukin if (sc->clkdom == NULL) 35154b96380SRuslan Bukin return (ENXIO); 35254b96380SRuslan Bukin 35354b96380SRuslan Bukin error = scmi_clk_discover(sc); 35454b96380SRuslan Bukin if (error) { 35554b96380SRuslan Bukin device_printf(sc->dev, "Could not discover clocks.\n"); 35654b96380SRuslan Bukin return (ENXIO); 35754b96380SRuslan Bukin } 35854b96380SRuslan Bukin 35954b96380SRuslan Bukin error = clkdom_finit(sc->clkdom); 36054b96380SRuslan Bukin if (error) { 36154b96380SRuslan Bukin device_printf(sc->dev, "Failed to init clock domain.\n"); 36254b96380SRuslan Bukin return (ENXIO); 36354b96380SRuslan Bukin } 36454b96380SRuslan Bukin 36554b96380SRuslan Bukin return (0); 36654b96380SRuslan Bukin } 36754b96380SRuslan Bukin 36854b96380SRuslan Bukin static int 36954b96380SRuslan Bukin scmi_clk_probe(device_t dev) 37054b96380SRuslan Bukin { 37154b96380SRuslan Bukin phandle_t node; 37254b96380SRuslan Bukin uint32_t reg; 37354b96380SRuslan Bukin int error; 37454b96380SRuslan Bukin 37554b96380SRuslan Bukin node = ofw_bus_get_node(dev); 37654b96380SRuslan Bukin 37754b96380SRuslan Bukin error = OF_getencprop(node, "reg", ®, sizeof(uint32_t)); 37854b96380SRuslan Bukin if (error < 0) 37954b96380SRuslan Bukin return (ENXIO); 38054b96380SRuslan Bukin 38154b96380SRuslan Bukin if (reg != SCMI_PROTOCOL_ID_CLOCK) 38254b96380SRuslan Bukin return (ENXIO); 38354b96380SRuslan Bukin 38454b96380SRuslan Bukin device_set_desc(dev, "SCMI Clock Management Unit"); 38554b96380SRuslan Bukin 38654b96380SRuslan Bukin return (BUS_PROBE_DEFAULT); 38754b96380SRuslan Bukin } 38854b96380SRuslan Bukin 38954b96380SRuslan Bukin static int 39054b96380SRuslan Bukin scmi_clk_attach(device_t dev) 39154b96380SRuslan Bukin { 39254b96380SRuslan Bukin struct scmi_clk_softc *sc; 39354b96380SRuslan Bukin phandle_t node; 39454b96380SRuslan Bukin 39554b96380SRuslan Bukin sc = device_get_softc(dev); 39654b96380SRuslan Bukin sc->dev = dev; 39754b96380SRuslan Bukin sc->scmi = device_get_parent(dev); 39854b96380SRuslan Bukin 39954b96380SRuslan Bukin node = ofw_bus_get_node(sc->dev); 40054b96380SRuslan Bukin 40154b96380SRuslan Bukin OF_device_register_xref(OF_xref_from_node(node), sc->dev); 40254b96380SRuslan Bukin 40354b96380SRuslan Bukin scmi_clk_init(sc); 40454b96380SRuslan Bukin 40554b96380SRuslan Bukin return (0); 40654b96380SRuslan Bukin } 40754b96380SRuslan Bukin 40854b96380SRuslan Bukin static int 40954b96380SRuslan Bukin scmi_clk_detach(device_t dev) 41054b96380SRuslan Bukin { 41154b96380SRuslan Bukin 41254b96380SRuslan Bukin return (0); 41354b96380SRuslan Bukin } 41454b96380SRuslan Bukin 41554b96380SRuslan Bukin static device_method_t scmi_clk_methods[] = { 41654b96380SRuslan Bukin /* Device interface */ 41754b96380SRuslan Bukin DEVMETHOD(device_probe, scmi_clk_probe), 41854b96380SRuslan Bukin DEVMETHOD(device_attach, scmi_clk_attach), 41954b96380SRuslan Bukin DEVMETHOD(device_detach, scmi_clk_detach), 42054b96380SRuslan Bukin DEVMETHOD_END 42154b96380SRuslan Bukin }; 42254b96380SRuslan Bukin 42354b96380SRuslan Bukin static driver_t scmi_clk_driver = { 42454b96380SRuslan Bukin "scmi_clk", 42554b96380SRuslan Bukin scmi_clk_methods, 42654b96380SRuslan Bukin sizeof(struct scmi_clk_softc), 42754b96380SRuslan Bukin }; 42854b96380SRuslan Bukin 42954b96380SRuslan Bukin EARLY_DRIVER_MODULE(scmi_clk, scmi, scmi_clk_driver, 0, 0, 43054b96380SRuslan Bukin BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 43154b96380SRuslan Bukin MODULE_VERSION(scmi_clk, 1); 432