Skip to content

Commit

Permalink
driver,rcc: add stm32wb support
Browse files Browse the repository at this point in the history
  • Loading branch information
fvalette-ledger committed Jan 8, 2025
1 parent abd6d4f commit ce4efff
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 0 deletions.
15 changes: 15 additions & 0 deletions kernel/src/drivers/clk/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@ stm32u5_rcc_h = dtsgen.process(
bsp_clk_private_gen_header_set.add(stm32u5_rcc_h)
endif

if kconfig_data.get('CONFIG_SOC_SUBFAMILY_STM32WB', 0) == 1
stm32wb_rcc_c_template = files('stm32wb-rcc.c.in')
stm32wb_rcc_c = dtsgen.process(
stm32wb_rcc_c_template,
preserve_path_from: meson.current_source_dir(),
)
bsp_clk_private_gen_source_set.add(stm32wb_rcc_c)
stm32wb_rcc_h_template = files('stm32wb-rcc.h.in')
stm32wb_rcc_h = dtsgen.process(
stm32wb_rcc_h_template,
preserve_path_from: meson.current_source_dir(),
)
bsp_clk_private_gen_header_set.add(stm32wb_rcc_h)
endif

pwr_h = custom_target('gen_pwr',
input: peripheral_defs_in,
output: '@0@_defs.h'.format('pwr'),
Expand Down
2 changes: 2 additions & 0 deletions kernel/src/drivers/clk/stm32-rcc.c.in
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "stm32l4-rcc.h"
#elif defined(CONFIG_SOC_SUBFAMILY_STM32U5)
#include "stm32u5-rcc.h"
#elif defined(CONFIG_SOC_SUBFAMILY_STM32WB)
#include "stm32wb-rcc.h"
#endif

#include "stm32-rcc.h"
Expand Down
120 changes: 120 additions & 0 deletions kernel/src/drivers/clk/stm32wb-rcc.c.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-FileCopyrightText: 2025 Ledger SAS
// SPDX-License-Identifier: Apache-2.0

/* RCC generated header for current platform */
#include "rcc_defs.h"
#include "stm32-rcc.h"
#include "stm32wb-rcc.h"

{%- set rcc_clock_source = dts.rcc.clocks %}

kstatus_t rcc_select_system_clock(void)
{
uint32_t rcc_cfgr;
uint32_t clocksource;

rcc_cfgr = ioread32(RCC_BASE_ADDR + RCC_CFGR_REG);

/* previously clear corresponding bits */
rcc_cfgr &= ~(RCC_CFGR_SW_MASK);

{%- if rcc_clock_source.label == 'clk_hsi' %}
clocksource = 0b01;
{%- elif rcc_clock_source.label == 'clk_hse' %}
clocksource = 0b10;
{%- elif rcc_clock_source.label == 'pll' %}
clocksource = 0b11;
{%- else %}
#error "clock source configuration error, please check your devicetree file"
{%- endif %}

rcc_cfgr |= clocksource;
iowrite32(RCC_BASE_ADDR + RCC_CFGR_REG, rcc_cfgr);

/* clocksource status is shifted by 2 on the same register */
clocksource = clocksource << 2UL;
/* XXX: same timeout as PLL ?! */
return iopoll32_until_set(RCC_BASE_ADDR + RCC_CFGR_REG, clocksource, PLL_STARTUP_TIMEOUT);
}

static inline void stm32wb_pll_configure(void)
{
uint32_t pllcfg = 0;

/*
* PLL clock source HSI16
* - M = 1
* - N = 12
* - R = 3
* - Q = 4
*
* VCO in = IN / M = 16 / 1 = 16
* VCO out = VCO in * N = 16 * 12 = 192
*
* R out = VCO out / R = 64 MHz --> sysclk
* Q out = VCO out / Q = 48 MHz --> usb
*/

pllcfg |= (0x02 << RCC_PLLCFGR_PLLSRC_SHIFT) & RCC_PLLCFGR_PLLSRC_MASK;
pllcfg |= (0x00 << RCC_PLLCFGR_PLLM_SHIFT) & RCC_PLLCFGR_PLLM_MASK;
pllcfg |= (0x0C << RCC_PLLCFGR_PLLN_SHIFT) & RCC_PLLCFGR_PLLN_MASK;
pllcfg |= (0x03 << RCC_PLLCFGR_PLLQ_SHIFT) & RCC_PLLCFGR_PLLQ_MASK;
pllcfg |= (0x02 << RCC_PLLCFGR_PLLR_SHIFT) & RCC_PLLCFGR_PLLR_MASK;

iowrite32(RCC_BASE_ADDR + RCC_PLLCFGR_REG, pllcfg);
}

static inline kstatus_t stm32wb_pll_start(void)
{
uint32_t rcc_cr = ioread32(RCC_BASE_ADDR + RCC_CR_REG);
rcc_cr |= RCC_CR_PLLON;
iowrite32(RCC_BASE_ADDR + RCC_CR_REG, rcc_cr);

return iopoll32_until_set(RCC_BASE_ADDR + RCC_CR_REG, RCC_CR_PLLRDY, PLL_STARTUP_TIMEOUT);
}

static inline void stm32wb_enable_pll_output(uint32_t en_bit)
{
uint32_t pllcfg = ioread32(RCC_BASE_ADDR + RCC_PLLCFGR_REG);
pllcfg |= en_bit;
iowrite32(RCC_BASE_ADDR + RCC_PLLCFGR_REG, pllcfg);
}

static inline void stm32wb_enable_pll_p_output(void)
{
stm32wb_enable_pll_output(RCC_PLLCFGR_PLLPEN);
}

static inline void stm32wb_enable_pll_q_output(void)
{
stm32wb_enable_pll_output(RCC_PLLCFGR_PLLQEN);
}

static inline void stm32wb_enable_pll_r_output(void)
{
stm32wb_enable_pll_output(RCC_PLLCFGR_PLLREN);
}

kstatus_t rcc_enable_pll(void)
{
kstatus_t status;

stm32wb_pll_configure();
status = stm32wb_pll_start();

if (status == K_STATUS_OKAY) {
stm32wb_enable_pll_r_output();
stm32wb_enable_pll_q_output();
}

return status;
}

kstatus_t rcc_mux_select_clock_source(
uint32_t clk_reg __MAYBE_UNUSED,
uint32_t clkmsk __MAYBE_UNUSED,
uint32_t val __MAYBE_UNUSED
)
{
return K_ERROR_NOENT;
}
61 changes: 61 additions & 0 deletions kernel/src/drivers/clk/stm32wb-rcc.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: 2025 Ledger SAS
// SPDX-License-Identifier: Apache-2.0

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#ifndef __STM32WB_RCC_H
#define __STM32WB_RCC_H

#ifndef CONFIG_SOC_SUBFAMILY_STM32WB
#error "this header should not be included in SoCs others than STM32WB family"
#endif

#include <sentry/io.h>
#include <sentry/arch/asm-generic/layout.h>
#include "rcc_defs.h"

#define RCC_SYSCLOCK_FREQUENCY_MAX (64*MEGA)
#define RCC_AHB_BUS_FREQUENCY_MAX RCC_SYSCLOCK_FREQUENCY_MAX
#define RCC_APB1_BUS_FREQUENCY_MAX RCC_SYSCLOCK_FREQUENCY_MAX
#define RCC_APB2_BUS_FREQUENCY_MAX RCC_SYSCLOCK_FREQUENCY_MAX

#define HAS_HSI48_CLOCK
#define RCC_HSI48_REG RCC_CRRCR_REG
#define RCC_HSI48ON RCC_CRRCR_HSI48ON
#define RCC_HSI48RDY RCC_CRRCR_HSI48RDY

static inline void __stm32_rcc_set_peripheral_bus_div(uint32_t hpre, uint32_t ppre1, uint32_t ppre2)
{
union {
rcc_cfgr_t cfgr;
uint32_t raw;
} reg;

reg.raw = ioread32(RCC_BASE_ADDR + RCC_CFGR_REG);
reg.cfgr.hpre = hpre;
reg.cfgr.ppre1 = ppre1;
reg.cfgr.ppre2 = ppre2;
iowrite32(RCC_BASE_ADDR + RCC_CFGR_REG, reg.raw);
}

kstatus_t rcc_select_system_clock(void);
kstatus_t rcc_enable_pll(void);

#endif /* __STM32WB_RCC_H */

0 comments on commit ce4efff

Please sign in to comment.