Browse Source

drivers: clock control: Initial support for RZ/A2M

Add clock control support for RZ/A2M

Signed-off-by: Hoang Nguyen <hoang.nguyen.jx@bp.renesas.com>
Signed-off-by: Binh Nguyen <binh.nguyen.xw@renesas.com>
pull/89093/head
Hoang Nguyen 3 months ago committed by Benjamin Cabé
parent
commit
1b8c77e4de
  1. 5
      drivers/clock_control/CMakeLists.txt
  2. 9
      drivers/clock_control/Kconfig.renesas_rz_cpg
  3. 112
      drivers/clock_control/clock_control_renesas_rza2m_cpg.c
  4. 438
      drivers/clock_control/clock_control_renesas_rza2m_cpg_lld.c
  5. 255
      drivers/clock_control/clock_control_renesas_rza2m_cpg_lld.h
  6. 23
      dts/arm/renesas/rz/rza/r7s9210.dtsi
  7. 7
      dts/bindings/clock/renesas,rza2m-cpg.yaml
  8. 78
      include/zephyr/dt-bindings/clock/renesas_rza2m_clock.h

5
drivers/clock_control/CMakeLists.txt

@ -52,6 +52,11 @@ if(CONFIG_CLOCK_CONTROL_NRF2) @@ -52,6 +52,11 @@ if(CONFIG_CLOCK_CONTROL_NRF2)
zephyr_library_sources(clock_control_nrf2_lfclk.c)
endif()
if(CONFIG_CLOCK_CONTROL_RENESAS_RZA2M_CPG)
zephyr_library_sources(clock_control_renesas_rza2m_cpg.c)
zephyr_library_sources(clock_control_renesas_rza2m_cpg_lld.c)
endif()
if(CONFIG_CLOCK_CONTROL_STM32_CUBE)
zephyr_library_sources_ifdef(CONFIG_CLOCK_STM32_MUX clock_stm32_mux.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_STM32_MCO clock_stm32_mco.c)

9
drivers/clock_control/Kconfig.renesas_rz_cpg

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
# Copyright (c) 2024 Renesas Electronics Corporation
# Copyright (c) 2024-2025 Renesas Electronics Corporation
# SPDX-License-Identifier: Apache-2.0
config CLOCK_CONTROL_RENESAS_RZ_CPG
@ -10,3 +10,10 @@ config CLOCK_CONTROL_RENESAS_RZ_CPG @@ -10,3 +10,10 @@ config CLOCK_CONTROL_RENESAS_RZ_CPG
Enable support for Renesas RZ CPG Clock Pulse Generator (CPG) driver.
The CPG driver supports only module's clocks.
The PLLs and core clocks are not configured by the CPG driver.
config CLOCK_CONTROL_RENESAS_RZA2M_CPG
bool "Renesas RZ/A2M Clock Control Driver"
default y
depends on DT_HAS_RENESAS_RZA2M_CPG_ENABLED
help
Enable support for Renesas RZ/A2M CPG Clock Pulse Generator (CPG) driver.

112
drivers/clock_control/clock_control_renesas_rza2m_cpg.c

@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT renesas_rza2m_cpg
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/clock_control.h>
#include "clock_control_renesas_rza2m_cpg_lld.h"
static int clock_control_renesas_rza2m_on_off(const struct device *dev, clock_control_subsys_t sys,
bool enable)
{
if (!dev || !sys) {
return -EINVAL;
}
int ret = -EINVAL;
uint32_t *clock_id = (uint32_t *)sys;
uint32_t clk_module = RZA2M_GET_MODULE(*clock_id);
ret = rza2m_cpg_mstp_clock_endisable(dev, clk_module, enable);
return ret;
}
static int clock_control_renesas_rza2m_on(const struct device *dev, clock_control_subsys_t sys)
{
/* Enable the specified clock */
return clock_control_renesas_rza2m_on_off(dev, sys, true);
}
static int clock_control_renesas_rza2m_off(const struct device *dev, clock_control_subsys_t sys)
{
/* Disable the specified clock */
return clock_control_renesas_rza2m_on_off(dev, sys, false);
}
static int clock_control_renesas_rza2m_get_rate(const struct device *dev,
clock_control_subsys_t sys, uint32_t *rate)
{
if (!dev || !sys || !rate) {
return -EINVAL;
}
int ret = -EINVAL;
uint32_t *clock_id = (uint32_t *)sys;
enum rza2m_cpg_get_freq_src clk_src = RZA2M_GET_CLOCK_SRC(*clock_id);
ret = rza2m_cpg_get_clock(dev, clk_src, rate);
return ret;
}
static int clock_control_renesas_rza2m_set_rate(const struct device *dev,
clock_control_subsys_t sys,
clock_control_subsys_rate_t rate)
{
int ret;
enum rza2m_cp_sub_clock clock_name = (enum rza2m_cp_sub_clock)sys;
uint32_t clock_rate = (uint32_t)rate;
ret = rza2m_cpg_set_sub_clock_divider(dev, clock_name, clock_rate);
return ret;
}
static int clock_control_renesas_rza2m_init(const struct device *dev)
{
const struct rza2m_cpg_clock_config *config = dev->config;
uint16_t reg_val;
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
rza2m_cpg_calculate_pll_frequency(dev);
/* Select Bφ Clock output for CLKIO */
sys_write16(0, CPG_REG_ADDR(CPG_CKIOSEL_OFFSET));
/* Enable CLKIO as Low-level output */
reg_val = sys_read16(CPG_REG_ADDR(CPG_FRQCR_OFFSET));
reg_val &= ~(CPG_FRQCR_CKOEN | CPG_FRQCR_CKOEN2);
reg_val |= (1U << CPG_FRQCR_CKOEN_SHIFT) | (1U << CPG_FRQCR_CKOEN2_SHIFT);
sys_write16(reg_val, CPG_REG_ADDR(CPG_FRQCR_OFFSET));
rza2m_cpg_set_sub_clock_divider(dev, CPG_SUB_CLOCK_ICLK, config->cpg_iclk_freq_hz_cfg);
rza2m_cpg_set_sub_clock_divider(dev, CPG_SUB_CLOCK_BCLK, config->cpg_bclk_freq_hz_cfg);
rza2m_cpg_set_sub_clock_divider(dev, CPG_SUB_CLOCK_P1CLK, config->cpg_p1clk_freq_hz_cfg);
return 0;
}
static DEVICE_API(clock_control, rza2m_clock_control_driver_api) = {
.on = clock_control_renesas_rza2m_on,
.off = clock_control_renesas_rza2m_off,
.get_rate = clock_control_renesas_rza2m_get_rate,
.set_rate = clock_control_renesas_rza2m_set_rate,
};
static const struct rza2m_cpg_clock_config g_rza2m_cpg_clock_config = {
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(0)),
.cpg_extal_freq_hz_cfg = DT_INST_PROP_BY_PHANDLE(0, clocks, clock_frequency),
.cpg_iclk_freq_hz_cfg = DT_PROP(DT_NODELABEL(iclk), clock_frequency),
.cpg_bclk_freq_hz_cfg = DT_PROP(DT_NODELABEL(bclk), clock_frequency),
.cpg_p1clk_freq_hz_cfg = DT_PROP(DT_NODELABEL(p1clk), clock_frequency),
};
static struct rza2m_cpg_clock_data g_rza2m_cpg_clock_data;
DEVICE_DT_INST_DEFINE(0, clock_control_renesas_rza2m_init, NULL, &g_rza2m_cpg_clock_data,
&g_rza2m_cpg_clock_config, PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
&rza2m_clock_control_driver_api);

438
drivers/clock_control/clock_control_renesas_rza2m_cpg_lld.c

@ -0,0 +1,438 @@ @@ -0,0 +1,438 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/kernel.h>
#include <zephyr/arch/cpu.h>
#include "clock_control_renesas_rza2m_cpg_lld.h"
static const struct rza2m_stb_module_info gs_stbcr[] = {
{MODULE_CORESIGHT, STBCR2_OFFSET, CPG_STBCR2_MSTP20},
{MODULE_OSTM0, STBCR3_OFFSET, CPG_STBCR3_MSTP36},
{MODULE_OSTM1, STBCR3_OFFSET, CPG_STBCR3_MSTP35},
{MODULE_OSTM2, STBCR3_OFFSET, CPG_STBCR3_MSTP34},
{MODULE_MTU3, STBCR3_OFFSET, CPG_STBCR3_MSTP33},
{MODULE_CANFD, STBCR3_OFFSET, CPG_STBCR3_MSTP32},
{MODULE_ADC, STBCR5_OFFSET, CPG_STBCR5_MSTP57},
{MODULE_GPT, STBCR3_OFFSET, CPG_STBCR3_MSTP30},
{MODULE_SCIFA0, STBCR4_OFFSET, CPG_STBCR4_MSTP47},
{MODULE_SCIFA1, STBCR4_OFFSET, CPG_STBCR4_MSTP46},
{MODULE_SCIFA2, STBCR4_OFFSET, CPG_STBCR4_MSTP45},
{MODULE_SCIFA3, STBCR4_OFFSET, CPG_STBCR4_MSTP44},
{MODULE_SCIFA4, STBCR4_OFFSET, CPG_STBCR4_MSTP43},
{MODULE_SCI0, STBCR4_OFFSET, CPG_STBCR4_MSTP42},
{MODULE_SCI1, STBCR4_OFFSET, CPG_STBCR4_MSTP41},
{MODULE_IrDA, STBCR4_OFFSET, CPG_STBCR4_MSTP40},
{MODULE_CEU, STBCR5_OFFSET, CPG_STBCR5_MSTP56},
{MODULE_RTC0, STBCR5_OFFSET, CPG_STBCR5_MSTP53},
{MODULE_RTC1, STBCR5_OFFSET, CPG_STBCR5_MSTP52},
{MODULE_JCU, STBCR5_OFFSET, CPG_STBCR5_MSTP51},
{MODULE_VIN, STBCR6_OFFSET, CPG_STBCR6_MSTP66},
{MODULE_ETHER, STBCR6_OFFSET,
CPG_STBCR6_MSTP65 | CPG_STBCR6_MSTP64 | CPG_STBCR6_MSTP63 | CPG_STBCR6_MSTP62},
{MODULE_USB0, STBCR6_OFFSET, CPG_STBCR6_MSTP61},
{MODULE_USB1, STBCR6_OFFSET, CPG_STBCR6_MSTP60},
{MODULE_IMR2, STBCR7_OFFSET, CPG_STBCR7_MSTP77},
{MODULE_DRW, STBCR7_OFFSET, CPG_STBCR7_MSTP76},
{MODULE_MIPI, STBCR7_OFFSET, CPG_STBCR7_MSTP75},
{MODULE_SSIF0, STBCR7_OFFSET, CPG_STBCR7_MSTP73},
{MODULE_SSIF1, STBCR7_OFFSET, CPG_STBCR7_MSTP72},
{MODULE_SSIF2, STBCR7_OFFSET, CPG_STBCR7_MSTP71},
{MODULE_SSIF3, STBCR7_OFFSET, CPG_STBCR7_MSTP70},
{MODULE_I2C0, STBCR8_OFFSET, CPG_STBCR8_MSTP87},
{MODULE_I2C1, STBCR8_OFFSET, CPG_STBCR8_MSTP86},
{MODULE_I2C2, STBCR8_OFFSET, CPG_STBCR8_MSTP85},
{MODULE_I2C3, STBCR8_OFFSET, CPG_STBCR8_MSTP84},
{MODULE_SPIBSC, STBCR8_OFFSET, CPG_STBCR8_MSTP83},
{MODULE_VDC6, STBCR8_OFFSET, CPG_STBCR8_MSTP81},
{MODULE_RSPI0, STBCR9_OFFSET, CPG_STBCR9_MSTP97},
{MODULE_RSPI1, STBCR9_OFFSET, CPG_STBCR9_MSTP96},
{MODULE_RSPI2, STBCR9_OFFSET, CPG_STBCR9_MSTP95},
{MODULE_HYPERBUS, STBCR9_OFFSET, CPG_STBCR9_MSTP93},
{MODULE_OCTAMEM, STBCR9_OFFSET, CPG_STBCR9_MSTP92},
{MODULE_RSPDIF, STBCR9_OFFSET, CPG_STBCR9_MSTP91},
{MODULE_DRP, STBCR9_OFFSET, CPG_STBCR9_MSTP90},
{MODULE_TSIP, STBCR10_OFFSET, CPG_STBCR10_MSTP107},
{MODULE_NAND, STBCR10_OFFSET, CPG_STBCR10_MSTP104},
{MODULE_SDMMC0, STBCR10_OFFSET, CPG_STBCR10_MSTP103 | CPG_STBCR10_MSTP102},
{MODULE_SDMMC1, STBCR10_OFFSET, CPG_STBCR10_MSTP101 | CPG_STBCR10_MSTP100},
};
static const struct rza2m_stb_module_info gs_stbreq[] = {
{MODULE_CORESIGHT, STBREQ1_OFFSET, CPG_STBREQ1_STBRQ15},
{MODULE_CEU, STBREQ1_OFFSET, CPG_STBREQ1_STBRQ10},
{MODULE_JCU, STBREQ1_OFFSET, CPG_STBREQ1_STBRQ13},
{MODULE_VIN, STBREQ2_OFFSET, CPG_STBREQ2_STBRQ27},
{MODULE_ETHER, STBREQ2_OFFSET, CPG_STBREQ2_STBRQ26},
{MODULE_USB0, STBREQ3_OFFSET, CPG_STBREQ3_STBRQ31 | CPG_STBREQ3_STBRQ30},
{MODULE_USB1, STBREQ3_OFFSET, CPG_STBREQ3_STBRQ33 | CPG_STBREQ3_STBRQ32},
{MODULE_IMR2, STBREQ2_OFFSET, CPG_STBREQ2_STBRQ23},
{MODULE_DRW, STBREQ2_OFFSET, CPG_STBREQ2_STBRQ21 | CPG_STBREQ2_STBRQ20},
{MODULE_VDC6, STBREQ2_OFFSET, CPG_STBREQ2_STBRQ25},
{MODULE_DRP, STBREQ2_OFFSET, CPG_STBREQ2_STBRQ24},
{MODULE_NAND, STBREQ2_OFFSET, CPG_STBREQ2_STBRQ22},
{MODULE_SDMMC0, STBREQ1_OFFSET, CPG_STBREQ1_STBRQ12},
{MODULE_SDMMC1, STBREQ1_OFFSET, CPG_STBREQ1_STBRQ11},
};
static const struct rza2m_stb_module_info gs_stback[] = {
{MODULE_CORESIGHT, STBACK1_OFFSET, CPG_STBACK1_STBAK15},
{MODULE_CEU, STBACK1_OFFSET, CPG_STBACK1_STBAK10},
{MODULE_JCU, STBACK1_OFFSET, CPG_STBACK1_STBAK13},
{MODULE_VIN, STBACK2_OFFSET, CPG_STBACK2_STBAK27},
{MODULE_ETHER, STBACK2_OFFSET, CPG_STBACK2_STBAK26},
{MODULE_USB0, STBACK3_OFFSET, CPG_STBACK3_STBAK31 | CPG_STBACK3_STBAK30},
{MODULE_USB1, STBACK3_OFFSET, CPG_STBACK3_STBAK33 | CPG_STBACK3_STBAK32},
{MODULE_IMR2, STBACK2_OFFSET, CPG_STBACK2_STBAK23},
{MODULE_DRW, STBACK2_OFFSET, CPG_STBACK2_STBAK21 | CPG_STBACK2_STBAK20},
{MODULE_VDC6, STBACK2_OFFSET, CPG_STBACK2_STBAK25},
{MODULE_DRP, STBACK2_OFFSET, CPG_STBACK2_STBAK24},
{MODULE_NAND, STBACK2_OFFSET, CPG_STBACK2_STBAK22},
{MODULE_SDMMC0, STBACK1_OFFSET, CPG_STBACK1_STBAK12},
{MODULE_SDMMC1, STBACK1_OFFSET, CPG_STBACK1_STBAK11},
};
void rza2m_pl310_set_standby_mode(void)
{
uint32_t reg_val;
/* Read current register value */
reg_val = sys_read32(PL310_BASE_ADDR + PL310_PWR_CTRL_OFFSET);
/* Set standby mode enable bit */
reg_val |= BIT(PL310_PWR_CTRL_STANDBY_MODE_EN_SHIFT);
sys_write32(reg_val, PL310_BASE_ADDR + PL310_PWR_CTRL_OFFSET);
sys_read32(PL310_BASE_ADDR + PL310_PWR_CTRL_OFFSET);
}
void rza2m_cpg_calculate_pll_frequency(const struct device *dev)
{
const struct rza2m_cpg_clock_config *config = dev->config;
struct rza2m_cpg_clock_data *data = dev->data;
data->cpg_extal_frequency_hz = config->cpg_extal_freq_hz_cfg;
if ((data->cpg_extal_frequency_hz >= RZA2M_CPG_MHZ(10)) &&
(data->cpg_extal_frequency_hz <= RZA2M_CPG_MHZ(12))) {
data->cpg_pll_frequency_hz = data->cpg_extal_frequency_hz * 88;
} else if ((data->cpg_extal_frequency_hz >= RZA2M_CPG_MHZ(20)) &&
(data->cpg_extal_frequency_hz <= RZA2M_CPG_MHZ(24))) {
data->cpg_pll_frequency_hz = data->cpg_extal_frequency_hz * 44;
}
}
static void rza2m_cpg_change_reg_bits(mem_addr_t reg, uint8_t bitmask, bool enable)
{
uint8_t reg_val;
reg_val = sys_read8(reg);
if (enable) {
reg_val &= ~bitmask;
} else {
reg_val |= bitmask;
}
sys_write8(reg_val, reg);
sys_read8(reg);
}
static const struct rza2m_stb_module_info *rza2m_cpg_get_stbcr_info(enum rza2m_stb_module module)
{
size_t index;
size_t count = ARRAY_SIZE(gs_stbcr);
for (index = 0; index < count; index++) {
if (module == gs_stbcr[index].module) {
return &gs_stbcr[index];
}
}
/* Return NULL if not found */
return NULL;
}
static const struct rza2m_stb_module_info *rza2m_cpg_get_stbreq_info(enum rza2m_stb_module module)
{
size_t index;
size_t count = ARRAY_SIZE(gs_stbreq);
for (index = 0; index < count; index++) {
if (module == gs_stbreq[index].module) {
return &gs_stbreq[index];
}
}
/* Return NULL if not found */
return NULL;
}
static const struct rza2m_stb_module_info *rza2m_cpg_get_stback_info(enum rza2m_stb_module module)
{
size_t index;
size_t count = ARRAY_SIZE(gs_stback);
for (index = 0; index < count; index++) {
if (module == gs_stback[index].module) {
return &gs_stback[index];
}
}
/* Return NULL if not found */
return NULL;
}
static uint8_t rza2m_cpg_wait_bit_val(uint32_t reg_addr, uint8_t bit_mask, uint8_t bits_val,
int32_t us_wait)
{
uint8_t reg_val;
int32_t wait_cnt = (us_wait / 5);
do {
reg_val = sys_read8(reg_addr) & bit_mask;
if (reg_val == bits_val) {
break;
}
if (wait_cnt > 0) {
k_busy_wait(5);
}
} while (wait_cnt-- > 0);
return reg_val;
}
int rza2m_cpg_mstp_clock_endisable(const struct device *dev, enum rza2m_stb_module module,
bool enable)
{
uint8_t reg_val = 0;
const struct rza2m_stb_module_info *p_stbcr;
const struct rza2m_stb_module_info *p_stbreq;
const struct rza2m_stb_module_info *p_stback;
/* Obtain the STBCR information */
p_stbcr = rza2m_cpg_get_stbcr_info(module);
/* Check if unsupported module */
if (NULL != p_stbcr) {
rza2m_cpg_change_reg_bits(CPG_REG_ADDR(p_stbcr->reg_offset), p_stbcr->mask, enable);
} else {
return -ENOTSUP;
}
p_stbreq = rza2m_cpg_get_stbreq_info(module);
p_stback = rza2m_cpg_get_stback_info(module);
if ((NULL != p_stback) && (NULL != p_stbreq)) {
rza2m_cpg_change_reg_bits(CPG_REG_ADDR(p_stbreq->reg_offset), p_stbreq->mask,
enable);
reg_val = rza2m_cpg_wait_bit_val(CPG_REG_ADDR(p_stback->reg_offset), p_stbreq->mask,
0, STBACK_REG_WAIT_US);
if (reg_val) {
return -EIO;
}
}
return 0;
}
static int rza2m_cpg_modify_frqcr(const struct device *dev, enum rza2m_cp_sub_clock clk_sub_src,
uint32_t sub_clk_frequency_hz, uint16_t *p_frqcr)
{
struct rza2m_cpg_clock_data *data = dev->data;
uint16_t div_d;
uint16_t fc;
/* Avoid divide by zero */
if (sub_clk_frequency_hz == 0) {
return -EINVAL;
}
div_d = data->cpg_pll_frequency_hz / sub_clk_frequency_hz;
if (CPG_SUB_CLOCK_ICLK == clk_sub_src) {
if (div_d == 2) {
fc = 0;
} else if (div_d == 4) {
fc = 1;
} else if (div_d == 8) {
fc = 2;
} else if (div_d == 16) {
fc = 3;
} else {
return -EINVAL;
}
/* Clear IFC bit */
(*p_frqcr) &= (uint16_t)(~CPG_FRQCR_IFC);
/* Modify IFC bit */
(*p_frqcr) |= (uint16_t)(fc << CPG_FRQCR_IFC_SHIFT);
} else if (CPG_SUB_CLOCK_BCLK == clk_sub_src) {
if (div_d == 8) {
fc = 1;
} else if (div_d == 16) {
fc = 2;
} else if (div_d == 32) {
fc = 3;
} else {
return -EINVAL;
}
/* Clear BFC bit */
(*p_frqcr) &= (uint16_t)(~CPG_FRQCR_BFC);
/* Modify BFC bit */
(*p_frqcr) |= (uint16_t)(fc << CPG_FRQCR_BFC_SHIFT);
} else if (CPG_SUB_CLOCK_P1CLK == clk_sub_src) {
if (div_d == 16) {
fc = 2;
} else if (div_d == 32) {
fc = 3;
} else {
return -EINVAL;
}
/* Clear PFC bit */
(*p_frqcr) &= (uint16_t)(~CPG_FRQCR_PFC);
/* Modify PFC bit */
(*p_frqcr) |= (uint16_t)(fc << CPG_FRQCR_PFC_SHIFT);
} else {
return -ENOTSUP;
}
return 0;
}
int rza2m_cpg_set_sub_clock_divider(const struct device *dev, enum rza2m_cp_sub_clock clk_sub_src,
uint32_t sub_clk_frequency_hz)
{
struct rza2m_cpg_clock_data *data = dev->data;
uint16_t frqcr;
uint16_t check_frqcr;
int ret;
/* Read previous settings */
frqcr = sys_read16(CPG_REG_ADDR(CPG_FRQCR_OFFSET));
ret = rza2m_cpg_modify_frqcr(dev, clk_sub_src, sub_clk_frequency_hz, &frqcr);
if (ret < 0) {
return ret;
}
/* Check unless valid combination */
check_frqcr = frqcr & (CPG_FRQCR_IFC | CPG_FRQCR_BFC | CPG_FRQCR_PFC);
switch (check_frqcr) {
case 0x012: /* "VALID":do nothing, fall through */
case 0x112: /* "VALID":do nothing, fall through */
case 0x212: /* "VALID":do nothing, fall through */
case 0x322: /* "VALID":do nothing, fall through */
case 0x333: /* "VALID":do nothing, fall through */
break;
default:
return !EINVAL;
}
/* Update local divisor variables based on the clock type */
switch (clk_sub_src) {
case CPG_SUB_CLOCK_ICLK:
switch ((frqcr & CPG_FRQCR_IFC) >> CPG_FRQCR_IFC_SHIFT) {
case 0:
data->cpg_iclk_divisor = 2;
break;
case 1:
data->cpg_iclk_divisor = 4;
break;
case 2:
data->cpg_iclk_divisor = 8;
break;
case 3:
data->cpg_iclk_divisor = 16;
break;
default:
break;
}
data->cpg_iclk_frequency_hz = data->cpg_pll_frequency_hz / data->cpg_iclk_divisor;
break;
case CPG_SUB_CLOCK_BCLK:
switch ((frqcr & CPG_FRQCR_BFC) >> CPG_FRQCR_BFC_SHIFT) {
case 1:
data->cpg_bclk_divisor = 8;
break;
case 2:
data->cpg_bclk_divisor = 16;
break;
case 3:
data->cpg_bclk_divisor = 32;
break;
default:
break;
}
data->cpg_bclk_frequency_hz = data->cpg_pll_frequency_hz / data->cpg_bclk_divisor;
break;
case CPG_SUB_CLOCK_P1CLK:
switch ((frqcr & CPG_FRQCR_PFC) >> CPG_FRQCR_PFC_SHIFT) {
case 2:
data->cpg_p1clk_divisor = 16;
break;
case 3:
data->cpg_p1clk_divisor = 32;
break;
default:
break;
}
data->cpg_p1clk_frequency_hz = data->cpg_pll_frequency_hz / data->cpg_p1clk_divisor;
break;
default:
return -ENOTSUP;
}
rza2m_pl310_set_standby_mode();
sys_write16(frqcr, CPG_REG_ADDR(CPG_FRQCR_OFFSET));
sys_read16(CPG_REG_ADDR(CPG_FRQCR_OFFSET));
return 0;
}
int rza2m_cpg_get_clock(const struct device *dev, enum rza2m_cpg_get_freq_src src, uint32_t *p_freq)
{
struct rza2m_cpg_clock_data *data = dev->data;
if (NULL == p_freq) {
return -EINVAL;
}
switch (src) {
case CPG_FREQ_EXTAL:
*p_freq = data->cpg_extal_frequency_hz;
break;
case CPG_FREQ_ICLK:
*p_freq = data->cpg_iclk_frequency_hz;
break;
case CPG_FREQ_GCLK:
*p_freq = (data->cpg_pll_frequency_hz * 2) / data->cpg_bclk_divisor;
break;
case CPG_FREQ_BCLK:
*p_freq = data->cpg_bclk_frequency_hz;
break;
case CPG_FREQ_P1CLK:
*p_freq = data->cpg_p1clk_frequency_hz;
break;
case CPG_FREQ_P0CLK:
*p_freq = data->cpg_pll_frequency_hz / 32;
break;
default:
return -ENOTSUP;
}
return 0;
}

255
drivers/clock_control/clock_control_renesas_rza2m_cpg_lld.h

@ -0,0 +1,255 @@ @@ -0,0 +1,255 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_RENESAS_RZA2M_CPG_LLD_H_
#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_RENESAS_RZA2M_CPG_LLD_H_
#include <stdint.h>
#include <zephyr/dt-bindings/clock/renesas_rza2m_clock.h>
struct rza2m_cpg_clock_config {
DEVICE_MMIO_ROM;
uint32_t cpg_extal_freq_hz_cfg;
uint32_t cpg_iclk_freq_hz_cfg;
uint32_t cpg_bclk_freq_hz_cfg;
uint32_t cpg_p1clk_freq_hz_cfg;
};
struct rza2m_cpg_clock_data {
DEVICE_MMIO_RAM;
uint32_t cpg_extal_frequency_hz;
uint32_t cpg_pll_frequency_hz;
uint32_t cpg_iclk_divisor;
uint32_t cpg_iclk_frequency_hz;
uint32_t cpg_bclk_divisor;
uint32_t cpg_bclk_frequency_hz;
uint32_t cpg_p1clk_divisor;
uint32_t cpg_p1clk_frequency_hz;
};
#define PL310_BASE_ADDR 0x1F003000UL
#define PL310_PWR_CTRL_OFFSET 0xF80UL
#define PL310_PWR_CTRL_STANDBY_MODE_EN_SHIFT 0UL
#define STBACK_REG_WAIT_US 50
#define RZA2M_CPG_KHZ(khz) ((khz) * 1000U)
#define RZA2M_CPG_MHZ(mhz) (RZA2M_CPG_KHZ(mhz) * 1000U)
#define CPG_BASE_ADDR DEVICE_MMIO_GET(dev)
#define CPG_FRQCR_OFFSET 0x0UL
#define CPG_CKIOSEL_OFFSET 0xF0UL
#define CPG_SCLKSEL_OFFSET 0xF4UL
#define CPG_REG_ADDR(off) ((mm_reg_t)(CPG_BASE_ADDR + (off)))
#define RZA2M_GET_MODULE(clock_id) ((clock_id >> RZA2M_MODULE_SHIFT) & 0xFF)
#define RZA2M_GET_CLOCK_SRC(clock_id) ((clock_id >> RZA2M_CLOCK_SRC_SHIFT) & 0xFF)
#define STBCR1_OFFSET 0x10UL
#define STBCR2_OFFSET 0x14UL
#define STBCR3_OFFSET 0x410UL
#define STBCR4_OFFSET 0x414UL
#define STBCR5_OFFSET 0x418UL
#define STBCR6_OFFSET 0x41CUL
#define STBCR7_OFFSET 0x420UL
#define STBCR8_OFFSET 0x424UL
#define STBCR9_OFFSET 0x428UL
#define STBCR10_OFFSET 0x42CUL
#define STBREQ1_OFFSET 0x20UL
#define STBREQ2_OFFSET 0x24UL
#define STBREQ3_OFFSET 0x28UL
#define STBACK1_OFFSET 0x30UL
#define STBACK2_OFFSET 0x34UL
#define STBACK3_OFFSET 0x38UL
#define CPG_FRQCR_PFC 0x0003UL
#define CPG_FRQCR_PFC_SHIFT 0UL
#define CPG_FRQCR_BFC 0x0030UL
#define CPG_FRQCR_BFC_SHIFT 4UL
#define CPG_FRQCR_IFC 0x0300UL
#define CPG_FRQCR_IFC_SHIFT 8UL
#define CPG_FRQCR_CKOEN 0x3000UL
#define CPG_FRQCR_CKOEN_SHIFT 12UL
#define CPG_FRQCR_CKOEN2 0x4000UL
#define CPG_FRQCR_CKOEN2_SHIFT 14UL
#define CPG_STBCR2_MSTP20 0x01UL
#define CPG_STBREQ1_STBRQ10 0x01UL
#define CPG_STBREQ1_STBRQ11 0x02UL
#define CPG_STBREQ1_STBRQ12 0x04UL
#define CPG_STBREQ1_STBRQ13 0x08UL
#define CPG_STBREQ1_STBRQ15 0x20UL
#define CPG_STBREQ2_STBRQ20 0x01UL
#define CPG_STBREQ2_STBRQ21 0x02UL
#define CPG_STBREQ2_STBRQ22 0x04UL
#define CPG_STBREQ2_STBRQ23 0x08UL
#define CPG_STBREQ2_STBRQ24 0x10UL
#define CPG_STBREQ2_STBRQ25 0x20UL
#define CPG_STBREQ2_STBRQ26 0x40UL
#define CPG_STBREQ2_STBRQ27 0x80UL
#define CPG_STBREQ3_STBRQ30 0x01UL
#define CPG_STBREQ3_STBRQ31 0x02UL
#define CPG_STBREQ3_STBRQ32 0x04UL
#define CPG_STBREQ3_STBRQ33 0x08UL
#define CPG_STBACK1_STBAK10 0x01UL
#define CPG_STBACK1_STBAK11 0x02UL
#define CPG_STBACK1_STBAK12 0x04UL
#define CPG_STBACK1_STBAK13 0x08UL
#define CPG_STBACK1_STBAK15 0x20UL
#define CPG_STBACK2_STBAK20 0x01UL
#define CPG_STBACK2_STBAK21 0x02UL
#define CPG_STBACK2_STBAK22 0x04UL
#define CPG_STBACK2_STBAK23 0x08UL
#define CPG_STBACK2_STBAK24 0x10UL
#define CPG_STBACK2_STBAK25 0x20UL
#define CPG_STBACK2_STBAK26 0x40UL
#define CPG_STBACK2_STBAK27 0x80UL
#define CPG_STBACK3_STBAK30 0x01UL
#define CPG_STBACK3_STBAK31 0x02UL
#define CPG_STBACK3_STBAK32 0x04UL
#define CPG_STBACK3_STBAK33 0x08UL
#define CPG_CKIOSEL_CKIOSEL 0x0003UL
#define CPG_SCLKSEL_SPICR 0x0003UL
#define CPG_SCLKSEL_HYMCR 0x0030UL
#define CPG_SCLKSEL_OCTCR 0x0300UL
#define CPG_STBCR3_MSTP30 0x01UL
#define CPG_STBCR3_MSTP32 0x04UL
#define CPG_STBCR3_MSTP33 0x08UL
#define CPG_STBCR3_MSTP34 0x10UL
#define CPG_STBCR3_MSTP35 0x20UL
#define CPG_STBCR3_MSTP36 0x40UL
#define CPG_STBCR4_MSTP40 0x01UL
#define CPG_STBCR4_MSTP41 0x02UL
#define CPG_STBCR4_MSTP42 0x04UL
#define CPG_STBCR4_MSTP43 0x08UL
#define CPG_STBCR4_MSTP44 0x10UL
#define CPG_STBCR4_MSTP45 0x20UL
#define CPG_STBCR4_MSTP46 0x40UL
#define CPG_STBCR4_MSTP47 0x80UL
#define CPG_STBCR5_MSTP51 0x02UL
#define CPG_STBCR5_MSTP52 0x04UL
#define CPG_STBCR5_MSTP53 0x08UL
#define CPG_STBCR5_MSTP56 0x40UL
#define CPG_STBCR5_MSTP57 0x80UL
#define CPG_STBCR6_MSTP60 0x01UL
#define CPG_STBCR6_MSTP61 0x02UL
#define CPG_STBCR6_MSTP62 0x04UL
#define CPG_STBCR6_MSTP63 0x08UL
#define CPG_STBCR6_MSTP64 0x10UL
#define CPG_STBCR6_MSTP65 0x20UL
#define CPG_STBCR6_MSTP66 0x40UL
#define CPG_STBCR7_MSTP70 0x01UL
#define CPG_STBCR7_MSTP71 0x02UL
#define CPG_STBCR7_MSTP72 0x04UL
#define CPG_STBCR7_MSTP73 0x08UL
#define CPG_STBCR7_MSTP75 0x20UL
#define CPG_STBCR7_MSTP76 0x40UL
#define CPG_STBCR7_MSTP77 0x80UL
#define CPG_STBCR8_MSTP81 0x02UL
#define CPG_STBCR8_MSTP83 0x08UL
#define CPG_STBCR8_MSTP84 0x10UL
#define CPG_STBCR8_MSTP85 0x20UL
#define CPG_STBCR8_MSTP86 0x40UL
#define CPG_STBCR8_MSTP87 0x80UL
#define CPG_STBCR9_MSTP90 0x01UL
#define CPG_STBCR9_MSTP91 0x02UL
#define CPG_STBCR9_MSTP92 0x04UL
#define CPG_STBCR9_MSTP93 0x08UL
#define CPG_STBCR9_MSTP95 0x20UL
#define CPG_STBCR9_MSTP96 0x40UL
#define CPG_STBCR9_MSTP97 0x80UL
#define CPG_STBCR10_MSTP100 0x01UL
#define CPG_STBCR10_MSTP101 0x02UL
#define CPG_STBCR10_MSTP102 0x04UL
#define CPG_STBCR10_MSTP103 0x08UL
#define CPG_STBCR10_MSTP104 0x10UL
#define CPG_STBCR10_MSTP107 0x80UL
enum rza2m_stb_module {
MODULE_CORESIGHT = 1,
MODULE_OSTM0,
MODULE_OSTM1,
MODULE_OSTM2,
MODULE_MTU3,
MODULE_CANFD,
MODULE_ADC,
MODULE_GPT,
MODULE_SCIFA0,
MODULE_SCIFA1,
MODULE_SCIFA2,
MODULE_SCIFA3,
MODULE_SCIFA4,
MODULE_SCI0,
MODULE_SCI1,
MODULE_IrDA,
MODULE_CEU,
MODULE_RTC0,
MODULE_RTC1,
MODULE_JCU,
MODULE_VIN,
MODULE_ETHER,
MODULE_USB0,
MODULE_USB1,
MODULE_IMR2,
MODULE_DRW,
MODULE_MIPI,
MODULE_SSIF0,
MODULE_SSIF1,
MODULE_SSIF2,
MODULE_SSIF3,
MODULE_I2C0,
MODULE_I2C1,
MODULE_I2C2,
MODULE_I2C3,
MODULE_SPIBSC,
MODULE_VDC6,
MODULE_RSPI0,
MODULE_RSPI1,
MODULE_RSPI2,
MODULE_HYPERBUS,
MODULE_OCTAMEM,
MODULE_RSPDIF,
MODULE_DRP,
MODULE_TSIP,
MODULE_NAND,
MODULE_SDMMC0,
MODULE_SDMMC1,
MODULE_MAX,
};
struct rza2m_stb_module_info {
enum rza2m_stb_module module;
uint32_t reg_offset;
uint8_t mask;
};
/* For setting any system sub-clock */
enum rza2m_cp_sub_clock {
CPG_SUB_CLOCK_ICLK = 0u, /*!< CPU Clock */
CPG_SUB_CLOCK_BCLK, /*!< Internal Bus Clock */
CPG_SUB_CLOCK_P1CLK, /*!< Peripheral Clock */
};
/* For retrieve clock frequency */
enum rza2m_cpg_get_freq_src {
CPG_FREQ_EXTAL = 0,
CPG_FREQ_ICLK,
CPG_FREQ_GCLK,
CPG_FREQ_BCLK,
CPG_FREQ_P1CLK,
CPG_FREQ_P0CLK,
};
int rza2m_cpg_set_sub_clock_divider(const struct device *dev, enum rza2m_cp_sub_clock clk_sub_src,
uint32_t sub_clk_frequency_hz);
int rza2m_cpg_mstp_clock_endisable(const struct device *dev, enum rza2m_stb_module module,
bool enable);
int rza2m_cpg_get_clock(const struct device *dev, enum rza2m_cpg_get_freq_src src,
uint32_t *p_freq);
void rza2m_cpg_calculate_pll_frequency(const struct device *dev);
void rza2m_pl310_set_standby_mode(void);
#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_RENESAS_RZA2M_CPG_LLD_H_ */

23
dts/arm/renesas/rz/rza/r7s9210.dtsi

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
#include <mem.h>
#include <arm/armv7-a.dtsi>
#include <zephyr/dt-bindings/interrupt-controller/arm-gic.h>
#include <zephyr/dt-bindings/clock/renesas_rza2m_clock.h>
/ {
compatible = "renesas,r7s9210";
@ -50,5 +51,27 @@ @@ -50,5 +51,27 @@
compatible = "mmio-sram";
reg = <0x80020000 (DT_SIZE_M(4) - 0x20000)>;
};
cpg: clock-controller@fcfe0010 {
compatible = "renesas,rza2m-cpg";
reg = <0xfcfe0010 0x455>;
#clock-cells = <1>;
clocks = <&osc>;
iclk: iclk {
compatible = "fixed-clock";
#clock-cells = <0>;
};
bclk: bclk {
compatible = "fixed-clock";
#clock-cells = <0>;
};
p1clk: p1clk {
compatible = "fixed-clock";
#clock-cells = <0>;
};
};
};
};

7
dts/bindings/clock/renesas,rza2m-cpg.yaml

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
# Copyright (c) 2025 Renesas Electronics Corporation24
# SPDX-License-Identifier: Apache-2.0
description: RZ/A2M Clock Pulse Generator
compatible: "renesas,rza2m-cpg"
include: renesas,rz-cpg.yml

78
include/zephyr/dt-bindings/clock/renesas_rza2m_clock.h

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RENESAS_RZA2M_CLOCK_H_
#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RENESAS_RZA2M_CLOCK_H_
#define RZA2M_MODULE_CORESIGHT 1UL
#define RZA2M_MODULE_OSTM0 2UL
#define RZA2M_MODULE_OSTM1 3UL
#define RZA2M_MODULE_OSTM2 4UL
#define RZA2M_MODULE_MTU3 5UL
#define RZA2M_MODULE_CANFD 6UL
#define RZA2M_MODULE_ADC 7UL
#define RZA2M_MODULE_GPT 8UL
#define RZA2M_MODULE_SCIFA0 9UL
#define RZA2M_MODULE_SCIFA1 10UL
#define RZA2M_MODULE_SCIFA2 11UL
#define RZA2M_MODULE_SCIFA3 12UL
#define RZA2M_MODULE_SCIFA4 13UL
#define RZA2M_MODULE_SCI0 14UL
#define RZA2M_MODULE_SCI1 15UL
#define RZA2M_MODULE_IrDA 16UL
#define RZA2M_MODULE_CEU 17UL
#define RZA2M_MODULE_RTC0 18UL
#define RZA2M_MODULE_RTC1 19UL
#define RZA2M_MODULE_JCU 20UL
#define RZA2M_MODULE_VIN 21UL
#define RZA2M_MODULE_ETHER 22UL
#define RZA2M_MODULE_USB0 23UL
#define RZA2M_MODULE_USB1 24UL
#define RZA2M_MODULE_IMR2 25UL
#define RZA2M_MODULE_DRW 26UL
#define RZA2M_MODULE_MIPI 27UL
#define RZA2M_MODULE_SSIF0 28UL
#define RZA2M_MODULE_SSIF1 29UL
#define RZA2M_MODULE_SSIF2 30UL
#define RZA2M_MODULE_SSIF3 31UL
#define RZA2M_MODULE_I2C0 32UL
#define RZA2M_MODULE_I2C1 33UL
#define RZA2M_MODULE_I2C2 34UL
#define RZA2M_MODULE_I2C3 35UL
#define RZA2M_MODULE_SPIBSC 36UL
#define RZA2M_MODULE_VDC6 37UL
#define RZA2M_MODULE_RSPI0 38UL
#define RZA2M_MODULE_RSPI1 39UL
#define RZA2M_MODULE_RSPI2 40UL
#define RZA2M_MODULE_HYPERBUS 41UL
#define RZA2M_MODULE_OCTAMEM 42UL
#define RZA2M_MODULE_RSPDIF 43UL
#define RZA2M_MODULE_DRP 44UL
#define RZA2M_MODULE_TSIP 45UL
#define RZA2M_MODULE_NAND 46UL
#define RZA2M_MODULE_SDMMC0 47UL
#define RZA2M_MODULE_SDMMC1 48UL
/** RZ/A2M clock configuration values */
#define RZA2M_MODULE_SHIFT 8UL
#define RZA2M_CLOCK_SRC_SHIFT 0UL
#define RZA2M_CLK_EXTAL 0UL
#define RZA2M_CLK_I 1UL
#define RZA2M_CLK_G 2UL
#define RZA2M_CLK_B 3UL
#define RZA2M_CLK_P1 4UL
#define RZA2M_CLK_P1C 4UL
#define RZA2M_CLK_P0 5UL
#define RZA2M_CLOCK(module, clk) \
(((module) << RZA2M_MODULE_SHIFT) | ((clk) << RZA2M_CLOCK_SRC_SHIFT))
/*
* Example: RZA2M_CLOCK(MODULE_SCIFA4, RZA2M_CLK_P1C) // SCIFA4
*/
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RENESAS_RZA2M_CLOCK_H_ */
Loading…
Cancel
Save