1*be9fefafSTom Jones /*- 2*be9fefafSTom Jones * SPDX-License-Identifier: BSD-2-Clause 3*be9fefafSTom Jones * 4*be9fefafSTom Jones * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org> 5*be9fefafSTom Jones * 6*be9fefafSTom Jones * Redistribution and use in source and binary forms, with or without 7*be9fefafSTom Jones * modification, are permitted provided that the following conditions 8*be9fefafSTom Jones * are met: 9*be9fefafSTom Jones * 1. Redistributions of source code must retain the above copyright 10*be9fefafSTom Jones * notice, this list of conditions and the following disclaimer. 11*be9fefafSTom Jones * 2. Redistributions in binary form must reproduce the above copyright 12*be9fefafSTom Jones * notice, this list of conditions and the following disclaimer in the 13*be9fefafSTom Jones * documentation and/or other materials provided with the distribution. 14*be9fefafSTom Jones * 15*be9fefafSTom Jones * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*be9fefafSTom Jones * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*be9fefafSTom Jones * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*be9fefafSTom Jones * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*be9fefafSTom Jones * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*be9fefafSTom Jones * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*be9fefafSTom Jones * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*be9fefafSTom Jones * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*be9fefafSTom Jones * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*be9fefafSTom Jones * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*be9fefafSTom Jones * SUCH DAMAGE. 26*be9fefafSTom Jones */ 27*be9fefafSTom Jones 28*be9fefafSTom Jones #ifndef IMX8_CCM_H 29*be9fefafSTom Jones #define IMX8_CCM_H 30*be9fefafSTom Jones 31*be9fefafSTom Jones #include <dev/clk/clk.h> 32*be9fefafSTom Jones #include <dev/clk/clk_div.h> 33*be9fefafSTom Jones #include <dev/clk/clk_fixed.h> 34*be9fefafSTom Jones #include <dev/clk/clk_gate.h> 35*be9fefafSTom Jones #include <dev/clk/clk_link.h> 36*be9fefafSTom Jones 37*be9fefafSTom Jones int imx_ccm_attach(device_t); 38*be9fefafSTom Jones int imx_ccm_detach(device_t); 39*be9fefafSTom Jones 40*be9fefafSTom Jones struct imx_ccm_softc { 41*be9fefafSTom Jones device_t dev; 42*be9fefafSTom Jones struct resource *mem_res; 43*be9fefafSTom Jones struct clkdom *clkdom; 44*be9fefafSTom Jones struct mtx mtx; 45*be9fefafSTom Jones struct imx_clk *clks; 46*be9fefafSTom Jones int nclks; 47*be9fefafSTom Jones }; 48*be9fefafSTom Jones 49*be9fefafSTom Jones DECLARE_CLASS(imx_ccm_driver); 50*be9fefafSTom Jones 51*be9fefafSTom Jones enum imx_clk_type { 52*be9fefafSTom Jones IMX_CLK_UNDEFINED = 0, 53*be9fefafSTom Jones IMX_CLK_FIXED, 54*be9fefafSTom Jones IMX_CLK_LINK, 55*be9fefafSTom Jones IMX_CLK_MUX, 56*be9fefafSTom Jones IMX_CLK_GATE, 57*be9fefafSTom Jones IMX_CLK_COMPOSITE, 58*be9fefafSTom Jones IMX_CLK_SSCG_PLL, 59*be9fefafSTom Jones IMX_CLK_FRAC_PLL, 60*be9fefafSTom Jones IMX_CLK_DIV, 61*be9fefafSTom Jones }; 62*be9fefafSTom Jones 63*be9fefafSTom Jones struct imx_clk { 64*be9fefafSTom Jones enum imx_clk_type type; 65*be9fefafSTom Jones union { 66*be9fefafSTom Jones struct clk_fixed_def *fixed; 67*be9fefafSTom Jones struct clk_link_def *link; 68*be9fefafSTom Jones struct imx_clk_mux_def *mux; 69*be9fefafSTom Jones struct imx_clk_gate_def *gate; 70*be9fefafSTom Jones struct imx_clk_composite_def *composite; 71*be9fefafSTom Jones struct imx_clk_sscg_pll_def *sscg_pll; 72*be9fefafSTom Jones struct imx_clk_frac_pll_def *frac_pll; 73*be9fefafSTom Jones struct clk_div_def *div; 74*be9fefafSTom Jones } clk; 75*be9fefafSTom Jones }; 76*be9fefafSTom Jones 77*be9fefafSTom Jones /* Linked clock. */ 78*be9fefafSTom Jones #define LINK(_id, _name) \ 79*be9fefafSTom Jones { \ 80*be9fefafSTom Jones .type = IMX_CLK_LINK, \ 81*be9fefafSTom Jones .clk.link = &(struct clk_link_def) { \ 82*be9fefafSTom Jones .clkdef.id = _id, \ 83*be9fefafSTom Jones .clkdef.name = _name, \ 84*be9fefafSTom Jones .clkdef.parent_names = NULL, \ 85*be9fefafSTom Jones .clkdef.parent_cnt = 0, \ 86*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 87*be9fefafSTom Jones }, \ 88*be9fefafSTom Jones } 89*be9fefafSTom Jones 90*be9fefafSTom Jones /* Complex clock without divider (multiplexer only). */ 91*be9fefafSTom Jones #define MUX(_id, _name, _pn, _f, _mo, _ms, _mw) \ 92*be9fefafSTom Jones { \ 93*be9fefafSTom Jones .type = IMX_CLK_MUX, \ 94*be9fefafSTom Jones .clk.mux = &(struct imx_clk_mux_def) { \ 95*be9fefafSTom Jones .clkdef.id = _id, \ 96*be9fefafSTom Jones .clkdef.name = _name, \ 97*be9fefafSTom Jones .clkdef.parent_names = _pn, \ 98*be9fefafSTom Jones .clkdef.parent_cnt = nitems(_pn), \ 99*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 100*be9fefafSTom Jones .offset = _mo, \ 101*be9fefafSTom Jones .shift = _ms, \ 102*be9fefafSTom Jones .width = _mw, \ 103*be9fefafSTom Jones .mux_flags = _f, \ 104*be9fefafSTom Jones }, \ 105*be9fefafSTom Jones } 106*be9fefafSTom Jones 107*be9fefafSTom Jones /* Fixed frequency clock */ 108*be9fefafSTom Jones #define FIXED(_id, _name, _freq) \ 109*be9fefafSTom Jones { \ 110*be9fefafSTom Jones .type = IMX_CLK_FIXED, \ 111*be9fefafSTom Jones .clk.fixed = &(struct clk_fixed_def) { \ 112*be9fefafSTom Jones .clkdef.id = _id, \ 113*be9fefafSTom Jones .clkdef.name = _name, \ 114*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 115*be9fefafSTom Jones .freq = _freq, \ 116*be9fefafSTom Jones }, \ 117*be9fefafSTom Jones } 118*be9fefafSTom Jones 119*be9fefafSTom Jones /* Fixed factor multipier/divider. */ 120*be9fefafSTom Jones #define FFACT(_id, _name, _pname, _mult, _div) \ 121*be9fefafSTom Jones { \ 122*be9fefafSTom Jones .type = IMX_CLK_FIXED, \ 123*be9fefafSTom Jones .clk.fixed = &(struct clk_fixed_def) { \ 124*be9fefafSTom Jones .clkdef.id = _id, \ 125*be9fefafSTom Jones .clkdef.name = _name, \ 126*be9fefafSTom Jones .clkdef.parent_names = (const char *[]){_pname}, \ 127*be9fefafSTom Jones .clkdef.parent_cnt = 1, \ 128*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 129*be9fefafSTom Jones .mult = _mult, \ 130*be9fefafSTom Jones .div = _div, \ 131*be9fefafSTom Jones }, \ 132*be9fefafSTom Jones } 133*be9fefafSTom Jones 134*be9fefafSTom Jones /* Clock gate */ 135*be9fefafSTom Jones #define GATE(_id, _name, _pname, _o, _shift) \ 136*be9fefafSTom Jones { \ 137*be9fefafSTom Jones .type = IMX_CLK_GATE, \ 138*be9fefafSTom Jones .clk.gate = &(struct imx_clk_gate_def) { \ 139*be9fefafSTom Jones .clkdef.id = _id, \ 140*be9fefafSTom Jones .clkdef.name = _name, \ 141*be9fefafSTom Jones .clkdef.parent_names = (const char *[]){_pname}, \ 142*be9fefafSTom Jones .clkdef.parent_cnt = 1, \ 143*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 144*be9fefafSTom Jones .offset = _o, \ 145*be9fefafSTom Jones .shift = _shift, \ 146*be9fefafSTom Jones .mask = 1, \ 147*be9fefafSTom Jones }, \ 148*be9fefafSTom Jones } 149*be9fefafSTom Jones 150*be9fefafSTom Jones /* Root clock gate */ 151*be9fefafSTom Jones #define ROOT_GATE(_id, _name, _pname, _reg) \ 152*be9fefafSTom Jones { \ 153*be9fefafSTom Jones .type = IMX_CLK_GATE, \ 154*be9fefafSTom Jones .clk.gate = &(struct imx_clk_gate_def) { \ 155*be9fefafSTom Jones .clkdef.id = _id, \ 156*be9fefafSTom Jones .clkdef.name = _name, \ 157*be9fefafSTom Jones .clkdef.parent_names = (const char *[]){_pname}, \ 158*be9fefafSTom Jones .clkdef.parent_cnt = 1, \ 159*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 160*be9fefafSTom Jones .offset = _reg, \ 161*be9fefafSTom Jones .shift = 0, \ 162*be9fefafSTom Jones .mask = 3, \ 163*be9fefafSTom Jones }, \ 164*be9fefafSTom Jones } 165*be9fefafSTom Jones 166*be9fefafSTom Jones /* Composite clock with GATE, MUX, PRE_DIV, and POST_DIV */ 167*be9fefafSTom Jones #define COMPOSITE(_id, _name, _pn, _o, _flags) \ 168*be9fefafSTom Jones { \ 169*be9fefafSTom Jones .type = IMX_CLK_COMPOSITE, \ 170*be9fefafSTom Jones .clk.composite = &(struct imx_clk_composite_def) { \ 171*be9fefafSTom Jones .clkdef.id = _id, \ 172*be9fefafSTom Jones .clkdef.name = _name, \ 173*be9fefafSTom Jones .clkdef.parent_names = _pn, \ 174*be9fefafSTom Jones .clkdef.parent_cnt = nitems(_pn), \ 175*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 176*be9fefafSTom Jones .offset = _o, \ 177*be9fefafSTom Jones .flags = _flags, \ 178*be9fefafSTom Jones }, \ 179*be9fefafSTom Jones } 180*be9fefafSTom Jones 181*be9fefafSTom Jones /* SSCG PLL */ 182*be9fefafSTom Jones #define SSCG_PLL(_id, _name, _pn, _o) \ 183*be9fefafSTom Jones { \ 184*be9fefafSTom Jones .type = IMX_CLK_SSCG_PLL, \ 185*be9fefafSTom Jones .clk.composite = &(struct imx_clk_composite_def) { \ 186*be9fefafSTom Jones .clkdef.id = _id, \ 187*be9fefafSTom Jones .clkdef.name = _name, \ 188*be9fefafSTom Jones .clkdef.parent_names = _pn, \ 189*be9fefafSTom Jones .clkdef.parent_cnt = nitems(_pn), \ 190*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 191*be9fefafSTom Jones .offset = _o, \ 192*be9fefafSTom Jones }, \ 193*be9fefafSTom Jones } 194*be9fefafSTom Jones 195*be9fefafSTom Jones /* Fractional PLL */ 196*be9fefafSTom Jones #define FRAC_PLL(_id, _name, _pname, _o) \ 197*be9fefafSTom Jones { \ 198*be9fefafSTom Jones .type = IMX_CLK_FRAC_PLL, \ 199*be9fefafSTom Jones .clk.frac_pll = &(struct imx_clk_frac_pll_def) { \ 200*be9fefafSTom Jones .clkdef.id = _id, \ 201*be9fefafSTom Jones .clkdef.name = _name, \ 202*be9fefafSTom Jones .clkdef.parent_names = (const char *[]){_pname}, \ 203*be9fefafSTom Jones .clkdef.parent_cnt = 1, \ 204*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 205*be9fefafSTom Jones .offset = _o, \ 206*be9fefafSTom Jones }, \ 207*be9fefafSTom Jones } 208*be9fefafSTom Jones 209*be9fefafSTom Jones #define DIV(_id, _name, _pname, _o, _shift, _width) \ 210*be9fefafSTom Jones { \ 211*be9fefafSTom Jones .type = IMX_CLK_DIV, \ 212*be9fefafSTom Jones .clk.div = &(struct clk_div_def) { \ 213*be9fefafSTom Jones .clkdef.id = _id, \ 214*be9fefafSTom Jones .clkdef.name = _name, \ 215*be9fefafSTom Jones .clkdef.parent_names = (const char *[]){_pname}, \ 216*be9fefafSTom Jones .clkdef.parent_cnt = 1, \ 217*be9fefafSTom Jones .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 218*be9fefafSTom Jones .offset = _o, \ 219*be9fefafSTom Jones .i_shift = _shift, \ 220*be9fefafSTom Jones .i_width = _width, \ 221*be9fefafSTom Jones }, \ 222*be9fefafSTom Jones } 223*be9fefafSTom Jones 224*be9fefafSTom Jones #endif /* IMX8_CCM_H */ 225