1*2305544bSClément Léger // SPDX-License-Identifier: BSD-2-Clause 2*2305544bSClément Léger /* 3*2305544bSClément Léger * Copyright (c) 2021, Bootlin 4*2305544bSClément Léger */ 5*2305544bSClément Léger 6*2305544bSClément Léger #include <drivers/clk.h> 7*2305544bSClément Léger #include <kernel/boot.h> 8*2305544bSClément Léger #include <kernel/panic.h> 9*2305544bSClément Léger #include <kernel/spinlock.h> 10*2305544bSClément Léger #include <libfdt.h> 11*2305544bSClément Léger #include <malloc.h> 12*2305544bSClément Léger #include <stddef.h> 13*2305544bSClément Léger 14*2305544bSClément Léger /* Global clock tree lock */ 15*2305544bSClément Léger static unsigned int clk_lock = SPINLOCK_UNLOCK; 16*2305544bSClément Léger 17*2305544bSClément Léger struct clk *clk_alloc(const char *name, const struct clk_ops *ops, 18*2305544bSClément Léger struct clk **parent_clks, size_t parent_count) 19*2305544bSClément Léger { 20*2305544bSClément Léger struct clk *clk = NULL; 21*2305544bSClément Léger size_t parent = 0; 22*2305544bSClément Léger 23*2305544bSClément Léger clk = calloc(1, sizeof(*clk) + parent_count * sizeof(clk)); 24*2305544bSClément Léger if (!clk) 25*2305544bSClément Léger return NULL; 26*2305544bSClément Léger 27*2305544bSClément Léger clk->num_parents = parent_count; 28*2305544bSClément Léger for (parent = 0; parent < parent_count; parent++) 29*2305544bSClément Léger clk->parents[parent] = parent_clks[parent]; 30*2305544bSClément Léger 31*2305544bSClément Léger clk->name = name; 32*2305544bSClément Léger clk->ops = ops; 33*2305544bSClément Léger refcount_set(&clk->enabled_count, 0); 34*2305544bSClément Léger 35*2305544bSClément Léger return clk; 36*2305544bSClément Léger } 37*2305544bSClément Léger 38*2305544bSClément Léger void clk_free(struct clk *clk) 39*2305544bSClément Léger { 40*2305544bSClément Léger free(clk); 41*2305544bSClément Léger } 42*2305544bSClément Léger 43*2305544bSClément Léger static bool __maybe_unused clk_check(struct clk *clk) 44*2305544bSClément Léger { 45*2305544bSClément Léger if (!clk->ops) 46*2305544bSClément Léger return false; 47*2305544bSClément Léger 48*2305544bSClément Léger if (clk->ops->set_parent && !clk->ops->get_parent) 49*2305544bSClément Léger return false; 50*2305544bSClément Léger 51*2305544bSClément Léger if (clk->num_parents > 1 && !clk->ops->get_parent) 52*2305544bSClément Léger return false; 53*2305544bSClément Léger 54*2305544bSClément Léger return true; 55*2305544bSClément Léger } 56*2305544bSClément Léger 57*2305544bSClément Léger static void clk_compute_rate_no_lock(struct clk *clk) 58*2305544bSClément Léger { 59*2305544bSClément Léger unsigned long parent_rate = 0; 60*2305544bSClément Léger 61*2305544bSClément Léger if (clk->parent) 62*2305544bSClément Léger parent_rate = clk->parent->rate; 63*2305544bSClément Léger 64*2305544bSClément Léger if (clk->ops->get_rate) 65*2305544bSClément Léger clk->rate = clk->ops->get_rate(clk, parent_rate); 66*2305544bSClément Léger else 67*2305544bSClément Léger clk->rate = parent_rate; 68*2305544bSClément Léger } 69*2305544bSClément Léger 70*2305544bSClément Léger struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx) 71*2305544bSClément Léger { 72*2305544bSClément Léger if (pidx >= clk->num_parents) 73*2305544bSClément Léger return NULL; 74*2305544bSClément Léger 75*2305544bSClément Léger return clk->parents[pidx]; 76*2305544bSClément Léger } 77*2305544bSClément Léger 78*2305544bSClément Léger static void clk_init_parent(struct clk *clk) 79*2305544bSClément Léger { 80*2305544bSClément Léger size_t pidx = 0; 81*2305544bSClément Léger 82*2305544bSClément Léger switch (clk->num_parents) { 83*2305544bSClément Léger case 0: 84*2305544bSClément Léger break; 85*2305544bSClément Léger case 1: 86*2305544bSClément Léger clk->parent = clk->parents[0]; 87*2305544bSClément Léger break; 88*2305544bSClément Léger default: 89*2305544bSClément Léger pidx = clk->ops->get_parent(clk); 90*2305544bSClément Léger assert(pidx < clk->num_parents); 91*2305544bSClément Léger 92*2305544bSClément Léger clk->parent = clk->parents[pidx]; 93*2305544bSClément Léger break; 94*2305544bSClément Léger } 95*2305544bSClément Léger } 96*2305544bSClément Léger 97*2305544bSClément Léger TEE_Result clk_register(struct clk *clk) 98*2305544bSClément Léger { 99*2305544bSClément Léger assert(clk_check(clk)); 100*2305544bSClément Léger 101*2305544bSClément Léger clk_init_parent(clk); 102*2305544bSClément Léger clk_compute_rate_no_lock(clk); 103*2305544bSClément Léger 104*2305544bSClément Léger DMSG("Registered clock %s, freq %lu", clk->name, clk_get_rate(clk)); 105*2305544bSClément Léger 106*2305544bSClément Léger return TEE_SUCCESS; 107*2305544bSClément Léger } 108*2305544bSClément Léger 109*2305544bSClément Léger static bool clk_is_enabled_no_lock(struct clk *clk) 110*2305544bSClément Léger { 111*2305544bSClément Léger return refcount_val(&clk->enabled_count) != 0; 112*2305544bSClément Léger } 113*2305544bSClément Léger 114*2305544bSClément Léger static void clk_disable_no_lock(struct clk *clk) 115*2305544bSClément Léger { 116*2305544bSClément Léger struct clk *parent = NULL; 117*2305544bSClément Léger 118*2305544bSClément Léger if (!refcount_dec(&clk->enabled_count)) 119*2305544bSClément Léger return; 120*2305544bSClément Léger 121*2305544bSClément Léger if (clk->ops->disable) 122*2305544bSClément Léger clk->ops->disable(clk); 123*2305544bSClément Léger 124*2305544bSClément Léger parent = clk_get_parent(clk); 125*2305544bSClément Léger if (parent) 126*2305544bSClément Léger clk_disable_no_lock(parent); 127*2305544bSClément Léger } 128*2305544bSClément Léger 129*2305544bSClément Léger static TEE_Result clk_enable_no_lock(struct clk *clk) 130*2305544bSClément Léger { 131*2305544bSClément Léger TEE_Result res = TEE_ERROR_GENERIC; 132*2305544bSClément Léger struct clk *parent = NULL; 133*2305544bSClément Léger 134*2305544bSClément Léger if (refcount_inc(&clk->enabled_count)) 135*2305544bSClément Léger return TEE_SUCCESS; 136*2305544bSClément Léger 137*2305544bSClément Léger parent = clk_get_parent(clk); 138*2305544bSClément Léger if (parent) { 139*2305544bSClément Léger res = clk_enable_no_lock(parent); 140*2305544bSClément Léger if (res) 141*2305544bSClément Léger return res; 142*2305544bSClément Léger } 143*2305544bSClément Léger 144*2305544bSClément Léger if (clk->ops->enable) { 145*2305544bSClément Léger res = clk->ops->enable(clk); 146*2305544bSClément Léger if (res) { 147*2305544bSClément Léger if (parent) 148*2305544bSClément Léger clk_disable_no_lock(parent); 149*2305544bSClément Léger 150*2305544bSClément Léger return res; 151*2305544bSClément Léger } 152*2305544bSClément Léger } 153*2305544bSClément Léger 154*2305544bSClément Léger refcount_set(&clk->enabled_count, 1); 155*2305544bSClément Léger 156*2305544bSClément Léger return TEE_SUCCESS; 157*2305544bSClément Léger } 158*2305544bSClément Léger 159*2305544bSClément Léger TEE_Result clk_enable(struct clk *clk) 160*2305544bSClément Léger { 161*2305544bSClément Léger uint32_t exceptions = 0; 162*2305544bSClément Léger TEE_Result res = TEE_ERROR_GENERIC; 163*2305544bSClément Léger 164*2305544bSClément Léger exceptions = cpu_spin_lock_xsave(&clk_lock); 165*2305544bSClément Léger res = clk_enable_no_lock(clk); 166*2305544bSClément Léger cpu_spin_unlock_xrestore(&clk_lock, exceptions); 167*2305544bSClément Léger 168*2305544bSClément Léger return res; 169*2305544bSClément Léger } 170*2305544bSClément Léger 171*2305544bSClément Léger void clk_disable(struct clk *clk) 172*2305544bSClément Léger { 173*2305544bSClément Léger uint32_t exceptions = 0; 174*2305544bSClément Léger 175*2305544bSClément Léger exceptions = cpu_spin_lock_xsave(&clk_lock); 176*2305544bSClément Léger clk_disable_no_lock(clk); 177*2305544bSClément Léger cpu_spin_unlock_xrestore(&clk_lock, exceptions); 178*2305544bSClément Léger } 179*2305544bSClément Léger 180*2305544bSClément Léger unsigned long clk_get_rate(struct clk *clk) 181*2305544bSClément Léger { 182*2305544bSClément Léger return clk->rate; 183*2305544bSClément Léger } 184*2305544bSClément Léger 185*2305544bSClément Léger static TEE_Result clk_set_rate_no_lock(struct clk *clk, unsigned long rate) 186*2305544bSClément Léger { 187*2305544bSClément Léger TEE_Result res = TEE_ERROR_GENERIC; 188*2305544bSClément Léger unsigned long parent_rate = 0; 189*2305544bSClément Léger 190*2305544bSClément Léger if (clk->parent) 191*2305544bSClément Léger parent_rate = clk_get_rate(clk->parent); 192*2305544bSClément Léger 193*2305544bSClément Léger res = clk->ops->set_rate(clk, rate, parent_rate); 194*2305544bSClément Léger if (res) 195*2305544bSClément Léger return res; 196*2305544bSClément Léger 197*2305544bSClément Léger clk_compute_rate_no_lock(clk); 198*2305544bSClément Léger 199*2305544bSClément Léger return TEE_SUCCESS; 200*2305544bSClément Léger } 201*2305544bSClément Léger 202*2305544bSClément Léger TEE_Result clk_set_rate(struct clk *clk, unsigned long rate) 203*2305544bSClément Léger { 204*2305544bSClément Léger uint32_t exceptions = 0; 205*2305544bSClément Léger TEE_Result res = TEE_ERROR_GENERIC; 206*2305544bSClément Léger 207*2305544bSClément Léger if (!clk->ops->set_rate) 208*2305544bSClément Léger return TEE_ERROR_NOT_SUPPORTED; 209*2305544bSClément Léger 210*2305544bSClément Léger exceptions = cpu_spin_lock_xsave(&clk_lock); 211*2305544bSClément Léger 212*2305544bSClément Léger if (clk->flags & CLK_SET_RATE_GATE && clk_is_enabled_no_lock(clk)) 213*2305544bSClément Léger res = TEE_ERROR_BAD_STATE; 214*2305544bSClément Léger else 215*2305544bSClément Léger res = clk_set_rate_no_lock(clk, rate); 216*2305544bSClément Léger 217*2305544bSClément Léger cpu_spin_unlock_xrestore(&clk_lock, exceptions); 218*2305544bSClément Léger 219*2305544bSClément Léger return res; 220*2305544bSClément Léger } 221*2305544bSClément Léger 222*2305544bSClément Léger struct clk *clk_get_parent(struct clk *clk) 223*2305544bSClément Léger { 224*2305544bSClément Léger return clk->parent; 225*2305544bSClément Léger } 226*2305544bSClément Léger 227*2305544bSClément Léger static TEE_Result clk_get_parent_idx(struct clk *clk, struct clk *parent, 228*2305544bSClément Léger size_t *pidx) 229*2305544bSClément Léger { 230*2305544bSClément Léger size_t i = 0; 231*2305544bSClément Léger 232*2305544bSClément Léger for (i = 0; i < clk_get_num_parents(clk); i++) { 233*2305544bSClément Léger if (clk_get_parent_by_index(clk, i) == parent) { 234*2305544bSClément Léger *pidx = i; 235*2305544bSClément Léger return TEE_SUCCESS; 236*2305544bSClément Léger } 237*2305544bSClément Léger } 238*2305544bSClément Léger EMSG("Clock %s is not a parent of clock %s", parent->name, clk->name); 239*2305544bSClément Léger 240*2305544bSClément Léger return TEE_ERROR_BAD_PARAMETERS; 241*2305544bSClément Léger } 242*2305544bSClément Léger 243*2305544bSClément Léger static TEE_Result clk_set_parent_no_lock(struct clk *clk, struct clk *parent, 244*2305544bSClément Léger size_t pidx) 245*2305544bSClément Léger { 246*2305544bSClément Léger TEE_Result res = TEE_ERROR_GENERIC; 247*2305544bSClément Léger bool was_enabled = false; 248*2305544bSClément Léger 249*2305544bSClément Léger /* Requested parent is already the one set */ 250*2305544bSClément Léger if (clk->parent == parent) 251*2305544bSClément Léger return TEE_SUCCESS; 252*2305544bSClément Léger 253*2305544bSClément Léger was_enabled = clk_is_enabled_no_lock(clk); 254*2305544bSClément Léger /* Call is needed to decrement refcount on current parent tree */ 255*2305544bSClément Léger if (was_enabled) 256*2305544bSClément Léger clk_disable_no_lock(clk); 257*2305544bSClément Léger 258*2305544bSClément Léger res = clk->ops->set_parent(clk, pidx); 259*2305544bSClément Léger if (res) 260*2305544bSClément Léger goto out; 261*2305544bSClément Léger 262*2305544bSClément Léger clk->parent = parent; 263*2305544bSClément Léger 264*2305544bSClément Léger /* The parent changed and the rate might also have changed */ 265*2305544bSClément Léger clk_compute_rate_no_lock(clk); 266*2305544bSClément Léger 267*2305544bSClément Léger out: 268*2305544bSClément Léger /* Call is needed to increment refcount on the new parent tree */ 269*2305544bSClément Léger if (was_enabled) { 270*2305544bSClément Léger res = clk_enable_no_lock(clk); 271*2305544bSClément Léger if (res) 272*2305544bSClément Léger panic("Failed to re-enable clock after setting parent"); 273*2305544bSClément Léger } 274*2305544bSClément Léger 275*2305544bSClément Léger return res; 276*2305544bSClément Léger } 277*2305544bSClément Léger 278*2305544bSClément Léger TEE_Result clk_set_parent(struct clk *clk, struct clk *parent) 279*2305544bSClément Léger { 280*2305544bSClément Léger size_t pidx = 0; 281*2305544bSClément Léger uint32_t exceptions = 0; 282*2305544bSClément Léger TEE_Result res = TEE_ERROR_GENERIC; 283*2305544bSClément Léger 284*2305544bSClément Léger if (clk_get_parent_idx(clk, parent, &pidx) || !clk->ops->set_parent) 285*2305544bSClément Léger return TEE_ERROR_BAD_PARAMETERS; 286*2305544bSClément Léger 287*2305544bSClément Léger exceptions = cpu_spin_lock_xsave(&clk_lock); 288*2305544bSClément Léger if (clk->flags & CLK_SET_PARENT_GATE && clk_is_enabled_no_lock(clk)) { 289*2305544bSClément Léger res = TEE_ERROR_BAD_STATE; 290*2305544bSClément Léger goto out; 291*2305544bSClément Léger } 292*2305544bSClément Léger 293*2305544bSClément Léger res = clk_set_parent_no_lock(clk, parent, pidx); 294*2305544bSClément Léger out: 295*2305544bSClément Léger cpu_spin_unlock_xrestore(&clk_lock, exceptions); 296*2305544bSClément Léger 297*2305544bSClément Léger return res; 298*2305544bSClément Léger } 299