mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-07 07:46:59 +02:00
- Add drivers for MFD STM32 TIMERS and STM32 PWM and enable them on stm32mp135f-dk
- Restrict _debug_uart_init() usage in STM32 serial driver - Add support for environment in eMMC on STM32MP13xx DHCOR SoM - Introduce DH STM32MP15xx DHSOM board specific defconfigs - Fix CONFIG_BOOTCOUNT_ALTBOOTCMD update on DH STM32MP1 DHSOM - Update maintainer for board stm32f746-disco - Fix Linux cmdline for stm32f769-disco - Cleanup in stm32f***-u-boot.dtsi and in board_late_init() by removing legacy led and button management. -----BEGIN PGP SIGNATURE----- iQJQBAABCgA6FiEEXyrViUccKBz9c35Jysd4L3sz/6YFAmfRsL4cHHBhdHJpY2Uu Y2hvdGFyZEBmb3NzLnN0LmNvbQAKCRDKx3gvezP/psU2D/9LPdhwyvmi595AgjNf 0t4rqKKTPhjb43UZeuAnFOg4PJcH7eXd2tQq5htK+ir8jeLU7cZWRGjA6eXtRQni IKYtWlz4OY/xuQhJbQqMBGb1EVJE432LlfVp3rKpCpBMoANU+h//opd/m4CKsMYN SiIikf3Xasgy7APSGTQcNGZyzVcVPeL8e68hEAOuFfCBMmd4JRb7RMwro9mG+/SU 9PzOLvCEfNTq9k87vT8SH4UQHv/NF8OaH6v77SJFt+RHdQr/G9MNbdP5IVwuWkgU CfcWRFzmofFACueZ/6vA+hFYarF5tsv043GJyJkTh/0CUbFx8vS0+x1WoL7YcviA 5Ro+tEEfpB1F1qLyOJV698l1vm3Zj452oZ6e2PBPMGqfKy1vkBjh9OjhfqpjILHX uAkxxd/dx6FzK8jo4Qki7JT4W2MmD3jTeHsVunLOC1tS1f44MHwnjpZZH2ttXT/4 VLPkIYf9kKJA/squ0Lx+ZCjFtiM/XenWHhQxsO9QxKUqSHgBZuwBj8VRNRrMs/N+ 3mN4PLNuYtagJjCvvsxiMg0aB7LH22kXA657nQfHM01WlR9I/B2K0aIil/I/kVV9 b9LtUven4sXUEexszEY/xFxF2utU+Xh57wKh+3qm2XVw8pfSKItvBXBK/lo/ULWV 62xL179ziFFGrE/2o/m87VT30w== =xL/c -----END PGP SIGNATURE----- Merge tag 'u-boot-stm32-20250312' of https://source.denx.de/u-boot/custodians/u-boot-stm into next CI: https://source.denx.de/u-boot/custodians/u-boot-stm/-/pipelines/25112 - Add drivers for MFD STM32 TIMERS and STM32 PWM and enable them on stm32mp135f-dk - Restrict _debug_uart_init() usage in STM32 serial driver - Add support for environment in eMMC on STM32MP13xx DHCOR SoM - Introduce DH STM32MP15xx DHSOM board specific defconfigs - Fix CONFIG_BOOTCOUNT_ALTBOOTCMD update on DH STM32MP1 DHSOM - Update maintainer for board stm32f746-disco - Fix Linux cmdline for stm32f769-disco - Cleanup in stm32f***-u-boot.dtsi and in board_late_init() by removing legacy led and button management.
This commit is contained in:
commit
eeefcacb85
@ -22,16 +22,6 @@
|
||||
mmc0 = &sdio1;
|
||||
spi0 = &qspi;
|
||||
};
|
||||
|
||||
button1 {
|
||||
compatible = "st,button1";
|
||||
button-gpio = <&gpioc 13 0>;
|
||||
};
|
||||
|
||||
led1 {
|
||||
compatible = "st,led1";
|
||||
led-gpio = <&gpiof 10 0>;
|
||||
};
|
||||
};
|
||||
|
||||
&fmc {
|
||||
|
@ -22,16 +22,6 @@
|
||||
mmc0 = &sdio1;
|
||||
spi0 = &qspi;
|
||||
};
|
||||
|
||||
button1 {
|
||||
compatible = "st,button1";
|
||||
button-gpio = <&gpioi 11 0>;
|
||||
};
|
||||
|
||||
led1 {
|
||||
compatible = "st,led1";
|
||||
led-gpio = <&gpioi 1 0>;
|
||||
};
|
||||
};
|
||||
|
||||
<dc {
|
||||
|
@ -23,16 +23,6 @@
|
||||
spi0 = &qspi;
|
||||
};
|
||||
|
||||
button1 {
|
||||
compatible = "st,button1";
|
||||
button-gpio = <&gpioa 0 0>;
|
||||
};
|
||||
|
||||
led1 {
|
||||
compatible = "st,led1";
|
||||
led-gpio = <&gpioj 5 0>;
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "orisetech,otm8009a";
|
||||
reset-gpios = <&gpioj 15 1>;
|
||||
|
@ -215,6 +215,21 @@
|
||||
};
|
||||
};
|
||||
|
||||
pwm1_ch3n_pins_a: pwm1-ch3n-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('E', 12, AF1)>; /* TIM1_CH3N */
|
||||
bias-pull-down;
|
||||
drive-push-pull;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
pwm1_ch3n_sleep_pins_a: pwm1-ch3n-sleep-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('E', 12, ANALOG)>; /* TIM1_CH3N */
|
||||
};
|
||||
};
|
||||
|
||||
pwm3_pins_a: pwm3-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('B', 1, AF2)>; /* TIM3_CH4 */
|
||||
|
@ -23,3 +23,25 @@
|
||||
&usbphyc {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&st33htph {
|
||||
reset-gpios = <&gpioe 12 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/* LDO2 is expansion connector 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */
|
||||
&vdd_ldo2 {
|
||||
bootph-all;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
/* LDO5 is carrier board 3V3 supply on STM32MP13xx DHCOR DHSBC rev.200 */
|
||||
&vdd_sd {
|
||||
bootph-all;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pwm/pwm.h>
|
||||
#include <dt-bindings/regulator/st,stm32mp13-regulator.h>
|
||||
#include "stm32mp135.dtsi"
|
||||
#include "stm32mp13xf.dtsi"
|
||||
@ -207,6 +208,19 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&timers1 {
|
||||
/* spare dmas for other usage */
|
||||
/delete-property/dmas;
|
||||
/delete-property/dma-names;
|
||||
status = "okay";
|
||||
pwm1: pwm {
|
||||
pinctrl-0 = <&pwm1_ch3n_pins_a>;
|
||||
pinctrl-1 = <&pwm1_ch3n_sleep_pins_a>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&timers3 {
|
||||
/delete-property/dmas;
|
||||
/delete-property/dma-names;
|
||||
|
@ -13,6 +13,8 @@
|
||||
config {
|
||||
dh,ddr3-coding-gpios = <&gpiod 5 0>, <&gpiod 9 0>;
|
||||
dh,som-coding-gpios = <&gpioa 13 0>, <&gpioi 1 0>;
|
||||
u-boot,mmc-env-offset = <0x3fc000>;
|
||||
u-boot,mmc-env-offset-redundant = <0x3fc000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -153,6 +153,12 @@ config CMD_STM32KEY
|
||||
This command is used to evaluate the secure boot on stm32mp SOC,
|
||||
it is deactivated by default in real products.
|
||||
|
||||
config MFD_STM32_TIMERS
|
||||
bool "STM32 multifonction timer support"
|
||||
help
|
||||
Select this to enable support for the multifunction timer found on
|
||||
STM32 devices.
|
||||
|
||||
source "arch/arm/mach-stm32mp/Kconfig.13x"
|
||||
source "arch/arm/mach-stm32mp/Kconfig.15x"
|
||||
source "arch/arm/mach-stm32mp/Kconfig.25x"
|
||||
|
@ -12,6 +12,7 @@ obj-$(CONFIG_STM32MP15X) += stm32mp1/
|
||||
obj-$(CONFIG_STM32MP13X) += stm32mp1/
|
||||
obj-$(CONFIG_STM32MP25X) += stm32mp2/
|
||||
|
||||
obj-$(CONFIG_MFD_STM32_TIMERS) += timers.o
|
||||
obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o
|
||||
ifndef CONFIG_XPL_BUILD
|
||||
obj-y += cmd_stm32prog/
|
||||
|
55
arch/arm/mach-stm32mp/include/mach/timers.h
Normal file
55
arch/arm/mach-stm32mp/include/mach/timers.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2025, STMicroelectronics - All Rights Reserved
|
||||
* Author: Cheick Traore <cheick.traore@foss.st.com>
|
||||
*
|
||||
* Originally based on the Linux kernel v6.1 include/linux/mfd/stm32-timers.h.
|
||||
*/
|
||||
|
||||
#ifndef __STM32_TIMERS_H
|
||||
#define __STM32_TIMERS_H
|
||||
|
||||
#include <clk.h>
|
||||
|
||||
#define TIM_CR1 0x00 /* Control Register 1 */
|
||||
#define TIM_CR2 0x04 /* Control Register 2 */
|
||||
#define TIM_SMCR 0x08 /* Slave mode control reg */
|
||||
#define TIM_DIER 0x0C /* DMA/interrupt register */
|
||||
#define TIM_SR 0x10 /* Status register */
|
||||
#define TIM_EGR 0x14 /* Event Generation Reg */
|
||||
#define TIM_CCMR1 0x18 /* Capt/Comp 1 Mode Reg */
|
||||
#define TIM_CCMR2 0x1C /* Capt/Comp 2 Mode Reg */
|
||||
#define TIM_CCER 0x20 /* Capt/Comp Enable Reg */
|
||||
#define TIM_CNT 0x24 /* Counter */
|
||||
#define TIM_PSC 0x28 /* Prescaler */
|
||||
#define TIM_ARR 0x2c /* Auto-Reload Register */
|
||||
#define TIM_CCRx(x) (0x34 + 4 * ((x) - 1)) /* Capt/Comp Register x (x ∈ {1, .. 4}) */
|
||||
#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */
|
||||
#define TIM_DCR 0x48 /* DMA control register */
|
||||
#define TIM_DMAR 0x4C /* DMA register for transfer */
|
||||
#define TIM_TISEL 0x68 /* Input Selection */
|
||||
|
||||
#define TIM_CR1_CEN BIT(0) /* Counter Enable */
|
||||
#define TIM_CR1_ARPE BIT(7)
|
||||
#define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12))
|
||||
#define TIM_CCER_CC1E BIT(0)
|
||||
#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */
|
||||
#define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */
|
||||
#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */
|
||||
#define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */
|
||||
#define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */
|
||||
#define TIM_BDTR_MOE BIT(15) /* Main Output Enable */
|
||||
#define TIM_EGR_UG BIT(0) /* Update Generation */
|
||||
|
||||
#define MAX_TIM_PSC 0xFFFF
|
||||
|
||||
struct stm32_timers_plat {
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
struct stm32_timers_priv {
|
||||
u32 max_arr;
|
||||
ulong rate;
|
||||
};
|
||||
|
||||
#endif
|
@ -138,8 +138,6 @@ int mach_cpu_init(void)
|
||||
if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) &&
|
||||
(boot_mode & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_UART)
|
||||
gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
|
||||
else if (IS_ENABLED(CONFIG_DEBUG_UART) && IS_ENABLED(CONFIG_XPL_BUILD))
|
||||
debug_uart_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
82
arch/arm/mach-stm32mp/timers.c
Normal file
82
arch/arm/mach-stm32mp/timers.c
Normal file
@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2025, STMicroelectronics - All Rights Reserved
|
||||
* Author: Cheick Traore <cheick.traore@foss.st.com>
|
||||
*
|
||||
* Originally based on the Linux kernel v6.1 drivers/mfd/stm32-timers.c.
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/timers.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
static void stm32_timers_get_arr_size(struct udevice *dev)
|
||||
{
|
||||
struct stm32_timers_plat *plat = dev_get_plat(dev);
|
||||
struct stm32_timers_priv *priv = dev_get_priv(dev);
|
||||
u32 arr;
|
||||
|
||||
/* Backup ARR to restore it after getting the maximum value */
|
||||
arr = readl(plat->base + TIM_ARR);
|
||||
|
||||
/*
|
||||
* Only the available bits will be written so when readback
|
||||
* we get the maximum value of auto reload register
|
||||
*/
|
||||
writel(~0L, plat->base + TIM_ARR);
|
||||
priv->max_arr = readl(plat->base + TIM_ARR);
|
||||
writel(arr, plat->base + TIM_ARR);
|
||||
}
|
||||
|
||||
static int stm32_timers_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct stm32_timers_plat *plat = dev_get_plat(dev);
|
||||
|
||||
plat->base = dev_read_addr_ptr(dev);
|
||||
if (!plat->base) {
|
||||
dev_err(dev, "can't get address\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_timers_probe(struct udevice *dev)
|
||||
{
|
||||
struct stm32_timers_priv *priv = dev_get_priv(dev);
|
||||
struct clk clk;
|
||||
int ret = 0;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(&clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable clock: ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->rate = clk_get_rate(&clk);
|
||||
|
||||
stm32_timers_get_arr_size(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct udevice_id stm32_timers_ids[] = {
|
||||
{ .compatible = "st,stm32-timers" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stm32_timers) = {
|
||||
.name = "stm32_timers",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = stm32_timers_ids,
|
||||
.of_to_plat = stm32_timers_of_to_plat,
|
||||
.plat_auto = sizeof(struct stm32_timers_plat),
|
||||
.probe = stm32_timers_probe,
|
||||
.priv_auto = sizeof(struct stm32_timers_priv),
|
||||
.bind = dm_scan_fdt_dev,
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
STM32F746 DISCOVERY BOARD
|
||||
M: Vikas Manocha <vikas.manocha@st.com>
|
||||
M: Patrice Chotard <patrice.chotard@foss.st.com>
|
||||
S: Maintained
|
||||
F: doc/board/st/
|
||||
F: board/st/stm32f746-disco
|
||||
|
@ -76,42 +76,6 @@ u32 spl_boot_device(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
struct gpio_desc gpio = {};
|
||||
int node;
|
||||
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "st,led1");
|
||||
if (node < 0)
|
||||
return -1;
|
||||
|
||||
gpio_request_by_name_nodev(offset_to_ofnode(node), "led-gpio", 0, &gpio,
|
||||
GPIOD_IS_OUT);
|
||||
|
||||
if (dm_gpio_is_valid(&gpio)) {
|
||||
dm_gpio_set_value(&gpio, 0);
|
||||
mdelay(10);
|
||||
dm_gpio_set_value(&gpio, 1);
|
||||
}
|
||||
|
||||
/* read button 1*/
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "st,button1");
|
||||
if (node < 0)
|
||||
return -1;
|
||||
|
||||
gpio_request_by_name_nodev(offset_to_ofnode(node), "button-gpio", 0,
|
||||
&gpio, GPIOD_IS_IN);
|
||||
|
||||
if (dm_gpio_is_valid(&gpio)) {
|
||||
if (dm_gpio_get_value(&gpio))
|
||||
puts("usr button is at HIGH LEVEL\n");
|
||||
else
|
||||
puts("usr button is at LOW LEVEL\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ETH_DESIGNWARE
|
||||
|
@ -21,7 +21,6 @@ CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
|
||||
CONFIG_SYS_PBSIZE=1050
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_BOARD_LATE_INIT=y
|
||||
CONFIG_SYS_PROMPT="U-Boot > "
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_MMC=y
|
||||
|
@ -30,7 +30,6 @@ CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
|
||||
CONFIG_SYS_PBSIZE=1050
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_BOARD_LATE_INIT=y
|
||||
CONFIG_SPL_PAD_TO=0x9000
|
||||
CONFIG_SPL_NO_BSS_LIMIT=y
|
||||
CONFIG_SPL_BOARD_INIT=y
|
||||
|
@ -21,7 +21,6 @@ CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
|
||||
CONFIG_SYS_PBSIZE=1050
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_BOARD_LATE_INIT=y
|
||||
CONFIG_SYS_PROMPT="U-Boot > "
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_MMC=y
|
||||
|
@ -30,7 +30,6 @@ CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
|
||||
CONFIG_SYS_PBSIZE=1050
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_BOARD_LATE_INIT=y
|
||||
CONFIG_SPL_PAD_TO=0x9000
|
||||
CONFIG_SPL_NO_BSS_LIMIT=y
|
||||
CONFIG_SPL_BOARD_INIT=y
|
||||
|
@ -18,7 +18,7 @@ CONFIG_AUTOBOOT_KEYED=y
|
||||
CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n"
|
||||
CONFIG_AUTOBOOT_STOP_STR=" "
|
||||
CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
|
||||
CONFIG_BOOTARGS="console=ttySTM0,115200n8 earlyprintk consoleblank=0 ignore_loglevel"
|
||||
CONFIG_SYS_PBSIZE=1050
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_CYCLIC_MAX_CPU_TIME_US=8000
|
||||
|
@ -10,6 +10,7 @@ CONFIG_SYS_LOAD_ADDR=0xc2000000
|
||||
CONFIG_STM32MP13X=y
|
||||
CONFIG_DDR_CACHEABLE_SIZE=0x8000000
|
||||
CONFIG_CMD_STM32KEY=y
|
||||
CONFIG_MFD_STM32_TIMERS=y
|
||||
CONFIG_TARGET_ST_STM32MP13X=y
|
||||
CONFIG_ENV_OFFSET_REDUND=0x940000
|
||||
CONFIG_CMD_STM32PROG=y
|
||||
@ -31,6 +32,7 @@ CONFIG_CMD_UNZIP=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_PWM=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_LSBLK=y
|
||||
CONFIG_CMD_MMC=y
|
||||
@ -80,6 +82,8 @@ CONFIG_DM_REGULATOR=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_DM_REGULATOR_SCMI=y
|
||||
CONFIG_DM_PWM=y
|
||||
CONFIG_PWM_STM32=y
|
||||
CONFIG_RESET_SCMI=y
|
||||
CONFIG_DM_RNG=y
|
||||
CONFIG_RNG_STM32=y
|
||||
|
@ -28,10 +28,14 @@ CONFIG_CMD_RNG=y
|
||||
CONFIG_CMD_LOG=y
|
||||
CONFIG_CMD_UBI=y
|
||||
CONFIG_ENV_IS_NOWHERE=y
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_ENV_MMC_USE_DT=y
|
||||
CONFIG_ENV_SPI_MAX_HZ=50000000
|
||||
CONFIG_CLK_SCMI=y
|
||||
CONFIG_SET_DFU_ALT_INFO=y
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR=0x50
|
||||
CONFIG_SYS_MMC_ENV_DEV=0
|
||||
CONFIG_SYS_MMC_ENV_PART=1
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_DM_REGULATOR_SCMI=y
|
||||
CONFIG_RESET_SCMI=y
|
||||
@ -44,4 +48,3 @@ CONFIG_OPTEE=y
|
||||
CONFIG_USB_ONBOARD_HUB=y
|
||||
CONFIG_USB_HUB_DEBOUNCE_TIMEOUT=2000
|
||||
CONFIG_ERRNO_STR=y
|
||||
CONFIG_BOOTCOUNT_ALTBOOTCMD="
|
||||
|
8
configs/stm32mp15_dhcom_basic.config
Normal file
8
configs/stm32mp15_dhcom_basic.config
Normal file
@ -0,0 +1,8 @@
|
||||
#include <configs/stm32mp15_dhsom.config>
|
||||
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_STM32MP=y
|
||||
CONFIG_SYS_MEMTEST_START=0xc0000000
|
||||
CONFIG_SYS_MEMTEST_END=0xc4000000
|
||||
CONFIG_SYS_I2C_EEPROM_BUS=3
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR=0x50
|
@ -1,11 +1,4 @@
|
||||
#include <configs/stm32mp15_dhsom.config>
|
||||
#include <configs/stm32mp15_dhcom_basic.config>
|
||||
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_STM32MP=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157c-dhcom-pdk2"
|
||||
CONFIG_SYS_MEMTEST_START=0xc0000000
|
||||
CONFIG_SYS_MEMTEST_END=0xc4000000
|
||||
CONFIG_SYS_I2C_EEPROM_BUS=3
|
||||
CONFIG_OF_LIST="st/stm32mp157c-dhcom-pdk2 st/stm32mp153c-dhcom-drc02 st/stm32mp157c-dhcom-picoitx"
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR=0x50
|
||||
CONFIG_BOOTCOUNT_ALTBOOTCMD="
|
||||
|
4
configs/stm32mp15_dhcom_drc02_basic_defconfig
Normal file
4
configs/stm32mp15_dhcom_drc02_basic_defconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include <configs/stm32mp15_dhcom_basic.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp153c-dhcom-drc02"
|
||||
CONFIG_OF_LIST="st/stm32mp153c-dhcom-drc02"
|
4
configs/stm32mp15_dhcom_pdk2_basic_defconfig
Normal file
4
configs/stm32mp15_dhcom_pdk2_basic_defconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include <configs/stm32mp15_dhcom_basic.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157c-dhcom-pdk2"
|
||||
CONFIG_OF_LIST="st/stm32mp157c-dhcom-pdk2"
|
4
configs/stm32mp15_dhcom_picoitx_basic_defconfig
Normal file
4
configs/stm32mp15_dhcom_picoitx_basic_defconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include <configs/stm32mp15_dhcom_basic.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157c-dhcom-picoitx"
|
||||
CONFIG_OF_LIST="st/stm32mp157c-dhcom-picoitx"
|
4
configs/stm32mp15_dhcor_avenger96_basic_defconfig
Normal file
4
configs/stm32mp15_dhcor_avenger96_basic_defconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include <configs/stm32mp15_dhcor_basic.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157a-dhcor-avenger96"
|
||||
CONFIG_OF_LIST="st/stm32mp157a-dhcor-avenger96"
|
8
configs/stm32mp15_dhcor_basic.config
Normal file
8
configs/stm32mp15_dhcor_basic.config
Normal file
@ -0,0 +1,8 @@
|
||||
#include <configs/stm32mp15_dhsom.config>
|
||||
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_STM32MP=y
|
||||
CONFIG_SYS_I2C_EEPROM_BUS=2
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR=0x53
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
@ -1,11 +1,4 @@
|
||||
#include <configs/stm32mp15_dhsom.config>
|
||||
#include <configs/stm32mp15_dhcor_basic.config>
|
||||
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_STM32MP=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp157a-dhcor-avenger96"
|
||||
CONFIG_SYS_I2C_EEPROM_BUS=2
|
||||
CONFIG_OF_LIST="st/stm32mp157a-dhcor-avenger96 st/stm32mp151a-dhcor-testbench st/stm32mp153c-dhcor-drc-compact"
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR=0x53
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
CONFIG_BOOTCOUNT_ALTBOOTCMD="
|
||||
|
4
configs/stm32mp15_dhcor_drc_compact_basic_defconfig
Normal file
4
configs/stm32mp15_dhcor_drc_compact_basic_defconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include <configs/stm32mp15_dhcor_basic.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp153c-dhcor-drc-compact"
|
||||
CONFIG_OF_LIST="st/stm32mp153c-dhcor-drc-compact"
|
4
configs/stm32mp15_dhcor_testbench_basic_defconfig
Normal file
4
configs/stm32mp15_dhcor_testbench_basic_defconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include <configs/stm32mp15_dhcor_basic.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="st/stm32mp151a-dhcor-testbench"
|
||||
CONFIG_OF_LIST="st/stm32mp151a-dhcor-testbench"
|
@ -105,6 +105,14 @@ config PWM_TEGRA
|
||||
32KHz clock is supported by the driver but the duty cycle is
|
||||
configurable.
|
||||
|
||||
config PWM_STM32
|
||||
bool "Enable support for STM32 PWM"
|
||||
depends on DM_PWM && MFD_STM32_TIMERS
|
||||
help
|
||||
This enables PWM driver for STMicroelectronics STM32 pulse width
|
||||
modulation. It uses STM32 timer devices that can have up to 4 output
|
||||
channels, with complementary outputs and configurable polarity.
|
||||
|
||||
config PWM_SUNXI
|
||||
bool "Enable support for the Allwinner Sunxi PWM"
|
||||
depends on DM_PWM
|
||||
|
@ -22,5 +22,6 @@ obj-$(CONFIG_PWM_ROCKCHIP) += rk_pwm.o
|
||||
obj-$(CONFIG_PWM_SANDBOX) += sandbox_pwm.o
|
||||
obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o
|
||||
obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o
|
||||
obj-$(CONFIG_PWM_STM32) += pwm-stm32.o
|
||||
obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o
|
||||
obj-$(CONFIG_PWM_TI_EHRPWM) += pwm-ti-ehrpwm.o
|
||||
|
205
drivers/pwm/pwm-stm32.c
Normal file
205
drivers/pwm/pwm-stm32.c
Normal file
@ -0,0 +1,205 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2025, STMicroelectronics - All Rights Reserved
|
||||
* Author: Cheick Traore <cheick.traore@foss.st.com>
|
||||
*
|
||||
* Originally based on the Linux kernel v6.10 drivers/pwm/pwm-stm32.c.
|
||||
*/
|
||||
|
||||
#include <div64.h>
|
||||
#include <dm.h>
|
||||
#include <pwm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/timers.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#define CCMR_CHANNEL_SHIFT 8
|
||||
#define CCMR_CHANNEL_MASK 0xFF
|
||||
|
||||
struct stm32_pwm_priv {
|
||||
bool have_complementary_output;
|
||||
bool invert_polarity;
|
||||
};
|
||||
|
||||
static u32 active_channels(struct stm32_timers_plat *plat)
|
||||
{
|
||||
return readl(plat->base + TIM_CCER) & TIM_CCER_CCXE;
|
||||
}
|
||||
|
||||
static int stm32_pwm_set_config(struct udevice *dev, uint channel,
|
||||
uint period_ns, uint duty_ns)
|
||||
{
|
||||
struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev));
|
||||
struct stm32_timers_priv *priv = dev_get_priv(dev_get_parent(dev));
|
||||
unsigned long long prd, div, dty;
|
||||
unsigned int prescaler = 0;
|
||||
u32 ccmr, mask, shift;
|
||||
|
||||
if (duty_ns > period_ns)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Period and prescaler values depends on clock rate
|
||||
* First we need to find the minimal value for prescaler such that
|
||||
*
|
||||
* period_ns * clkrate
|
||||
* ------------------------------ < max_arr + 1
|
||||
* NSEC_PER_SEC * (prescaler + 1)
|
||||
*
|
||||
* This equation is equivalent to
|
||||
*
|
||||
* period_ns * clkrate
|
||||
* ---------------------------- < prescaler + 1
|
||||
* NSEC_PER_SEC * (max_arr + 1)
|
||||
*
|
||||
* Using integer division and knowing that the right hand side is
|
||||
* integer, this is further equivalent to
|
||||
*
|
||||
* (period_ns * clkrate) // (NSEC_PER_SEC * (max_arr + 1)) ≤ prescaler
|
||||
*/
|
||||
|
||||
div = (unsigned long long)priv->rate * period_ns;
|
||||
do_div(div, NSEC_PER_SEC);
|
||||
prd = div;
|
||||
|
||||
do_div(div, priv->max_arr + 1);
|
||||
prescaler = div;
|
||||
if (prescaler > MAX_TIM_PSC)
|
||||
return -EINVAL;
|
||||
|
||||
do_div(prd, prescaler + 1);
|
||||
if (!prd)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* All channels share the same prescaler and counter so when two
|
||||
* channels are active at the same time we can't change them
|
||||
*/
|
||||
if (active_channels(plat) & ~(1 << channel * 4)) {
|
||||
u32 psc, arr;
|
||||
|
||||
psc = readl(plat->base + TIM_PSC);
|
||||
arr = readl(plat->base + TIM_ARR);
|
||||
if (psc != prescaler || arr != prd - 1)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
writel(prescaler, plat->base + TIM_PSC);
|
||||
writel(prd - 1, plat->base + TIM_ARR);
|
||||
setbits_le32(plat->base + TIM_CR1, TIM_CR1_ARPE);
|
||||
|
||||
/* Calculate the duty cycles */
|
||||
dty = prd * duty_ns;
|
||||
do_div(dty, period_ns);
|
||||
|
||||
writel(dty, plat->base + TIM_CCRx(channel + 1));
|
||||
|
||||
/* Configure output mode */
|
||||
shift = (channel & 0x1) * CCMR_CHANNEL_SHIFT;
|
||||
ccmr = (TIM_CCMR_PE | TIM_CCMR_M1) << shift;
|
||||
mask = CCMR_CHANNEL_MASK << shift;
|
||||
if (channel < 2)
|
||||
clrsetbits_le32(plat->base + TIM_CCMR1, mask, ccmr);
|
||||
else
|
||||
clrsetbits_le32(plat->base + TIM_CCMR2, mask, ccmr);
|
||||
|
||||
setbits_le32(plat->base + TIM_BDTR, TIM_BDTR_MOE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_pwm_set_enable(struct udevice *dev, uint channel,
|
||||
bool enable)
|
||||
{
|
||||
struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev));
|
||||
struct stm32_pwm_priv *priv = dev_get_priv(dev);
|
||||
u32 mask;
|
||||
|
||||
/* Enable channel */
|
||||
mask = TIM_CCER_CC1E << (channel * 4);
|
||||
if (priv->have_complementary_output)
|
||||
mask |= TIM_CCER_CC1NE << (channel * 4);
|
||||
|
||||
if (enable) {
|
||||
setbits_le32(plat->base + TIM_CCER, mask);
|
||||
/* Make sure that registers are updated */
|
||||
setbits_le32(plat->base + TIM_EGR, TIM_EGR_UG);
|
||||
/* Enable controller */
|
||||
setbits_le32(plat->base + TIM_CR1, TIM_CR1_CEN);
|
||||
} else {
|
||||
clrbits_le32(plat->base + TIM_CCER, mask);
|
||||
/* When all channels are disabled, we can disable the controller */
|
||||
if (!active_channels(plat))
|
||||
clrbits_le32(plat->base + TIM_CR1, TIM_CR1_CEN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_pwm_set_invert(struct udevice *dev, uint channel,
|
||||
bool polarity)
|
||||
{
|
||||
struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev));
|
||||
struct stm32_pwm_priv *priv = dev_get_priv(dev);
|
||||
u32 mask;
|
||||
|
||||
mask = TIM_CCER_CC1P << (channel * 4);
|
||||
if (priv->have_complementary_output)
|
||||
mask |= TIM_CCER_CC1NP << (channel * 4);
|
||||
|
||||
clrsetbits_le32(plat->base + TIM_CCER, mask, polarity ? mask : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stm32_pwm_detect_complementary(struct udevice *dev)
|
||||
{
|
||||
struct stm32_timers_plat *plat = dev_get_plat(dev_get_parent(dev));
|
||||
struct stm32_pwm_priv *priv = dev_get_priv(dev);
|
||||
u32 ccer;
|
||||
|
||||
/*
|
||||
* If complementary bit doesn't exist writing 1 will have no
|
||||
* effect so we can detect it.
|
||||
*/
|
||||
setbits_le32(plat->base + TIM_CCER, TIM_CCER_CC1NE);
|
||||
ccer = readl(plat->base + TIM_CCER);
|
||||
clrbits_le32(plat->base + TIM_CCER, TIM_CCER_CC1NE);
|
||||
|
||||
priv->have_complementary_output = (ccer != 0);
|
||||
}
|
||||
|
||||
static int stm32_pwm_probe(struct udevice *dev)
|
||||
{
|
||||
struct stm32_timers_priv *timer = dev_get_priv(dev_get_parent(dev));
|
||||
|
||||
if (timer->rate > 1000000000) {
|
||||
dev_err(dev, "Clock freq too high (%lu)\n", timer->rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stm32_pwm_detect_complementary(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pwm_ops stm32_pwm_ops = {
|
||||
.set_config = stm32_pwm_set_config,
|
||||
.set_enable = stm32_pwm_set_enable,
|
||||
.set_invert = stm32_pwm_set_invert,
|
||||
};
|
||||
|
||||
static const struct udevice_id stm32_pwm_ids[] = {
|
||||
{ .compatible = "st,stm32-pwm" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stm32_pwm) = {
|
||||
.name = "stm32_pwm",
|
||||
.id = UCLASS_PWM,
|
||||
.of_match = stm32_pwm_ids,
|
||||
.ops = &stm32_pwm_ops,
|
||||
.probe = stm32_pwm_probe,
|
||||
.priv_auto = sizeof(struct stm32_pwm_priv),
|
||||
};
|
@ -299,13 +299,19 @@ static inline struct stm32_uart_info *_debug_uart_info(void)
|
||||
|
||||
static inline void _debug_uart_init(void)
|
||||
{
|
||||
void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE);
|
||||
struct stm32_uart_info *uart_info = _debug_uart_info();
|
||||
void __maybe_unused __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE);
|
||||
struct stm32_uart_info *uart_info __maybe_unused = _debug_uart_info();
|
||||
|
||||
/*
|
||||
* debug_uart_init() is only usable when SPL_BUILD is enabled
|
||||
* (STM32MP1 case only)
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_DEBUG_UART) && IS_ENABLED(CONFIG_SPL_BUILD)) {
|
||||
_stm32_serial_init(base, uart_info);
|
||||
_stm32_serial_setbrg(base, uart_info,
|
||||
CONFIG_DEBUG_UART_CLOCK,
|
||||
CONFIG_BAUDRATE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _debug_uart_putc(int c)
|
||||
|
Loading…
Reference in New Issue
Block a user