1 // SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause 2 /* 3 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 4 * Copyright (C) 2021 Microchip 5 */ 6 7 #include <io.h> 8 #include <kernel/delay.h> 9 #include <kernel/panic.h> 10 #include <mm/core_memprot.h> 11 #include <types_ext.h> 12 13 #include "at91_clk.h" 14 15 #define SYSTEM_MAX_ID 31 16 17 #define SYSTEM_MAX_NAME_SZ 32 18 19 struct clk_system { 20 vaddr_t base; 21 uint8_t id; 22 }; 23 24 static bool is_pck(int id) 25 { 26 return (id >= 8) && (id <= 15); 27 } 28 29 static bool clk_system_ready(vaddr_t base, int id) 30 { 31 uint32_t status = io_read32(base + AT91_PMC_SR); 32 33 return status & BIT(id); 34 } 35 36 static TEE_Result clk_system_enable(struct clk *clk) 37 { 38 struct clk_system *sys = clk->priv; 39 40 io_write32(sys->base + AT91_PMC_SCER, 1 << sys->id); 41 42 if (!is_pck(sys->id)) 43 return TEE_SUCCESS; 44 45 while (!clk_system_ready(sys->base, sys->id)) 46 ; 47 48 return TEE_SUCCESS; 49 } 50 51 static void clk_system_disable(struct clk *clk) 52 { 53 struct clk_system *sys = clk->priv; 54 55 io_write32(sys->base + AT91_PMC_SCDR, 1 << sys->id); 56 } 57 58 static const struct clk_ops system_ops = { 59 .enable = clk_system_enable, 60 .disable = clk_system_disable, 61 }; 62 63 struct clk * 64 at91_clk_register_system(struct pmc_data *pmc, const char *name, 65 struct clk *parent, uint8_t id) 66 { 67 struct clk_system *sys = NULL; 68 struct clk *clk = NULL; 69 70 if (!parent || id > SYSTEM_MAX_ID) 71 return NULL; 72 73 clk = clk_alloc(name, &system_ops, &parent, 1); 74 if (!clk) 75 return NULL; 76 77 sys = calloc(1, sizeof(*sys)); 78 if (!sys) { 79 clk_free(clk); 80 return NULL; 81 } 82 83 sys->id = id; 84 sys->base = pmc->base; 85 86 clk->priv = sys; 87 88 if (clk_register(clk)) { 89 clk_free(clk); 90 free(sys); 91 return NULL; 92 } 93 94 return clk; 95 } 96