1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2020 Alstom Group. 5 * Copyright (c) 2020 Semihalf. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #include <sys/param.h> 31 #include <sys/bus.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/mutex.h> 35 #include <sys/rman.h> 36 #include <machine/bus.h> 37 38 #include <dev/fdt/simplebus.h> 39 40 #include <dev/ofw/ofw_bus.h> 41 #include <dev/ofw/ofw_bus_subr.h> 42 43 #include <dev/extres/clk/clk_fixed.h> 44 45 #include <arm64/qoriq/clk/qoriq_clkgen.h> 46 47 static uint8_t ls1046a_pltfrm_pll_divs[] = { 48 2, 4, 0 49 }; 50 51 static struct qoriq_clk_pll_def ls1046a_pltfrm_pll = { 52 .clkdef = { 53 .name = "ls1046a_platform_pll", 54 .id = QORIQ_CLK_ID(QORIQ_TYPE_PLATFORM_PLL, 0), 55 .flags = 0 56 }, 57 .offset = 0xC00, 58 .shift = 1, 59 .mask = 0x7E, 60 .dividers = ls1046a_pltfrm_pll_divs, 61 .flags = 0 62 }; 63 64 static const uint8_t ls1046a_cga1_pll_divs[] = { 65 2, 3, 4, 0 66 }; 67 68 static struct qoriq_clk_pll_def ls1046a_cga1_pll = { 69 .clkdef = { 70 .name = "ls1046a_cga_pll1", 71 .id = QORIQ_CLK_ID(QORIQ_TYPE_INTERNAL, 0), 72 .flags = 0 73 }, 74 .offset = 0x800, 75 .shift = 1, 76 .mask = 0x1FE, 77 .dividers = ls1046a_cga1_pll_divs, 78 .flags = QORIQ_CLK_PLL_HAS_KILL_BIT 79 }; 80 81 static struct qoriq_clk_pll_def ls1046a_cga2_pll = { 82 .clkdef = { 83 .name = "ls1046a_cga_pll2", 84 .id = QORIQ_CLK_ID(QORIQ_TYPE_INTERNAL, 20), 85 .flags = 0 86 }, 87 .offset = 0x820, 88 .shift = 1, 89 .mask = 0x1FE, 90 .dividers = ls1046a_cga1_pll_divs, 91 .flags = QORIQ_CLK_PLL_HAS_KILL_BIT 92 }; 93 94 static struct qoriq_clk_pll_def *ls1046a_cga_plls[] = { 95 &ls1046a_cga1_pll, 96 &ls1046a_cga2_pll 97 }; 98 99 static const char *ls1046a_cmux0_parent_names[] = { 100 "ls1046a_cga_pll1", 101 NULL, 102 "ls1046a_cga_pll1_div2", 103 NULL, 104 "ls1046a_cga_pll2", 105 NULL, 106 "ls1046a_cga_pll2_div2" 107 }; 108 109 static struct clk_mux_def ls1046a_cmux0 = { 110 .clkdef = { 111 .name = "ls1046a_cmux0", 112 .id = QORIQ_CLK_ID(QORIQ_TYPE_CMUX, 0), 113 .parent_names = ls1046a_cmux0_parent_names, 114 .parent_cnt = nitems(ls1046a_cmux0_parent_names), 115 .flags = 0 116 }, 117 .offset = 0, 118 .shift = 27, 119 .width = 4, 120 .mux_flags = 0 121 }; 122 123 static const char *ls1046a_hwaccel1_parent_names[] = { 124 NULL, 125 NULL, 126 "ls1046a_cga_pll1_div2", 127 "ls1046a_cga_pll1_div3", 128 "ls1046a_cga_pll1_div4", 129 "ls1046a_platform_pll", 130 "ls1046a_cga_pll2_div2", 131 "ls1046a_cga_pll2_div3" 132 }; 133 134 static const char *ls1046a_hwaccel2_parent_names[] = { 135 NULL, 136 "ls1046a_cga_pll2", 137 "ls1046a_cga_pll2_div2", 138 "ls1046a_cga_pll2_div3", 139 NULL, 140 NULL, 141 "ls1046a_cga_pll1_div2" 142 }; 143 144 static struct clk_mux_def ls1046a_hwaccel1 = { 145 .clkdef = { 146 .name = "ls1046a_hwaccel1", 147 .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 0), 148 .parent_names = ls1046a_hwaccel1_parent_names, 149 .parent_cnt = nitems(ls1046a_hwaccel1_parent_names), 150 .flags = 0 151 }, 152 .offset = 0x10, 153 .shift = 27, 154 .width = 4, 155 .mux_flags = 0 156 }; 157 158 static struct clk_mux_def ls1046a_hwaccel2 = { 159 .clkdef = { 160 .name = "ls1046a_hwaccel2", 161 .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 1), 162 .parent_names = ls1046a_hwaccel2_parent_names, 163 .parent_cnt = nitems(ls1046a_hwaccel2_parent_names), 164 .flags = 0 165 }, 166 .offset = 0x30, 167 .shift = 27, 168 .width = 4, 169 .mux_flags = 0 170 }; 171 172 static struct clk_mux_def *ls1046a_mux_nodes[] = { 173 &ls1046a_cmux0, 174 &ls1046a_hwaccel1, 175 &ls1046a_hwaccel2 176 }; 177 178 const char *ls1046a_fman_srcs[] = { 179 "ls1046a_hwaccel1" 180 }; 181 182 static int ls1046a_clkgen_probe(device_t); 183 static int ls1046a_clkgen_attach(device_t); 184 185 static device_method_t ls1046a_clkgen_methods[] = { 186 DEVMETHOD(device_probe, ls1046a_clkgen_probe), 187 DEVMETHOD(device_attach, ls1046a_clkgen_attach), 188 189 DEVMETHOD_END 190 }; 191 192 DEFINE_CLASS_1(ls1046a_clkgen, ls1046a_clkgen_driver, ls1046a_clkgen_methods, 193 sizeof(struct qoriq_clkgen_softc), qoriq_clkgen_driver); 194 195 EARLY_DRIVER_MODULE(ls1046a_clkgen, simplebus, ls1046a_clkgen_driver, 0, 0, 196 BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); 197 198 static int 199 ls1046a_fman_init(device_t dev) 200 { 201 struct qoriq_clkgen_softc *sc; 202 struct clk_fixed_def def; 203 int error; 204 205 sc = device_get_softc(dev); 206 207 def.clkdef.name = "ls1046a_fman", 208 def.clkdef.id = QORIQ_CLK_ID(QORIQ_TYPE_FMAN, 0), 209 def.clkdef.parent_names = ls1046a_fman_srcs; 210 def.clkdef.parent_cnt = nitems(ls1046a_fman_srcs); 211 def.clkdef.flags = 0; 212 def.freq = 0; 213 def.mult = 1; 214 def.div = 1; 215 def.fixed_flags = 0; 216 217 error = clknode_fixed_register(sc->clkdom, &def); 218 return (error); 219 } 220 221 static int 222 ls1046a_clkgen_probe(device_t dev) 223 { 224 225 if (!ofw_bus_status_okay(dev)) 226 return (ENXIO); 227 228 if(!ofw_bus_is_compatible(dev, "fsl,ls1046a-clockgen")) 229 return (ENXIO); 230 231 device_set_desc(dev, "LS1046A clockgen"); 232 return (BUS_PROBE_DEFAULT); 233 } 234 235 static int 236 ls1046a_clkgen_attach(device_t dev) 237 { 238 struct qoriq_clkgen_softc *sc; 239 240 sc = device_get_softc(dev); 241 242 sc->pltfrm_pll_def = &ls1046a_pltfrm_pll; 243 sc->cga_pll = ls1046a_cga_plls; 244 sc->cga_pll_num = nitems(ls1046a_cga_plls); 245 sc->mux = ls1046a_mux_nodes; 246 sc->mux_num = nitems(ls1046a_mux_nodes); 247 sc->init_func = ls1046a_fman_init; 248 sc->flags = 0; 249 250 return (qoriq_clkgen_attach(dev)); 251 } 252