1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2021 Semihalf. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/bus.h> 30 #include <sys/kernel.h> 31 #include <sys/module.h> 32 #include <sys/mutex.h> 33 #include <sys/rman.h> 34 #include <machine/bus.h> 35 36 #include <dev/fdt/simplebus.h> 37 38 #include <dev/extres/clk/clk.h> 39 #include <dev/extres/clk/clk_fixed.h> 40 41 #include <dev/ofw/ofw_bus.h> 42 #include <dev/ofw/ofw_bus_subr.h> 43 44 #include "clkdev_if.h" 45 #include "periph.h" 46 47 #define TBG_COUNT 4 48 #define XTAL_OFW_INDEX 4 49 50 static struct resource_spec a37x0_periph_clk_spec[] = { 51 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 52 { -1, 0 } 53 }; 54 55 int 56 a37x0_periph_clk_attach(device_t dev) 57 { 58 struct a37x0_periph_clknode_def *dev_defs; 59 struct a37x0_periph_clk_softc *sc; 60 const char *tbg_clocks[5]; 61 const char *xtal_clock; 62 phandle_t node; 63 int error, i; 64 clk_t clock; 65 66 sc = device_get_softc(dev); 67 node = ofw_bus_get_node(dev); 68 sc->dev = dev; 69 70 mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); 71 72 if (bus_alloc_resources(dev, a37x0_periph_clk_spec, &sc->res) != 0) { 73 device_printf(dev, "Cannot allocate resources\n"); 74 return (ENXIO); 75 } 76 77 sc->clkdom = clkdom_create(dev); 78 if (sc->clkdom == NULL) { 79 device_printf(dev, "Cannot create clock domain\n"); 80 return (ENXIO); 81 } 82 83 for (i = 0; i < TBG_COUNT; i++){ 84 error = clk_get_by_ofw_index(dev, node, i, &clock); 85 if (error) 86 goto fail; 87 tbg_clocks[i] = clk_get_name(clock); 88 } 89 90 error = clk_get_by_ofw_index(dev, node, XTAL_OFW_INDEX, &clock); 91 if (error) 92 goto fail; 93 xtal_clock = clk_get_name(clock); 94 95 dev_defs = sc->devices; 96 97 for (i = 0; i< sc->device_count; i++) { 98 dev_defs[i].common_def.tbgs = tbg_clocks; 99 dev_defs[i].common_def.xtal = xtal_clock; 100 dev_defs[i].common_def.tbg_cnt = TBG_COUNT; 101 switch (dev_defs[i].type) { 102 case CLK_FULL_DD: 103 error = a37x0_periph_d_register_full_clk_dd( 104 sc->clkdom, &dev_defs[i]); 105 if (error) 106 goto fail; 107 break; 108 109 case CLK_FULL: 110 error = a37x0_periph_d_register_full_clk( 111 sc->clkdom, &dev_defs[i]); 112 if (error) 113 goto fail; 114 break; 115 116 case CLK_GATE: 117 error = a37x0_periph_gate_register_gate( 118 sc->clkdom, &dev_defs[i]); 119 if (error) 120 goto fail; 121 break; 122 123 case CLK_MUX_GATE: 124 error = a37x0_periph_register_mux_gate( 125 sc->clkdom, &dev_defs[i]); 126 if (error) 127 goto fail; 128 break; 129 130 case CLK_FIXED: 131 error = a37x0_periph_fixed_register_fixed( 132 sc->clkdom, &dev_defs[i]); 133 if (error) 134 goto fail; 135 break; 136 137 case CLK_CPU: 138 error = a37x0_periph_d_register_periph_cpu( 139 sc->clkdom, &dev_defs[i]); 140 if (error) 141 goto fail; 142 break; 143 144 case CLK_MDD: 145 error = a37x0_periph_d_register_mdd( 146 sc->clkdom, &dev_defs[i]); 147 if (error) 148 goto fail; 149 break; 150 151 case CLK_MUX_GATE_FIXED: 152 error = a37x0_periph_register_mux_gate_fixed( 153 sc->clkdom, &dev_defs[i]); 154 if (error) 155 goto fail; 156 break; 157 158 default: 159 return (ENXIO); 160 } 161 } 162 163 error = clkdom_finit(sc->clkdom); 164 if (error) 165 goto fail; 166 167 if (bootverbose) 168 clkdom_dump(sc->clkdom); 169 170 return (0); 171 172 fail: 173 bus_release_resources(dev, a37x0_periph_clk_spec, &sc->res); 174 175 return (error); 176 177 } 178 179 int 180 a37x0_periph_clk_read_4(device_t dev, bus_addr_t addr, uint32_t *val) 181 { 182 struct a37x0_periph_clk_softc *sc; 183 184 sc = device_get_softc(dev); 185 *val = bus_read_4(sc->res, addr); 186 187 return (0); 188 } 189 190 void 191 a37x0_periph_clk_device_lock(device_t dev) 192 { 193 struct a37x0_periph_clk_softc *sc; 194 195 sc = device_get_softc(dev); 196 mtx_lock(&sc->mtx); 197 } 198 199 void 200 a37x0_periph_clk_device_unlock(device_t dev) 201 { 202 struct a37x0_periph_clk_softc *sc; 203 204 sc = device_get_softc(dev); 205 mtx_unlock(&sc->mtx); 206 } 207 208 int 209 a37x0_periph_clk_detach(device_t dev) 210 { 211 212 return (EBUSY); 213 } 214