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