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
is_pck(int id)24 static bool is_pck(int id)
25 {
26 return (id >= 8) && (id <= 15);
27 }
28
clk_system_ready(vaddr_t base,int id)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
clk_system_enable(struct clk * clk)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
clk_system_disable(struct clk * clk)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 *
at91_clk_register_system(struct pmc_data * pmc,const char * name,struct clk * parent,uint8_t id)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