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