1*f21c469dSHubert Mazur /*- 2*f21c469dSHubert Mazur * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*f21c469dSHubert Mazur * 4*f21c469dSHubert Mazur * Copyright (c) 2021 Semihalf. 5*f21c469dSHubert Mazur * 6*f21c469dSHubert Mazur * Redistribution and use in source and binary forms, with or without 7*f21c469dSHubert Mazur * modification, are permitted provided that the following conditions 8*f21c469dSHubert Mazur * are met: 9*f21c469dSHubert Mazur * 1. Redistributions of source code must retain the above copyright 10*f21c469dSHubert Mazur * notice, this list of conditions and the following disclaimer. 11*f21c469dSHubert Mazur * 2. Redistributions in binary form must reproduce the above copyright 12*f21c469dSHubert Mazur * notice, this list of conditions and the following disclaimer in the 13*f21c469dSHubert Mazur * documentation and/or other materials provided with the distribution. 14*f21c469dSHubert Mazur * 15*f21c469dSHubert Mazur * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*f21c469dSHubert Mazur * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*f21c469dSHubert Mazur * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*f21c469dSHubert Mazur * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*f21c469dSHubert Mazur * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*f21c469dSHubert Mazur * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*f21c469dSHubert Mazur * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*f21c469dSHubert Mazur * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*f21c469dSHubert Mazur * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*f21c469dSHubert Mazur * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*f21c469dSHubert Mazur * SUCH DAMAGE. 26*f21c469dSHubert Mazur */ 27*f21c469dSHubert Mazur 28*f21c469dSHubert Mazur #include <sys/cdefs.h> 29*f21c469dSHubert Mazur __FBSDID("$FreeBSD$"); 30*f21c469dSHubert Mazur 31*f21c469dSHubert Mazur #include <sys/param.h> 32*f21c469dSHubert Mazur #include <sys/bus.h> 33*f21c469dSHubert Mazur #include <sys/kernel.h> 34*f21c469dSHubert Mazur #include <sys/module.h> 35*f21c469dSHubert Mazur #include <sys/mutex.h> 36*f21c469dSHubert Mazur #include <sys/rman.h> 37*f21c469dSHubert Mazur #include <machine/bus.h> 38*f21c469dSHubert Mazur 39*f21c469dSHubert Mazur #include <dev/fdt/simplebus.h> 40*f21c469dSHubert Mazur 41*f21c469dSHubert Mazur #include <dev/extres/clk/clk.h> 42*f21c469dSHubert Mazur #include <dev/extres/clk/clk_div.h> 43*f21c469dSHubert Mazur #include <dev/extres/clk/clk_fixed.h> 44*f21c469dSHubert Mazur #include <dev/extres/clk/clk_gate.h> 45*f21c469dSHubert Mazur #include <dev/extres/clk/clk_mux.h> 46*f21c469dSHubert Mazur 47*f21c469dSHubert Mazur #include <dev/ofw/ofw_bus.h> 48*f21c469dSHubert Mazur #include <dev/ofw/ofw_bus_subr.h> 49*f21c469dSHubert Mazur 50*f21c469dSHubert Mazur #include "clkdev_if.h" 51*f21c469dSHubert Mazur #include "periph.h" 52*f21c469dSHubert Mazur 53*f21c469dSHubert Mazur #define PARENT_CNT 2 54*f21c469dSHubert Mazur 55*f21c469dSHubert Mazur /* 56*f21c469dSHubert Mazur * Register chain: mux (select proper TBG) -> div1 (first frequency divider) -> 57*f21c469dSHubert Mazur * div2 (second frequency divider) -> mux (select divided freq. 58*f21c469dSHubert Mazur * or xtal output) -> gate (enable or disable clock), which is also final node 59*f21c469dSHubert Mazur */ 60*f21c469dSHubert Mazur 61*f21c469dSHubert Mazur int 62*f21c469dSHubert Mazur a37x0_periph_d_register_full_clk_dd(struct clkdom *clkdom, 63*f21c469dSHubert Mazur struct a37x0_periph_clknode_def *device_def) 64*f21c469dSHubert Mazur { 65*f21c469dSHubert Mazur const char *parent_names[PARENT_CNT]; 66*f21c469dSHubert Mazur struct clk_mux_def *clk_mux; 67*f21c469dSHubert Mazur struct clk_mux_def *tbg_mux; 68*f21c469dSHubert Mazur struct clk_gate_def *gate; 69*f21c469dSHubert Mazur struct clk_div_def *div1; 70*f21c469dSHubert Mazur struct clk_div_def *div2; 71*f21c469dSHubert Mazur const char *dev_name; 72*f21c469dSHubert Mazur int error, dev_id; 73*f21c469dSHubert Mazur 74*f21c469dSHubert Mazur dev_id = device_def->common_def.device_id; 75*f21c469dSHubert Mazur dev_name = device_def->common_def.device_name; 76*f21c469dSHubert Mazur tbg_mux = &device_def->clk_def.full_dd.tbg_mux; 77*f21c469dSHubert Mazur div1 = &device_def->clk_def.full_dd.div1; 78*f21c469dSHubert Mazur div2 = &device_def->clk_def.full_dd.div2; 79*f21c469dSHubert Mazur gate = &device_def->clk_def.full_dd.gate; 80*f21c469dSHubert Mazur clk_mux = &device_def->clk_def.full_dd.clk_mux; 81*f21c469dSHubert Mazur 82*f21c469dSHubert Mazur a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs, 83*f21c469dSHubert Mazur device_def->common_def.tbg_cnt); 84*f21c469dSHubert Mazur 85*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, 86*f21c469dSHubert Mazur tbg_mux, A37x0_INTERNAL_CLK_ID(dev_id, MUX_POS)); 87*f21c469dSHubert Mazur if (error) 88*f21c469dSHubert Mazur goto fail; 89*f21c469dSHubert Mazur 90*f21c469dSHubert Mazur a37x0_periph_set_props(&div1->clkdef, &tbg_mux->clkdef.name, 1); 91*f21c469dSHubert Mazur error = a37x0_periph_create_div(clkdom, div1, 92*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, DIV1_POS)); 93*f21c469dSHubert Mazur if (error) 94*f21c469dSHubert Mazur goto fail; 95*f21c469dSHubert Mazur 96*f21c469dSHubert Mazur a37x0_periph_set_props(&div2->clkdef, &div1->clkdef.name, 1); 97*f21c469dSHubert Mazur error = a37x0_periph_create_div(clkdom, div2, 98*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, DIV2_POS)); 99*f21c469dSHubert Mazur if (error) 100*f21c469dSHubert Mazur goto fail; 101*f21c469dSHubert Mazur 102*f21c469dSHubert Mazur parent_names[0] = device_def->common_def.xtal; 103*f21c469dSHubert Mazur parent_names[1] = div2->clkdef.name; 104*f21c469dSHubert Mazur 105*f21c469dSHubert Mazur a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT); 106*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, clk_mux, 107*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, CLK_MUX_POS)); 108*f21c469dSHubert Mazur if (error) 109*f21c469dSHubert Mazur goto fail; 110*f21c469dSHubert Mazur 111*f21c469dSHubert Mazur a37x0_periph_set_props(&gate->clkdef, &clk_mux->clkdef.name, 1); 112*f21c469dSHubert Mazur error = a37x0_periph_create_gate(clkdom, gate, 113*f21c469dSHubert Mazur dev_id); 114*f21c469dSHubert Mazur if (error) 115*f21c469dSHubert Mazur goto fail; 116*f21c469dSHubert Mazur 117*f21c469dSHubert Mazur fail: 118*f21c469dSHubert Mazur 119*f21c469dSHubert Mazur return (error); 120*f21c469dSHubert Mazur } 121*f21c469dSHubert Mazur 122*f21c469dSHubert Mazur /* 123*f21c469dSHubert Mazur * Register chain: mux (select proper TBG) -> div1 (first frequency divider) -> 124*f21c469dSHubert Mazur * mux (select divided freq. or xtal output) -> gate (enable or disable clock), 125*f21c469dSHubert Mazur * which is also final node 126*f21c469dSHubert Mazur */ 127*f21c469dSHubert Mazur 128*f21c469dSHubert Mazur int 129*f21c469dSHubert Mazur a37x0_periph_d_register_full_clk(struct clkdom *clkdom, 130*f21c469dSHubert Mazur struct a37x0_periph_clknode_def *device_def) 131*f21c469dSHubert Mazur { 132*f21c469dSHubert Mazur const char *parent_names[PARENT_CNT]; 133*f21c469dSHubert Mazur struct clk_mux_def *tbg_mux; 134*f21c469dSHubert Mazur struct clk_mux_def *clk_mux; 135*f21c469dSHubert Mazur struct clk_gate_def *gate; 136*f21c469dSHubert Mazur struct clk_div_def *div; 137*f21c469dSHubert Mazur const char *dev_name; 138*f21c469dSHubert Mazur int error, dev_id; 139*f21c469dSHubert Mazur 140*f21c469dSHubert Mazur dev_id = device_def->common_def.device_id; 141*f21c469dSHubert Mazur dev_name = device_def->common_def.device_name; 142*f21c469dSHubert Mazur tbg_mux = &device_def->clk_def.full_d.tbg_mux; 143*f21c469dSHubert Mazur div = &device_def->clk_def.full_d.div; 144*f21c469dSHubert Mazur gate = &device_def->clk_def.full_d.gate; 145*f21c469dSHubert Mazur clk_mux = &device_def->clk_def.full_d. clk_mux; 146*f21c469dSHubert Mazur 147*f21c469dSHubert Mazur a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs, 148*f21c469dSHubert Mazur device_def->common_def.tbg_cnt); 149*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, tbg_mux, 150*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(device_def->common_def.device_id, MUX_POS)); 151*f21c469dSHubert Mazur if (error) 152*f21c469dSHubert Mazur goto fail; 153*f21c469dSHubert Mazur 154*f21c469dSHubert Mazur a37x0_periph_set_props(&div->clkdef, &tbg_mux->clkdef.name, 1); 155*f21c469dSHubert Mazur error = a37x0_periph_create_div(clkdom, div, 156*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(device_def->common_def.device_id, DIV1_POS)); 157*f21c469dSHubert Mazur if (error) 158*f21c469dSHubert Mazur goto fail; 159*f21c469dSHubert Mazur 160*f21c469dSHubert Mazur parent_names[0] = device_def->common_def.xtal; 161*f21c469dSHubert Mazur parent_names[1] = div->clkdef.name; 162*f21c469dSHubert Mazur 163*f21c469dSHubert Mazur a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT); 164*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, clk_mux, 165*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, CLK_MUX_POS)); 166*f21c469dSHubert Mazur if (error) 167*f21c469dSHubert Mazur goto fail; 168*f21c469dSHubert Mazur 169*f21c469dSHubert Mazur a37x0_periph_set_props(&gate->clkdef, &clk_mux->clkdef.name, 1); 170*f21c469dSHubert Mazur error = a37x0_periph_create_gate(clkdom, gate, 171*f21c469dSHubert Mazur dev_id); 172*f21c469dSHubert Mazur if (error) 173*f21c469dSHubert Mazur goto fail; 174*f21c469dSHubert Mazur 175*f21c469dSHubert Mazur fail: 176*f21c469dSHubert Mazur 177*f21c469dSHubert Mazur return (error); 178*f21c469dSHubert Mazur } 179*f21c469dSHubert Mazur 180*f21c469dSHubert Mazur /* 181*f21c469dSHubert Mazur * Register CPU clock. It consists of mux (select proper TBG) -> div (frequency 182*f21c469dSHubert Mazur * divider) -> mux (choose divided or xtal output). 183*f21c469dSHubert Mazur */ 184*f21c469dSHubert Mazur 185*f21c469dSHubert Mazur int 186*f21c469dSHubert Mazur a37x0_periph_d_register_periph_cpu(struct clkdom *clkdom, 187*f21c469dSHubert Mazur struct a37x0_periph_clknode_def *device_def) 188*f21c469dSHubert Mazur { 189*f21c469dSHubert Mazur const char *parent_names[PARENT_CNT]; 190*f21c469dSHubert Mazur struct clk_mux_def *clk_mux; 191*f21c469dSHubert Mazur struct clk_mux_def *tbg_mux; 192*f21c469dSHubert Mazur struct clk_div_def *div; 193*f21c469dSHubert Mazur const char *dev_name; 194*f21c469dSHubert Mazur int error, dev_id; 195*f21c469dSHubert Mazur 196*f21c469dSHubert Mazur dev_name = device_def->common_def.device_name; 197*f21c469dSHubert Mazur dev_id = device_def->common_def.device_id; 198*f21c469dSHubert Mazur tbg_mux = &device_def->clk_def.cpu.tbg_mux; 199*f21c469dSHubert Mazur div = &device_def->clk_def.cpu.div; 200*f21c469dSHubert Mazur clk_mux = &device_def->clk_def.cpu.clk_mux; 201*f21c469dSHubert Mazur 202*f21c469dSHubert Mazur a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs, 203*f21c469dSHubert Mazur device_def->common_def.tbg_cnt); 204*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, tbg_mux, 205*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, MUX_POS)); 206*f21c469dSHubert Mazur if (error) 207*f21c469dSHubert Mazur goto fail; 208*f21c469dSHubert Mazur 209*f21c469dSHubert Mazur a37x0_periph_set_props(&div->clkdef, &tbg_mux->clkdef.name, 1); 210*f21c469dSHubert Mazur error = a37x0_periph_create_div(clkdom, div, 211*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, DIV1_POS)); 212*f21c469dSHubert Mazur if (error) 213*f21c469dSHubert Mazur goto fail; 214*f21c469dSHubert Mazur 215*f21c469dSHubert Mazur parent_names[0] = device_def->common_def.xtal; 216*f21c469dSHubert Mazur parent_names[1] = div->clkdef.name; 217*f21c469dSHubert Mazur 218*f21c469dSHubert Mazur a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT); 219*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, clk_mux, 220*f21c469dSHubert Mazur dev_id); 221*f21c469dSHubert Mazur 222*f21c469dSHubert Mazur fail: 223*f21c469dSHubert Mazur 224*f21c469dSHubert Mazur return (error); 225*f21c469dSHubert Mazur } 226*f21c469dSHubert Mazur 227*f21c469dSHubert Mazur /* 228*f21c469dSHubert Mazur * Register chain: mux (choose proper TBG) -> div1 (first frequency divider) -> 229*f21c469dSHubert Mazur * div2 (second frequency divider) -> mux (choose divided or xtal output). 230*f21c469dSHubert Mazur */ 231*f21c469dSHubert Mazur int 232*f21c469dSHubert Mazur a37x0_periph_d_register_mdd(struct clkdom *clkdom, 233*f21c469dSHubert Mazur struct a37x0_periph_clknode_def *device_def) 234*f21c469dSHubert Mazur { 235*f21c469dSHubert Mazur const char *parent_names[PARENT_CNT]; 236*f21c469dSHubert Mazur struct clk_mux_def *tbg_mux; 237*f21c469dSHubert Mazur struct clk_mux_def *clk_mux; 238*f21c469dSHubert Mazur struct clk_div_def *div1; 239*f21c469dSHubert Mazur struct clk_div_def *div2; 240*f21c469dSHubert Mazur const char * dev_name; 241*f21c469dSHubert Mazur int error, dev_id; 242*f21c469dSHubert Mazur 243*f21c469dSHubert Mazur dev_name = device_def->common_def.device_name; 244*f21c469dSHubert Mazur dev_id = device_def->common_def.device_id; 245*f21c469dSHubert Mazur tbg_mux = &device_def->clk_def.mdd.tbg_mux; 246*f21c469dSHubert Mazur div1 = &device_def->clk_def.mdd.div1; 247*f21c469dSHubert Mazur div2 = &device_def->clk_def.mdd.div2; 248*f21c469dSHubert Mazur clk_mux = &device_def->clk_def.mdd.clk_mux; 249*f21c469dSHubert Mazur 250*f21c469dSHubert Mazur a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs, 251*f21c469dSHubert Mazur device_def->common_def.tbg_cnt); 252*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, tbg_mux, 253*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, MUX_POS)); 254*f21c469dSHubert Mazur if (error) 255*f21c469dSHubert Mazur goto fail; 256*f21c469dSHubert Mazur 257*f21c469dSHubert Mazur a37x0_periph_set_props(&div1->clkdef, &tbg_mux->clkdef.name, 1); 258*f21c469dSHubert Mazur error = a37x0_periph_create_div(clkdom, div1, 259*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, DIV1_POS)); 260*f21c469dSHubert Mazur if (error) 261*f21c469dSHubert Mazur goto fail; 262*f21c469dSHubert Mazur 263*f21c469dSHubert Mazur a37x0_periph_set_props(&div2->clkdef, &div1->clkdef.name, 1); 264*f21c469dSHubert Mazur error = a37x0_periph_create_div(clkdom, div2, 265*f21c469dSHubert Mazur A37x0_INTERNAL_CLK_ID(dev_id, DIV2_POS)); 266*f21c469dSHubert Mazur 267*f21c469dSHubert Mazur if (error) 268*f21c469dSHubert Mazur goto fail; 269*f21c469dSHubert Mazur 270*f21c469dSHubert Mazur parent_names[0] = device_def->common_def.xtal; 271*f21c469dSHubert Mazur parent_names[1] = div2->clkdef.name; 272*f21c469dSHubert Mazur 273*f21c469dSHubert Mazur a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT); 274*f21c469dSHubert Mazur error = a37x0_periph_create_mux(clkdom, clk_mux, 275*f21c469dSHubert Mazur dev_id); 276*f21c469dSHubert Mazur if (error) 277*f21c469dSHubert Mazur goto fail; 278*f21c469dSHubert Mazur 279*f21c469dSHubert Mazur fail: 280*f21c469dSHubert Mazur 281*f21c469dSHubert Mazur return (error); 282*f21c469dSHubert Mazur } 283