1e37e8677SEmmanuel Vadot /*- 2e37e8677SEmmanuel Vadot * Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org> 3e37e8677SEmmanuel Vadot * 4e37e8677SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 5e37e8677SEmmanuel Vadot * modification, are permitted provided that the following conditions 6e37e8677SEmmanuel Vadot * are met: 7e37e8677SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 8e37e8677SEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 9e37e8677SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 10e37e8677SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 11e37e8677SEmmanuel Vadot * documentation and/or other materials provided with the distribution. 12e37e8677SEmmanuel Vadot * 13e37e8677SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14e37e8677SEmmanuel Vadot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15e37e8677SEmmanuel Vadot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16e37e8677SEmmanuel Vadot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17e37e8677SEmmanuel Vadot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 18e37e8677SEmmanuel Vadot * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19e37e8677SEmmanuel Vadot * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 20e37e8677SEmmanuel Vadot * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21e37e8677SEmmanuel Vadot * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22e37e8677SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23e37e8677SEmmanuel Vadot * SUCH DAMAGE. 24e37e8677SEmmanuel Vadot */ 25e37e8677SEmmanuel Vadot 26e37e8677SEmmanuel Vadot #include <sys/param.h> 27e37e8677SEmmanuel Vadot #include <sys/systm.h> 28e37e8677SEmmanuel Vadot #include <sys/bus.h> 29e37e8677SEmmanuel Vadot 30e37e8677SEmmanuel Vadot #include <dev/extres/clk/clk.h> 31e37e8677SEmmanuel Vadot 32e37e8677SEmmanuel Vadot #include <dev/clk/allwinner/aw_clk.h> 33e37e8677SEmmanuel Vadot #include <dev/clk/allwinner/aw_clk_nkmp.h> 34e37e8677SEmmanuel Vadot 35e37e8677SEmmanuel Vadot #include "clkdev_if.h" 36e37e8677SEmmanuel Vadot 37e37e8677SEmmanuel Vadot /* 38e37e8677SEmmanuel Vadot * clknode for clocks matching the formula : 39e37e8677SEmmanuel Vadot * 40e37e8677SEmmanuel Vadot * clk = (clkin * n * k) / (m * p) 41e37e8677SEmmanuel Vadot * 42e37e8677SEmmanuel Vadot */ 43e37e8677SEmmanuel Vadot 44e37e8677SEmmanuel Vadot struct aw_clk_nkmp_sc { 45e37e8677SEmmanuel Vadot uint32_t offset; 46e37e8677SEmmanuel Vadot 47e37e8677SEmmanuel Vadot struct aw_clk_factor n; 48e37e8677SEmmanuel Vadot struct aw_clk_factor k; 49e37e8677SEmmanuel Vadot struct aw_clk_factor m; 50e37e8677SEmmanuel Vadot struct aw_clk_factor p; 51e37e8677SEmmanuel Vadot 52e37e8677SEmmanuel Vadot uint32_t mux_shift; 53e37e8677SEmmanuel Vadot uint32_t mux_mask; 54e37e8677SEmmanuel Vadot uint32_t gate_shift; 55e37e8677SEmmanuel Vadot uint32_t lock_shift; 56e37e8677SEmmanuel Vadot uint32_t lock_retries; 57e37e8677SEmmanuel Vadot uint32_t update_shift; 58e37e8677SEmmanuel Vadot 59e37e8677SEmmanuel Vadot uint32_t flags; 60e37e8677SEmmanuel Vadot }; 61e37e8677SEmmanuel Vadot 62e37e8677SEmmanuel Vadot #define WRITE4(_clk, off, val) \ 63e37e8677SEmmanuel Vadot CLKDEV_WRITE_4(clknode_get_device(_clk), off, val) 64e37e8677SEmmanuel Vadot #define READ4(_clk, off, val) \ 65e37e8677SEmmanuel Vadot CLKDEV_READ_4(clknode_get_device(_clk), off, val) 66e37e8677SEmmanuel Vadot #define MODIFY4(_clk, off, clr, set ) \ 67e37e8677SEmmanuel Vadot CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set) 68e37e8677SEmmanuel Vadot #define DEVICE_LOCK(_clk) \ 69e37e8677SEmmanuel Vadot CLKDEV_DEVICE_LOCK(clknode_get_device(_clk)) 70e37e8677SEmmanuel Vadot #define DEVICE_UNLOCK(_clk) \ 71e37e8677SEmmanuel Vadot CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) 72e37e8677SEmmanuel Vadot 73e37e8677SEmmanuel Vadot static int 74e37e8677SEmmanuel Vadot aw_clk_nkmp_init(struct clknode *clk, device_t dev) 75e37e8677SEmmanuel Vadot { 76e37e8677SEmmanuel Vadot struct aw_clk_nkmp_sc *sc; 77e37e8677SEmmanuel Vadot uint32_t val, idx; 78e37e8677SEmmanuel Vadot 79e37e8677SEmmanuel Vadot sc = clknode_get_softc(clk); 80e37e8677SEmmanuel Vadot 81e37e8677SEmmanuel Vadot idx = 0; 82e37e8677SEmmanuel Vadot if ((sc->flags & AW_CLK_HAS_MUX) != 0) { 83e37e8677SEmmanuel Vadot DEVICE_LOCK(clk); 84e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 85e37e8677SEmmanuel Vadot DEVICE_UNLOCK(clk); 86e37e8677SEmmanuel Vadot 87e37e8677SEmmanuel Vadot idx = (val & sc->mux_mask) >> sc->mux_shift; 88e37e8677SEmmanuel Vadot } 89e37e8677SEmmanuel Vadot 90e37e8677SEmmanuel Vadot clknode_init_parent_idx(clk, idx); 91e37e8677SEmmanuel Vadot return (0); 92e37e8677SEmmanuel Vadot } 93e37e8677SEmmanuel Vadot 94e37e8677SEmmanuel Vadot static int 95e37e8677SEmmanuel Vadot aw_clk_nkmp_set_gate(struct clknode *clk, bool enable) 96e37e8677SEmmanuel Vadot { 97e37e8677SEmmanuel Vadot struct aw_clk_nkmp_sc *sc; 98e37e8677SEmmanuel Vadot uint32_t val; 99e37e8677SEmmanuel Vadot 100e37e8677SEmmanuel Vadot sc = clknode_get_softc(clk); 101e37e8677SEmmanuel Vadot 102e37e8677SEmmanuel Vadot if ((sc->flags & AW_CLK_HAS_GATE) == 0) 103e37e8677SEmmanuel Vadot return (0); 104e37e8677SEmmanuel Vadot 105e37e8677SEmmanuel Vadot DEVICE_LOCK(clk); 106e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 107e37e8677SEmmanuel Vadot if (enable) 108e37e8677SEmmanuel Vadot val |= (1 << sc->gate_shift); 109e37e8677SEmmanuel Vadot else 110e37e8677SEmmanuel Vadot val &= ~(1 << sc->gate_shift); 111e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 112e37e8677SEmmanuel Vadot DEVICE_UNLOCK(clk); 113e37e8677SEmmanuel Vadot 114e37e8677SEmmanuel Vadot return (0); 115e37e8677SEmmanuel Vadot } 116e37e8677SEmmanuel Vadot 117e37e8677SEmmanuel Vadot static int 118e37e8677SEmmanuel Vadot aw_clk_nkmp_set_mux(struct clknode *clk, int index) 119e37e8677SEmmanuel Vadot { 120e37e8677SEmmanuel Vadot struct aw_clk_nkmp_sc *sc; 121e37e8677SEmmanuel Vadot uint32_t val; 122e37e8677SEmmanuel Vadot 123e37e8677SEmmanuel Vadot sc = clknode_get_softc(clk); 124e37e8677SEmmanuel Vadot 125e37e8677SEmmanuel Vadot if ((sc->flags & AW_CLK_HAS_MUX) == 0) 126e37e8677SEmmanuel Vadot return (0); 127e37e8677SEmmanuel Vadot 128e37e8677SEmmanuel Vadot DEVICE_LOCK(clk); 129e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 130e37e8677SEmmanuel Vadot val &= ~sc->mux_mask; 131e37e8677SEmmanuel Vadot val |= index << sc->mux_shift; 132e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 133e37e8677SEmmanuel Vadot DEVICE_UNLOCK(clk); 134e37e8677SEmmanuel Vadot 135e37e8677SEmmanuel Vadot return (0); 136e37e8677SEmmanuel Vadot } 137e37e8677SEmmanuel Vadot 138e37e8677SEmmanuel Vadot static uint64_t 139e37e8677SEmmanuel Vadot aw_clk_nkmp_find_best(struct aw_clk_nkmp_sc *sc, uint64_t fparent, uint64_t *fout, 140e37e8677SEmmanuel Vadot uint32_t *factor_n, uint32_t *factor_k, uint32_t *factor_m, uint32_t *factor_p) 141e37e8677SEmmanuel Vadot { 142e37e8677SEmmanuel Vadot uint64_t cur, best; 143e37e8677SEmmanuel Vadot uint32_t n, k, m, p; 144e37e8677SEmmanuel Vadot 145e37e8677SEmmanuel Vadot best = 0; 146e37e8677SEmmanuel Vadot *factor_n = 0; 147e37e8677SEmmanuel Vadot *factor_k = 0; 148e37e8677SEmmanuel Vadot *factor_m = 0; 149e37e8677SEmmanuel Vadot *factor_p = 0; 150e37e8677SEmmanuel Vadot 151e37e8677SEmmanuel Vadot for (n = aw_clk_factor_get_min(&sc->n); n <= aw_clk_factor_get_max(&sc->n); ) { 152e37e8677SEmmanuel Vadot for (k = aw_clk_factor_get_min(&sc->k); k <= aw_clk_factor_get_max(&sc->k); ) { 153e37e8677SEmmanuel Vadot for (m = aw_clk_factor_get_min(&sc->m); m <= aw_clk_factor_get_max(&sc->m); ) { 154e37e8677SEmmanuel Vadot for (p = aw_clk_factor_get_min(&sc->p); p <= aw_clk_factor_get_max(&sc->p); ) { 155e37e8677SEmmanuel Vadot cur = (fparent * n * k) / (m * p); 156e37e8677SEmmanuel Vadot if ((*fout - cur) < (*fout - best)) { 157e37e8677SEmmanuel Vadot best = cur; 158e37e8677SEmmanuel Vadot *factor_n = n; 159e37e8677SEmmanuel Vadot *factor_k = k; 160e37e8677SEmmanuel Vadot *factor_m = m; 161e37e8677SEmmanuel Vadot *factor_p = p; 162e37e8677SEmmanuel Vadot } 163e37e8677SEmmanuel Vadot if (best == *fout) 164e37e8677SEmmanuel Vadot return (best); 165e37e8677SEmmanuel Vadot if ((sc->p.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) 166e37e8677SEmmanuel Vadot p <<= 1; 167e37e8677SEmmanuel Vadot else 168e37e8677SEmmanuel Vadot p++; 169e37e8677SEmmanuel Vadot } 170e37e8677SEmmanuel Vadot if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) 171e37e8677SEmmanuel Vadot m <<= 1; 172e37e8677SEmmanuel Vadot else 173e37e8677SEmmanuel Vadot m++; 174e37e8677SEmmanuel Vadot } 175e37e8677SEmmanuel Vadot if ((sc->k.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) 176e37e8677SEmmanuel Vadot k <<= 1; 177e37e8677SEmmanuel Vadot else 178e37e8677SEmmanuel Vadot k++; 179e37e8677SEmmanuel Vadot } 180e37e8677SEmmanuel Vadot if ((sc->n.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0) 181e37e8677SEmmanuel Vadot n <<= 1; 182e37e8677SEmmanuel Vadot else 183e37e8677SEmmanuel Vadot n++; 184e37e8677SEmmanuel Vadot } 185e37e8677SEmmanuel Vadot 186e37e8677SEmmanuel Vadot return best; 187e37e8677SEmmanuel Vadot } 188e37e8677SEmmanuel Vadot 189e37e8677SEmmanuel Vadot static void 190e37e8677SEmmanuel Vadot aw_clk_nkmp_set_freq_scale(struct clknode *clk, struct aw_clk_nkmp_sc *sc, 191e37e8677SEmmanuel Vadot uint32_t factor_n, uint32_t factor_k, uint32_t factor_m, uint32_t factor_p) 192e37e8677SEmmanuel Vadot { 193e37e8677SEmmanuel Vadot uint32_t val, m, p; 194e37e8677SEmmanuel Vadot int retry; 195e37e8677SEmmanuel Vadot 196e37e8677SEmmanuel Vadot DEVICE_LOCK(clk); 197e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 198e37e8677SEmmanuel Vadot 199e37e8677SEmmanuel Vadot m = aw_clk_get_factor(val, &sc->m); 200e37e8677SEmmanuel Vadot p = aw_clk_get_factor(val, &sc->p); 201e37e8677SEmmanuel Vadot 202e37e8677SEmmanuel Vadot if (p < factor_p) { 203e37e8677SEmmanuel Vadot val &= ~sc->p.mask; 204e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->p, factor_p) << sc->p.shift; 205e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 206e37e8677SEmmanuel Vadot DELAY(2000); 207e37e8677SEmmanuel Vadot } 208e37e8677SEmmanuel Vadot 209e37e8677SEmmanuel Vadot if (m < factor_m) { 210e37e8677SEmmanuel Vadot val &= ~sc->m.mask; 211e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->m, factor_m) << sc->m.shift; 212e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 213e37e8677SEmmanuel Vadot DELAY(2000); 214e37e8677SEmmanuel Vadot } 215e37e8677SEmmanuel Vadot 216e37e8677SEmmanuel Vadot val &= ~sc->n.mask; 217e37e8677SEmmanuel Vadot val &= ~sc->k.mask; 218e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->n, factor_n) << sc->n.shift; 219e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->k, factor_k) << sc->k.shift; 220e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 221e37e8677SEmmanuel Vadot DELAY(2000); 222e37e8677SEmmanuel Vadot 223e37e8677SEmmanuel Vadot if (m > factor_m) { 224e37e8677SEmmanuel Vadot val &= ~sc->m.mask; 225e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->m, factor_m) << sc->m.shift; 226e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 227e37e8677SEmmanuel Vadot DELAY(2000); 228e37e8677SEmmanuel Vadot } 229e37e8677SEmmanuel Vadot 230e37e8677SEmmanuel Vadot if (p > factor_p) { 231e37e8677SEmmanuel Vadot val &= ~sc->p.mask; 232e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->p, factor_p) << sc->p.shift; 233e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 234e37e8677SEmmanuel Vadot DELAY(2000); 235e37e8677SEmmanuel Vadot } 236e37e8677SEmmanuel Vadot 237e37e8677SEmmanuel Vadot if ((sc->flags & AW_CLK_HAS_LOCK) != 0) { 238e37e8677SEmmanuel Vadot for (retry = 0; retry < sc->lock_retries; retry++) { 239e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 240e37e8677SEmmanuel Vadot if ((val & (1 << sc->lock_shift)) != 0) 241e37e8677SEmmanuel Vadot break; 242e37e8677SEmmanuel Vadot DELAY(1000); 243e37e8677SEmmanuel Vadot } 244e37e8677SEmmanuel Vadot } 245e37e8677SEmmanuel Vadot 246e37e8677SEmmanuel Vadot DEVICE_UNLOCK(clk); 247e37e8677SEmmanuel Vadot } 248e37e8677SEmmanuel Vadot 249e37e8677SEmmanuel Vadot static int 250e37e8677SEmmanuel Vadot aw_clk_nkmp_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout, 251e37e8677SEmmanuel Vadot int flags, int *stop) 252e37e8677SEmmanuel Vadot { 253e37e8677SEmmanuel Vadot struct aw_clk_nkmp_sc *sc; 254e37e8677SEmmanuel Vadot uint64_t best; 255e37e8677SEmmanuel Vadot uint32_t val, best_n, best_k, best_m, best_p; 256e37e8677SEmmanuel Vadot int retry; 257e37e8677SEmmanuel Vadot 258e37e8677SEmmanuel Vadot sc = clknode_get_softc(clk); 259e37e8677SEmmanuel Vadot 260e37e8677SEmmanuel Vadot best = aw_clk_nkmp_find_best(sc, fparent, fout, 261e37e8677SEmmanuel Vadot &best_n, &best_k, &best_m, &best_p); 262e37e8677SEmmanuel Vadot if ((flags & CLK_SET_DRYRUN) != 0) { 263e37e8677SEmmanuel Vadot *fout = best; 264e37e8677SEmmanuel Vadot *stop = 1; 265e37e8677SEmmanuel Vadot return (0); 266e37e8677SEmmanuel Vadot } 267e37e8677SEmmanuel Vadot 268e37e8677SEmmanuel Vadot if ((best < *fout) && 269e37e8677SEmmanuel Vadot ((flags & CLK_SET_ROUND_DOWN) != 0)) { 270e37e8677SEmmanuel Vadot *stop = 1; 271e37e8677SEmmanuel Vadot return (ERANGE); 272e37e8677SEmmanuel Vadot } 273e37e8677SEmmanuel Vadot if ((best > *fout) && 274e37e8677SEmmanuel Vadot ((flags & CLK_SET_ROUND_UP) != 0)) { 275e37e8677SEmmanuel Vadot *stop = 1; 276e37e8677SEmmanuel Vadot return (ERANGE); 277e37e8677SEmmanuel Vadot } 278e37e8677SEmmanuel Vadot 279e37e8677SEmmanuel Vadot if ((sc->flags & AW_CLK_SCALE_CHANGE) != 0) 280e37e8677SEmmanuel Vadot aw_clk_nkmp_set_freq_scale(clk, sc, 281e37e8677SEmmanuel Vadot best_n, best_k, best_m, best_p); 282e37e8677SEmmanuel Vadot else { 283e37e8677SEmmanuel Vadot DEVICE_LOCK(clk); 284e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 285e37e8677SEmmanuel Vadot val &= ~sc->n.mask; 286e37e8677SEmmanuel Vadot val &= ~sc->k.mask; 287e37e8677SEmmanuel Vadot val &= ~sc->m.mask; 288e37e8677SEmmanuel Vadot val &= ~sc->p.mask; 289e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->n, best_n) << sc->n.shift; 290e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->k, best_k) << sc->k.shift; 291e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->m, best_m) << sc->m.shift; 292e37e8677SEmmanuel Vadot val |= aw_clk_factor_get_value(&sc->p, best_p) << sc->p.shift; 293e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 294e37e8677SEmmanuel Vadot DELAY(2000); 295e37e8677SEmmanuel Vadot DEVICE_UNLOCK(clk); 296e37e8677SEmmanuel Vadot 297e37e8677SEmmanuel Vadot if ((sc->flags & AW_CLK_HAS_UPDATE) != 0) { 298e37e8677SEmmanuel Vadot DEVICE_LOCK(clk); 299e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 300e37e8677SEmmanuel Vadot val |= 1 << sc->update_shift; 301e37e8677SEmmanuel Vadot WRITE4(clk, sc->offset, val); 302e37e8677SEmmanuel Vadot DELAY(2000); 303e37e8677SEmmanuel Vadot DEVICE_UNLOCK(clk); 304e37e8677SEmmanuel Vadot } 305e37e8677SEmmanuel Vadot 306e37e8677SEmmanuel Vadot if ((sc->flags & AW_CLK_HAS_LOCK) != 0) { 307e37e8677SEmmanuel Vadot for (retry = 0; retry < sc->lock_retries; retry++) { 308e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 309e37e8677SEmmanuel Vadot if ((val & (1 << sc->lock_shift)) != 0) 310e37e8677SEmmanuel Vadot break; 311e37e8677SEmmanuel Vadot DELAY(1000); 312e37e8677SEmmanuel Vadot } 313e37e8677SEmmanuel Vadot } 314e37e8677SEmmanuel Vadot } 315e37e8677SEmmanuel Vadot 316e37e8677SEmmanuel Vadot *fout = best; 317e37e8677SEmmanuel Vadot *stop = 1; 318e37e8677SEmmanuel Vadot 319e37e8677SEmmanuel Vadot return (0); 320e37e8677SEmmanuel Vadot } 321e37e8677SEmmanuel Vadot 322e37e8677SEmmanuel Vadot static int 323e37e8677SEmmanuel Vadot aw_clk_nkmp_recalc(struct clknode *clk, uint64_t *freq) 324e37e8677SEmmanuel Vadot { 325e37e8677SEmmanuel Vadot struct aw_clk_nkmp_sc *sc; 326e37e8677SEmmanuel Vadot uint32_t val, m, n, k, p; 327e37e8677SEmmanuel Vadot 328e37e8677SEmmanuel Vadot sc = clknode_get_softc(clk); 329e37e8677SEmmanuel Vadot 330e37e8677SEmmanuel Vadot DEVICE_LOCK(clk); 331e37e8677SEmmanuel Vadot READ4(clk, sc->offset, &val); 332e37e8677SEmmanuel Vadot DEVICE_UNLOCK(clk); 333e37e8677SEmmanuel Vadot 334e37e8677SEmmanuel Vadot n = aw_clk_get_factor(val, &sc->n); 335e37e8677SEmmanuel Vadot k = aw_clk_get_factor(val, &sc->k); 336e37e8677SEmmanuel Vadot m = aw_clk_get_factor(val, &sc->m); 337e37e8677SEmmanuel Vadot p = aw_clk_get_factor(val, &sc->p); 338e37e8677SEmmanuel Vadot 339e37e8677SEmmanuel Vadot *freq = (*freq * n * k) / (m * p); 340e37e8677SEmmanuel Vadot 341e37e8677SEmmanuel Vadot return (0); 342e37e8677SEmmanuel Vadot } 343e37e8677SEmmanuel Vadot 344e37e8677SEmmanuel Vadot static clknode_method_t aw_nkmp_clknode_methods[] = { 345e37e8677SEmmanuel Vadot /* Device interface */ 346e37e8677SEmmanuel Vadot CLKNODEMETHOD(clknode_init, aw_clk_nkmp_init), 347e37e8677SEmmanuel Vadot CLKNODEMETHOD(clknode_set_gate, aw_clk_nkmp_set_gate), 348e37e8677SEmmanuel Vadot CLKNODEMETHOD(clknode_set_mux, aw_clk_nkmp_set_mux), 349e37e8677SEmmanuel Vadot CLKNODEMETHOD(clknode_recalc_freq, aw_clk_nkmp_recalc), 350e37e8677SEmmanuel Vadot CLKNODEMETHOD(clknode_set_freq, aw_clk_nkmp_set_freq), 351e37e8677SEmmanuel Vadot CLKNODEMETHOD_END 352e37e8677SEmmanuel Vadot }; 353e37e8677SEmmanuel Vadot 354e37e8677SEmmanuel Vadot DEFINE_CLASS_1(aw_nkmp_clknode, aw_nkmp_clknode_class, aw_nkmp_clknode_methods, 355e37e8677SEmmanuel Vadot sizeof(struct aw_clk_nkmp_sc), clknode_class); 356e37e8677SEmmanuel Vadot 357e37e8677SEmmanuel Vadot int 358e37e8677SEmmanuel Vadot aw_clk_nkmp_register(struct clkdom *clkdom, struct aw_clk_nkmp_def *clkdef) 359e37e8677SEmmanuel Vadot { 360e37e8677SEmmanuel Vadot struct clknode *clk; 361e37e8677SEmmanuel Vadot struct aw_clk_nkmp_sc *sc; 362e37e8677SEmmanuel Vadot 363e37e8677SEmmanuel Vadot clk = clknode_create(clkdom, &aw_nkmp_clknode_class, &clkdef->clkdef); 364e37e8677SEmmanuel Vadot if (clk == NULL) 365e37e8677SEmmanuel Vadot return (1); 366e37e8677SEmmanuel Vadot 367e37e8677SEmmanuel Vadot sc = clknode_get_softc(clk); 368e37e8677SEmmanuel Vadot 369e37e8677SEmmanuel Vadot sc->offset = clkdef->offset; 370e37e8677SEmmanuel Vadot 371e37e8677SEmmanuel Vadot sc->n.shift = clkdef->n.shift; 372e37e8677SEmmanuel Vadot sc->n.width = clkdef->n.width; 373e37e8677SEmmanuel Vadot sc->n.mask = ((1 << clkdef->n.width) - 1) << sc->n.shift; 374e37e8677SEmmanuel Vadot sc->n.value = clkdef->n.value; 375e37e8677SEmmanuel Vadot sc->n.flags = clkdef->n.flags; 376e37e8677SEmmanuel Vadot 377e37e8677SEmmanuel Vadot sc->k.shift = clkdef->k.shift; 378e37e8677SEmmanuel Vadot sc->k.width = clkdef->k.width; 379e37e8677SEmmanuel Vadot sc->k.mask = ((1 << clkdef->k.width) - 1) << sc->k.shift; 380e37e8677SEmmanuel Vadot sc->k.value = clkdef->k.value; 381e37e8677SEmmanuel Vadot sc->k.flags = clkdef->k.flags; 382e37e8677SEmmanuel Vadot 383e37e8677SEmmanuel Vadot sc->m.shift = clkdef->m.shift; 384e37e8677SEmmanuel Vadot sc->m.width = clkdef->m.width; 385e37e8677SEmmanuel Vadot sc->m.mask = ((1 << clkdef->m.width) - 1) << sc->m.shift; 386e37e8677SEmmanuel Vadot sc->m.value = clkdef->m.value; 387e37e8677SEmmanuel Vadot sc->m.flags = clkdef->m.flags; 388e37e8677SEmmanuel Vadot 389e37e8677SEmmanuel Vadot sc->p.shift = clkdef->p.shift; 390e37e8677SEmmanuel Vadot sc->p.width = clkdef->p.width; 391e37e8677SEmmanuel Vadot sc->p.mask = ((1 << clkdef->p.width) - 1) << sc->p.shift; 392e37e8677SEmmanuel Vadot sc->p.value = clkdef->p.value; 393e37e8677SEmmanuel Vadot sc->p.flags = clkdef->p.flags; 394e37e8677SEmmanuel Vadot 395e37e8677SEmmanuel Vadot sc->mux_shift = clkdef->mux_shift; 396e37e8677SEmmanuel Vadot sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift; 397e37e8677SEmmanuel Vadot 398e37e8677SEmmanuel Vadot sc->gate_shift = clkdef->gate_shift; 399e37e8677SEmmanuel Vadot sc->lock_shift = clkdef->lock_shift; 400e37e8677SEmmanuel Vadot sc->lock_retries = clkdef->lock_retries; 401e37e8677SEmmanuel Vadot sc->update_shift = clkdef->update_shift; 402e37e8677SEmmanuel Vadot sc->flags = clkdef->flags; 403e37e8677SEmmanuel Vadot 404e37e8677SEmmanuel Vadot clknode_register(clkdom, clk); 405e37e8677SEmmanuel Vadot 406e37e8677SEmmanuel Vadot return (0); 407e37e8677SEmmanuel Vadot } 408