1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2021 Alstom Group. 5 * Copyright (c) 2021 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 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/kernel.h> 35 #include <sys/module.h> 36 #include <sys/mutex.h> 37 #include <sys/rman.h> 38 #include <machine/bus.h> 39 40 #include <dev/fdt/simplebus.h> 41 42 #include <dev/ofw/ofw_bus.h> 43 #include <dev/ofw/ofw_bus_subr.h> 44 45 #include <dev/extres/clk/clk_fixed.h> 46 47 #include <arm64/qoriq/clk/qoriq_clkgen.h> 48 49 static uint8_t ls1028a_pltfrm_pll_divs[] = { 50 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 51 }; 52 53 static struct qoriq_clk_pll_def ls1028a_pltfrm_pll = { 54 .clkdef = { 55 .name = "ls1028a_platform_pll", 56 .id = QORIQ_CLK_ID(QORIQ_TYPE_PLATFORM_PLL, 0), 57 .flags = 0 58 }, 59 .offset = 0x60080, 60 .shift = 1, 61 .mask = 0xFE, 62 .dividers = ls1028a_pltfrm_pll_divs, 63 .flags = QORIQ_CLK_PLL_HAS_KILL_BIT 64 }; 65 66 static const uint8_t ls1028a_cga_pll_divs[] = { 67 2, 3, 4, 0 68 }; 69 70 static struct qoriq_clk_pll_def ls1028a_cga_pll1 = { 71 .clkdef = { 72 .name = "ls1028a_cga_pll1", 73 .id = QORIQ_CLK_ID(QORIQ_TYPE_INTERNAL, 0), 74 .flags = 0 75 }, 76 .offset = 0x80, 77 .shift = 1, 78 .mask = 0xFE, 79 .dividers = ls1028a_cga_pll_divs, 80 .flags = QORIQ_CLK_PLL_HAS_KILL_BIT 81 }; 82 83 static struct qoriq_clk_pll_def ls1028a_cga_pll2 = { 84 .clkdef = { 85 .name = "ls1028a_cga_pll2", 86 .id = QORIQ_CLK_ID(QORIQ_TYPE_INTERNAL, 20), 87 .flags = 0 88 }, 89 .offset = 0xA0, 90 .shift = 1, 91 .mask = 0xFE, 92 .dividers = ls1028a_cga_pll_divs, 93 .flags = QORIQ_CLK_PLL_HAS_KILL_BIT 94 }; 95 96 static struct qoriq_clk_pll_def *ls1028a_cga_plls[] = { 97 &ls1028a_cga_pll1, 98 &ls1028a_cga_pll2 99 }; 100 101 static const char *ls1028a_cmux0_parent_names[] = { 102 "ls1028a_cga_pll1", 103 "ls1028a_cga_pll1_div2", 104 "ls1028a_cga_pll1_div4", 105 NULL, 106 "ls1028a_cga_pll2", 107 "ls1028a_cga_pll2_div2", 108 "ls1028a_cga_pll2_div4" 109 }; 110 111 static struct clk_mux_def ls1028a_cmux0 = { 112 .clkdef = { 113 .name = "ls1028a_cmux0", 114 .id = QORIQ_CLK_ID(QORIQ_TYPE_CMUX, 0), 115 .parent_names = ls1028a_cmux0_parent_names, 116 .parent_cnt = nitems(ls1028a_cmux0_parent_names), 117 .flags = 0 118 }, 119 .offset = 0x70000, 120 .shift = 27, 121 .width = 4, 122 .mux_flags = 0 123 }; 124 125 static struct clk_mux_def ls1028a_cmux1 = { 126 .clkdef = { 127 .name = "ls1028a_cmux1", 128 .id = QORIQ_CLK_ID(QORIQ_TYPE_CMUX, 1), 129 .parent_names = ls1028a_cmux0_parent_names, 130 .parent_cnt = nitems(ls1028a_cmux0_parent_names), 131 .flags = 0 132 }, 133 .offset = 0x70020, 134 .shift = 27, 135 .width = 4, 136 .mux_flags = 0 137 }; 138 139 static struct clk_mux_def ls1028a_cmux2 = { 140 .clkdef = { 141 .name = "ls1028a_cmux2", 142 .id = QORIQ_CLK_ID(QORIQ_TYPE_CMUX, 2), 143 .parent_names = ls1028a_cmux0_parent_names, 144 .parent_cnt = nitems(ls1028a_cmux0_parent_names), 145 .flags = 0 146 }, 147 .offset = 0x70040, 148 .shift = 27, 149 .width = 4, 150 .mux_flags = 0 151 }; 152 153 static struct clk_mux_def ls1028a_cmux3 = { 154 .clkdef = { 155 .name = "ls1028a_cmux3", 156 .id = QORIQ_CLK_ID(QORIQ_TYPE_CMUX, 3), 157 .parent_names = ls1028a_cmux0_parent_names, 158 .parent_cnt = nitems(ls1028a_cmux0_parent_names), 159 .flags = 0 160 }, 161 .offset = 0x70060, 162 .shift = 27, 163 .width = 4, 164 .mux_flags = 0 165 }; 166 167 static const char *ls1028a_hwaccel1_parent_names[] = { 168 "ls1028a_platform_pll", 169 "ls1028a_cga_pll1", 170 "ls1028a_cga_pll1_div2", 171 "ls1028a_cga_pll1_div3", 172 "ls1028a_cga_pll1_div4", 173 NULL, 174 "ls1028a_cga_pll2_div2", 175 "ls1028a_cga_pll2_div3" 176 }; 177 178 static const char *ls1028a_hwaccel2_parent_names[] = { 179 "ls1028a_platform_pll", 180 "ls1028a_cga_pll2", 181 "ls1028a_cga_pll2_div2", 182 "ls1028a_cga_pll2_div3", 183 "ls1028a_cga_pll2_div4", 184 NULL, 185 "ls1028a_cga_pll1_div2", 186 "ls1028a_cga_pll1_div3" 187 }; 188 189 static struct clk_mux_def ls1028a_hwaccel1 = { 190 .clkdef = { 191 .name = "ls1028a_hwaccel1", 192 .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 0), 193 .parent_names = ls1028a_hwaccel1_parent_names, 194 .parent_cnt = nitems(ls1028a_hwaccel1_parent_names), 195 .flags = 0 196 }, 197 .offset = 0x10, 198 .shift = 27, 199 .width = 4, 200 .mux_flags = 0 201 }; 202 203 static struct clk_mux_def ls1028a_hwaccel2 = { 204 .clkdef = { 205 .name = "ls1028a_hwaccel2", 206 .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 1), 207 .parent_names = ls1028a_hwaccel2_parent_names, 208 .parent_cnt = nitems(ls1028a_hwaccel2_parent_names), 209 .flags = 0 210 }, 211 .offset = 0x30, 212 .shift = 27, 213 .width = 4, 214 .mux_flags = 0 215 }; 216 217 static struct clk_mux_def ls1028a_hwaccel3 = { 218 .clkdef = { 219 .name = "ls1028a_hwaccel3", 220 .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 2), 221 .parent_names = ls1028a_hwaccel1_parent_names, 222 .parent_cnt = nitems(ls1028a_hwaccel1_parent_names), 223 .flags = 0 224 }, 225 .offset = 0x50, 226 .shift = 27, 227 .width = 4, 228 .mux_flags = 0 229 }; 230 231 static struct clk_mux_def ls1028a_hwaccel4 = { 232 .clkdef = { 233 .name = "ls1028a_hwaccel4", 234 .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 3), 235 .parent_names = ls1028a_hwaccel2_parent_names, 236 .parent_cnt = nitems(ls1028a_hwaccel2_parent_names), 237 .flags = 0 238 }, 239 .offset = 0x70, 240 .shift = 27, 241 .width = 4, 242 .mux_flags = 0 243 }; 244 245 static struct clk_mux_def *ls1028a_mux_nodes[] = { 246 &ls1028a_cmux0, 247 &ls1028a_cmux1, 248 &ls1028a_cmux2, 249 &ls1028a_cmux3, 250 &ls1028a_hwaccel1, 251 &ls1028a_hwaccel2, 252 &ls1028a_hwaccel3, 253 &ls1028a_hwaccel4 254 }; 255 256 static int ls1028a_clkgen_probe(device_t); 257 static int ls1028a_clkgen_attach(device_t); 258 259 static device_method_t ls1028a_clkgen_methods[] = { 260 DEVMETHOD(device_probe, ls1028a_clkgen_probe), 261 DEVMETHOD(device_attach, ls1028a_clkgen_attach), 262 263 DEVMETHOD_END 264 }; 265 266 DEFINE_CLASS_1(ls1028a_clkgen, ls1028a_clkgen_driver, ls1028a_clkgen_methods, 267 sizeof(struct qoriq_clkgen_softc), qoriq_clkgen_driver); 268 269 static devclass_t ls1028a_clkgen_devclass; 270 271 EARLY_DRIVER_MODULE(ls1028a_clkgen, simplebus, ls1028a_clkgen_driver, 272 ls1028a_clkgen_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); 273 274 static int 275 ls1028a_clkgen_probe(device_t dev) 276 { 277 278 if (!ofw_bus_status_okay(dev)) 279 return (ENXIO); 280 281 if(!ofw_bus_is_compatible(dev, "fsl,ls1028a-clockgen")) 282 return (ENXIO); 283 284 device_set_desc(dev, "LS1028A clockgen"); 285 return (BUS_PROBE_DEFAULT); 286 } 287 288 static int 289 ls1028a_clkgen_attach(device_t dev) 290 { 291 struct qoriq_clkgen_softc *sc; 292 293 sc = device_get_softc(dev); 294 295 sc->pltfrm_pll_def = &ls1028a_pltfrm_pll; 296 sc->cga_pll = ls1028a_cga_plls; 297 sc->cga_pll_num = nitems(ls1028a_cga_plls); 298 sc->mux = ls1028a_mux_nodes; 299 sc->mux_num = nitems(ls1028a_mux_nodes); 300 sc->flags = QORIQ_LITTLE_ENDIAN; 301 302 return (qoriq_clkgen_attach(dev)); 303 } 304