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 static unsigned long clk_plldiv_get_rate(struct clk *clk, 16 unsigned long parent_rate) 17 { 18 struct pmc_data *pmc = clk->priv; 19 unsigned int mckr = io_read32(pmc->base + AT91_PMC_MCKR); 20 21 if (mckr & AT91_PMC_PLLADIV2) 22 return parent_rate / 2; 23 24 return parent_rate; 25 } 26 27 static TEE_Result clk_plldiv_set_rate(struct clk *clk, unsigned long rate, 28 unsigned long parent_rate) 29 { 30 struct pmc_data *pmc = clk->priv; 31 32 if (parent_rate != rate && (parent_rate / 2 != rate)) 33 return TEE_ERROR_GENERIC; 34 35 io_clrsetbits32(pmc->base + AT91_PMC_MCKR, AT91_PMC_PLLADIV2, 36 parent_rate != rate ? AT91_PMC_PLLADIV2 : 0); 37 38 return TEE_SUCCESS; 39 } 40 41 static const struct clk_ops plldiv_ops = { 42 .get_rate = clk_plldiv_get_rate, 43 .set_rate = clk_plldiv_set_rate, 44 }; 45 46 struct clk * 47 at91_clk_register_plldiv(struct pmc_data *pmc, const char *name, 48 struct clk *parent) 49 { 50 struct clk *clk = NULL; 51 52 clk = clk_alloc(name, &plldiv_ops, &parent, 1); 53 if (!clk) 54 return NULL; 55 56 clk->priv = pmc; 57 clk->flags = CLK_SET_RATE_GATE; 58 59 if (clk_register(clk)) { 60 clk_free(clk); 61 return NULL; 62 } 63 64 return clk; 65 } 66