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