177f22241SEmmanuel Vadot /*- 277f22241SEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause 377f22241SEmmanuel Vadot * 477f22241SEmmanuel Vadot * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org> 577f22241SEmmanuel Vadot * 677f22241SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 777f22241SEmmanuel Vadot * modification, are permitted provided that the following conditions 877f22241SEmmanuel Vadot * are met: 977f22241SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 1077f22241SEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 1177f22241SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 1277f22241SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 1377f22241SEmmanuel Vadot * documentation and/or other materials provided with the distribution. 1477f22241SEmmanuel Vadot * 1577f22241SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1677f22241SEmmanuel Vadot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1777f22241SEmmanuel Vadot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1877f22241SEmmanuel Vadot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1977f22241SEmmanuel Vadot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2077f22241SEmmanuel Vadot * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2177f22241SEmmanuel Vadot * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2277f22241SEmmanuel Vadot * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2377f22241SEmmanuel Vadot * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2477f22241SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2577f22241SEmmanuel Vadot * SUCH DAMAGE. 2677f22241SEmmanuel Vadot */ 2777f22241SEmmanuel Vadot 2877f22241SEmmanuel Vadot #ifndef __RK_CRU_H__ 2977f22241SEmmanuel Vadot #define __RK_CRU_H__ 3077f22241SEmmanuel Vadot 31*be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h> 32*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_div.h> 33*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_gate.h> 34*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_fixed.h> 35*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_link.h> 3677f22241SEmmanuel Vadot 3777f22241SEmmanuel Vadot #include <dev/clk/rockchip/rk_clk_armclk.h> 3877f22241SEmmanuel Vadot #include <dev/clk/rockchip/rk_clk_composite.h> 3977f22241SEmmanuel Vadot #include <dev/clk/rockchip/rk_clk_fract.h> 4077f22241SEmmanuel Vadot #include <dev/clk/rockchip/rk_clk_gate.h> 4177f22241SEmmanuel Vadot #include <dev/clk/rockchip/rk_clk_mux.h> 4277f22241SEmmanuel Vadot #include <dev/clk/rockchip/rk_clk_pll.h> 4377f22241SEmmanuel Vadot 4477f22241SEmmanuel Vadot /* Macro for defining various types of clocks. */ 4577f22241SEmmanuel Vadot 4677f22241SEmmanuel Vadot /* Parent list */ 4777f22241SEmmanuel Vadot #define PLIST(_name) static const char *_name[] 4877f22241SEmmanuel Vadot 4977f22241SEmmanuel Vadot /* Pure gate */ 5077f22241SEmmanuel Vadot #define GATE(_idx, _clkname, _pname, _o, _s) \ 5177f22241SEmmanuel Vadot { \ 5277f22241SEmmanuel Vadot .id = _idx, \ 5377f22241SEmmanuel Vadot .name = _clkname, \ 5477f22241SEmmanuel Vadot .parent_name = _pname, \ 5577f22241SEmmanuel Vadot .offset = CRU_CLKGATE_CON(_o), \ 5677f22241SEmmanuel Vadot .shift = _s, \ 5777f22241SEmmanuel Vadot } 5877f22241SEmmanuel Vadot 5977f22241SEmmanuel Vadot /* Fixed rate clock. */ 6077f22241SEmmanuel Vadot #define FRATE(_id, _name, _freq) \ 6177f22241SEmmanuel Vadot { \ 6277f22241SEmmanuel Vadot .type = RK_CLK_FIXED, \ 6377f22241SEmmanuel Vadot .clk.fixed = &(struct clk_fixed_def) { \ 6477f22241SEmmanuel Vadot .clkdef.id = _id, \ 6577f22241SEmmanuel Vadot .clkdef.name = _name, \ 6677f22241SEmmanuel Vadot .clkdef.parent_names = NULL, \ 6777f22241SEmmanuel Vadot .clkdef.parent_cnt = 0, \ 6877f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 6977f22241SEmmanuel Vadot .freq = _freq, \ 7077f22241SEmmanuel Vadot }, \ 7177f22241SEmmanuel Vadot } 7277f22241SEmmanuel Vadot 7377f22241SEmmanuel Vadot /* Fixed factor multipier/divider. */ 7477f22241SEmmanuel Vadot #define FFACT(_id, _name, _pname, _mult, _div) \ 7577f22241SEmmanuel Vadot { \ 7677f22241SEmmanuel Vadot .type = RK_CLK_FIXED, \ 7777f22241SEmmanuel Vadot .clk.fixed = &(struct clk_fixed_def) { \ 7877f22241SEmmanuel Vadot .clkdef.id = _id, \ 7977f22241SEmmanuel Vadot .clkdef.name = _name, \ 8077f22241SEmmanuel Vadot .clkdef.parent_names = (const char *[]){_pname}, \ 8177f22241SEmmanuel Vadot .clkdef.parent_cnt = 1, \ 8277f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 8377f22241SEmmanuel Vadot .mult = _mult, \ 8477f22241SEmmanuel Vadot .div = _div, \ 8577f22241SEmmanuel Vadot }, \ 8677f22241SEmmanuel Vadot } 8777f22241SEmmanuel Vadot 8877f22241SEmmanuel Vadot /* Linked clock. */ 8977f22241SEmmanuel Vadot #define LINK(_name) \ 9077f22241SEmmanuel Vadot { \ 9177f22241SEmmanuel Vadot .type = RK_CLK_LINK, \ 9277f22241SEmmanuel Vadot .clk.link = &(struct clk_link_def) { \ 9377f22241SEmmanuel Vadot .clkdef.id = 0, \ 9477f22241SEmmanuel Vadot .clkdef.name = _name, \ 9577f22241SEmmanuel Vadot .clkdef.parent_names = NULL, \ 9677f22241SEmmanuel Vadot .clkdef.parent_cnt = 0, \ 9777f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 9877f22241SEmmanuel Vadot }, \ 9977f22241SEmmanuel Vadot } 10077f22241SEmmanuel Vadot 10177f22241SEmmanuel Vadot /* Complex clock fo ARM cores. */ 10277f22241SEmmanuel Vadot #define ARMDIV(_id, _name, _pn, _r, _o, _ds, _dw, _ms, _mw, _mp, _ap) \ 10377f22241SEmmanuel Vadot { \ 10477f22241SEmmanuel Vadot .type = RK_CLK_ARMCLK, \ 10577f22241SEmmanuel Vadot .clk.armclk = &(struct rk_clk_armclk_def) { \ 10677f22241SEmmanuel Vadot .clkdef.id = _id, \ 10777f22241SEmmanuel Vadot .clkdef.name = _name, \ 10877f22241SEmmanuel Vadot .clkdef.parent_names = _pn, \ 10977f22241SEmmanuel Vadot .clkdef.parent_cnt = nitems(_pn), \ 11077f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 11177f22241SEmmanuel Vadot .muxdiv_offset = CRU_CLKSEL_CON(_o), \ 11277f22241SEmmanuel Vadot .mux_shift = _ms, \ 11377f22241SEmmanuel Vadot .mux_width = _mw, \ 11477f22241SEmmanuel Vadot .div_shift = _ds, \ 11577f22241SEmmanuel Vadot .div_width = _dw, \ 11677f22241SEmmanuel Vadot .main_parent = _mp, \ 11777f22241SEmmanuel Vadot .alt_parent = _ap, \ 11877f22241SEmmanuel Vadot .rates = _r, \ 11977f22241SEmmanuel Vadot .nrates = nitems(_r), \ 12077f22241SEmmanuel Vadot }, \ 12177f22241SEmmanuel Vadot } 12277f22241SEmmanuel Vadot 12377f22241SEmmanuel Vadot /* Fractional rate multipier/divider. */ 12477f22241SEmmanuel Vadot #define FRACT(_id, _name, _pname, _f, _o) \ 12577f22241SEmmanuel Vadot { \ 12677f22241SEmmanuel Vadot .type = RK_CLK_FRACT, \ 12777f22241SEmmanuel Vadot .clk.fract = &(struct rk_clk_fract_def) { \ 12877f22241SEmmanuel Vadot .clkdef.id = _id, \ 12977f22241SEmmanuel Vadot .clkdef.name = _name, \ 13077f22241SEmmanuel Vadot .clkdef.parent_names = (const char *[]){_pname}, \ 13177f22241SEmmanuel Vadot .clkdef.parent_cnt = 1, \ 13277f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 13377f22241SEmmanuel Vadot .offset = CRU_CLKSEL_CON(_o), \ 13477f22241SEmmanuel Vadot .flags = _f, \ 13577f22241SEmmanuel Vadot }, \ 13677f22241SEmmanuel Vadot } 13777f22241SEmmanuel Vadot 13877f22241SEmmanuel Vadot /* Full composite clock. */ 13977f22241SEmmanuel Vadot #define COMP(_id, _name, _pnames, _f, _o, _ds, _dw, _ms, _mw) \ 14077f22241SEmmanuel Vadot { \ 14177f22241SEmmanuel Vadot .type = RK_CLK_COMPOSITE, \ 14277f22241SEmmanuel Vadot .clk.composite = &(struct rk_clk_composite_def) { \ 14377f22241SEmmanuel Vadot .clkdef.id = _id, \ 14477f22241SEmmanuel Vadot .clkdef.name = _name, \ 14577f22241SEmmanuel Vadot .clkdef.parent_names = _pnames, \ 14677f22241SEmmanuel Vadot .clkdef.parent_cnt = nitems(_pnames), \ 14777f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 14877f22241SEmmanuel Vadot .muxdiv_offset = CRU_CLKSEL_CON(_o), \ 14977f22241SEmmanuel Vadot .mux_shift = _ms, \ 15077f22241SEmmanuel Vadot .mux_width = _mw, \ 15177f22241SEmmanuel Vadot .div_shift = _ds, \ 15277f22241SEmmanuel Vadot .div_width = _dw, \ 15377f22241SEmmanuel Vadot .flags = RK_CLK_COMPOSITE_HAVE_MUX | _f, \ 15477f22241SEmmanuel Vadot }, \ 15577f22241SEmmanuel Vadot } 15677f22241SEmmanuel Vadot 15777f22241SEmmanuel Vadot /* Composite clock without mux (divider only). */ 15877f22241SEmmanuel Vadot #define CDIV(_id, _name, _pname, _f, _o, _ds, _dw) \ 15977f22241SEmmanuel Vadot { \ 16077f22241SEmmanuel Vadot .type = RK_CLK_COMPOSITE, \ 16177f22241SEmmanuel Vadot .clk.composite = &(struct rk_clk_composite_def) { \ 16277f22241SEmmanuel Vadot .clkdef.id = _id, \ 16377f22241SEmmanuel Vadot .clkdef.name = _name, \ 16477f22241SEmmanuel Vadot .clkdef.parent_names = (const char *[]){_pname}, \ 16577f22241SEmmanuel Vadot .clkdef.parent_cnt = 1, \ 16677f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 16777f22241SEmmanuel Vadot .muxdiv_offset = CRU_CLKSEL_CON(_o), \ 16877f22241SEmmanuel Vadot .div_shift = _ds, \ 16977f22241SEmmanuel Vadot .div_width = _dw, \ 17077f22241SEmmanuel Vadot .flags = _f, \ 17177f22241SEmmanuel Vadot }, \ 17277f22241SEmmanuel Vadot } 17377f22241SEmmanuel Vadot 17477f22241SEmmanuel Vadot /* Complex clock without divider (multiplexer only). */ 17577f22241SEmmanuel Vadot #define MUXRAW(_id, _name, _pn, _f, _mo, _ms, _mw) \ 17677f22241SEmmanuel Vadot { \ 17777f22241SEmmanuel Vadot .type = RK_CLK_MUX, \ 17877f22241SEmmanuel Vadot .clk.mux = &(struct rk_clk_mux_def) { \ 17977f22241SEmmanuel Vadot .clkdef.id = _id, \ 18077f22241SEmmanuel Vadot .clkdef.name = _name, \ 18177f22241SEmmanuel Vadot .clkdef.parent_names = _pn, \ 18277f22241SEmmanuel Vadot .clkdef.parent_cnt = nitems(_pn), \ 18377f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 18477f22241SEmmanuel Vadot .offset = _mo, \ 18577f22241SEmmanuel Vadot .shift = _ms, \ 18677f22241SEmmanuel Vadot .width = _mw, \ 18777f22241SEmmanuel Vadot .mux_flags = _f, \ 18877f22241SEmmanuel Vadot }, \ 18977f22241SEmmanuel Vadot } 19077f22241SEmmanuel Vadot 19177f22241SEmmanuel Vadot #define MUX(_id, _name, _pn, _f, _mo, _ms, _mw) \ 19277f22241SEmmanuel Vadot MUXRAW(_id, _name, _pn, _f, CRU_CLKSEL_CON(_mo), _ms, _mw) 19377f22241SEmmanuel Vadot 19477f22241SEmmanuel Vadot /* Complex clock without divider (multiplexer only in GRF). */ 19577f22241SEmmanuel Vadot #define MUXGRF(_id, _name, _pn, _f, _mo, _ms, _mw) \ 19677f22241SEmmanuel Vadot { \ 19777f22241SEmmanuel Vadot .type = RK_CLK_MUX, \ 19877f22241SEmmanuel Vadot .clk.mux = &(struct rk_clk_mux_def) { \ 19977f22241SEmmanuel Vadot .clkdef.id = _id, \ 20077f22241SEmmanuel Vadot .clkdef.name = _name, \ 20177f22241SEmmanuel Vadot .clkdef.parent_names = _pn, \ 20277f22241SEmmanuel Vadot .clkdef.parent_cnt = nitems(_pn), \ 20377f22241SEmmanuel Vadot .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 20477f22241SEmmanuel Vadot .offset = _mo, \ 20577f22241SEmmanuel Vadot .shift = _ms, \ 20677f22241SEmmanuel Vadot .width = _mw, \ 20777f22241SEmmanuel Vadot .mux_flags = RK_CLK_MUX_GRF | _f, \ 20877f22241SEmmanuel Vadot }, \ 20977f22241SEmmanuel Vadot } 21077f22241SEmmanuel Vadot 21177f22241SEmmanuel Vadot struct rk_cru_gate { 21277f22241SEmmanuel Vadot const char *name; 21377f22241SEmmanuel Vadot const char *parent_name; 21477f22241SEmmanuel Vadot uint32_t id; 21577f22241SEmmanuel Vadot uint32_t offset; 21677f22241SEmmanuel Vadot uint32_t shift; 21777f22241SEmmanuel Vadot }; 21877f22241SEmmanuel Vadot 21977f22241SEmmanuel Vadot enum rk_clk_type { 22077f22241SEmmanuel Vadot RK_CLK_UNDEFINED = 0, 22177f22241SEmmanuel Vadot RK3066_CLK_PLL, 22277f22241SEmmanuel Vadot RK3328_CLK_PLL, 22377f22241SEmmanuel Vadot RK3399_CLK_PLL, 22477f22241SEmmanuel Vadot RK_CLK_COMPOSITE, 22577f22241SEmmanuel Vadot RK_CLK_FIXED, 22677f22241SEmmanuel Vadot RK_CLK_FRACT, 22777f22241SEmmanuel Vadot RK_CLK_MUX, 22877f22241SEmmanuel Vadot RK_CLK_ARMCLK, 22977f22241SEmmanuel Vadot RK_CLK_LINK, 23077f22241SEmmanuel Vadot }; 23177f22241SEmmanuel Vadot 23277f22241SEmmanuel Vadot struct rk_clk { 23377f22241SEmmanuel Vadot enum rk_clk_type type; 23477f22241SEmmanuel Vadot union { 23577f22241SEmmanuel Vadot struct rk_clk_pll_def *pll; 23677f22241SEmmanuel Vadot struct rk_clk_composite_def *composite; 23777f22241SEmmanuel Vadot struct rk_clk_mux_def *mux; 23877f22241SEmmanuel Vadot struct rk_clk_armclk_def *armclk; 23977f22241SEmmanuel Vadot struct clk_fixed_def *fixed; 24077f22241SEmmanuel Vadot struct rk_clk_fract_def *fract; 24177f22241SEmmanuel Vadot struct clk_link_def *link; 24277f22241SEmmanuel Vadot } clk; 24377f22241SEmmanuel Vadot }; 24477f22241SEmmanuel Vadot 24577f22241SEmmanuel Vadot struct rk_cru_softc { 24677f22241SEmmanuel Vadot device_t dev; 24777f22241SEmmanuel Vadot struct resource *res; 24877f22241SEmmanuel Vadot struct clkdom *clkdom; 24977f22241SEmmanuel Vadot struct mtx mtx; 25077f22241SEmmanuel Vadot int type; 25177f22241SEmmanuel Vadot uint32_t reset_offset; 25277f22241SEmmanuel Vadot uint32_t reset_num; 25377f22241SEmmanuel Vadot struct rk_cru_gate *gates; 25477f22241SEmmanuel Vadot int ngates; 25577f22241SEmmanuel Vadot struct rk_clk *clks; 25677f22241SEmmanuel Vadot int nclks; 25777f22241SEmmanuel Vadot struct rk_clk_armclk_def *armclk; 25877f22241SEmmanuel Vadot struct rk_clk_armclk_rates *armclk_rates; 25977f22241SEmmanuel Vadot int narmclk_rates; 26077f22241SEmmanuel Vadot }; 26177f22241SEmmanuel Vadot 26277f22241SEmmanuel Vadot DECLARE_CLASS(rk_cru_driver); 26377f22241SEmmanuel Vadot 26477f22241SEmmanuel Vadot int rk_cru_attach(device_t dev); 26577f22241SEmmanuel Vadot 26677f22241SEmmanuel Vadot #endif /* __RK_CRU_H__ */ 267