mirror of
https://github.com/Dasharo/zephyr.git
synced 2026-03-06 14:57:20 -08:00
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>
This commit is contained in:
committed by
Marti Bolivar
parent
2e3d68e7d5
commit
88cedcf5c5
@@ -21,6 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF clock_cont
|
||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_DRIVER_CALIBRATION nrf_clock_calibration.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RV32M1_PCC clock_control_rv32m1_pcc.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_INFINEON_CAT1 clock_control_ifx_cat1.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SAM clock_control_sam_pmc.c)
|
||||
|
||||
|
||||
if(CONFIG_CLOCK_CONTROL_STM32_CUBE)
|
||||
|
||||
@@ -68,4 +68,6 @@ source "drivers/clock_control/Kconfig.aspeed"
|
||||
|
||||
source "drivers/clock_control/Kconfig.gd32"
|
||||
|
||||
source "drivers/clock_control/Kconfig.sam"
|
||||
|
||||
endif # CLOCK_CONTROL
|
||||
|
||||
9
drivers/clock_control/Kconfig.sam
Normal file
9
drivers/clock_control/Kconfig.sam
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config CLOCK_CONTROL_SAM
|
||||
bool "Atmel SAM clock control"
|
||||
default y
|
||||
depends on DT_HAS_ATMEL_SAM_PMC_ENABLED
|
||||
help
|
||||
Enable driver for Atmel SAM Clock Control.
|
||||
150
drivers/clock_control/clock_control_sam_pmc.c
Normal file
150
drivers/clock_control/clock_control_sam_pmc.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 <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,
|
||||
};
|
||||
|
||||
static int atmel_sam_clock_control_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, atmel_sam_clock_control_init,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
|
||||
&atmel_sam_clock_control_api);
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <arm/armv7-m.dtsi>
|
||||
#include <zephyr/dt-bindings/i2c/i2c.h>
|
||||
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
@@ -28,6 +29,14 @@
|
||||
};
|
||||
|
||||
soc {
|
||||
pmc: pmc@400e0600 {
|
||||
compatible = "atmel,sam-pmc";
|
||||
reg = <0x400e0600 0x200>;
|
||||
interrupts = <5 0>;
|
||||
#clock-cells = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sram0: memory@20070000 {
|
||||
compatible = "mmio-sram";
|
||||
reg = <0x20070000 0x18000>;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <arm/armv7-m.dtsi>
|
||||
#include <zephyr/dt-bindings/i2c/i2c.h>
|
||||
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
@@ -37,6 +38,14 @@
|
||||
};
|
||||
|
||||
soc {
|
||||
pmc: pmc@400e0400 {
|
||||
compatible = "atmel,sam-pmc";
|
||||
reg = <0x400e0400 0x200>;
|
||||
interrupts = <5 0>;
|
||||
#clock-cells = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sram0: memory@20000000 {
|
||||
compatible = "mmio-sram";
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <arm/armv7-m.dtsi>
|
||||
#include <zephyr/dt-bindings/i2c/i2c.h>
|
||||
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
@@ -50,6 +51,14 @@
|
||||
};
|
||||
|
||||
soc {
|
||||
pmc: pmc@400e0000 {
|
||||
compatible = "atmel,sam-pmc";
|
||||
reg = <0x400e0000 0x740>;
|
||||
interrupts = <22 0>;
|
||||
#clock-cells = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
flashcalw: flash-controller@400a0000 {
|
||||
compatible = "atmel,sam4l-flashcalw-controller";
|
||||
reg = <0x400a0000 0x400>;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <zephyr/dt-bindings/i2c/i2c.h>
|
||||
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
@@ -39,6 +40,14 @@
|
||||
};
|
||||
|
||||
soc {
|
||||
pmc: pmc@400e0400 {
|
||||
compatible = "atmel,sam-pmc";
|
||||
reg = <0x400e0400 0x200>;
|
||||
interrupts = <5 0>;
|
||||
#clock-cells = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sram0: memory@20100000 {
|
||||
compatible = "mmio-sram";
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <zephyr/dt-bindings/i2c/i2c.h>
|
||||
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
@@ -47,6 +48,14 @@
|
||||
};
|
||||
|
||||
soc {
|
||||
pmc: pmc@400e0600 {
|
||||
compatible = "atmel,sam-pmc";
|
||||
reg = <0x400e0600 0x200>;
|
||||
interrupts = <5 0>;
|
||||
#clock-cells = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
eefc: flash-controller@400e0c00 {
|
||||
compatible = "atmel,sam-flash-controller";
|
||||
reg = <0x400e0c00 0x200>;
|
||||
|
||||
51
dts/bindings/clock/atmel,sam-pmc.yaml
Normal file
51
dts/bindings/clock/atmel,sam-pmc.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
# Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Atmel Power Management Controller (PMC)
|
||||
|
||||
The Power Management Controller (PMC) optimizes power consumption by
|
||||
controlling all system and user peripheral clocks. The PMC enables/disables
|
||||
the clock inputs to many of the peripherals and the processor.
|
||||
|
||||
To specify the clocks in a peripheral, the standard clocks property needs
|
||||
to be used, e.g.:
|
||||
|
||||
uart: uart@xxx {
|
||||
...
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL p-id>;
|
||||
...
|
||||
};
|
||||
|
||||
In this example the clock-type was defined as PMC_TYPE_PERIPHERAL and the
|
||||
peripheral-id was defined as p-id. The p-id number should be consulted on
|
||||
datasheet, usually it is available at Product Mapping figure.
|
||||
|
||||
NOTE: The predefined clock type cell is defined at
|
||||
include/zephyr/drivers/clock_clontrol/atmel_sam_pmc.h header file.
|
||||
|
||||
The clock-type constants are:
|
||||
PMC_TYPE_CORE
|
||||
PMC_TYPE_SYSTEM
|
||||
PMC_TYPE_PERIPHERAL
|
||||
PMC_TYPE_GCK
|
||||
PMC_TYPE_PROGRAMMABLE
|
||||
|
||||
compatible: "atmel,sam-pmc"
|
||||
|
||||
include: [clock-controller.yaml, base.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
"#clock-cells":
|
||||
const: 2
|
||||
description: |
|
||||
from common clock binding; shall be set to 2. The first entry is the type
|
||||
of the clock (core, system, peripheral or generated) and the second entry
|
||||
it's the peripheral identification index as provided by the datasheet.
|
||||
|
||||
clock-cells:
|
||||
- clock-type
|
||||
- peripheral-id
|
||||
37
include/zephyr/drivers/clock_control/atmel_sam_pmc.h
Normal file
37
include/zephyr/drivers/clock_control/atmel_sam_pmc.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ATMEL_SAM_PMC_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ATMEL_SAM_PMC_H_
|
||||
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
#include <zephyr/dt-bindings/clock/atmel_sam_pmc.h>
|
||||
|
||||
#define SAM_DT_PMC_CONTROLLER DEVICE_DT_GET(DT_NODELABEL(pmc))
|
||||
|
||||
struct atmel_sam_pmc_config {
|
||||
uint32_t clock_type;
|
||||
uint32_t peripheral_id;
|
||||
};
|
||||
|
||||
#define SAM_DT_CLOCK_PMC_CFG(clock_id, node_id) \
|
||||
{ \
|
||||
.clock_type = DT_CLOCKS_CELL_BY_IDX(node_id, clock_id, clock_type), \
|
||||
.peripheral_id = DT_CLOCKS_CELL_BY_IDX(node_id, clock_id, peripheral_id)\
|
||||
}
|
||||
|
||||
#define SAM_DT_INST_CLOCK_PMC_CFG(inst) SAM_DT_CLOCK_PMC_CFG(0, DT_DRV_INST(inst))
|
||||
|
||||
#define SAM_DT_CLOCKS_PMC_CFG(node_id) \
|
||||
{ \
|
||||
LISTIFY(DT_NUM_CLOCKS(node_id), \
|
||||
SAM_DT_CLOCK_PMC_CFG, (,), node_id) \
|
||||
}
|
||||
|
||||
#define SAM_DT_INST_CLOCKS_PMC_CFG(inst) \
|
||||
SAM_DT_CLOCKS_PMC_CFG(DT_DRV_INST(inst))
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ATMEL_SAM_PMC_H_ */
|
||||
16
include/zephyr/dt-bindings/clock/atmel_sam_pmc.h
Normal file
16
include/zephyr/dt-bindings/clock/atmel_sam_pmc.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ATMEL_SAM_PMC_H_
|
||||
#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ATMEL_SAM_PMC_H_
|
||||
|
||||
#define PMC_TYPE_CORE 0
|
||||
#define PMC_TYPE_SYSTEM 1
|
||||
#define PMC_TYPE_PERIPHERAL 2
|
||||
#define PMC_TYPE_GCK 3
|
||||
#define PMC_TYPE_PROGRAMMABLE 4
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ATMEL_SAM_PMC_H_ */
|
||||
@@ -10,6 +10,9 @@ if SOC_FAMILY_SAM
|
||||
config SYS_CLOCK_HW_CYCLES_PER_SEC
|
||||
default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency)
|
||||
|
||||
config CLOCK_CONTROL
|
||||
default y
|
||||
|
||||
config PINCTRL
|
||||
default y
|
||||
|
||||
|
||||
Reference in New Issue
Block a user