1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org> 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 #ifndef IMX8_CCM_H 29 #define IMX8_CCM_H 30 31 #include <dev/clk/clk.h> 32 #include <dev/clk/clk_div.h> 33 #include <dev/clk/clk_fixed.h> 34 #include <dev/clk/clk_gate.h> 35 #include <dev/clk/clk_link.h> 36 37 int imx_ccm_attach(device_t); 38 int imx_ccm_detach(device_t); 39 40 struct imx_ccm_softc { 41 device_t dev; 42 struct resource *mem_res; 43 struct clkdom *clkdom; 44 struct mtx mtx; 45 struct imx_clk *clks; 46 int nclks; 47 }; 48 49 DECLARE_CLASS(imx_ccm_driver); 50 51 enum imx_clk_type { 52 IMX_CLK_UNDEFINED = 0, 53 IMX_CLK_FIXED, 54 IMX_CLK_LINK, 55 IMX_CLK_MUX, 56 IMX_CLK_GATE, 57 IMX_CLK_COMPOSITE, 58 IMX_CLK_SSCG_PLL, 59 IMX_CLK_FRAC_PLL, 60 IMX_CLK_DIV, 61 }; 62 63 struct imx_clk { 64 enum imx_clk_type type; 65 union { 66 struct clk_fixed_def *fixed; 67 struct clk_link_def *link; 68 struct imx_clk_mux_def *mux; 69 struct imx_clk_gate_def *gate; 70 struct imx_clk_composite_def *composite; 71 struct imx_clk_sscg_pll_def *sscg_pll; 72 struct imx_clk_frac_pll_def *frac_pll; 73 struct clk_div_def *div; 74 } clk; 75 }; 76 77 /* Linked clock. */ 78 #define LINK(_id, _name) \ 79 { \ 80 .type = IMX_CLK_LINK, \ 81 .clk.link = &(struct clk_link_def) { \ 82 .clkdef.id = _id, \ 83 .clkdef.name = _name, \ 84 .clkdef.parent_names = NULL, \ 85 .clkdef.parent_cnt = 0, \ 86 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 87 }, \ 88 } 89 90 /* Complex clock without divider (multiplexer only). */ 91 #define MUX(_id, _name, _pn, _f, _mo, _ms, _mw) \ 92 { \ 93 .type = IMX_CLK_MUX, \ 94 .clk.mux = &(struct imx_clk_mux_def) { \ 95 .clkdef.id = _id, \ 96 .clkdef.name = _name, \ 97 .clkdef.parent_names = _pn, \ 98 .clkdef.parent_cnt = nitems(_pn), \ 99 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 100 .offset = _mo, \ 101 .shift = _ms, \ 102 .width = _mw, \ 103 .mux_flags = _f, \ 104 }, \ 105 } 106 107 /* Fixed frequency clock */ 108 #define FIXED(_id, _name, _freq) \ 109 { \ 110 .type = IMX_CLK_FIXED, \ 111 .clk.fixed = &(struct clk_fixed_def) { \ 112 .clkdef.id = _id, \ 113 .clkdef.name = _name, \ 114 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 115 .freq = _freq, \ 116 }, \ 117 } 118 119 /* Fixed factor multipier/divider. */ 120 #define FFACT(_id, _name, _pname, _mult, _div) \ 121 { \ 122 .type = IMX_CLK_FIXED, \ 123 .clk.fixed = &(struct clk_fixed_def) { \ 124 .clkdef.id = _id, \ 125 .clkdef.name = _name, \ 126 .clkdef.parent_names = (const char *[]){_pname}, \ 127 .clkdef.parent_cnt = 1, \ 128 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 129 .mult = _mult, \ 130 .div = _div, \ 131 }, \ 132 } 133 134 /* Clock gate */ 135 #define GATE(_id, _name, _pname, _o, _shift) \ 136 { \ 137 .type = IMX_CLK_GATE, \ 138 .clk.gate = &(struct imx_clk_gate_def) { \ 139 .clkdef.id = _id, \ 140 .clkdef.name = _name, \ 141 .clkdef.parent_names = (const char *[]){_pname}, \ 142 .clkdef.parent_cnt = 1, \ 143 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 144 .offset = _o, \ 145 .shift = _shift, \ 146 .mask = 1, \ 147 }, \ 148 } 149 150 /* Root clock gate */ 151 #define ROOT_GATE(_id, _name, _pname, _reg) \ 152 { \ 153 .type = IMX_CLK_GATE, \ 154 .clk.gate = &(struct imx_clk_gate_def) { \ 155 .clkdef.id = _id, \ 156 .clkdef.name = _name, \ 157 .clkdef.parent_names = (const char *[]){_pname}, \ 158 .clkdef.parent_cnt = 1, \ 159 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 160 .offset = _reg, \ 161 .shift = 0, \ 162 .mask = 3, \ 163 }, \ 164 } 165 166 /* Composite clock with GATE, MUX, PRE_DIV, and POST_DIV */ 167 #define COMPOSITE(_id, _name, _pn, _o, _flags) \ 168 { \ 169 .type = IMX_CLK_COMPOSITE, \ 170 .clk.composite = &(struct imx_clk_composite_def) { \ 171 .clkdef.id = _id, \ 172 .clkdef.name = _name, \ 173 .clkdef.parent_names = _pn, \ 174 .clkdef.parent_cnt = nitems(_pn), \ 175 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 176 .offset = _o, \ 177 .flags = _flags, \ 178 }, \ 179 } 180 181 /* SSCG PLL */ 182 #define SSCG_PLL(_id, _name, _pn, _o) \ 183 { \ 184 .type = IMX_CLK_SSCG_PLL, \ 185 .clk.composite = &(struct imx_clk_composite_def) { \ 186 .clkdef.id = _id, \ 187 .clkdef.name = _name, \ 188 .clkdef.parent_names = _pn, \ 189 .clkdef.parent_cnt = nitems(_pn), \ 190 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 191 .offset = _o, \ 192 }, \ 193 } 194 195 /* Fractional PLL */ 196 #define FRAC_PLL(_id, _name, _pname, _o) \ 197 { \ 198 .type = IMX_CLK_FRAC_PLL, \ 199 .clk.frac_pll = &(struct imx_clk_frac_pll_def) { \ 200 .clkdef.id = _id, \ 201 .clkdef.name = _name, \ 202 .clkdef.parent_names = (const char *[]){_pname}, \ 203 .clkdef.parent_cnt = 1, \ 204 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 205 .offset = _o, \ 206 }, \ 207 } 208 209 #define DIV(_id, _name, _pname, _o, _shift, _width) \ 210 { \ 211 .type = IMX_CLK_DIV, \ 212 .clk.div = &(struct clk_div_def) { \ 213 .clkdef.id = _id, \ 214 .clkdef.name = _name, \ 215 .clkdef.parent_names = (const char *[]){_pname}, \ 216 .clkdef.parent_cnt = 1, \ 217 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ 218 .offset = _o, \ 219 .i_shift = _shift, \ 220 .i_width = _width, \ 221 }, \ 222 } 223 224 #endif /* IMX8_CCM_H */ 225