
HSE and LSE bypass shall support both analog and digital signals. This patch add a way to select digital bypas case in the device tree and set the associated bit DIGBYP in RCC_BDCR and RCC_OCEN register during clock tree initialization.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
doc/device-tree-bindings/clock/st,stm32mp1.txt | 4 +++- drivers/clk/clk_stm32mp1.c | 27 +++++++++++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/doc/device-tree-bindings/clock/st,stm32mp1.txt b/doc/device-tree-bindings/clock/st,stm32mp1.txt index c29d90f..6a9397e 100644 --- a/doc/device-tree-bindings/clock/st,stm32mp1.txt +++ b/doc/device-tree-bindings/clock/st,stm32mp1.txt @@ -170,8 +170,10 @@ Optional properties :
a) for external oscillator: "clk-lse", "clk-hse"
- 3 optional fields are managed + 4 optional fields are managed - "st,bypass" Configure the oscillator bypass mode (HSEBYP, LSEBYP) + - "st,digbypass" Configure the bypass mode as full-swing digital signal + (DIGBYP) - "st,css" Activate the clock security system (HSECSSON, LSECSSON) - "st,drive" (only for LSE) value of the drive for the oscillator (see LSEDRV_ define in the file dt-bindings/clock/stm32mp1-clksrc.h) diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index fc97642..45c417e 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -149,6 +149,7 @@ #define RCC_BDCR_LSEON BIT(0) #define RCC_BDCR_LSEBYP BIT(1) #define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) #define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) #define RCC_BDCR_LSEDRV_SHIFT 4 #define RCC_BDCR_LSECSSON BIT(8) @@ -203,6 +204,7 @@ /* used for RCC_OCENSETR and RCC_OCENCLRR registers */ #define RCC_OCENR_HSION BIT(0) #define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_DIGBYP BIT(7) #define RCC_OCENR_HSEON BIT(8) #define RCC_OCENR_HSEBYP BIT(10) #define RCC_OCENR_HSECSSON BIT(11) @@ -1202,11 +1204,15 @@ static int stm32mp1_osc_wait(int enable, fdt_addr_t rcc, u32 offset, return ret; }
-static void stm32mp1_lse_enable(fdt_addr_t rcc, int bypass, int lsedrv) +static void stm32mp1_lse_enable(fdt_addr_t rcc, int bypass, int digbyp, + int lsedrv) { u32 value;
- if (bypass) + if (digbyp) + setbits_le32(rcc + RCC_BDCR, RCC_BDCR_DIGBYP); + + if (bypass || digbyp) setbits_le32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP);
/* @@ -1241,9 +1247,11 @@ static void stm32mp1_lsi_set(fdt_addr_t rcc, int enable) stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY); }
-static void stm32mp1_hse_enable(fdt_addr_t rcc, int bypass, int css) +static void stm32mp1_hse_enable(fdt_addr_t rcc, int bypass, int digbyp, int css) { - if (bypass) + if (digbyp) + setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_DIGBYP); + if (bypass || digbyp) setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_HSEBYP);
stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON); @@ -1606,26 +1614,27 @@ static int stm32mp1_clktree(struct udevice *dev) stm32mp1_lsi_set(rcc, 1);
if (priv->osc[_LSE]) { - int bypass; - int lsedrv; + int bypass, digbyp, lsedrv; struct udevice *dev = priv->osc_dev[_LSE];
bypass = dev_read_bool(dev, "st,bypass"); + digbyp = dev_read_bool(dev, "st,digbypass"); lse_css = dev_read_bool(dev, "st,css"); lsedrv = dev_read_u32_default(dev, "st,drive", LSEDRV_MEDIUM_HIGH);
- stm32mp1_lse_enable(rcc, bypass, lsedrv); + stm32mp1_lse_enable(rcc, bypass, digbyp, lsedrv); }
if (priv->osc[_HSE]) { - int bypass, css; + int bypass, digbyp, css; struct udevice *dev = priv->osc_dev[_HSE];
bypass = dev_read_bool(dev, "st,bypass"); + digbyp = dev_read_bool(dev, "st,digbypass"); css = dev_read_bool(dev, "st,css");
- stm32mp1_hse_enable(rcc, bypass, css); + stm32mp1_hse_enable(rcc, bypass, digbyp, css); } /* CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) * => switch on CSI even if node is not present in device tree