Skip to content

Commit 88cedcf

Browse files
nandojvembolivar-nordic
authored andcommitted
drivers: clock: Add Atmel SAM PMC driver
Add initial version of clock control for Atmel SAM SoC series. This add support to Power Management which allows control peripherals clock. Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
1 parent 2e3d68e commit 88cedcf

File tree

13 files changed

+314
-0
lines changed

13 files changed

+314
-0
lines changed

drivers/clock_control/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF clock_cont
2121
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_DRIVER_CALIBRATION nrf_clock_calibration.c)
2222
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RV32M1_PCC clock_control_rv32m1_pcc.c)
2323
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_INFINEON_CAT1 clock_control_ifx_cat1.c)
24+
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SAM clock_control_sam_pmc.c)
2425

2526

2627
if(CONFIG_CLOCK_CONTROL_STM32_CUBE)

drivers/clock_control/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,6 @@ source "drivers/clock_control/Kconfig.aspeed"
6868

6969
source "drivers/clock_control/Kconfig.gd32"
7070

71+
source "drivers/clock_control/Kconfig.sam"
72+
7173
endif # CLOCK_CONTROL

drivers/clock_control/Kconfig.sam

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

dts/arm/atmel/sam3x.dtsi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <arm/armv7-m.dtsi>
88
#include <zephyr/dt-bindings/i2c/i2c.h>
9+
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
910

1011
/ {
1112
aliases {
@@ -28,6 +29,14 @@
2829
};
2930

3031
soc {
32+
pmc: pmc@400e0600 {
33+
compatible = "atmel,sam-pmc";
34+
reg = <0x400e0600 0x200>;
35+
interrupts = <5 0>;
36+
#clock-cells = <2>;
37+
status = "okay";
38+
};
39+
3140
sram0: memory@20070000 {
3241
compatible = "mmio-sram";
3342
reg = <0x20070000 0x18000>;

dts/arm/atmel/sam4e.dtsi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <arm/armv7-m.dtsi>
88
#include <zephyr/dt-bindings/i2c/i2c.h>
99
#include <zephyr/dt-bindings/gpio/gpio.h>
10+
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
1011

1112
/ {
1213
aliases {
@@ -37,6 +38,14 @@
3738
};
3839

3940
soc {
41+
pmc: pmc@400e0400 {
42+
compatible = "atmel,sam-pmc";
43+
reg = <0x400e0400 0x200>;
44+
interrupts = <5 0>;
45+
#clock-cells = <2>;
46+
status = "okay";
47+
};
48+
4049
sram0: memory@20000000 {
4150
compatible = "mmio-sram";
4251
};

dts/arm/atmel/sam4l.dtsi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <arm/armv7-m.dtsi>
88
#include <zephyr/dt-bindings/i2c/i2c.h>
99
#include <zephyr/dt-bindings/gpio/gpio.h>
10+
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
1011

1112
/ {
1213
chosen {
@@ -50,6 +51,14 @@
5051
};
5152

5253
soc {
54+
pmc: pmc@400e0000 {
55+
compatible = "atmel,sam-pmc";
56+
reg = <0x400e0000 0x740>;
57+
interrupts = <22 0>;
58+
#clock-cells = <2>;
59+
status = "okay";
60+
};
61+
5362
flashcalw: flash-controller@400a0000 {
5463
compatible = "atmel,sam4l-flashcalw-controller";
5564
reg = <0x400a0000 0x400>;

dts/arm/atmel/sam4s.dtsi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <zephyr/dt-bindings/i2c/i2c.h>
1010
#include <zephyr/dt-bindings/gpio/gpio.h>
1111
#include <zephyr/dt-bindings/pwm/pwm.h>
12+
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
1213

1314
/ {
1415
aliases {
@@ -39,6 +40,14 @@
3940
};
4041

4142
soc {
43+
pmc: pmc@400e0400 {
44+
compatible = "atmel,sam-pmc";
45+
reg = <0x400e0400 0x200>;
46+
interrupts = <5 0>;
47+
#clock-cells = <2>;
48+
status = "okay";
49+
};
50+
4251
sram0: memory@20100000 {
4352
compatible = "mmio-sram";
4453
};

dts/arm/atmel/same70.dtsi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <zephyr/dt-bindings/i2c/i2c.h>
1010
#include <zephyr/dt-bindings/gpio/gpio.h>
1111
#include <zephyr/dt-bindings/pwm/pwm.h>
12+
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
1213

1314
/ {
1415
aliases {
@@ -47,6 +48,14 @@
4748
};
4849

4950
soc {
51+
pmc: pmc@400e0600 {
52+
compatible = "atmel,sam-pmc";
53+
reg = <0x400e0600 0x200>;
54+
interrupts = <5 0>;
55+
#clock-cells = <2>;
56+
status = "okay";
57+
};
58+
5059
eefc: flash-controller@400e0c00 {
5160
compatible = "atmel,sam-flash-controller";
5261
reg = <0x400e0c00 0x200>;

dts/bindings/clock/atmel,sam-pmc.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
Atmel Power Management Controller (PMC)
6+
7+
The Power Management Controller (PMC) optimizes power consumption by
8+
controlling all system and user peripheral clocks. The PMC enables/disables
9+
the clock inputs to many of the peripherals and the processor.
10+
11+
To specify the clocks in a peripheral, the standard clocks property needs
12+
to be used, e.g.:
13+
14+
uart: uart@xxx {
15+
...
16+
clocks = <&pmc PMC_TYPE_PERIPHERAL p-id>;
17+
...
18+
};
19+
20+
In this example the clock-type was defined as PMC_TYPE_PERIPHERAL and the
21+
peripheral-id was defined as p-id. The p-id number should be consulted on
22+
datasheet, usually it is available at Product Mapping figure.
23+
24+
NOTE: The predefined clock type cell is defined at
25+
include/zephyr/drivers/clock_clontrol/atmel_sam_pmc.h header file.
26+
27+
The clock-type constants are:
28+
PMC_TYPE_CORE
29+
PMC_TYPE_SYSTEM
30+
PMC_TYPE_PERIPHERAL
31+
PMC_TYPE_GCK
32+
PMC_TYPE_PROGRAMMABLE
33+
34+
compatible: "atmel,sam-pmc"
35+
36+
include: [clock-controller.yaml, base.yaml]
37+
38+
properties:
39+
reg:
40+
required: true
41+
42+
"#clock-cells":
43+
const: 2
44+
description: |
45+
from common clock binding; shall be set to 2. The first entry is the type
46+
of the clock (core, system, peripheral or generated) and the second entry
47+
it's the peripheral identification index as provided by the datasheet.
48+
49+
clock-cells:
50+
- clock-type
51+
- peripheral-id

0 commit comments

Comments
 (0)