-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
clock_control_sam_pmc.c
141 lines (110 loc) · 3.29 KB
/
clock_control_sam_pmc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT atmel_sam_pmc
#include <stdint.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/atmel_sam_pmc.h>
#include <soc.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
static int atmel_sam_clock_control_on(const struct device *dev,
clock_control_subsys_t sys)
{
ARG_UNUSED(dev);
const struct atmel_sam_pmc_config *cfg = (const struct atmel_sam_pmc_config *)sys;
if (cfg == NULL) {
LOG_ERR("The PMC config can not be NULL.");
return -ENXIO;
}
LOG_DBG("Type: %x, Id: %d", cfg->clock_type, cfg->peripheral_id);
switch (cfg->clock_type) {
case PMC_TYPE_PERIPHERAL:
soc_pmc_peripheral_enable(cfg->peripheral_id);
break;
default:
LOG_ERR("The PMC clock type is not implemented.");
return -ENODEV;
}
return 0;
}
static int atmel_sam_clock_control_off(const struct device *dev,
clock_control_subsys_t sys)
{
ARG_UNUSED(dev);
const struct atmel_sam_pmc_config *cfg = (const struct atmel_sam_pmc_config *)sys;
if (cfg == NULL) {
LOG_ERR("The PMC config can not be NULL.");
return -ENXIO;
}
LOG_DBG("Type: %x, Id: %d", cfg->clock_type, cfg->peripheral_id);
switch (cfg->clock_type) {
case PMC_TYPE_PERIPHERAL:
soc_pmc_peripheral_disable(cfg->peripheral_id);
break;
default:
LOG_ERR("The PMC clock type is not implemented.");
return -ENODEV;
}
return 0;
}
static int atmel_sam_clock_control_get_rate(const struct device *dev,
clock_control_subsys_t sys,
uint32_t *rate)
{
ARG_UNUSED(dev);
const struct atmel_sam_pmc_config *cfg = (const struct atmel_sam_pmc_config *)sys;
if (cfg == NULL) {
LOG_ERR("The PMC config can not be NULL.");
return -ENXIO;
}
LOG_DBG("Type: %x, Id: %d", cfg->clock_type, cfg->peripheral_id);
switch (cfg->clock_type) {
case PMC_TYPE_PERIPHERAL:
*rate = SOC_ATMEL_SAM_MCK_FREQ_HZ;
break;
default:
LOG_ERR("The PMC clock type is not implemented.");
return -ENODEV;
}
LOG_DBG("Rate: %d", *rate);
return 0;
}
static enum clock_control_status
atmel_sam_clock_control_get_status(const struct device *dev,
clock_control_subsys_t sys)
{
ARG_UNUSED(dev);
const struct atmel_sam_pmc_config *cfg = (const struct atmel_sam_pmc_config *)sys;
enum clock_control_status status;
if (cfg == NULL) {
LOG_ERR("The PMC config can not be NULL.");
return -ENXIO;
}
LOG_DBG("Type: %x, Id: %d", cfg->clock_type, cfg->peripheral_id);
switch (cfg->clock_type) {
case PMC_TYPE_PERIPHERAL:
status = soc_pmc_peripheral_is_enabled(cfg->peripheral_id) > 0
? CLOCK_CONTROL_STATUS_ON
: CLOCK_CONTROL_STATUS_OFF;
break;
default:
LOG_ERR("The PMC clock type is not implemented.");
return -ENODEV;
}
return status;
}
static struct clock_control_driver_api atmel_sam_clock_control_api = {
.on = atmel_sam_clock_control_on,
.off = atmel_sam_clock_control_off,
.get_rate = atmel_sam_clock_control_get_rate,
.get_status = atmel_sam_clock_control_get_status,
};
DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, PRE_KERNEL_1,
CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
&atmel_sam_clock_control_api);