diff --git a/recipes-kernel/linux/linux-stm32mp.inc b/recipes-kernel/linux/linux-stm32mp.inc index 90d39d0..8621a91 100644 --- a/recipes-kernel/linux/linux-stm32mp.inc +++ b/recipes-kernel/linux/linux-stm32mp.inc @@ -12,9 +12,6 @@ EXTERNALSRC_BUILD_pn-${PN} = "${WORKDIR}/build" # To share config fragments between layers FILESEXTRAPATHS_prepend := "${THISDIR}:" -# ------------------------------------------------------------- -# Do not deploy kernel module with specfic tarball -MODULE_TARBALL_DEPLOY = "0" do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel" #--------------------------------------------------------------- @@ -22,13 +19,16 @@ do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel" KERNEL_SIGN_ENABLE ?= "0" EXTRA_OEMAKE += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', 'INSTALL_MOD_STRIP=1','')}" +# YoctoProject bugzilla : 140044 +# There's a race between do_symlink_kernsrc and do_populate_lic, since the latter is ordered "after do_patch"; # -# Force task order for link creation -# +# Below a STMicroelectonics' hacks waiting for official Yocto patch: +# commit already exists in gathesgarth : +#a2b50b74d609ce079ab36b82d4c7c3539fb56485 kernel.bbclass: ensure symlink_kernsrc task gets run even with externalsrc python () { - d.appendVarFlag("do_unpack", "postfuncs", " do_symlink_kernsrc") + bb.build.deltask('do_symlink_kernsrc', d) + bb.build.addtask('do_symlink_kernsrc', 'do_patch do_configure', 'do_unpack', d) } -do_symlink_kernsrc[noexec] = "1" # --------------------------------------------------------------------- @@ -77,6 +77,15 @@ do_configure_prepend() { #oe_runmake -C ${S} O=${B} savedefconfig && cp ${B}/defconfig ${WORKDIR}/defconfig.saved } +# --------------------------------------------------------------------- +do_compile_kernelmodules_append() { + if (grep -q -i -e '^CONFIG_MODULES=y$' ${B}/.config); then + # 5.10+ kernels have module.lds that we need to copy for external module builds + if [ -e "${B}/scripts/module.lds" ]; then + install -Dm 0644 ${B}/scripts/module.lds ${STAGING_KERNEL_BUILDDIR}/scripts/module.lds + fi + fi +} # --------------------------------------------------------------------- do_install_append() { # Install KERNEL_IMAGETYPE for kernel-imagebootfs package @@ -86,8 +95,19 @@ do_install_append() { # when ACCEPT_EULA are filled echo "blacklist etnaviv" > ${D}/${sysconfdir}/modprobe.d/blacklist.conf fi + #snd dependencies + install -d ${D}/${sysconfdir}/modprobe.d/ + echo "softdep snd-soc-cs42l51 pre: snd-soc-cs42l51-i2c" > ${D}/${sysconfdir}/modprobe.d/stm32mp1-snd.conf } - +# --------------------------------------------------------------------- +do_deploy_append() { + if [ ${MODULE_TARBALL_DEPLOY} = "1" ] && (grep -q -i -e '^CONFIG_MODULES=y$' .config); then + mkdir -p ${D}${root_prefix}/lib + tar -cvzf $deployDir/modules-stripped-${MODULE_TARBALL_NAME}.tgz -C ${WORKDIR}/package/${root_prefix} lib + ln -sf modules-stripped-${MODULE_TARBALL_NAME}.tgz $deployDir/modules-stripped-${MODULE_TARBALL_LINK_NAME}.tgz + fi +} +do_deploy[depends] += " virtual/kernel:do_package " # --------------------------------------------------------------------- # Support checking the kernel load address parameter: expecting proper value for ST kernel. # diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0001-ARM-5.10.10-stm32mp1-r1-MACHINE.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0001-ARM-5.10.10-stm32mp1-r1-MACHINE.patch new file mode 100644 index 0000000..083bb15 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0001-ARM-5.10.10-stm32mp1-r1-MACHINE.patch @@ -0,0 +1,40 @@ +From ac8315bbe1279affc860703a9062143e9eab9fa0 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 08:54:31 +0100 +Subject: [PATCH 01/22] ARM 5.10.10-stm32mp1-r1 MACHINE + +Signed-off-by: Romuald JEANNE +--- + arch/arm/mach-stm32/Kconfig | 2 ++ + arch/arm/mach-stm32/board-dt.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig +index 57699bd8f107..d1f79bc2ccda 100644 +--- a/arch/arm/mach-stm32/Kconfig ++++ b/arch/arm/mach-stm32/Kconfig +@@ -46,6 +46,8 @@ if ARCH_MULTI_V7 + config MACH_STM32MP157 + bool "STMicroelectronics STM32MP157" + select ARM_ERRATA_814220 ++ select REGULATOR ++ select ARCH_SUPPORTS_RT + default y + + endif # ARMv7-A +diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c +index 011d57b488c2..8e06a94421d9 100644 +--- a/arch/arm/mach-stm32/board-dt.c ++++ b/arch/arm/mach-stm32/board-dt.c +@@ -17,6 +17,8 @@ static const char *const stm32_compat[] __initconst = { + "st,stm32f746", + "st,stm32f769", + "st,stm32h743", ++ "st,stm32mp151", ++ "st,stm32mp153", + "st,stm32mp157", + NULL + }; +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0005-ARM-stm32mp1-r2-CLOCK.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0002-ARM-5.10.10-stm32mp1-r1-CLOCK.patch similarity index 72% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0005-ARM-stm32mp1-r2-CLOCK.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0002-ARM-5.10.10-stm32mp1-r1-CLOCK.patch index 631d8ac..b1cc72e 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0005-ARM-stm32mp1-r2-CLOCK.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0002-ARM-5.10.10-stm32mp1-r1-CLOCK.patch @@ -1,23 +1,18 @@ -From 791f0dfb6aaf584e1a73c0aca77cb95d8dae8070 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:42 +0200 -Subject: [PATCH 05/22] ARM-stm32mp1-r2-rc8-CLOCK +From f2f9b8ceceeb143fd478d89126a475d26b11f488 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 08:58:27 +0100 +Subject: [PATCH 02/22] ARM 5.10.10-stm32mp1-r1 CLOCK --- - drivers/clk/clk-composite.c | 15 + - drivers/clk/clk-stm32mp1.c | 933 ++++++++++++++++------ - drivers/clk/clk.c | 7 +- - drivers/clocksource/Kconfig | 4 + - drivers/clocksource/Makefile | 1 + - drivers/clocksource/timer-stm32-lp.c | 221 +++++ - drivers/counter/stm32-lptimer-cnt.c | 2 +- - drivers/counter/stm32-timer-cnt.c | 68 +- - include/dt-bindings/clock/stm32mp1-clks.h | 33 + - 9 files changed, 1026 insertions(+), 258 deletions(-) - create mode 100644 drivers/clocksource/timer-stm32-lp.c + drivers/clk/clk-composite.c | 15 + + drivers/clk/clk-stm32mp1.c | 1081 ++++++++++++++++----- + drivers/clk/clk.c | 7 +- + drivers/clocksource/timer-stm32-lp.c | 4 +- + include/dt-bindings/clock/stm32mp1-clks.h | 33 + + 5 files changed, 873 insertions(+), 267 deletions(-) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c -index 4f13a681ddfcd..853558156bda1 100644 +index 2ddb54f7d3ab..b49ecd1b9e56 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -41,6 +41,18 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, @@ -39,7 +34,7 @@ index 4f13a681ddfcd..853558156bda1 100644 static int clk_composite_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { -@@ -246,6 +258,9 @@ struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name, +@@ -250,6 +262,9 @@ static struct clk_hw *__clk_hw_register_composite(struct device *dev, } clk_composite_ops->recalc_rate = clk_composite_recalc_rate; @@ -50,10 +45,10 @@ index 4f13a681ddfcd..853558156bda1 100644 clk_composite_ops->determine_rate = clk_composite_determine_rate; diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c -index a875649df8b8f..2a1de15cd9813 100644 +index a875649df8b8..bf927befe97b 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c -@@ -5,15 +5,26 @@ +@@ -5,15 +5,28 @@ * Author: Gabriel Fernandez for STMicroelectronics. */ @@ -66,6 +61,7 @@ index a875649df8b8f..2a1de15cd9813 100644 #include +#include #include ++#include +#include +#include +#include @@ -74,13 +70,14 @@ index a875649df8b8f..2a1de15cd9813 100644 +#include +#include +#include ++#include #include #include +#include #include -@@ -45,6 +56,7 @@ static DEFINE_SPINLOCK(rlock); +@@ -45,6 +58,7 @@ static DEFINE_SPINLOCK(rlock); #define RCC_AHB5ENSETR 0x210 #define RCC_AHB6ENSETR 0x218 #define RCC_AHB6LPENSETR 0x318 @@ -88,7 +85,7 @@ index a875649df8b8f..2a1de15cd9813 100644 #define RCC_RCK12SELR 0x28 #define RCC_RCK3SELR 0x820 #define RCC_RCK4SELR 0x824 -@@ -101,8 +113,12 @@ static DEFINE_SPINLOCK(rlock); +@@ -101,8 +115,12 @@ static DEFINE_SPINLOCK(rlock); #define RCC_TIMG2PRER 0x82C #define RCC_RTCDIVR 0x44 #define RCC_DBGCFGR 0x80C @@ -102,7 +99,7 @@ index a875649df8b8f..2a1de15cd9813 100644 static const char * const ref12_parents[] = { "ck_hsi", "ck_hse" -@@ -113,7 +129,7 @@ static const char * const ref3_parents[] = { +@@ -113,7 +131,7 @@ static const char * const ref3_parents[] = { }; static const char * const ref4_parents[] = { @@ -111,7 +108,7 @@ index a875649df8b8f..2a1de15cd9813 100644 }; static const char * const cpu_src[] = { -@@ -245,7 +261,7 @@ static const char * const dsi_src[] = { +@@ -245,7 +263,7 @@ static const char * const dsi_src[] = { }; static const char * const rtc_src[] = { @@ -120,7 +117,7 @@ index a875649df8b8f..2a1de15cd9813 100644 }; static const char * const mco1_src[] = { -@@ -291,6 +307,7 @@ static const struct clk_div_table ck_trace_div_table[] = { +@@ -291,6 +309,7 @@ static const struct clk_div_table ck_trace_div_table[] = { struct stm32_mmux { u8 nbr_clk; struct clk_hw *hws[MAX_MUX_CLK]; @@ -128,7 +125,7 @@ index a875649df8b8f..2a1de15cd9813 100644 }; struct stm32_clk_mmux { -@@ -323,7 +340,7 @@ struct clock_config { +@@ -323,7 +342,7 @@ struct clock_config { const struct clock_config *cfg); }; @@ -137,7 +134,7 @@ index a875649df8b8f..2a1de15cd9813 100644 struct gate_cfg { u32 reg_off; -@@ -469,7 +486,7 @@ static const struct clk_ops mp1_gate_clk_ops = { +@@ -469,7 +488,7 @@ static const struct clk_ops mp1_gate_clk_ops = { .is_enabled = clk_gate_is_enabled, }; @@ -146,7 +143,7 @@ index a875649df8b8f..2a1de15cd9813 100644 const struct stm32_mux_cfg *cfg, spinlock_t *lock) { -@@ -478,7 +495,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, +@@ -478,7 +497,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, struct clk_hw *mux_hw; if (cfg->mmux) { @@ -155,7 +152,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!mmux) return ERR_PTR(-ENOMEM); -@@ -493,7 +510,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, +@@ -493,7 +512,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, cfg->mmux->hws[cfg->mmux->nbr_clk++] = mux_hw; } else { @@ -164,7 +161,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!mux) return ERR_PTR(-ENOMEM); -@@ -509,13 +526,13 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, +@@ -509,13 +528,13 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, return mux_hw; } @@ -180,7 +177,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!div) return ERR_PTR(-ENOMEM); -@@ -530,16 +547,16 @@ static struct clk_hw *_get_stm32_div(void __iomem *base, +@@ -530,16 +549,16 @@ static struct clk_hw *_get_stm32_div(void __iomem *base, return &div->hw; } @@ -201,7 +198,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!mgate) return ERR_PTR(-ENOMEM); -@@ -554,7 +571,7 @@ _get_stm32_gate(void __iomem *base, +@@ -554,7 +573,7 @@ _get_stm32_gate(void __iomem *base, gate_hw = &mgate->gate.hw; } else { @@ -210,7 +207,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!gate) return ERR_PTR(-ENOMEM); -@@ -592,7 +609,7 @@ clk_stm32_register_gate_ops(struct device *dev, +@@ -592,7 +611,7 @@ clk_stm32_register_gate_ops(struct device *dev, if (cfg->ops) init.ops = cfg->ops; @@ -219,7 +216,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (IS_ERR(hw)) return ERR_PTR(-ENOMEM); -@@ -623,7 +640,7 @@ clk_stm32_register_composite(struct device *dev, +@@ -623,7 +642,7 @@ clk_stm32_register_composite(struct device *dev, gate_ops = NULL; if (cfg->mux) { @@ -228,7 +225,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!IS_ERR(mux_hw)) { mux_ops = &clk_mux_ops; -@@ -634,7 +651,7 @@ clk_stm32_register_composite(struct device *dev, +@@ -634,7 +653,7 @@ clk_stm32_register_composite(struct device *dev, } if (cfg->div) { @@ -237,7 +234,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!IS_ERR(div_hw)) { div_ops = &clk_divider_ops; -@@ -645,7 +662,7 @@ clk_stm32_register_composite(struct device *dev, +@@ -645,7 +664,7 @@ clk_stm32_register_composite(struct device *dev, } if (cfg->gate) { @@ -246,7 +243,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!IS_ERR(gate_hw)) { gate_ops = &clk_gate_ops; -@@ -714,7 +731,7 @@ static int clk_mmux_set_parent(struct clk_hw *hw, u8 index) +@@ -714,7 +733,7 @@ static int clk_mmux_set_parent(struct clk_hw *hw, u8 index) for (n = 0; n < clk_mmux->mmux->nbr_clk; n++) if (clk_mmux->mmux->hws[n] != hw) @@ -255,7 +252,7 @@ index a875649df8b8f..2a1de15cd9813 100644 return 0; } -@@ -725,178 +742,266 @@ static const struct clk_ops clk_mmux_ops = { +@@ -725,178 +744,266 @@ static const struct clk_ops clk_mmux_ops = { .determine_rate = __clk_mux_determine_rate, }; @@ -383,14 +380,14 @@ index a875649df8b8f..2a1de15cd9813 100644 - u32 reg; - unsigned long flags = 0; + struct clk_hw *composite_hw = __clk_get_hw(hw->clk); - -- spin_lock_irqsave(clk_elem->lock, flags); ++ + clk_mmux_restore_parent(composite_hw); + mp1_mgate_clk_enable(hw); + + return 0; +} -+ + +- spin_lock_irqsave(clk_elem->lock, flags); +static void mp1_mgate_clk_disable_safe(struct clk_hw *hw) +{ + struct clk_hw *composite_hw = __clk_get_hw(hw->clk); @@ -527,10 +524,10 @@ index a875649df8b8f..2a1de15cd9813 100644 - } + if (bit_status) + udelay(120); -+ -+ } while (bit_status && --timeout); - return rate + rate_frac; ++ } while (bit_status && --timeout); ++ + return bit_status; } @@ -637,7 +634,7 @@ index a875649df8b8f..2a1de15cd9813 100644 } /* Kernel Timer */ -@@ -1005,7 +1110,7 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, +@@ -1005,7 +1112,7 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, struct clk_hw *hw; int err; @@ -646,7 +643,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!tim_ker) return ERR_PTR(-ENOMEM); -@@ -1023,16 +1128,90 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, +@@ -1023,16 +1130,90 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, hw = &tim_ker->hw; err = clk_hw_register(dev, hw); @@ -740,7 +737,7 @@ index a875649df8b8f..2a1de15cd9813 100644 }; static struct clk_hw *_clk_register_pll(struct device *dev, -@@ -1042,8 +1221,11 @@ static struct clk_hw *_clk_register_pll(struct device *dev, +@@ -1042,8 +1223,11 @@ static struct clk_hw *_clk_register_pll(struct device *dev, { struct stm32_pll_cfg *stm_pll_cfg = cfg->cfg; @@ -754,7 +751,7 @@ index a875649df8b8f..2a1de15cd9813 100644 } struct stm32_cktim_cfg { -@@ -1153,14 +1335,16 @@ _clk_stm32_register_composite(struct device *dev, +@@ -1153,14 +1337,16 @@ _clk_stm32_register_composite(struct device *dev, .func = _clk_hw_register_mux,\ } @@ -775,7 +772,7 @@ index a875649df8b8f..2a1de15cd9813 100644 },\ .func = _clk_register_pll,\ } -@@ -1216,7 +1400,7 @@ _clk_stm32_register_composite(struct device *dev, +@@ -1216,7 +1402,7 @@ _clk_stm32_register_composite(struct device *dev, NULL, &mp1_gate_clk_ops)\ #define _MGATE_MP1(_mgate)\ @@ -784,7 +781,7 @@ index a875649df8b8f..2a1de15cd9813 100644 #define GATE_MP1(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\ STM32_GATE(_id, _name, _parent, _flags,\ -@@ -1228,7 +1412,7 @@ _clk_stm32_register_composite(struct device *dev, +@@ -1228,7 +1414,7 @@ _clk_stm32_register_composite(struct device *dev, #define _STM32_DIV(_div_offset, _div_shift, _div_width,\ _div_flags, _div_table, _ops)\ @@ -793,7 +790,7 @@ index a875649df8b8f..2a1de15cd9813 100644 &(struct div_cfg) {\ .reg_off = _div_offset,\ .shift = _div_shift,\ -@@ -1237,14 +1421,23 @@ _clk_stm32_register_composite(struct device *dev, +@@ -1237,14 +1423,23 @@ _clk_stm32_register_composite(struct device *dev, .table = _div_table,\ },\ .ops = _ops,\ @@ -820,7 +817,7 @@ index a875649df8b8f..2a1de15cd9813 100644 &(struct mux_cfg) {\ .reg_off = _offset,\ .shift = _shift,\ -@@ -1254,18 +1447,18 @@ _clk_stm32_register_composite(struct device *dev, +@@ -1254,18 +1449,18 @@ _clk_stm32_register_composite(struct device *dev, },\ .mmux = _mmux,\ .ops = _ops,\ @@ -846,7 +843,7 @@ index a875649df8b8f..2a1de15cd9813 100644 #define COMPOSITE(_id, _name, _parents, _flags, _gate, _mux, _div)\ {\ -@@ -1275,9 +1468,9 @@ _clk_stm32_register_composite(struct device *dev, +@@ -1275,9 +1470,9 @@ _clk_stm32_register_composite(struct device *dev, .num_parents = ARRAY_SIZE(_parents),\ .flags = _flags,\ .cfg = &(struct stm32_composite_cfg) {\ @@ -859,7 +856,7 @@ index a875649df8b8f..2a1de15cd9813 100644 },\ .func = _clk_stm32_register_composite,\ } -@@ -1292,6 +1485,11 @@ _clk_stm32_register_composite(struct device *dev, +@@ -1292,6 +1487,11 @@ _clk_stm32_register_composite(struct device *dev, _MMUX(_mmux),\ _NO_DIV) @@ -871,7 +868,7 @@ index a875649df8b8f..2a1de15cd9813 100644 enum { G_SAI1, G_SAI2, -@@ -1409,8 +1607,7 @@ enum { +@@ -1409,8 +1609,7 @@ enum { static struct stm32_mgate mp1_mgate[G_LAST]; @@ -881,7 +878,7 @@ index a875649df8b8f..2a1de15cd9813 100644 [_id] = {\ &(struct gate_cfg) {\ .reg_off = _gate_offset,\ -@@ -1429,6 +1626,10 @@ static struct stm32_mgate mp1_mgate[G_LAST]; +@@ -1429,6 +1628,10 @@ static struct stm32_mgate mp1_mgate[G_LAST]; _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\ &mp1_mgate[_id], &mp1_mgate_clk_ops) @@ -892,7 +889,7 @@ index a875649df8b8f..2a1de15cd9813 100644 /* Peripheral gates */ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = { /* Multi gates */ -@@ -1540,16 +1741,19 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = { +@@ -1540,16 +1743,19 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = { K_GATE(G_USBH, RCC_AHB6ENSETR, 24, 0), K_GATE(G_CRC1, RCC_AHB6ENSETR, 20, 0), @@ -916,7 +913,7 @@ index a875649df8b8f..2a1de15cd9813 100644 K_GATE(G_ETHSTP, RCC_AHB6LPENSETR, 11, 0), }; -@@ -1615,9 +1819,13 @@ static struct stm32_mmux ker_mux[M_LAST]; +@@ -1615,9 +1821,13 @@ static struct stm32_mmux ker_mux[M_LAST]; _K_MUX(_id, _offset, _shift, _width, _mux_flags,\ &ker_mux[_id], &clk_mmux_ops) @@ -931,7 +928,7 @@ index a875649df8b8f..2a1de15cd9813 100644 K_MMUX(M_SPI23, RCC_SPI2S23CKSELR, 0, 3, 0), K_MMUX(M_SPI45, RCC_SPI2S45CKSELR, 0, 3, 0), K_MMUX(M_I2C12, RCC_I2C12CKSELR, 0, 3, 0), -@@ -1634,8 +1842,8 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = { +@@ -1634,8 +1844,8 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = { /* Kernel simple mux */ K_MUX(M_RNG2, RCC_RNG2CKSELR, 0, 2, 0), K_MUX(M_SDMMC3, RCC_SDMMC3CKSELR, 0, 3, 0), @@ -942,7 +939,7 @@ index a875649df8b8f..2a1de15cd9813 100644 K_MUX(M_USBPHY, RCC_USBCKSELR, 0, 2, 0), K_MUX(M_USBO, RCC_USBCKSELR, 4, 1, 0), K_MUX(M_SPDIF, RCC_SPDIFCKSELR, 0, 2, 0), -@@ -1656,40 +1864,43 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = { +@@ -1656,40 +1866,43 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = { K_MUX(M_SPI6, RCC_SPI6CKSELR, 0, 3, 0), }; @@ -1010,7 +1007,7 @@ index a875649df8b8f..2a1de15cd9813 100644 _GATE(RCC_PLL1CR, 4, 0), _NO_MUX, _DIV(RCC_PLL1CFGR2, 0, 7, 0, NULL)), -@@ -1717,7 +1928,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = { +@@ -1717,7 +1930,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = { COMPOSITE(PLL3_Q, "pll3_q", PARENT("pll3"), 0, _GATE(RCC_PLL3CR, 5, 0), _NO_MUX, @@ -1019,7 +1016,7 @@ index a875649df8b8f..2a1de15cd9813 100644 COMPOSITE(PLL3_R, "pll3_r", PARENT("pll3"), 0, _GATE(RCC_PLL3CR, 6, 0), -@@ -1737,40 +1948,42 @@ static const struct clock_config stm32mp1_clock_cfg[] = { +@@ -1737,40 +1950,42 @@ static const struct clock_config stm32mp1_clock_cfg[] = { COMPOSITE(PLL4_R, "pll4_r", PARENT("pll4"), 0, _GATE(RCC_PLL4CR, 6, 0), _NO_MUX, @@ -1080,7 +1077,7 @@ index a875649df8b8f..2a1de15cd9813 100644 3, CLK_DIVIDER_READ_ONLY, apb_div_table), /* Kernel Timers */ -@@ -1852,8 +2065,8 @@ static const struct clock_config stm32mp1_clock_cfg[] = { +@@ -1852,8 +2067,8 @@ static const struct clock_config stm32mp1_clock_cfg[] = { PCLK(I2C4, "i2c4", "pclk5", 0, G_I2C4), PCLK(I2C6, "i2c6", "pclk5", 0, G_I2C6), PCLK(USART1, "usart1", "pclk5", 0, G_USART1), @@ -1091,7 +1088,7 @@ index a875649df8b8f..2a1de15cd9813 100644 PCLK(TZC1, "tzc1", "ck_axi", CLK_IGNORE_UNUSED, G_TZC1), PCLK(TZC2, "tzc2", "ck_axi", CLK_IGNORE_UNUSED, G_TZC2), PCLK(TZPC, "tzpc", "pclk5", CLK_IGNORE_UNUSED, G_TZPC), -@@ -1888,16 +2101,13 @@ static const struct clock_config stm32mp1_clock_cfg[] = { +@@ -1888,16 +2103,13 @@ static const struct clock_config stm32mp1_clock_cfg[] = { PCLK(CRYP1, "cryp1", "ck_axi", CLK_IGNORE_UNUSED, G_CRYP1), PCLK(HASH1, "hash1", "ck_axi", CLK_IGNORE_UNUSED, G_HASH1), PCLK(RNG1, "rng1", "ck_axi", 0, G_RNG1), @@ -1110,7 +1107,7 @@ index a875649df8b8f..2a1de15cd9813 100644 PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1), PCLK(USBH, "usbh", "ck_axi", 0, G_USBH), PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP), -@@ -1912,7 +2122,8 @@ static const struct clock_config stm32mp1_clock_cfg[] = { +@@ -1912,7 +2124,8 @@ static const struct clock_config stm32mp1_clock_cfg[] = { KCLK(RNG1_K, "rng1_k", rng_src, 0, G_RNG1, M_RNG1), KCLK(RNG2_K, "rng2_k", rng_src, 0, G_RNG2, M_RNG2), KCLK(USBPHY_K, "usbphy_k", usbphy_src, 0, G_USBPHY, M_USBPHY), @@ -1120,7 +1117,7 @@ index a875649df8b8f..2a1de15cd9813 100644 KCLK(SPDIF_K, "spdif_k", spdif_src, 0, G_SPDIF, M_SPDIF), KCLK(SPI1_K, "spi1_k", spi123_src, 0, G_SPI1, M_SPI1), KCLK(SPI2_K, "spi2_k", spi123_src, 0, G_SPI2, M_SPI23), -@@ -1965,23 +2176,21 @@ static const struct clock_config stm32mp1_clock_cfg[] = { +@@ -1965,23 +2178,21 @@ static const struct clock_config stm32mp1_clock_cfg[] = { _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)), /* RTC clock */ @@ -1151,7 +1148,7 @@ index a875649df8b8f..2a1de15cd9813 100644 _GATE(RCC_MCO2CFGR, 12, 0), _MUX(RCC_MCO2CFGR, 0, 3, 0), _DIV(RCC_MCO2CFGR, 4, 4, 0, NULL)), -@@ -1990,16 +2199,67 @@ static const struct clock_config stm32mp1_clock_cfg[] = { +@@ -1990,22 +2201,83 @@ static const struct clock_config stm32mp1_clock_cfg[] = { GATE(CK_DBG, "ck_sys_dbg", "ck_axi", CLK_IGNORE_UNUSED, RCC_DBGCFGR, 8, 0), @@ -1163,6 +1160,7 @@ index a875649df8b8f..2a1de15cd9813 100644 _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)), }; +-struct stm32_clock_match_data { +static const u32 stm32mp1_clock_secured[] = { + CK_HSE, + CK_HSI, @@ -1212,27 +1210,32 @@ index a875649df8b8f..2a1de15cd9813 100644 + return false; +} + - struct stm32_clock_match_data { ++struct stm32_rcc_match_data { const struct clock_config *cfg; unsigned int num; unsigned int maxbinding; + bool (*check_security)(const struct clock_config *cfg); ++ u32 clear_offset; }; - static struct stm32_clock_match_data stm32mp1_data = { -@@ -2008,13 +2268,25 @@ static struct stm32_clock_match_data stm32mp1_data = { +-static struct stm32_clock_match_data stm32mp1_data = { ++static struct stm32_rcc_match_data stm32mp1_data = { + .cfg = stm32mp1_clock_cfg, + .num = ARRAY_SIZE(stm32mp1_clock_cfg), .maxbinding = STM32MP1_LAST_CLK, - }; - -+static struct stm32_clock_match_data stm32mp1_data_secure = { ++ .clear_offset = RCC_CLR, ++}; ++ ++static struct stm32_rcc_match_data stm32mp1_data_secure = { + .cfg = stm32mp1_clock_cfg, + .num = ARRAY_SIZE(stm32mp1_clock_cfg), + .maxbinding = STM32MP1_LAST_CLK, -+ .check_security = &stm32_check_security -+}; -+ ++ .check_security = &stm32_check_security, ++ .clear_offset = RCC_CLR, + }; + static const struct of_device_id stm32mp1_match_data[] = { - { +@@ -2013,8 +2285,13 @@ static const struct of_device_id stm32mp1_match_data[] = { .compatible = "st,stm32mp1-rcc", .data = &stm32mp1_data, }, @@ -1246,30 +1249,138 @@ index a875649df8b8f..2a1de15cd9813 100644 static int stm32_register_hw_clk(struct device *dev, struct clk_hw_onecell_data *clk_data, -@@ -2040,8 +2312,7 @@ static int stm32_register_hw_clk(struct device *dev, +@@ -2040,28 +2317,126 @@ static int stm32_register_hw_clk(struct device *dev, return 0; } -static int stm32_rcc_init(struct device_node *np, - void __iomem *base, -+static int stm32_rcc_init(struct device *dev, void __iomem *base, - const struct of_device_id *match_data) +- const struct of_device_id *match_data) ++#define STM32_RESET_ID_MASK GENMASK(15, 0) ++ ++struct stm32_reset_data { ++ /* reset lock */ ++ spinlock_t lock; ++ struct reset_controller_dev rcdev; ++ void __iomem *membase; ++ u32 clear_offset; ++}; ++ ++static inline struct stm32_reset_data * ++to_stm32_reset_data(struct reset_controller_dev *rcdev) { - struct clk_hw_onecell_data *clk_data; -@@ -2050,9 +2321,9 @@ static int stm32_rcc_init(struct device_node *np, - const struct stm32_clock_match_data *data; - int err, n, max_binding; +- struct clk_hw_onecell_data *clk_data; +- struct clk_hw **hws; +- const struct of_device_id *match; +- const struct stm32_clock_match_data *data; +- int err, n, max_binding; ++ return container_of(rcdev, struct stm32_reset_data, rcdev); ++} - match = of_match_node(match_data, np); -+ match = of_match_node(match_data, dev_of_node(dev)); - if (!match) { +- if (!match) { - pr_err("%s: match data not found\n", __func__); -+ dev_err(dev, "match data not found\n"); - return -ENODEV; +- return -ENODEV; ++static int stm32_reset_update(struct reset_controller_dev *rcdev, ++ unsigned long id, bool assert) ++{ ++ struct stm32_reset_data *data = to_stm32_reset_data(rcdev); ++ int reg_width = sizeof(u32); ++ int bank = id / (reg_width * BITS_PER_BYTE); ++ int offset = id % (reg_width * BITS_PER_BYTE); ++ ++ if (data->clear_offset) { ++ void __iomem *addr; ++ ++ addr = data->membase + (bank * reg_width); ++ if (!assert) ++ addr += data->clear_offset; ++ ++ writel(BIT(offset), addr); ++ ++ } else { ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&data->lock, flags); ++ ++ reg = readl(data->membase + (bank * reg_width)); ++ ++ if (assert) ++ reg |= BIT(offset); ++ else ++ reg &= ~BIT(offset); ++ ++ writel(reg, data->membase + (bank * reg_width)); ++ ++ spin_unlock_irqrestore(&data->lock, flags); } -@@ -2060,8 +2331,8 @@ static int stm32_rcc_init(struct device_node *np, ++ return 0; ++} ++ ++static int stm32_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return stm32_reset_update(rcdev, id, true); ++} ++ ++static int stm32_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return stm32_reset_update(rcdev, id, false); ++} ++ ++static int stm32_reset_status(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct stm32_reset_data *data = to_stm32_reset_data(rcdev); ++ int reg_width = sizeof(u32); ++ int bank = id / (reg_width * BITS_PER_BYTE); ++ int offset = id % (reg_width * BITS_PER_BYTE); ++ u32 reg; ++ ++ reg = readl(data->membase + (bank * reg_width)); ++ ++ return !!(reg & BIT(offset)); ++} ++ ++static const struct reset_control_ops stm32_reset_ops = { ++ .assert = stm32_reset_assert, ++ .deassert = stm32_reset_deassert, ++ .status = stm32_reset_status, ++}; ++ ++static int stm32_rcc_reset_init(struct device *dev, void __iomem *base, ++ const struct of_device_id *match) ++{ ++ const struct stm32_rcc_match_data *data = match->data; ++ struct stm32_reset_data *reset_data = NULL; ++ + data = match->data; ++ reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); ++ if (!reset_data) ++ return -ENOMEM; ++ ++ reset_data->membase = base; ++ reset_data->rcdev.owner = THIS_MODULE; ++ reset_data->rcdev.ops = &stm32_reset_ops; ++ reset_data->rcdev.of_node = dev_of_node(dev); ++ reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK; ++ reset_data->clear_offset = data->clear_offset; ++ ++ return reset_controller_register(&reset_data->rcdev); ++} ++ ++static int stm32_rcc_clock_init(struct device *dev, void __iomem *base, ++ const struct of_device_id *match) ++{ ++ const struct stm32_rcc_match_data *data = match->data; ++ struct clk_hw_onecell_data *clk_data; ++ struct clk_hw **hws; ++ int err, n, max_binding; ++ max_binding = data->maxbinding; - clk_data = kzalloc(struct_size(clk_data, hws, max_binding), @@ -1279,7 +1390,7 @@ index a875649df8b8f..2a1de15cd9813 100644 if (!clk_data) return -ENOMEM; -@@ -2073,36 +2344,194 @@ static int stm32_rcc_init(struct device_node *np, +@@ -2073,36 +2448,218 @@ static int stm32_rcc_init(struct device_node *np, hws[n] = ERR_PTR(-ENOENT); for (n = 0; n < data->num; n++) { @@ -1307,28 +1418,57 @@ index a875649df8b8f..2a1de15cd9813 100644 } -static void stm32mp1_rcc_init(struct device_node *np) -+static int stm32_rcc_init_pwr(struct device *dev, void __iomem *rcc_base); -+ -+static int stm32mp1_rcc_init(struct device *dev) ++static int stm32_rcc_init(struct device *dev, void __iomem *base, ++ const struct of_device_id *match_data) { - void __iomem *base; -+ void __iomem *rcc_base; -+ int ret = -ENOMEM; ++ const struct of_device_id *match; ++ int err; - base = of_iomap(np, 0); - if (!base) { - pr_err("%pOFn: unable to map resource", np); - of_node_put(np); - return; -+ rcc_base = of_iomap(dev_of_node(dev), 0); -+ if (!rcc_base) { -+ dev_err(dev, "%pOFn: unable to map resource", dev_of_node(dev)); -+ goto out; ++ match = of_match_node(match_data, dev_of_node(dev)); ++ if (!match) { ++ dev_err(dev, "match data not found\n"); ++ return -ENODEV; ++ } ++ ++ /* RCC Reset Configuration */ ++ err = stm32_rcc_reset_init(dev, base, match); ++ if (err) { ++ pr_err("stm32mp1 reset failed to initialize\n"); ++ return err; } - if (stm32_rcc_init(np, base, stm32mp1_match_data)) { - iounmap(base); - of_node_put(np); ++ /* RCC Clock Configuration */ ++ err = stm32_rcc_clock_init(dev, base, match); ++ if (err) { ++ pr_err("stm32mp1 clock failed to initialize\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int stm32_rcc_init_pwr(struct device *dev, void __iomem *rcc_base); ++ ++static int stm32mp1_rcc_init(struct device *dev) ++{ ++ void __iomem *rcc_base; ++ int ret = -ENOMEM; ++ ++ rcc_base = of_iomap(dev_of_node(dev), 0); ++ if (!rcc_base) { ++ dev_err(dev, "%pOFn: unable to map resource", dev_of_node(dev)); ++ goto out; + } ++ + ret = stm32_rcc_init(dev, rcc_base, stm32mp1_match_data); + if (ret) + goto out; @@ -1342,7 +1482,7 @@ index a875649df8b8f..2a1de15cd9813 100644 + rcc_base = NULL; + + of_node_put(dev_of_node(dev)); - } ++ } + + return ret; +} @@ -1393,12 +1533,6 @@ index a875649df8b8f..2a1de15cd9813 100644 } -CLK_OF_DECLARE_DRIVER(stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_rcc_init); -+static struct irqaction rcc_irq = { -+ .name = "rcc irq", -+ .flags = IRQF_ONESHOT, -+ .handler = stm32mp1_rcc_irq_handler, -+}; -+ +static int stm32_rcc_init_pwr(struct device *dev, void __iomem *rcc_base) +{ + int irq; @@ -1412,7 +1546,8 @@ index a875649df8b8f..2a1de15cd9813 100644 + return irq ? irq : -ENXIO; + } + -+ ret = setup_irq(irq, &rcc_irq); ++ ret = devm_request_irq(dev, irq, stm32mp1_rcc_irq_handler, IRQF_ONESHOT, ++ "rcc irq", NULL); + if (ret) { + pr_err("%s: failed to register generic IRQ\n", __func__); + return ret; @@ -1492,10 +1627,10 @@ index a875649df8b8f..2a1de15cd9813 100644 +} +core_initcall(stm32mp1_clocks_init); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c -index 36e9f38a38824..b986c72a497a0 100644 +index f83dac54ed85..6939ea978868 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c -@@ -1717,6 +1717,7 @@ static void clk_reparent(struct clk_core *core, struct clk_core *new_parent) +@@ -1743,6 +1743,7 @@ static void clk_reparent(struct clk_core *core, struct clk_core *new_parent) core->parent = new_parent; } @@ -1503,7 +1638,7 @@ index 36e9f38a38824..b986c72a497a0 100644 static struct clk_core *__clk_set_parent_before(struct clk_core *core, struct clk_core *parent) { -@@ -1745,7 +1746,8 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core, +@@ -1771,7 +1772,8 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core, /* enable old_parent & parent if CLK_OPS_PARENT_ENABLE is set */ if (core->flags & CLK_OPS_PARENT_ENABLE) { @@ -1513,7 +1648,7 @@ index 36e9f38a38824..b986c72a497a0 100644 clk_core_prepare_enable(parent); } -@@ -1779,7 +1781,8 @@ static void __clk_set_parent_after(struct clk_core *core, +@@ -1805,7 +1807,8 @@ static void __clk_set_parent_after(struct clk_core *core, /* re-balance ref counting if CLK_OPS_PARENT_ENABLE is set */ if (core->flags & CLK_OPS_PARENT_ENABLE) { clk_core_disable_unprepare(parent); @@ -1523,396 +1658,23 @@ index 36e9f38a38824..b986c72a497a0 100644 } } -diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig -index f35a53ce8988a..19ec0a78a316a 100644 ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -292,6 +292,10 @@ config CLKSRC_STM32 - select CLKSRC_MMIO - select TIMER_OF - -+config CLKSRC_STM32_LP -+ bool "Low power clocksource for STM32 SoCs" -+ depends on MFD_STM32_LPTIMER || COMPILE_TEST -+ - config CLKSRC_MPS2 - bool "Clocksource for MPS2 SoCs" if COMPILE_TEST - depends on GENERIC_SCHED_CLOCK -diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile -index 4dfe4225ece78..c6eef37be9ccc 100644 ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -44,6 +44,7 @@ obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o - obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o - obj-$(CONFIG_CLKSRC_EFM32) += timer-efm32.o - obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o -+obj-$(CONFIG_CLKSRC_STM32_LP) += timer-stm32-lp.o - obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o - obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o - obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c -new file mode 100644 -index 0000000000000..db2841d0beb81 ---- /dev/null +index db2841d0beb8..90c10f378df2 100644 +--- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c -@@ -0,0 +1,221 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Authors: Benjamin Gaignard for STMicroelectronics. -+ * Pascal Paillet for STMicroelectronics. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CFGR_PSC_OFFSET 9 -+#define STM32_LP_RATING 1000 -+#define STM32_TARGET_CLKRATE (32000 * HZ) -+#define STM32_LP_MAX_PSC 7 -+ -+struct stm32_lp_private { -+ struct regmap *reg; -+ struct clock_event_device clkevt; -+ unsigned long period; -+ struct device *dev; -+}; -+ -+static struct stm32_lp_private* -+to_priv(struct clock_event_device *clkevt) -+{ -+ return container_of(clkevt, struct stm32_lp_private, clkevt); -+} -+ -+static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt) -+{ -+ struct stm32_lp_private *priv = to_priv(clkevt); -+ -+ regmap_write(priv->reg, STM32_LPTIM_CR, 0); -+ regmap_write(priv->reg, STM32_LPTIM_IER, 0); -+ /* clear pending flags */ -+ regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); -+ -+ return 0; -+} -+ -+static int stm32_clkevent_lp_set_timer(unsigned long evt, -+ struct clock_event_device *clkevt, -+ int is_periodic) -+{ -+ struct stm32_lp_private *priv = to_priv(clkevt); -+ -+ /* disable LPTIMER to be able to write into IER register*/ -+ regmap_write(priv->reg, STM32_LPTIM_CR, 0); -+ /* enable ARR interrupt */ -+ regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); -+ /* enable LPTIMER to be able to write into ARR register */ -+ regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); -+ /* set next event counter */ -+ regmap_write(priv->reg, STM32_LPTIM_ARR, evt); -+ -+ /* start counter */ -+ if (is_periodic) -+ regmap_write(priv->reg, STM32_LPTIM_CR, -+ STM32_LPTIM_CNTSTRT | STM32_LPTIM_ENABLE); -+ else -+ regmap_write(priv->reg, STM32_LPTIM_CR, -+ STM32_LPTIM_SNGSTRT | STM32_LPTIM_ENABLE); -+ -+ return 0; -+} -+ -+static int stm32_clkevent_lp_set_next_event(unsigned long evt, -+ struct clock_event_device *clkevt) -+{ -+ return stm32_clkevent_lp_set_timer(evt, clkevt, -+ clockevent_state_periodic(clkevt)); -+} -+ -+static int stm32_clkevent_lp_set_periodic(struct clock_event_device *clkevt) -+{ -+ struct stm32_lp_private *priv = to_priv(clkevt); -+ -+ return stm32_clkevent_lp_set_timer(priv->period, clkevt, true); -+} -+ -+static int stm32_clkevent_lp_set_oneshot(struct clock_event_device *clkevt) -+{ -+ struct stm32_lp_private *priv = to_priv(clkevt); -+ -+ return stm32_clkevent_lp_set_timer(priv->period, clkevt, false); -+} -+ -+static irqreturn_t stm32_clkevent_lp_irq_handler(int irq, void *dev_id) -+{ -+ struct clock_event_device *clkevt = (struct clock_event_device *)dev_id; -+ struct stm32_lp_private *priv = to_priv(clkevt); -+ -+ regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); -+ -+ if (clkevt->event_handler) -+ clkevt->event_handler(clkevt); -+ -+ return IRQ_HANDLED; -+} -+ -+static void stm32_clkevent_lp_set_prescaler(struct stm32_lp_private *priv, -+ unsigned long *rate) -+{ -+ int i; -+ -+ for (i = 0; i <= STM32_LP_MAX_PSC; i++) { -+ if (DIV_ROUND_CLOSEST(*rate, 1 << i) < STM32_TARGET_CLKRATE) -+ break; -+ } -+ -+ regmap_write(priv->reg, STM32_LPTIM_CFGR, i << CFGR_PSC_OFFSET); -+ -+ /* Adjust rate and period given the prescaler value */ -+ *rate = DIV_ROUND_CLOSEST(*rate, (1 << i)); -+ priv->period = DIV_ROUND_UP(*rate, HZ); -+} -+ -+static void stm32_clkevent_lp_init(struct stm32_lp_private *priv, -+ struct device_node *np, unsigned long rate) -+{ -+ priv->clkevt.name = np->full_name; -+ priv->clkevt.cpumask = cpu_possible_mask; -+ priv->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | -+ CLOCK_EVT_FEAT_ONESHOT; -+ priv->clkevt.set_state_shutdown = stm32_clkevent_lp_shutdown; -+ priv->clkevt.set_state_periodic = stm32_clkevent_lp_set_periodic; -+ priv->clkevt.set_state_oneshot = stm32_clkevent_lp_set_oneshot; -+ priv->clkevt.set_next_event = stm32_clkevent_lp_set_next_event; -+ priv->clkevt.rating = STM32_LP_RATING; -+ -+ clockevents_config_and_register(&priv->clkevt, rate, 0x1, -+ STM32_LPTIM_MAX_ARR); -+} -+ -+static int stm32_clkevent_lp_probe(struct platform_device *pdev) -+{ -+ struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); -+ struct stm32_lp_private *priv; -+ unsigned long rate; -+ int ret, irq; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->reg = ddata->regmap; -+ ret = clk_prepare_enable(ddata->clk); -+ if (ret) -+ return -EINVAL; -+ -+ rate = clk_get_rate(ddata->clk); -+ if (!rate) { -+ ret = -EINVAL; -+ goto out_clk_disable; -+ } -+ -+ irq = platform_get_irq(to_platform_device(pdev->dev.parent), 0); -+ if (irq <= 0) { -+ ret = irq; -+ goto out_clk_disable; -+ } -+ -+ if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { -+ ret = device_init_wakeup(&pdev->dev, true); -+ if (ret) -+ goto out_clk_disable; -+ -+ ret = dev_pm_set_wake_irq(&pdev->dev, irq); -+ if (ret) -+ goto out_clk_disable; -+ } -+ -+ ret = devm_request_irq(&pdev->dev, irq, stm32_clkevent_lp_irq_handler, -+ IRQF_TIMER, pdev->name, &priv->clkevt); -+ if (ret) -+ goto out_clk_disable; -+ -+ stm32_clkevent_lp_set_prescaler(priv, &rate); -+ -+ stm32_clkevent_lp_init(priv, pdev->dev.parent->of_node, rate); -+ -+ priv->dev = &pdev->dev; -+ -+ return 0; -+ -+out_clk_disable: -+ clk_disable_unprepare(ddata->clk); -+ return ret; -+} -+ -+static int stm32_clkevent_lp_remove(struct platform_device *pdev) -+{ -+ return -EBUSY; /* cannot unregister clockevent */ -+} -+ -+static const struct of_device_id stm32_clkevent_lp_of_match[] = { -+ { .compatible = "st,stm32-lptimer-timer", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, stm32_clkevent_lp_of_match); -+ -+static struct platform_driver stm32_clkevent_lp_driver = { -+ .probe = stm32_clkevent_lp_probe, -+ .remove = stm32_clkevent_lp_remove, -+ .driver = { -+ .name = "stm32-lptimer-timer", -+ .of_match_table = of_match_ptr(stm32_clkevent_lp_of_match), -+ }, -+}; -+module_platform_driver(stm32_clkevent_lp_driver); -+ -+MODULE_ALIAS("platform:stm32-lptimer-timer"); -+MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c -index bbc930a5962c6..28b63645c4118 100644 ---- a/drivers/counter/stm32-lptimer-cnt.c -+++ b/drivers/counter/stm32-lptimer-cnt.c -@@ -347,7 +347,7 @@ static const struct iio_chan_spec stm32_lptim_cnt_channels = { - }; - - /** -- * stm32_lptim_cnt_function - enumerates stm32 LPTimer counter & encoder modes -+ * enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes - * @STM32_LPTIM_COUNTER_INCREASE: up count on IN1 rising, falling or both edges - * @STM32_LPTIM_ENCODER_BOTH_EDGE: count on both edges (IN1 & IN2 quadrature) - */ -diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c -index 644ba18a72ad5..6c51ff2cf5758 100644 ---- a/drivers/counter/stm32-timer-cnt.c -+++ b/drivers/counter/stm32-timer-cnt.c -@@ -8,10 +8,10 @@ - * - */ - #include --#include --#include - #include -+#include - #include -+#include - #include - - #define TIM_CCMR_CCXS (BIT(8) | BIT(0)) -@@ -20,15 +20,24 @@ - #define TIM_CCER_MASK (TIM_CCER_CC1P | TIM_CCER_CC1NP | \ - TIM_CCER_CC2P | TIM_CCER_CC2NP) - -+struct stm32_timer_regs { -+ u32 cr1; -+ u32 cnt; -+ u32 smcr; -+ u32 arr; -+}; -+ - struct stm32_timer_cnt { - struct counter_device counter; - struct regmap *regmap; - struct clk *clk; - u32 ceiling; -+ bool enabled; -+ struct stm32_timer_regs bak; - }; - - /** -- * stm32_count_function - enumerates stm32 timer counter encoder modes -+ * enum stm32_count_function - enumerates stm32 timer counter encoder modes - * @STM32_COUNT_SLAVE_MODE_DISABLED: counts on internal clock when CEN=1 - * @STM32_COUNT_ENCODER_MODE_1: counts TI1FP1 edges, depending on TI2FP2 level - * @STM32_COUNT_ENCODER_MODE_2: counts TI2FP2 edges, depending on TI1FP1 level -@@ -231,6 +240,9 @@ static ssize_t stm32_count_enable_write(struct counter_device *counter, - clk_disable(priv->clk); +@@ -168,9 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev) } -+ /* Keep enabled state to properly handle low power states */ -+ priv->enabled = enable; -+ - return len; - } + if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { +- ret = device_init_wakeup(&pdev->dev, true); +- if (ret) +- goto out_clk_disable; ++ device_set_wakeup_capable(&pdev->dev, true); -@@ -365,10 +377,59 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev) - priv->counter.num_signals = ARRAY_SIZE(stm32_signals); - priv->counter.priv = priv; - -+ platform_set_drvdata(pdev, priv); -+ - /* Register Counter device */ - return devm_counter_register(dev, &priv->counter); - } - -+static int __maybe_unused stm32_timer_cnt_suspend(struct device *dev) -+{ -+ struct stm32_timer_cnt *priv = dev_get_drvdata(dev); -+ -+ /* Only take care of enabled counter: don't disturb other MFD child */ -+ if (priv->enabled) { -+ /* Backup registers that may get lost in low power mode */ -+ regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr); -+ regmap_read(priv->regmap, TIM_ARR, &priv->bak.arr); -+ regmap_read(priv->regmap, TIM_CNT, &priv->bak.cnt); -+ regmap_read(priv->regmap, TIM_CR1, &priv->bak.cr1); -+ -+ /* Disable the counter */ -+ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); -+ clk_disable(priv->clk); -+ } -+ -+ return pinctrl_pm_select_sleep_state(dev); -+} -+ -+static int __maybe_unused stm32_timer_cnt_resume(struct device *dev) -+{ -+ struct stm32_timer_cnt *priv = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = pinctrl_pm_select_default_state(dev); -+ if (ret) -+ return ret; -+ -+ if (priv->enabled) { -+ clk_enable(priv->clk); -+ -+ /* Restore registers that may have been lost */ -+ regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr); -+ regmap_write(priv->regmap, TIM_ARR, priv->bak.arr); -+ regmap_write(priv->regmap, TIM_CNT, priv->bak.cnt); -+ -+ /* Also re-enables the counter */ -+ regmap_write(priv->regmap, TIM_CR1, priv->bak.cr1); -+ } -+ -+ return 0; -+} -+ -+static SIMPLE_DEV_PM_OPS(stm32_timer_cnt_pm_ops, stm32_timer_cnt_suspend, -+ stm32_timer_cnt_resume); -+ - static const struct of_device_id stm32_timer_cnt_of_match[] = { - { .compatible = "st,stm32-timer-counter", }, - {}, -@@ -380,6 +441,7 @@ static struct platform_driver stm32_timer_cnt_driver = { - .driver = { - .name = "stm32-timer-counter", - .of_match_table = stm32_timer_cnt_of_match, -+ .pm = &stm32_timer_cnt_pm_ops, - }, - }; - module_platform_driver(stm32_timer_cnt_driver); + ret = dev_pm_set_wake_irq(&pdev->dev, irq); + if (ret) diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h -index 4cdaf135829c6..ec7b1a93200fa 100644 +index 4cdaf135829c..ec7b1a93200f 100644 --- a/include/dt-bindings/clock/stm32mp1-clks.h +++ b/include/dt-bindings/clock/stm32mp1-clks.h @@ -179,6 +179,12 @@ diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0002-ARM-stm32mp1-r2-CPUFREQ.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0003-ARM-5.10.10-stm32mp1-r1-CPUFREQ.patch similarity index 72% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0002-ARM-stm32mp1-r2-CPUFREQ.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0003-ARM-5.10.10-stm32mp1-r1-CPUFREQ.patch index 4a15358..e697216 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0002-ARM-stm32mp1-r2-CPUFREQ.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0003-ARM-5.10.10-stm32mp1-r1-CPUFREQ.patch @@ -1,22 +1,21 @@ -From 458e623d9cf01cde1dc2404da5377064b3136389 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:41 +0200 -Subject: [PATCH 02/22] ARM-stm32mp1-r2-rc8-CPUFREQ +From 147c507542ee7feb5bd85212669eeaec2c0420b1 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 08:56:21 +0100 +Subject: [PATCH 03/22] ARM 5.10.10-stm32mp1-r1 CPUFREQ --- drivers/cpufreq/Kconfig.arm | 7 ++ drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + drivers/cpufreq/cpufreq-dt-platdev.c | 3 + drivers/cpufreq/stm32-cpufreq.c | 101 +++++++++++++++++++++++++++ - drivers/opp/core.c | 12 +++- - 5 files changed, 121 insertions(+), 1 deletion(-) + 4 files changed, 112 insertions(+) create mode 100644 drivers/cpufreq/stm32-cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index a905796f7f856..b2beb170840be 100644 +index 1f73fa75b1a0..56b210670b50 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -295,6 +295,13 @@ config ARM_STI_CPUFREQ +@@ -289,6 +289,13 @@ config ARM_STI_CPUFREQ this config option if you wish to add CPUFreq support for STi based SoCs. @@ -31,10 +30,10 @@ index a905796f7f856..b2beb170840be 100644 bool depends on CPUFREQ_DT && ARCH_TANGO diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 9a9f5ccd13d98..6139d2aebea40 100644 +index f1b7e3dd6e5d..b373f97f26a2 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -80,6 +80,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ) += scmi-cpufreq.o +@@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ) += scmi-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o @@ -43,20 +42,22 @@ index 9a9f5ccd13d98..6139d2aebea40 100644 obj-$(CONFIG_ARM_TANGO_CPUFREQ) += tango-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c -index bca8d1f47fd2c..7ac5715e43597 100644 +index 3776d960f405..86fcbb6fa5b8 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c -@@ -131,6 +131,7 @@ static const struct of_device_id blacklist[] __initconst = { - +@@ -138,6 +138,9 @@ static const struct of_device_id blacklist[] __initconst = { { .compatible = "st,stih407", }, { .compatible = "st,stih410", }, + { .compatible = "st,stih418", }, ++ { .compatible = "st,stm32mp151", }, ++ { .compatible = "st,stm32mp153", }, + { .compatible = "st,stm32mp157", }, { .compatible = "sigma,tango4", }, diff --git a/drivers/cpufreq/stm32-cpufreq.c b/drivers/cpufreq/stm32-cpufreq.c new file mode 100644 -index 0000000000000..35fb3520d48df +index 000000000000..35fb3520d48d --- /dev/null +++ b/drivers/cpufreq/stm32-cpufreq.c @@ -0,0 +1,101 @@ @@ -161,38 +162,6 @@ index 0000000000000..35fb3520d48df +MODULE_DESCRIPTION("STM32 CPU freq driver"); +MODULE_AUTHOR("Alexandre Torgue "); +MODULE_LICENSE("GPL v2"); -diff --git a/drivers/opp/core.c b/drivers/opp/core.c -index 9ff0538ee83a0..ec692884c170f 100644 ---- a/drivers/opp/core.c -+++ b/drivers/opp/core.c -@@ -980,9 +980,15 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) - opp_table->clk = clk_get(dev, NULL); - if (IS_ERR(opp_table->clk)) { - ret = PTR_ERR(opp_table->clk); -- if (ret != -EPROBE_DEFER) -+ if (ret != -EPROBE_DEFER) { - dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__, - ret); -+ } -+ else { -+ _remove_opp_dev(opp_dev, opp_table); -+ kfree(opp_table); -+ return ERR_PTR(-EPROBE_DEFER); -+ } - } - - BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); -@@ -1443,6 +1449,10 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev, - struct opp_table *opp_table; - - opp_table = dev_pm_opp_get_opp_table(dev); -+ -+ if (PTR_ERR(opp_table) == -EPROBE_DEFER) -+ return opp_table; -+ - if (!opp_table) - return ERR_PTR(-ENOMEM); - -- 2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0003-ARM-stm32mp1-r2-CRYPTO.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0004-ARM-5.10.10-stm32mp1-r1-CRYPTO.patch similarity index 59% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0003-ARM-stm32mp1-r2-CRYPTO.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0004-ARM-5.10.10-stm32mp1-r1-CRYPTO.patch index cc7fdf0..78a09cd 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0003-ARM-stm32mp1-r2-CRYPTO.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0004-ARM-5.10.10-stm32mp1-r1-CRYPTO.patch @@ -1,244 +1,18 @@ -From 0f32661351778c6c282c9509defdcec61abf7fab Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:41 +0200 -Subject: [PATCH 03/22] ARM-stm32mp1-r2-rc8-CRYPTO +From 56442e69cbaf31555a9bb4f3311a0593a0c172cc Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 08:56:48 +0100 +Subject: [PATCH 04/22] ARM 5.10.10-stm32mp1-r1 CRYPTO --- - drivers/crypto/stm32/Kconfig | 2 + - drivers/crypto/stm32/stm32-crc32.c | 99 +++++++++- - drivers/crypto/stm32/stm32-cryp.c | 300 +++++++++++++++++++++-------- - drivers/crypto/stm32/stm32-hash.c | 57 ++++-- - 4 files changed, 348 insertions(+), 110 deletions(-) + drivers/crypto/stm32/stm32-cryp.c | 300 +++++++++++++++++++++--------- + drivers/crypto/stm32/stm32-hash.c | 19 +- + 2 files changed, 228 insertions(+), 91 deletions(-) -diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig -index 1aba9372cd232..425c68d42a5fe 100644 ---- a/drivers/crypto/stm32/Kconfig -+++ b/drivers/crypto/stm32/Kconfig -@@ -3,6 +3,8 @@ config CRYPTO_DEV_STM32_CRC - tristate "Support for STM32 crc accelerators" - depends on ARCH_STM32 - select CRYPTO_HASH -+ select CRYPTO_CRC32 -+ select CRYPTO_CRC32C - help - This enables support for the CRC32 hw accelerator which can be found - on STMicroelectronics STM32 SOC. -diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c -index e68b856d03b6e..22b301c684f09 100644 ---- a/drivers/crypto/stm32/stm32-crc32.c -+++ b/drivers/crypto/stm32/stm32-crc32.c -@@ -6,6 +6,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -35,11 +36,16 @@ - - #define CRC_AUTOSUSPEND_DELAY 50 - -+static unsigned int burst_size; -+module_param(burst_size, uint, 0644); -+MODULE_PARM_DESC(burst_size, "Select burst byte size (0 unlimited)"); -+ - struct stm32_crc { - struct list_head list; - struct device *dev; - void __iomem *regs; - struct clk *clk; -+ spinlock_t lock; - }; - - struct stm32_crc_list { -@@ -111,6 +117,7 @@ static int stm32_crc_init(struct shash_desc *desc) - struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc); - struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm); - struct stm32_crc *crc; -+ unsigned long flags; - - crc = stm32_crc_get_next_crc(); - if (!crc) -@@ -118,6 +125,8 @@ static int stm32_crc_init(struct shash_desc *desc) - - pm_runtime_get_sync(crc->dev); - -+ spin_lock_irqsave(&crc->lock, flags); -+ - /* Reset, set key, poly and configure in bit reverse mode */ - writel_relaxed(bitrev32(mctx->key), crc->regs + CRC_INIT); - writel_relaxed(bitrev32(mctx->poly), crc->regs + CRC_POL); -@@ -127,14 +136,16 @@ static int stm32_crc_init(struct shash_desc *desc) - /* Store partial result */ - ctx->partial = readl_relaxed(crc->regs + CRC_DR); - -+ spin_unlock_irqrestore(&crc->lock, flags); -+ - pm_runtime_mark_last_busy(crc->dev); - pm_runtime_put_autosuspend(crc->dev); - - return 0; - } - --static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, -- unsigned int length) -+static int burst_update(struct shash_desc *desc, const u8 *d8, -+ size_t length) - { - struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc); - struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm); -@@ -146,6 +157,16 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, - - pm_runtime_get_sync(crc->dev); - -+ if (!spin_trylock(&crc->lock)) { -+ /* Hardware is busy, calculate crc32 by software */ -+ if (mctx->poly == CRC32_POLY_LE) -+ ctx->partial = crc32_le(ctx->partial, d8, length); -+ else -+ ctx->partial = __crc32c_le(ctx->partial, d8, length); -+ -+ goto pm_out; -+ } -+ - /* - * Restore previously calculated CRC for this context as init value - * Restore polynomial configuration -@@ -184,12 +205,41 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, - /* Store partial result */ - ctx->partial = readl_relaxed(crc->regs + CRC_DR); - -+ spin_unlock(&crc->lock); -+ -+pm_out: - pm_runtime_mark_last_busy(crc->dev); - pm_runtime_put_autosuspend(crc->dev); - - return 0; - } - -+static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, -+ unsigned int length) -+{ -+ const unsigned int burst_sz = burst_size; -+ unsigned int rem_sz; -+ const u8 *cur; -+ size_t size; -+ int ret; -+ -+ if (!burst_sz) -+ return burst_update(desc, d8, length); -+ -+ /* Digest first bytes not 32bit aligned at first pass in the loop */ -+ size = min(length, -+ burst_sz + (unsigned int)d8 - ALIGN_DOWN((unsigned int)d8, -+ sizeof(u32))); -+ for (rem_sz = length, cur = d8; rem_sz; -+ rem_sz -= size, cur += size, size = min(rem_sz, burst_sz)) { -+ ret = burst_update(desc, cur, size); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int stm32_crc_final(struct shash_desc *desc, u8 *out) - { - struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc); -@@ -284,7 +334,9 @@ static int stm32_crc_probe(struct platform_device *pdev) - - crc->clk = devm_clk_get(dev, NULL); - if (IS_ERR(crc->clk)) { -- dev_err(dev, "Could not get clock\n"); -+ if (PTR_ERR(crc->clk) != -EPROBE_DEFER) -+ dev_err(dev, "Could not get clock\n"); -+ - return PTR_ERR(crc->clk); - } - -@@ -299,8 +351,11 @@ static int stm32_crc_probe(struct platform_device *pdev) - - pm_runtime_get_noresume(dev); - pm_runtime_set_active(dev); -+ pm_runtime_irq_safe(dev); - pm_runtime_enable(dev); - -+ spin_lock_init(&crc->lock); -+ - platform_set_drvdata(pdev, crc); - - spin_lock(&crc_list.lock); -@@ -353,11 +408,39 @@ static int stm32_crc_remove(struct platform_device *pdev) - } - - #ifdef CONFIG_PM -+static int stm32_crc_suspend(struct device *dev) -+{ -+ struct stm32_crc *crc = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = pm_runtime_force_suspend(dev); -+ if (ret) -+ return ret; -+ -+ clk_unprepare(crc->clk); -+ -+ return 0; -+} -+ -+static int stm32_crc_resume(struct device *dev) -+{ -+ struct stm32_crc *crc = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = clk_prepare(crc->clk); -+ if (ret) { -+ dev_err(crc->dev, "Failed to prepare clock\n"); -+ return ret; -+ } -+ -+ return pm_runtime_force_resume(dev); -+} -+ - static int stm32_crc_runtime_suspend(struct device *dev) - { - struct stm32_crc *crc = dev_get_drvdata(dev); - -- clk_disable_unprepare(crc->clk); -+ clk_disable(crc->clk); - - return 0; - } -@@ -367,9 +450,9 @@ static int stm32_crc_runtime_resume(struct device *dev) - struct stm32_crc *crc = dev_get_drvdata(dev); - int ret; - -- ret = clk_prepare_enable(crc->clk); -+ ret = clk_enable(crc->clk); - if (ret) { -- dev_err(crc->dev, "Failed to prepare_enable clock\n"); -+ dev_err(crc->dev, "Failed to enable clock\n"); - return ret; - } - -@@ -378,8 +461,8 @@ static int stm32_crc_runtime_resume(struct device *dev) - #endif - - static const struct dev_pm_ops stm32_crc_pm_ops = { -- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, -- pm_runtime_force_resume) -+ SET_SYSTEM_SLEEP_PM_OPS(stm32_crc_suspend, -+ stm32_crc_resume) - SET_RUNTIME_PM_OPS(stm32_crc_runtime_suspend, - stm32_crc_runtime_resume, NULL) - }; diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c -index ba5ea6434f9ca..fbf522dc3d63f 100644 +index 2670c30332fa..503428bf15cb 100644 --- a/drivers/crypto/stm32/stm32-cryp.c +++ b/drivers/crypto/stm32/stm32-cryp.c -@@ -143,10 +143,10 @@ struct stm32_cryp { +@@ -144,10 +144,10 @@ struct stm32_cryp { size_t authsize; size_t hw_blocksize; @@ -251,7 +25,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 struct scatterlist *in_sg; struct scatterlist *out_sg; -@@ -156,9 +156,6 @@ struct stm32_cryp { +@@ -157,9 +157,6 @@ struct stm32_cryp { struct scatterlist out_sgl; bool sgs_copied; @@ -261,7 +35,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 struct scatter_walk in_walk; struct scatter_walk out_walk; -@@ -321,28 +318,46 @@ static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp) +@@ -322,28 +319,46 @@ static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp) ret = stm32_cryp_check_aligned(cryp->out_sg, cryp->total_out, cryp->hw_blocksize); @@ -311,7 +85,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 if (!stm32_cryp_check_io_aligned(cryp)) { cryp->sgs_copied = 0; -@@ -350,29 +365,37 @@ static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp) +@@ -351,29 +366,37 @@ static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp) } total_in = ALIGN(cryp->total_in, cryp->hw_blocksize); @@ -356,7 +130,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 cryp->sgs_copied = 1; -@@ -649,14 +672,14 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err) +@@ -654,14 +677,14 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err) buf_in = sg_virt(&cryp->in_sgl); buf_out = sg_virt(&cryp->out_sgl); @@ -375,7 +149,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 pages = len ? get_order(len) : 1; free_pages((unsigned long)buf_out, pages); } -@@ -796,7 +819,20 @@ static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key, +@@ -801,7 +824,20 @@ static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key, static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize) { @@ -397,69 +171,69 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm, -@@ -820,31 +856,61 @@ static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm, +@@ -825,31 +861,61 @@ static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm, - static int stm32_cryp_aes_ecb_encrypt(struct ablkcipher_request *req) + static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req) { -+ if (req->nbytes % AES_BLOCK_SIZE) ++ if (req->cryptlen % AES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT); } - static int stm32_cryp_aes_ecb_decrypt(struct ablkcipher_request *req) + static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req) { -+ if (req->nbytes % AES_BLOCK_SIZE) ++ if (req->cryptlen % AES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_AES | FLG_ECB); } - static int stm32_cryp_aes_cbc_encrypt(struct ablkcipher_request *req) + static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req) { -+ if (req->nbytes % AES_BLOCK_SIZE) ++ if (req->cryptlen % AES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT); } - static int stm32_cryp_aes_cbc_decrypt(struct ablkcipher_request *req) + static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req) { -+ if (req->nbytes % AES_BLOCK_SIZE) ++ if (req->cryptlen % AES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_AES | FLG_CBC); } - static int stm32_cryp_aes_ctr_encrypt(struct ablkcipher_request *req) + static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req) { -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT); } - static int stm32_cryp_aes_ctr_decrypt(struct ablkcipher_request *req) + static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req) { -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_AES | FLG_CTR); } -@@ -858,53 +924,122 @@ static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req) +@@ -863,53 +929,122 @@ static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req) return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM); } @@ -494,95 +268,95 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM); } - static int stm32_cryp_des_ecb_encrypt(struct ablkcipher_request *req) + static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT); } - static int stm32_cryp_des_ecb_decrypt(struct ablkcipher_request *req) + static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_DES | FLG_ECB); } - static int stm32_cryp_des_cbc_encrypt(struct ablkcipher_request *req) + static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT); } - static int stm32_cryp_des_cbc_decrypt(struct ablkcipher_request *req) + static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_DES | FLG_CBC); } - static int stm32_cryp_tdes_ecb_encrypt(struct ablkcipher_request *req) + static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT); } - static int stm32_cryp_tdes_ecb_decrypt(struct ablkcipher_request *req) + static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB); } - static int stm32_cryp_tdes_cbc_encrypt(struct ablkcipher_request *req) + static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT); } - static int stm32_cryp_tdes_cbc_decrypt(struct ablkcipher_request *req) + static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req) { -+ if (req->nbytes % DES_BLOCK_SIZE) ++ if (req->cryptlen % DES_BLOCK_SIZE) + return -EINVAL; + -+ if (req->nbytes == 0) ++ if (req->cryptlen == 0) + return 0; + return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC); } -@@ -966,36 +1101,25 @@ static int stm32_cryp_prepare_req(struct ablkcipher_request *req, +@@ -971,36 +1106,25 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, cryp->areq = areq; cryp->req = NULL; cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq)); @@ -627,7 +401,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 ret = stm32_cryp_copy_sgs(cryp); if (ret) return ret; -@@ -1006,7 +1130,7 @@ static int stm32_cryp_prepare_req(struct ablkcipher_request *req, +@@ -1011,7 +1135,7 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, if (is_gcm(cryp) || is_ccm(cryp)) { /* In output, jump after assoc data */ scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen); @@ -636,7 +410,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } ret = stm32_cryp_hw_init(cryp); -@@ -1125,7 +1249,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) +@@ -1130,7 +1254,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) stm32_cryp_write(cryp, CRYP_DIN, size_bit); size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen : @@ -644,8 +418,8 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 + cryp->areq->cryptlen - cryp->authsize; size_bit *= 8; if (cryp->caps->swap_final) - size_bit = cpu_to_be32(size_bit); -@@ -1159,14 +1283,14 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) + size_bit = (__force u32)cpu_to_be32(size_bit); +@@ -1169,14 +1293,14 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) dst = sg_virt(cryp->out_sg) + _walked_out; for (i = 0; i < AES_BLOCK_32; i++) { @@ -663,7 +437,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 /* Empty fifo out (data from input padding) */ stm32_cryp_read(cryp, CRYP_DOUT); } else { -@@ -1174,11 +1298,11 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) +@@ -1184,11 +1308,11 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) d32 = stm32_cryp_read(cryp, CRYP_DOUT); d8 = (u8 *)&d32; @@ -677,7 +451,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } } } else { -@@ -1186,7 +1310,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) +@@ -1196,7 +1320,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32]; scatterwalk_map_and_copy(in_tag, cryp->in_sg, @@ -686,7 +460,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 cryp->authsize, 0); for (i = 0; i < AES_BLOCK_32; i++) -@@ -1246,13 +1370,13 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp) +@@ -1256,13 +1380,13 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp) dst = sg_virt(cryp->out_sg) + _walked_out; for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { @@ -703,7 +477,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 /* Empty fifo out (data from input padding) */ d32 = stm32_cryp_read(cryp, CRYP_DOUT); } else { -@@ -1260,15 +1384,15 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp) +@@ -1270,15 +1394,15 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp) d32 = stm32_cryp_read(cryp, CRYP_DOUT); d8 = (u8 *)&d32; @@ -722,7 +496,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp) -@@ -1287,25 +1411,25 @@ static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp) +@@ -1297,25 +1421,25 @@ static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp) src = sg_virt(cryp->in_sg) + _walked_in; for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { @@ -753,7 +527,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } } } -@@ -1314,7 +1438,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) +@@ -1324,7 +1448,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) { int err; u32 cfg, tmp[AES_BLOCK_32]; @@ -762,7 +536,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 struct scatterlist *out_sg_ori = cryp->out_sg; unsigned int i; -@@ -1340,7 +1464,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) +@@ -1350,7 +1474,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) /* b) pad and write the last block */ stm32_cryp_irq_write_block(cryp); @@ -771,7 +545,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 err = stm32_cryp_wait_output(cryp); if (err) { dev_err(cryp->dev, "Timeout (write gcm header)\n"); -@@ -1350,8 +1474,8 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) +@@ -1360,8 +1484,8 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) /* c) get and store encrypted data */ stm32_cryp_irq_read_data(cryp); scatterwalk_map_and_copy(tmp, out_sg_ori, @@ -782,7 +556,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 /* d) change mode back to AES GCM */ cfg &= ~CR_ALGO_MASK; -@@ -1365,12 +1489,12 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) +@@ -1375,12 +1499,12 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) /* f) write padded data */ for (i = 0; i < AES_BLOCK_32; i++) { @@ -797,7 +571,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } /* g) Empty fifo out */ -@@ -1396,8 +1520,8 @@ static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp) +@@ -1406,8 +1530,8 @@ static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp) cfg &= ~CR_CRYPEN; stm32_cryp_write(cryp, CRYP_CR, cfg); @@ -808,7 +582,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 cfg |= (cryp->hw_blocksize - payload_bytes) << CR_NBPBL_SHIFT; cfg |= CR_CRYPEN; stm32_cryp_write(cryp, CRYP_CR, cfg); -@@ -1408,7 +1532,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) +@@ -1418,7 +1542,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) int err = 0; u32 cfg, iv1tmp; u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32], tmp[AES_BLOCK_32]; @@ -817,7 +591,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 struct scatterlist *out_sg_ori = cryp->out_sg; unsigned int i; -@@ -1443,7 +1567,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) +@@ -1453,7 +1577,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) /* b) pad and write the last block */ stm32_cryp_irq_write_block(cryp); @@ -826,7 +600,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 err = stm32_cryp_wait_output(cryp); if (err) { dev_err(cryp->dev, "Timeout (wite ccm padded data)\n"); -@@ -1451,13 +1575,13 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) +@@ -1461,13 +1585,13 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) } /* c) get and store decrypted data */ @@ -843,7 +617,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 /* d) Load again CRYP_CSGCMCCMxR */ for (i = 0; i < ARRAY_SIZE(cstmp2); i++) -@@ -1491,12 +1615,12 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) +@@ -1501,12 +1625,12 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp) { @@ -858,7 +632,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) && is_encrypt(cryp))) { /* Padding for AES GCM encryption */ -@@ -1508,7 +1632,7 @@ static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp) +@@ -1518,7 +1642,7 @@ static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp) stm32_cryp_irq_set_npblb(cryp); } @@ -867,7 +641,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) && is_decrypt(cryp))) { /* Padding for AES CCM decryption */ -@@ -1538,10 +1662,10 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp) +@@ -1548,10 +1672,10 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp) stm32_cryp_write(cryp, CRYP_DIN, *src); src = stm32_cryp_next_in(cryp, src, sizeof(u32)); @@ -880,7 +654,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 cryp->areq->assoclen) { /* Write padding if needed */ for (j = i + 1; j < AES_BLOCK_32; j++) -@@ -1573,7 +1697,7 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp) +@@ -1583,7 +1707,7 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp) break; } @@ -889,7 +663,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 break; } } -@@ -1601,7 +1725,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) +@@ -1611,7 +1735,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); i++; @@ -898,7 +672,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } else { /* Build the two first u32 of B1 */ d8[0] = 0xFF; -@@ -1622,7 +1746,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) +@@ -1632,7 +1756,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); i++; @@ -907,7 +681,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 } } -@@ -1634,14 +1758,14 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) +@@ -1644,14 +1768,14 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) d8[k] = *((u8 *)src); src = stm32_cryp_next_in(cryp, src, 1); @@ -925,7 +699,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 /* Write padding if needed */ for (j = i + 1; j < AES_BLOCK_32; j++) stm32_cryp_write(cryp, CRYP_DIN, 0); -@@ -1966,7 +2090,9 @@ static int stm32_cryp_probe(struct platform_device *pdev) +@@ -1955,7 +2079,9 @@ static int stm32_cryp_probe(struct platform_device *pdev) cryp->clk = devm_clk_get(dev, NULL); if (IS_ERR(cryp->clk)) { @@ -936,7 +710,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 return PTR_ERR(cryp->clk); } -@@ -1984,7 +2110,11 @@ static int stm32_cryp_probe(struct platform_device *pdev) +@@ -1973,7 +2099,11 @@ static int stm32_cryp_probe(struct platform_device *pdev) pm_runtime_enable(dev); rst = devm_reset_control_get(dev, NULL); @@ -949,7 +723,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 reset_control_assert(rst); udelay(2); reset_control_deassert(rst); -@@ -2035,7 +2165,7 @@ static int stm32_cryp_probe(struct platform_device *pdev) +@@ -2024,7 +2154,7 @@ static int stm32_cryp_probe(struct platform_device *pdev) spin_lock(&cryp_list.lock); list_del(&cryp->list); spin_unlock(&cryp_list.lock); @@ -959,35 +733,10 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644 pm_runtime_put_noidle(dev); pm_runtime_disable(dev); diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c -index cfc8e0e37beec..f8b0e1b28971e 100644 +index e3e25278a970..da9c3e913e55 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c -@@ -507,6 +507,7 @@ static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev) - static int stm32_hash_dma_init(struct stm32_hash_dev *hdev) - { - struct dma_slave_config dma_conf; -+ struct dma_chan *chan; - int err; - - memset(&dma_conf, 0, sizeof(dma_conf)); -@@ -518,11 +519,11 @@ static int stm32_hash_dma_init(struct stm32_hash_dev *hdev) - dma_conf.dst_maxburst = hdev->dma_maxburst; - dma_conf.device_fc = false; - -- hdev->dma_lch = dma_request_slave_channel(hdev->dev, "in"); -- if (!hdev->dma_lch) { -- dev_err(hdev->dev, "Couldn't acquire a slave DMA channel.\n"); -- return -EBUSY; -- } -+ chan = dma_request_chan(hdev->dev, "in"); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); -+ -+ hdev->dma_lch = chan; - - err = dmaengine_slave_config(hdev->dma_lch, &dma_conf); - if (err) { -@@ -923,15 +924,10 @@ static int stm32_hash_final(struct ahash_request *req) +@@ -925,15 +925,10 @@ static int stm32_hash_final(struct ahash_request *req) static int stm32_hash_finup(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); @@ -1003,7 +752,7 @@ index cfc8e0e37beec..f8b0e1b28971e 100644 err1 = stm32_hash_update(req); if (err1 == -EINPROGRESS || err1 == -EBUSY) -@@ -948,7 +944,19 @@ static int stm32_hash_finup(struct ahash_request *req) +@@ -950,7 +945,19 @@ static int stm32_hash_finup(struct ahash_request *req) static int stm32_hash_digest(struct ahash_request *req) { @@ -1024,64 +773,6 @@ index cfc8e0e37beec..f8b0e1b28971e 100644 } static int stm32_hash_export(struct ahash_request *req, void *out) -@@ -1463,8 +1471,11 @@ static int stm32_hash_probe(struct platform_device *pdev) - - hdev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(hdev->clk)) { -- dev_err(dev, "failed to get clock for hash (%lu)\n", -- PTR_ERR(hdev->clk)); -+ if (PTR_ERR(hdev->clk) != -EPROBE_DEFER) { -+ dev_err(dev, "failed to get clock for hash (%lu)\n", -+ PTR_ERR(hdev->clk)); -+ } -+ - return PTR_ERR(hdev->clk); - } - -@@ -1482,7 +1493,12 @@ static int stm32_hash_probe(struct platform_device *pdev) - pm_runtime_enable(dev); - - hdev->rst = devm_reset_control_get(&pdev->dev, NULL); -- if (!IS_ERR(hdev->rst)) { -+ if (IS_ERR(hdev->rst)) { -+ if (PTR_ERR(hdev->rst) == -EPROBE_DEFER) { -+ ret = -EPROBE_DEFER; -+ goto err_reset; -+ } -+ } else { - reset_control_assert(hdev->rst); - udelay(2); - reset_control_deassert(hdev->rst); -@@ -1493,8 +1509,15 @@ static int stm32_hash_probe(struct platform_device *pdev) - platform_set_drvdata(pdev, hdev); - - ret = stm32_hash_dma_init(hdev); -- if (ret) -+ switch (ret) { -+ case 0: -+ break; -+ case -ENOENT: - dev_dbg(dev, "DMA mode not available\n"); -+ break; -+ default: -+ goto err_dma; -+ } - - spin_lock(&stm32_hash.lock); - list_add_tail(&hdev->list, &stm32_hash.dev_list); -@@ -1532,10 +1555,10 @@ static int stm32_hash_probe(struct platform_device *pdev) - spin_lock(&stm32_hash.lock); - list_del(&hdev->list); - spin_unlock(&stm32_hash.lock); -- -+err_dma: - if (hdev->dma_lch) - dma_release_channel(hdev->dma_lch); -- -+err_reset: - pm_runtime_disable(dev); - pm_runtime_put_noidle(dev); - -- 2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0006-ARM-stm32mp1-r2-DMA.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0005-ARM-5.10.10-stm32mp1-r1-DMA.patch similarity index 65% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0006-ARM-stm32mp1-r2-DMA.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0005-ARM-5.10.10-stm32mp1-r1-DMA.patch index 39d5330..4aabd5b 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0006-ARM-stm32mp1-r2-DMA.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0005-ARM-5.10.10-stm32mp1-r1-DMA.patch @@ -1,106 +1,20 @@ -From ea9107d1f4dde411886c614bfa5f7403e28c4d0b Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:42 +0200 -Subject: [PATCH 06/22] ARM-stm32mp1-r2-rc8-DMA +From 8419770f37f0543bc5c2390651c46892dc520018 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 08:58:56 +0100 +Subject: [PATCH 05/22] ARM 5.10.10-stm32mp1-r1 DMA --- - drivers/dma/dmaengine.c | 113 +++- - drivers/dma/stm32-dma.c | 1119 +++++++++++++++++++++++++++++++----- - drivers/dma/stm32-dmamux.c | 95 ++- - drivers/dma/stm32-mdma.c | 273 +++++++-- - include/linux/dmaengine.h | 18 + - 5 files changed, 1380 insertions(+), 238 deletions(-) + drivers/dma/dmaengine.c | 34 ++ + drivers/dma/stm32-dma.c | 1011 ++++++++++++++++++++++++++++++++----- + drivers/dma/stm32-mdma.c | 188 +++++-- + include/linux/dmaengine.h | 11 + + 4 files changed, 1070 insertions(+), 174 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c -index 4b604086b1b3a..3db3f8e36dea0 100644 +index 962cbb5e5f7f..1381f15eb6f2 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c -@@ -58,6 +58,65 @@ static DEFINE_IDA(dma_ida); - static LIST_HEAD(dma_device_list); - static long dmaengine_ref_count; - -+/* --- debugfs implementation --- */ -+#ifdef CONFIG_DEBUG_FS -+#include -+ -+static void dmaengine_dbg_summary_show(struct seq_file *s, -+ struct dma_device *dma_dev) -+{ -+ struct dma_chan *chan; -+ -+ list_for_each_entry(chan, &dma_dev->channels, device_node) { -+ if (chan->client_count) { -+ seq_printf(s, " %-13s| %s", dma_chan_name(chan), -+ chan->dbg_client_name ?: "in-use"); -+ -+ if (chan->router) -+ seq_printf(s, " (via router: %s)\n", -+ dev_name(chan->router->dev)); -+ else -+ seq_puts(s, "\n"); -+ } -+ } -+} -+ -+static int dmaengine_summary_show(struct seq_file *s, void *data) -+{ -+ struct dma_device *dma_dev = NULL; -+ -+ mutex_lock(&dma_list_mutex); -+ list_for_each_entry(dma_dev, &dma_device_list, global_node) { -+ seq_printf(s, "dma%d (%s): number of channels: %u\n", -+ dma_dev->dev_id, dev_name(dma_dev->dev), -+ dma_dev->chancnt); -+ -+ if (dma_dev->dbg_summary_show) -+ dma_dev->dbg_summary_show(s, dma_dev); -+ else -+ dmaengine_dbg_summary_show(s, dma_dev); -+ -+ if (!list_is_last(&dma_dev->global_node, &dma_device_list)) -+ seq_puts(s, "\n"); -+ } -+ mutex_unlock(&dma_list_mutex); -+ -+ return 0; -+} -+DEFINE_SHOW_ATTRIBUTE(dmaengine_summary); -+ -+static void __init dmaengine_debugfs_init(void) -+{ -+ struct dentry *rootdir = debugfs_create_dir("dmaengine", NULL); -+ -+ /* /sys/kernel/debug/dmaengine/summary */ -+ debugfs_create_file("summary", 0444, rootdir, NULL, -+ &dmaengine_summary_fops); -+} -+#else -+static inline void dmaengine_debugfs_init(void) { } -+#endif /* DEBUG_FS */ -+ - /* --- sysfs implementation --- */ - - /** -@@ -707,7 +766,7 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name) - if (chan) { - /* Valid channel found or requester needs to be deferred */ - if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER) -- return chan; -+ goto found; - } - - /* Try to find the channel via the DMA filter map(s) */ -@@ -728,10 +787,44 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name) - } - mutex_unlock(&dma_list_mutex); - -+found: -+#ifdef CONFIG_DEBUG_FS -+ if (!IS_ERR_OR_NULL(chan)) -+ chan->dbg_client_name = kasprintf(GFP_KERNEL, "%s:%s", -+ dev_name(dev), name); -+#endif - return chan ? chan : ERR_PTR(-EPROBE_DEFER); +@@ -873,6 +873,33 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name) } EXPORT_SYMBOL_GPL(dma_request_chan); @@ -114,36 +28,27 @@ index 4b604086b1b3a..3db3f8e36dea0 100644 + */ +struct dma_chan *dma_request_chan_linked(struct device *dev, const char *name) +{ -+ struct dma_chan *ch = dma_request_chan(dev, name); -+ struct device *provider_dev = ch->device->dev; ++ struct dma_chan *chan = dma_request_chan(dev, name); ++ struct device *provider_dev = chan->device->dev; + struct device_link *link; + -+ if (!IS_ERR_OR_NULL(ch)) { ++ if (!IS_ERR_OR_NULL(chan)) { + link = device_link_add(dev, provider_dev, DL_FLAG_STATELESS); + if (!link) { -+ dev_err(provider_dev, -+ "failed to add dev link with %s\n", -+ dev_name(dev)); ++ dev_err(provider_dev, "failed to add dev link with %s\n", dev_name(dev)); ++ dma_release_channel(chan); + return ERR_PTR(-EINVAL); + } + } + -+ return ch; ++ return chan; +} +EXPORT_SYMBOL_GPL(dma_request_chan_linked); + /** - * dma_request_slave_channel - try to allocate an exclusive slave channel - * @dev: pointer to client device structure -@@ -786,10 +879,21 @@ void dma_release_channel(struct dma_chan *chan) - /* drop PRIVATE cap enabled by __dma_request_channel() */ - if (--chan->device->privatecnt == 0) - dma_cap_clear(DMA_PRIVATE, chan->device->cap_mask); -+#ifdef CONFIG_DEBUG_FS -+ kfree(chan->dbg_client_name); -+ chan->dbg_client_name = NULL; -+#endif - mutex_unlock(&dma_list_mutex); + * dma_request_chan_by_mask - allocate a channel satisfying certain capabilities + * @mask: capabilities that the channel must satisfy +@@ -926,6 +953,13 @@ void dma_release_channel(struct dma_chan *chan) } EXPORT_SYMBOL_GPL(dma_release_channel); @@ -157,31 +62,17 @@ index 4b604086b1b3a..3db3f8e36dea0 100644 /** * dmaengine_get - register interest in dma_channels */ -@@ -1372,7 +1476,12 @@ static int __init dma_bus_init(void) - - if (err) - return err; -- return class_register(&dma_devclass); -+ -+ err = class_register(&dma_devclass); -+ if (!err) -+ dmaengine_debugfs_init(); -+ -+ return err; - } - arch_initcall(dma_bus_init); - diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c -index 5989b08935211..e8bedbad125c3 100644 +index d0055d2f0b9a..1d89e0807ef0 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c -@@ -14,11 +14,14 @@ +@@ -14,12 +14,14 @@ #include #include #include +#include #include -+#include + #include #include #include #include @@ -190,24 +81,29 @@ index 5989b08935211..e8bedbad125c3 100644 #include #include #include -@@ -116,8 +119,10 @@ - #define STM32_DMA_FIFO_THRESHOLD_HALFFULL 0x01 - #define STM32_DMA_FIFO_THRESHOLD_3QUARTERSFULL 0x02 - #define STM32_DMA_FIFO_THRESHOLD_FULL 0x03 -+#define STM32_DMA_FIFO_THRESHOLD_NONE 0x04 +@@ -60,6 +62,7 @@ + #define STM32_DMA_SCR_PSIZE_GET(n) ((n & STM32_DMA_SCR_PSIZE_MASK) >> 11) + #define STM32_DMA_SCR_DIR_MASK GENMASK(7, 6) + #define STM32_DMA_SCR_DIR(n) ((n & 0x3) << 6) ++#define STM32_DMA_SCR_TRBUFF BIT(20) /* Bufferable transfer for USART/UART */ + #define STM32_DMA_SCR_CT BIT(19) /* Target in double buffer */ + #define STM32_DMA_SCR_DBM BIT(18) /* Double Buffer Mode */ + #define STM32_DMA_SCR_PINCOS BIT(15) /* Peripheral inc offset size */ +@@ -120,6 +123,7 @@ + #define STM32_DMA_FIFO_THRESHOLD_NONE 0x04 #define STM32_DMA_MAX_DATA_ITEMS 0xffff +#define STM32_DMA_SRAM_GRANULARITY PAGE_SIZE /* * Valid transfer starts from @0 to @0xFFFE leading to unaligned scatter * gather at boundary. Thus it's safer to round down this value on FIFO -@@ -135,6 +140,15 @@ - /* DMA Features */ - #define STM32_DMA_THRESHOLD_FTR_MASK GENMASK(1, 0) - #define STM32_DMA_THRESHOLD_FTR_GET(n) ((n) & STM32_DMA_THRESHOLD_FTR_MASK) -+#define STM32_DMA_DIRECT_MODE_MASK BIT(2) -+#define STM32_DMA_DIRECT_MODE_GET(n) (((n) & STM32_DMA_DIRECT_MODE_MASK) \ -+ >> 2) +@@ -140,6 +144,15 @@ + #define STM32_DMA_DIRECT_MODE_MASK BIT(2) + #define STM32_DMA_DIRECT_MODE_GET(n) (((n) & STM32_DMA_DIRECT_MODE_MASK) \ + >> 2) ++#define STM32_DMA_ALT_ACK_MODE_MASK BIT(4) ++#define STM32_DMA_ALT_ACK_MODE_GET(n) (((n) & STM32_DMA_ALT_ACK_MODE_MASK) \ ++ >> 4) +#define STM32_DMA_MDMA_CHAIN_FTR_MASK BIT(31) +#define STM32_DMA_MDMA_CHAIN_FTR_GET(n) (((n) & STM32_DMA_MDMA_CHAIN_FTR_MASK) \ + >> 31) @@ -217,7 +113,7 @@ index 5989b08935211..e8bedbad125c3 100644 enum stm32_dma_width { STM32_DMA_BYTE, -@@ -176,15 +190,32 @@ struct stm32_dma_chan_reg { +@@ -181,15 +194,32 @@ struct stm32_dma_chan_reg { u32 dma_sfcr; }; @@ -251,7 +147,7 @@ index 5989b08935211..e8bedbad125c3 100644 struct stm32_dma_sg_req sg_req[]; }; -@@ -201,15 +232,19 @@ struct stm32_dma_chan { +@@ -206,6 +236,10 @@ struct stm32_dma_chan { u32 threshold; u32 mem_burst; u32 mem_width; @@ -262,97 +158,33 @@ index 5989b08935211..e8bedbad125c3 100644 }; struct stm32_dma_device { - struct dma_device ddev; - void __iomem *base; +@@ -214,6 +248,7 @@ struct stm32_dma_device { struct clk *clk; -- struct reset_control *rst; bool mem2mem; struct stm32_dma_chan chan[STM32_DMA_MAX_CHANNELS]; + struct gen_pool *sram_pool; }; static struct stm32_dma_device *stm32_dma_get_dev(struct stm32_dma_chan *chan) -@@ -260,9 +295,11 @@ static int stm32_dma_get_width(struct stm32_dma_chan *chan, +@@ -264,6 +299,7 @@ static int stm32_dma_get_width(struct stm32_dma_chan *chan, } static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, -+ dma_addr_t buf_addr, ++ u64 buf_addr, u32 threshold) { enum dma_slave_buswidth max_width; -+ u64 addr = buf_addr; - - if (threshold == STM32_DMA_FIFO_THRESHOLD_FULL) - max_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -@@ -273,6 +310,9 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, +@@ -277,6 +313,9 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, max_width > DMA_SLAVE_BUSWIDTH_1_BYTE) max_width = max_width >> 1; -+ if (do_div(addr, max_width)) ++ if (do_div(buf_addr, max_width)) + max_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + return max_width; } -@@ -281,6 +321,9 @@ static bool stm32_dma_fifo_threshold_is_allowed(u32 burst, u32 threshold, - { - u32 remaining; - -+ if (threshold == STM32_DMA_FIFO_THRESHOLD_NONE) -+ return false; -+ - if (width != DMA_SLAVE_BUSWIDTH_UNDEFINED) { - if (burst != 0) { - /* -@@ -302,6 +345,10 @@ static bool stm32_dma_fifo_threshold_is_allowed(u32 burst, u32 threshold, - - static bool stm32_dma_is_burst_possible(u32 buf_len, u32 threshold) - { -+ /* If FIFO direct mode, burst is not possible */ -+ if (threshold == STM32_DMA_FIFO_THRESHOLD_NONE) -+ return false; -+ - /* - * Buffer or period length has to be aligned on FIFO depth. - * Otherwise bytes may be stuck within FIFO at buffer or period -@@ -422,29 +469,19 @@ static void stm32_dma_irq_clear(struct stm32_dma_chan *chan, u32 flags) - static int stm32_dma_disable_chan(struct stm32_dma_chan *chan) - { - struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); -- unsigned long timeout = jiffies + msecs_to_jiffies(5000); -- u32 dma_scr, id; -+ u32 dma_scr, id, reg; - - id = chan->id; -- dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); -+ reg = STM32_DMA_SCR(id); -+ dma_scr = stm32_dma_read(dmadev, reg); - - if (dma_scr & STM32_DMA_SCR_EN) { - dma_scr &= ~STM32_DMA_SCR_EN; -- stm32_dma_write(dmadev, STM32_DMA_SCR(id), dma_scr); -- -- do { -- dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); -- dma_scr &= STM32_DMA_SCR_EN; -- if (!dma_scr) -- break; -+ stm32_dma_write(dmadev, reg, dma_scr); - -- if (time_after_eq(jiffies, timeout)) { -- dev_err(chan2dev(chan), "%s: timeout!\n", -- __func__); -- return -EBUSY; -- } -- cond_resched(); -- } while (1); -+ return readl_relaxed_poll_timeout_atomic(dmadev->base + reg, -+ dma_scr, !(dma_scr & STM32_DMA_SCR_EN), -+ 10, 1000000); - } - - return 0; -@@ -483,13 +520,22 @@ static void stm32_dma_stop(struct stm32_dma_chan *chan) +@@ -484,12 +523,20 @@ static void stm32_dma_stop(struct stm32_dma_chan *chan) static int stm32_dma_terminate_all(struct dma_chan *c) { struct stm32_dma_chan *chan = to_stm32_dma_chan(c); @@ -369,16 +201,12 @@ index 5989b08935211..e8bedbad125c3 100644 + spin_lock_irqsave(&chan->vchan.lock, flags); + } -- if (chan->busy) { -- stm32_dma_stop(chan); -+ if (chan->desc) { -+ vchan_terminate_vdesc(&chan->desc->vdesc); -+ if (chan->busy) -+ stm32_dma_stop(chan); - chan->desc = NULL; - } - -@@ -500,9 +546,103 @@ static int stm32_dma_terminate_all(struct dma_chan *c) + if (chan->desc) { ++ dma_cookie_complete(&chan->desc->vdesc.tx); + vchan_terminate_vdesc(&chan->desc->vdesc); + if (chan->busy) + stm32_dma_stop(chan); +@@ -503,9 +550,103 @@ static int stm32_dma_terminate_all(struct dma_chan *c) return 0; } @@ -482,7 +310,7 @@ index 5989b08935211..e8bedbad125c3 100644 vchan_synchronize(&chan->vchan); } -@@ -525,62 +665,213 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) +@@ -528,65 +669,213 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr); } @@ -507,8 +335,7 @@ index 5989b08935211..e8bedbad125c3 100644 + dev_err(chan2dev(chan), "Source buffer map failed\n"); + return ret; + } - --static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) ++ + dma_dst_buf = dma_map_single(ddev->dev, &dst_buf, len, DMA_FROM_DEVICE); + ret = dma_mapping_error(ddev->dev, dma_dst_buf); + if (ret < 0) { @@ -516,7 +343,8 @@ index 5989b08935211..e8bedbad125c3 100644 + dma_unmap_single(ddev->dev, dma_src_buf, len, DMA_TO_DEVICE); + return ret; + } -+ + +-static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) + reg.dma_scr = STM32_DMA_SCR_DIR(STM32_DMA_MEM_TO_MEM) | + STM32_DMA_SCR_PBURST(STM32_DMA_BURST_SINGLE) | + STM32_DMA_SCR_MBURST(STM32_DMA_BURST_SINGLE) | @@ -621,13 +449,14 @@ index 5989b08935211..e8bedbad125c3 100644 + } + stm32_dma_disable_chan(chan); -- chan->desc = to_stm32_dma_desc(vdesc); -- chan->next_sg = 0; +- list_del(&vdesc->node); + src_buf = mchan->sram_buf + ((len / mchan->sram_period) & 0x1) + * mchan->sram_period; + dst_buf = sg_dma_address(&sg_req->stm32_sgl_req) + len - + (len % mchan->sram_period); -+ + +- chan->desc = to_stm32_dma_desc(vdesc); +- chan->next_sg = 0; + desc = ddev->device_prep_dma_memcpy(mchan->chan, + dst_buf, src_buf, + len % mchan->sram_period, @@ -656,6 +485,7 @@ index 5989b08935211..e8bedbad125c3 100644 - reg = &sg_req->chan_reg; +static void stm32_dma_start_transfer(struct stm32_dma_chan *chan); +- reg->dma_scr &= ~STM32_DMA_SCR_EN; - stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), reg->dma_scr); - stm32_dma_write(dmadev, STM32_DMA_SPAR(chan->id), reg->dma_spar); - stm32_dma_write(dmadev, STM32_DMA_SM0AR(chan->id), reg->dma_sm0ar); @@ -733,7 +563,7 @@ index 5989b08935211..e8bedbad125c3 100644 } static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) -@@ -612,23 +903,134 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) +@@ -618,22 +907,134 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) } } @@ -811,7 +641,6 @@ index 5989b08935211..e8bedbad125c3 100644 } else { - chan->busy = false; - if (chan->next_sg == chan->desc->num_sgs) { -- list_del(&chan->desc->vdesc.node); - vchan_cookie_complete(&chan->desc->vdesc); + reg->dma_scr &= ~STM32_DMA_SCR_TCIE; + } @@ -879,55 +708,51 @@ index 5989b08935211..e8bedbad125c3 100644 } static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) -@@ -643,26 +1045,37 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) +@@ -648,21 +1049,12 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); sfcr = stm32_dma_read(dmadev, STM32_DMA_SFCR(chan->id)); -+ if (status & STM32_DMA_FEI) { -+ stm32_dma_irq_clear(chan, STM32_DMA_FEI); -+ status &= ~STM32_DMA_FEI; -+ if (sfcr & STM32_DMA_SFCR_FEIE) { +- if (status & STM32_DMA_TCI) { +- stm32_dma_irq_clear(chan, STM32_DMA_TCI); +- if (scr & STM32_DMA_SCR_TCIE) +- stm32_dma_handle_chan_done(chan); +- status &= ~STM32_DMA_TCI; +- } +- if (status & STM32_DMA_HTI) { +- stm32_dma_irq_clear(chan, STM32_DMA_HTI); +- status &= ~STM32_DMA_HTI; +- } + if (status & STM32_DMA_FEI) { + stm32_dma_irq_clear(chan, STM32_DMA_FEI); + status &= ~STM32_DMA_FEI; + if (sfcr & STM32_DMA_SFCR_FEIE) { +- if (!(scr & STM32_DMA_SCR_EN)) + if (!(scr & STM32_DMA_SCR_EN) && + !(status & STM32_DMA_TCI)) -+ dev_err(chan2dev(chan), "FIFO Error\n"); -+ else -+ dev_dbg(chan2dev(chan), "FIFO over/underrun\n"); -+ } -+ } -+ if (status & STM32_DMA_DMEI) { -+ stm32_dma_irq_clear(chan, STM32_DMA_DMEI); -+ status &= ~STM32_DMA_DMEI; -+ if (sfcr & STM32_DMA_SCR_DMEIE) { -+ dev_dbg(chan2dev(chan), "Direct mode overrun\n"); -+ } -+ } -+ - if (status & STM32_DMA_TCI) { - stm32_dma_irq_clear(chan, STM32_DMA_TCI); - if (scr & STM32_DMA_SCR_TCIE) - stm32_dma_handle_chan_done(chan); - status &= ~STM32_DMA_TCI; + dev_err(chan2dev(chan), "FIFO Error\n"); + else + dev_dbg(chan2dev(chan), "FIFO over/underrun\n"); +@@ -674,6 +1066,19 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) + if (sfcr & STM32_DMA_SCR_DMEIE) + dev_dbg(chan2dev(chan), "Direct mode overrun\n"); } + - if (status & STM32_DMA_HTI) { - stm32_dma_irq_clear(chan, STM32_DMA_HTI); - status &= ~STM32_DMA_HTI; - } -- if (status & STM32_DMA_FEI) { -- stm32_dma_irq_clear(chan, STM32_DMA_FEI); -- status &= ~STM32_DMA_FEI; -- if (sfcr & STM32_DMA_SFCR_FEIE) { -- if (!(scr & STM32_DMA_SCR_EN)) -- dev_err(chan2dev(chan), "FIFO Error\n"); -- else -- dev_dbg(chan2dev(chan), "FIFO over/underrun\n"); -- } -- } ++ if (status & STM32_DMA_TCI) { ++ stm32_dma_irq_clear(chan, STM32_DMA_TCI); ++ if (scr & STM32_DMA_SCR_TCIE) ++ stm32_dma_handle_chan_done(chan); ++ status &= ~STM32_DMA_TCI; ++ } ++ ++ if (status & STM32_DMA_HTI) { ++ stm32_dma_irq_clear(chan, STM32_DMA_HTI); ++ status &= ~STM32_DMA_HTI; ++ } + if (status) { stm32_dma_irq_clear(chan, status); dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status); -@@ -680,31 +1093,37 @@ static void stm32_dma_issue_pending(struct dma_chan *c) +@@ -691,19 +1096,25 @@ static void stm32_dma_issue_pending(struct dma_chan *c) struct stm32_dma_chan *chan = to_stm32_dma_chan(c); unsigned long flags; @@ -951,101 +776,61 @@ index 5989b08935211..e8bedbad125c3 100644 enum dma_transfer_direction direction, enum dma_slave_buswidth *buswidth, - u32 buf_len) -+ u32 buf_len, dma_addr_t buf_addr) ++ u32 buf_len, u64 buf_addr) { enum dma_slave_buswidth src_addr_width, dst_addr_width; int src_bus_width, dst_bus_width; - int src_burst_size, dst_burst_size; - u32 src_maxburst, dst_maxburst, src_best_burst, dst_best_burst; -- u32 dma_scr, threshold; -+ u32 dma_scr, fifoth; - - src_addr_width = chan->dma_sconfig.src_addr_width; - dst_addr_width = chan->dma_sconfig.dst_addr_width; - src_maxburst = chan->dma_sconfig.src_maxburst; - dst_maxburst = chan->dma_sconfig.dst_maxburst; -- threshold = chan->threshold; -+ fifoth = chan->threshold; - - switch (direction) { - case DMA_MEM_TO_DEV: -@@ -716,7 +1135,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - /* Set device burst size */ - dst_best_burst = stm32_dma_get_best_burst(buf_len, - dst_maxburst, -- threshold, -+ fifoth, - dst_addr_width); - - dst_burst_size = stm32_dma_get_burst(chan, dst_best_burst); -@@ -724,7 +1143,8 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, +@@ -735,14 +1146,21 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, return dst_burst_size; /* Set memory data size */ -- src_addr_width = stm32_dma_get_max_width(buf_len, threshold); +- src_addr_width = stm32_dma_get_max_width(buf_len, fifoth); + src_addr_width = stm32_dma_get_max_width(buf_len, buf_addr, + fifoth); chan->mem_width = src_addr_width; src_bus_width = stm32_dma_get_width(chan, src_addr_width); if (src_bus_width < 0) -@@ -734,7 +1154,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - src_maxburst = STM32_DMA_MAX_BURST; + return src_bus_width; + +- /* Set memory burst size */ +- src_maxburst = STM32_DMA_MAX_BURST; ++ /* ++ * Set memory burst size - burst not possible if address is not aligned on ++ * the address boundary equal to the size of the transfer ++ */ ++ if (do_div(buf_addr, buf_len)) ++ src_maxburst = 1; ++ else ++ src_maxburst = STM32_DMA_MAX_BURST; src_best_burst = stm32_dma_get_best_burst(buf_len, src_maxburst, -- threshold, -+ fifoth, - src_addr_width); - src_burst_size = stm32_dma_get_burst(chan, src_best_burst); - if (src_burst_size < 0) -@@ -748,7 +1168,8 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - - /* Set FIFO threshold */ - chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_FTH_MASK; -- chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(threshold); -+ if (fifoth != STM32_DMA_FIFO_THRESHOLD_NONE) -+ chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(fifoth); - - /* Set peripheral address */ - chan->chan_reg.dma_spar = chan->dma_sconfig.dst_addr; -@@ -764,7 +1185,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - /* Set device burst size */ - src_best_burst = stm32_dma_get_best_burst(buf_len, - src_maxburst, -- threshold, -+ fifoth, - src_addr_width); - chan->mem_burst = src_best_burst; - src_burst_size = stm32_dma_get_burst(chan, src_best_burst); -@@ -772,7 +1193,8 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, + fifoth, +@@ -784,14 +1202,21 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, return src_burst_size; /* Set memory data size */ -- dst_addr_width = stm32_dma_get_max_width(buf_len, threshold); +- dst_addr_width = stm32_dma_get_max_width(buf_len, fifoth); + dst_addr_width = stm32_dma_get_max_width(buf_len, buf_addr, + fifoth); chan->mem_width = dst_addr_width; dst_bus_width = stm32_dma_get_width(chan, dst_addr_width); if (dst_bus_width < 0) -@@ -782,7 +1204,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - dst_maxburst = STM32_DMA_MAX_BURST; + return dst_bus_width; + +- /* Set memory burst size */ +- dst_maxburst = STM32_DMA_MAX_BURST; ++ /* ++ * Set memory burst size - burst not possible if address is not aligned on ++ * the address boundary equal to the size of the transfer ++ */ ++ if (do_div(buf_addr, buf_len)) ++ dst_maxburst = 1; ++ else ++ dst_maxburst = STM32_DMA_MAX_BURST; dst_best_burst = stm32_dma_get_best_burst(buf_len, dst_maxburst, -- threshold, -+ fifoth, - dst_addr_width); - chan->mem_burst = dst_best_burst; - dst_burst_size = stm32_dma_get_burst(chan, dst_best_burst); -@@ -797,7 +1219,8 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - - /* Set FIFO threshold */ - chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_FTH_MASK; -- chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(threshold); -+ if (fifoth != STM32_DMA_FIFO_THRESHOLD_NONE) -+ chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(fifoth); - - /* Set peripheral address */ - chan->chan_reg.dma_spar = chan->dma_sconfig.src_addr; -@@ -825,6 +1248,162 @@ static void stm32_dma_clear_reg(struct stm32_dma_chan_reg *regs) + fifoth, +@@ -838,6 +1263,162 @@ static void stm32_dma_clear_reg(struct stm32_dma_chan_reg *regs) memset(regs, 0, sizeof(struct stm32_dma_chan_reg)); } @@ -1178,7 +963,7 @@ index 5989b08935211..e8bedbad125c3 100644 + for_each_sg(sgl, sg, sg_len, i) { + ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, + sg_dma_len(sg), -+ sg_dma_address(sg)); ++ (u64)sg_dma_address(sg)); + if (ret < 0) + return ret; + @@ -1208,7 +993,7 @@ index 5989b08935211..e8bedbad125c3 100644 static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( struct dma_chan *c, struct scatterlist *sgl, u32 sg_len, enum dma_transfer_direction direction, -@@ -832,9 +1411,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( +@@ -845,9 +1426,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( { struct stm32_dma_chan *chan = to_stm32_dma_chan(c); struct stm32_dma_desc *desc; @@ -1218,7 +1003,7 @@ index 5989b08935211..e8bedbad125c3 100644 int i, ret; if (!chan->config_init) { -@@ -857,48 +1433,140 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( +@@ -870,48 +1448,140 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( else chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; @@ -1227,12 +1012,12 @@ index 5989b08935211..e8bedbad125c3 100644 - sg_dma_len(sg)); - if (ret < 0) - goto err; -- -- desc->sg_req[i].len = sg_dma_len(sg); + if (chan->use_mdma) { + struct sg_table new_sgt; + struct scatterlist *s, *_sgl; +- desc->sg_req[i].len = sg_dma_len(sg); +- - nb_data_items = desc->sg_req[i].len / buswidth; - if (nb_data_items > STM32_DMA_ALIGNED_MAX_DATA_ITEMS) { - dev_err(chan2dev(chan), "nb items not supported\n"); @@ -1379,17 +1164,16 @@ index 5989b08935211..e8bedbad125c3 100644 int i, ret; if (!buf_len || !period_len) { -@@ -927,7 +1595,8 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( +@@ -940,7 +1610,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( return NULL; } - ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, period_len); -+ ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, period_len, -+ buf_addr); ++ ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, period_len, (u64)buf_addr); if (ret < 0) return NULL; -@@ -946,28 +1615,49 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( +@@ -959,28 +1629,49 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( /* Clear periph ctrl if client set it */ chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; @@ -1407,10 +1191,10 @@ index 5989b08935211..e8bedbad125c3 100644 - desc->sg_req[i].len = period_len; + desc->num_sgs = num_periods; + desc->cyclic = true; -+ + + if (chan->use_mdma) { + chan->mchan.dir = direction; - ++ + ret = stm32_dma_mdma_prep_dma_cyclic(chan, buf_addr, buf_len, + period_len, desc); + if (ret < 0) @@ -1451,7 +1235,7 @@ index 5989b08935211..e8bedbad125c3 100644 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); } -@@ -1008,13 +1698,13 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy( +@@ -1021,13 +1712,13 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy( STM32_DMA_SCR_PINC | STM32_DMA_SCR_TCIE | STM32_DMA_SCR_TEIE; @@ -1467,7 +1251,7 @@ index 5989b08935211..e8bedbad125c3 100644 } desc->num_sgs = num_sgs; -@@ -1023,18 +1713,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy( +@@ -1036,18 +1727,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy( return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); } @@ -1486,7 +1270,7 @@ index 5989b08935211..e8bedbad125c3 100644 /** * stm32_dma_is_current_sg - check that expected sg_req is currently transferred * @chan: dma channel -@@ -1081,6 +1759,10 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, +@@ -1094,6 +1773,10 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, struct stm32_dma_sg_req *sg_req = &chan->desc->sg_req[chan->next_sg]; int i; @@ -1497,7 +1281,7 @@ index 5989b08935211..e8bedbad125c3 100644 /* * Calculate the residue means compute the descriptors * information: -@@ -1112,7 +1794,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, +@@ -1125,7 +1808,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, n_sg++; if (n_sg == chan->desc->num_sgs) n_sg = 0; @@ -1506,7 +1290,7 @@ index 5989b08935211..e8bedbad125c3 100644 } /* -@@ -1124,7 +1806,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, +@@ -1137,7 +1820,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, */ if (!chan->desc->cyclic || n_sg != 0) for (i = n_sg; i < desc->num_sgs; i++) @@ -1515,7 +1299,7 @@ index 5989b08935211..e8bedbad125c3 100644 if (!chan->mem_burst) return residue; -@@ -1142,11 +1824,23 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c, +@@ -1155,11 +1838,23 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c, struct dma_tx_state *state) { struct stm32_dma_chan *chan = to_stm32_dma_chan(c); @@ -1539,7 +1323,7 @@ index 5989b08935211..e8bedbad125c3 100644 status = dma_cookie_status(c, cookie, state); if (status == DMA_COMPLETE || !state) return status; -@@ -1203,25 +1897,51 @@ static void stm32_dma_free_chan_resources(struct dma_chan *c) +@@ -1216,27 +1911,53 @@ static void stm32_dma_free_chan_resources(struct dma_chan *c) pm_runtime_put(dmadev->ddev.dev); vchan_free_chan_resources(to_virt_chan(c)); @@ -1588,15 +1372,17 @@ index 5989b08935211..e8bedbad125c3 100644 chan->chan_reg.dma_scr |= STM32_DMA_SCR_TEIE | STM32_DMA_SCR_TCIE; - chan->threshold = STM32_DMA_THRESHOLD_FTR_GET(cfg->features); + if (STM32_DMA_DIRECT_MODE_GET(cfg->features)) + chan->threshold = STM32_DMA_FIFO_THRESHOLD_NONE; ++ if (STM32_DMA_ALT_ACK_MODE_GET(cfg->features)) ++ chan->chan_reg.dma_scr |= STM32_DMA_SCR_TRBUFF; + chan->use_mdma = STM32_DMA_MDMA_CHAIN_FTR_GET(cfg->features); + chan->sram_size = (1 << STM32_DMA_MDMA_SRAM_SIZE_GET(cfg->features)) * + STM32_DMA_SRAM_GRANULARITY; -+ if (STM32_DMA_DIRECT_MODE_GET(cfg->features)) -+ chan->threshold = STM32_DMA_FIFO_THRESHOLD_NONE; } static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec, -@@ -1259,6 +1979,9 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec, +@@ -1274,6 +1995,9 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec, stm32_dma_set_config(chan, &cfg); @@ -1606,7 +1392,7 @@ index 5989b08935211..e8bedbad125c3 100644 return c; } -@@ -1271,10 +1994,13 @@ MODULE_DEVICE_TABLE(of, stm32_dma_of_match); +@@ -1286,11 +2010,13 @@ MODULE_DEVICE_TABLE(of, stm32_dma_of_match); static int stm32_dma_probe(struct platform_device *pdev) { struct stm32_dma_chan *chan; @@ -1615,41 +1401,13 @@ index 5989b08935211..e8bedbad125c3 100644 struct dma_device *dd; const struct of_device_id *match; struct resource *res; -+ struct reset_control *rst; + struct reset_control *rst; + char name[4]; int i, ret; match = of_match_device(stm32_dma_of_match, &pdev->dev); -@@ -1296,8 +2022,10 @@ static int stm32_dma_probe(struct platform_device *pdev) - - dmadev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(dmadev->clk)) { -- dev_err(&pdev->dev, "Error: Missing controller clock\n"); -- return PTR_ERR(dmadev->clk); -+ ret = PTR_ERR(dmadev->clk); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Can't get clock\n"); -+ return ret; - } - - ret = clk_prepare_enable(dmadev->clk); -@@ -1309,13 +2037,26 @@ static int stm32_dma_probe(struct platform_device *pdev) - dmadev->mem2mem = of_property_read_bool(pdev->dev.of_node, - "st,mem2mem"); - -- dmadev->rst = devm_reset_control_get(&pdev->dev, NULL); -- if (!IS_ERR(dmadev->rst)) { -- reset_control_assert(dmadev->rst); -+ rst = devm_reset_control_get(&pdev->dev, NULL); -+ if (IS_ERR(rst)) { -+ ret = PTR_ERR(rst); -+ if (ret == -EPROBE_DEFER) -+ goto err_clk; -+ } else { -+ reset_control_assert(rst); - udelay(2); -- reset_control_deassert(dmadev->rst); -+ reset_control_deassert(rst); +@@ -1334,6 +2060,13 @@ static int stm32_dma_probe(struct platform_device *pdev) + reset_control_deassert(rst); } + dmadev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0); @@ -1659,22 +1417,10 @@ index 5989b08935211..e8bedbad125c3 100644 + dev_dbg(&pdev->dev, "SRAM pool: %zu KiB\n", + gen_pool_size(dmadev->sram_pool) / 1024); + -+ dma_set_max_seg_size(&pdev->dev, STM32_DMA_ALIGNED_MAX_DATA_ITEMS); -+ - dma_cap_set(DMA_SLAVE, dd->cap_mask); - dma_cap_set(DMA_PRIVATE, dd->cap_mask); - dma_cap_set(DMA_CYCLIC, dd->cap_mask); -@@ -1336,7 +2077,9 @@ static int stm32_dma_probe(struct platform_device *pdev) - BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); - dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; -+ dd->copy_align = DMAENGINE_ALIGN_32_BYTES; - dd->max_burst = STM32_DMA_MAX_BURST; -+ dd->descriptor_reuse = true; - dd->dev = &pdev->dev; - INIT_LIST_HEAD(&dd->channels); + dma_set_max_seg_size(&pdev->dev, STM32_DMA_ALIGNED_MAX_DATA_ITEMS); -@@ -1351,11 +2094,27 @@ static int stm32_dma_probe(struct platform_device *pdev) + dma_cap_set(DMA_SLAVE, dd->cap_mask); +@@ -1373,11 +2106,27 @@ static int stm32_dma_probe(struct platform_device *pdev) chan->id = i; chan->vchan.desc_free = stm32_dma_desc_free; vchan_init(&chan->vchan, dd); @@ -1703,232 +1449,25 @@ index 5989b08935211..e8bedbad125c3 100644 for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) { chan = &dmadev->chan[i]; -@@ -1396,7 +2155,11 @@ static int stm32_dma_probe(struct platform_device *pdev) +@@ -1418,6 +2167,10 @@ static int stm32_dma_probe(struct platform_device *pdev) err_unregister: dma_async_device_unregister(dd); --clk_free: +err_dma: + for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) + if (dmadev->chan[i].mchan.chan) + dma_release_channel(dmadev->chan[i].mchan.chan); -+err_clk: + clk_free: clk_disable_unprepare(dmadev->clk); - return ret; -@@ -1427,7 +2190,44 @@ static int stm32_dma_runtime_resume(struct device *dev) - } - #endif - -+#ifdef CONFIG_PM_SLEEP -+static int stm32_dma_suspend(struct device *dev) -+{ -+ struct stm32_dma_device *dmadev = dev_get_drvdata(dev); -+ int id, ret, scr; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) -+ return ret; -+ -+ for (id = 0; id < STM32_DMA_MAX_CHANNELS; id++) { -+ scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); -+ if (scr & STM32_DMA_SCR_EN) { -+ dev_warn(dev, "Suspend is prevented by Chan %i\n", id); -+ return -EBUSY; -+ } -+ } -+ -+ pm_runtime_put_sync(dev); -+ -+ pm_runtime_force_suspend(dev); -+ return 0; -+} -+ -+static int stm32_dma_resume(struct device *dev) -+{ -+ int ret; -+ -+ ret = pm_runtime_force_resume(dev); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+#endif -+ - static const struct dev_pm_ops stm32_dma_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(stm32_dma_suspend, stm32_dma_resume) - SET_RUNTIME_PM_OPS(stm32_dma_runtime_suspend, - stm32_dma_runtime_resume, NULL) - }; -@@ -1438,10 +2238,11 @@ static struct platform_driver stm32_dma_driver = { - .of_match_table = stm32_dma_of_match, - .pm = &stm32_dma_pm_ops, - }, -+ .probe = stm32_dma_probe, - }; - - static int __init stm32_dma_init(void) +@@ -1499,4 +2252,4 @@ static int __init stm32_dma_init(void) { -- return platform_driver_probe(&stm32_dma_driver, stm32_dma_probe); -+ return platform_driver_register(&stm32_dma_driver); + return platform_driver_register(&stm32_dma_driver); } -subsys_initcall(stm32_dma_init); +device_initcall(stm32_dma_init); -diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c -index 3c89bd39e0968..bbfa141004cdf 100644 ---- a/drivers/dma/stm32-dmamux.c -+++ b/drivers/dma/stm32-dmamux.c -@@ -35,12 +35,14 @@ struct stm32_dmamux { - struct stm32_dmamux_data { - struct dma_router dmarouter; - struct clk *clk; -- struct reset_control *rst; - void __iomem *iomem; - u32 dma_requests; /* Number of DMA requests connected to DMAMUX */ - u32 dmamux_requests; /* Number of DMA requests routed toward DMAs */ - spinlock_t lock; /* Protects register access */ - unsigned long *dma_inuse; /* Used DMA channel */ -+ u32 ccr[STM32_DMAMUX_MAX_DMA_REQUESTS]; /* Use to backup CCR register -+ * in suspend -+ */ - u32 dma_reqs[]; /* Number of DMA Request per DMA masters. - * [0] holds number of DMA Masters. - * To be kept at very end end of this structure -@@ -179,6 +181,7 @@ static int stm32_dmamux_probe(struct platform_device *pdev) - struct stm32_dmamux_data *stm32_dmamux; - struct resource *res; - void __iomem *iomem; -+ struct reset_control *rst; - int i, count, ret; - u32 dma_req; - -@@ -251,16 +254,26 @@ static int stm32_dmamux_probe(struct platform_device *pdev) - stm32_dmamux->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(stm32_dmamux->clk)) { - ret = PTR_ERR(stm32_dmamux->clk); -- if (ret == -EPROBE_DEFER) -- dev_info(&pdev->dev, "Missing controller clock\n"); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Missing clock controller\n"); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(stm32_dmamux->clk); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret); - return ret; - } - -- stm32_dmamux->rst = devm_reset_control_get(&pdev->dev, NULL); -- if (!IS_ERR(stm32_dmamux->rst)) { -- reset_control_assert(stm32_dmamux->rst); -+ rst = devm_reset_control_get(&pdev->dev, NULL); -+ if (IS_ERR(rst)) { -+ ret = PTR_ERR(rst); -+ if (ret == -EPROBE_DEFER) -+ goto err_clk; -+ } else { -+ reset_control_assert(rst); - udelay(2); -- reset_control_deassert(stm32_dmamux->rst); -+ reset_control_deassert(rst); - } - - stm32_dmamux->iomem = iomem; -@@ -271,14 +284,6 @@ static int stm32_dmamux_probe(struct platform_device *pdev) - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - -- if (!IS_ERR(stm32_dmamux->clk)) { -- ret = clk_prepare_enable(stm32_dmamux->clk); -- if (ret < 0) { -- dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret); -- return ret; -- } -- } -- - pm_runtime_get_noresume(&pdev->dev); - - /* Reset the dmamux */ -@@ -287,8 +292,17 @@ static int stm32_dmamux_probe(struct platform_device *pdev) - - pm_runtime_put(&pdev->dev); - -- return of_dma_router_register(node, stm32_dmamux_route_allocate, -+ ret = of_dma_router_register(node, stm32_dmamux_route_allocate, - &stm32_dmamux->dmarouter); -+ if (ret) -+ goto err_clk; -+ -+ return 0; -+ -+err_clk: -+ clk_disable_unprepare(stm32_dmamux->clk); -+ -+ return ret; - } - - #ifdef CONFIG_PM -@@ -318,7 +332,56 @@ static int stm32_dmamux_runtime_resume(struct device *dev) - } - #endif - -+#ifdef CONFIG_PM_SLEEP -+static int stm32_dmamux_suspend(struct device *dev) -+{ -+ struct platform_device *pdev = -+ container_of(dev, struct platform_device, dev); -+ struct stm32_dmamux_data *stm32_dmamux = platform_get_drvdata(pdev); -+ int i, ret; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) -+ return ret; -+ -+ for (i = 0; i < stm32_dmamux->dma_requests; i++) -+ stm32_dmamux->ccr[i] = stm32_dmamux_read(stm32_dmamux->iomem, -+ STM32_DMAMUX_CCR(i)); -+ -+ pm_runtime_put_sync(dev); -+ -+ pm_runtime_force_suspend(dev); -+ -+ return 0; -+} -+ -+static int stm32_dmamux_resume(struct device *dev) -+{ -+ struct platform_device *pdev = -+ container_of(dev, struct platform_device, dev); -+ struct stm32_dmamux_data *stm32_dmamux = platform_get_drvdata(pdev); -+ int i, ret; -+ -+ ret = pm_runtime_force_resume(dev); -+ if (ret < 0) -+ return ret; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) -+ return ret; -+ -+ for (i = 0; i < stm32_dmamux->dma_requests; i++) -+ stm32_dmamux_write(stm32_dmamux->iomem, STM32_DMAMUX_CCR(i), -+ stm32_dmamux->ccr[i]); -+ -+ pm_runtime_put_sync(dev); -+ -+ return 0; -+} -+#endif -+ - static const struct dev_pm_ops stm32_dmamux_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(stm32_dmamux_suspend, stm32_dmamux_resume) - SET_RUNTIME_PM_OPS(stm32_dmamux_runtime_suspend, - stm32_dmamux_runtime_resume, NULL) - }; diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c -index 5838311cf9900..85642133554eb 100644 +index 08cfbfab837b..a4b25944fba4 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -199,7 +199,9 @@ @@ -1958,15 +1497,7 @@ index 5838311cf9900..85642133554eb 100644 struct stm32_mdma_desc_node node[]; }; -@@ -273,7 +277,6 @@ struct stm32_mdma_device { - void __iomem *base; - struct clk *clk; - int irq; -- struct reset_control *rst; - u32 nr_channels; - u32 nr_requests; - u32 nr_ahb_addr_masks; -@@ -567,13 +570,25 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, +@@ -566,13 +570,25 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, dst_addr = chan->dma_config.dst_addr; /* Set device data size */ @@ -1992,7 +1523,7 @@ index 5838311cf9900..85642133554eb 100644 dst_best_burst = stm32_mdma_get_best_burst(buf_len, tlen, dst_maxburst, dst_addr_width); -@@ -616,13 +631,25 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, +@@ -615,13 +631,25 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, src_addr = chan->dma_config.src_addr; /* Set device data size */ @@ -2018,7 +1549,7 @@ index 5838311cf9900..85642133554eb 100644 src_best_burst = stm32_mdma_get_best_burst(buf_len, tlen, src_maxburst, src_addr_width); -@@ -730,6 +757,7 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, +@@ -729,6 +757,7 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, { struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); struct dma_slave_config *dma_config = &chan->dma_config; @@ -2026,7 +1557,7 @@ index 5838311cf9900..85642133554eb 100644 struct scatterlist *sg; dma_addr_t src_addr, dst_addr; u32 ccr, ctcr, ctbr; -@@ -752,6 +780,8 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, +@@ -751,6 +780,8 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, } else { src_addr = dma_config->src_addr; dst_addr = sg_dma_address(sg); @@ -2035,7 +1566,7 @@ index 5838311cf9900..85642133554eb 100644 ret = stm32_mdma_set_xfer_param(chan, direction, &ccr, &ctcr, &ctbr, dst_addr, sg_dma_len(sg)); -@@ -770,8 +800,6 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, +@@ -769,8 +800,6 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, /* Enable interrupts */ ccr &= ~STM32_MDMA_CCR_IRQ_MASK; ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE; @@ -2044,7 +1575,7 @@ index 5838311cf9900..85642133554eb 100644 desc->ccr = ccr; return 0; -@@ -783,7 +811,9 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, +@@ -782,7 +811,9 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, unsigned long flags, void *context) { struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c); @@ -2054,7 +1585,7 @@ index 5838311cf9900..85642133554eb 100644 int i, ret; /* -@@ -805,6 +835,20 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, +@@ -804,6 +835,20 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, if (ret < 0) goto xfer_setup_err; @@ -2075,7 +1606,7 @@ index 5838311cf9900..85642133554eb 100644 desc->cyclic = false; return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -@@ -826,9 +870,10 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, +@@ -825,9 +870,10 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c); struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); struct dma_slave_config *dma_config = &chan->dma_config; @@ -2087,7 +1618,7 @@ index 5838311cf9900..85642133554eb 100644 int i, ret; /* -@@ -882,12 +927,29 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, +@@ -881,12 +927,29 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, desc->ccr = ccr; /* Configure hwdesc list */ @@ -2119,7 +1650,7 @@ index 5838311cf9900..85642133554eb 100644 dst_addr = buf_addr + i * period_len; } -@@ -897,6 +959,7 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, +@@ -896,6 +959,7 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, } desc->cyclic = true; @@ -2127,29 +1658,7 @@ index 5838311cf9900..85642133554eb 100644 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -@@ -1127,6 +1190,8 @@ static void stm32_mdma_start_transfer(struct stm32_mdma_chan *chan) - return; - } - -+ list_del(&vdesc->node); -+ - chan->desc = to_stm32_mdma_desc(vdesc); - hwdesc = chan->desc->node[0].hwdesc; - chan->curr_hwdesc = 0; -@@ -1242,8 +1307,10 @@ static int stm32_mdma_terminate_all(struct dma_chan *c) - LIST_HEAD(head); - - spin_lock_irqsave(&chan->vchan.lock, flags); -- if (chan->busy) { -- stm32_mdma_stop(chan); -+ if (chan->desc) { -+ vchan_terminate_vdesc(&chan->desc->vdesc); -+ if (chan->busy) -+ stm32_mdma_stop(chan); - chan->desc = NULL; - } - vchan_get_all_descriptors(&chan->vchan, &head); -@@ -1277,14 +1344,28 @@ static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan, +@@ -1280,14 +1344,28 @@ static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan, { struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); struct stm32_mdma_hwdesc *hwdesc = desc->node[0].hwdesc; @@ -2181,7 +1690,7 @@ index 5838311cf9900..85642133554eb 100644 cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id)); residue += cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK; -@@ -1304,24 +1385,39 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c, +@@ -1307,24 +1385,39 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c, struct dma_tx_state *state) { struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c); @@ -2226,15 +1735,7 @@ index 5838311cf9900..85642133554eb 100644 dma_set_residue(state, residue); spin_unlock_irqrestore(&chan->vchan.lock, flags); -@@ -1331,7 +1427,6 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c, - - static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan) - { -- list_del(&chan->desc->vdesc.node); - vchan_cookie_complete(&chan->desc->vdesc); - chan->desc = NULL; - chan->busy = false; -@@ -1344,7 +1439,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) +@@ -1346,7 +1439,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) { struct stm32_mdma_device *dmadev = devid; struct stm32_mdma_chan *chan = devid; @@ -2243,7 +1744,7 @@ index 5838311cf9900..85642133554eb 100644 /* Find out which channel generates the interrupt */ status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0); -@@ -1366,67 +1461,71 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) +@@ -1368,67 +1461,71 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) chan = &dmadev->chan[id]; if (!chan) { @@ -2344,7 +1845,7 @@ index 5838311cf9900..85642133554eb 100644 return IRQ_HANDLED; } -@@ -1486,7 +1585,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, +@@ -1488,7 +1585,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, struct dma_chan *c; struct stm32_mdma_chan_config config; @@ -2353,7 +1854,7 @@ index 5838311cf9900..85642133554eb 100644 dev_err(mdma2dev(dmadev), "Bad number of args\n"); return NULL; } -@@ -1496,6 +1595,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, +@@ -1498,6 +1595,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, config.transfer_config = dma_spec->args[2]; config.mask_addr = dma_spec->args[3]; config.mask_data = dma_spec->args[4]; @@ -2361,173 +1862,12 @@ index 5838311cf9900..85642133554eb 100644 if (config.request >= dmadev->nr_requests) { dev_err(mdma2dev(dmadev), "Bad request line\n"); -@@ -1532,6 +1632,7 @@ static int stm32_mdma_probe(struct platform_device *pdev) - struct dma_device *dd; - struct device_node *of_node; - struct resource *res; -+ struct reset_control *rst; - u32 nr_channels, nr_requests; - int i, count, ret; - -@@ -1579,8 +1680,8 @@ static int stm32_mdma_probe(struct platform_device *pdev) - dmadev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(dmadev->clk)) { - ret = PTR_ERR(dmadev->clk); -- if (ret == -EPROBE_DEFER) -- dev_info(&pdev->dev, "Missing controller clock\n"); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Missing clock controller\n"); - return ret; - } - -@@ -1590,11 +1691,15 @@ static int stm32_mdma_probe(struct platform_device *pdev) - return ret; - } - -- dmadev->rst = devm_reset_control_get(&pdev->dev, NULL); -- if (!IS_ERR(dmadev->rst)) { -- reset_control_assert(dmadev->rst); -+ rst = devm_reset_control_get(&pdev->dev, NULL); -+ if (IS_ERR(rst)) { -+ ret = PTR_ERR(rst); -+ if (ret == -EPROBE_DEFER) -+ goto err_clk; -+ } else { -+ reset_control_assert(rst); - udelay(2); -- reset_control_deassert(dmadev->rst); -+ reset_control_deassert(rst); - } - - dd = &dmadev->ddev; -@@ -1614,6 +1719,8 @@ static int stm32_mdma_probe(struct platform_device *pdev) - dd->device_resume = stm32_mdma_resume; - dd->device_terminate_all = stm32_mdma_terminate_all; - dd->device_synchronize = stm32_mdma_synchronize; -+ dd->descriptor_reuse = true; -+ - dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | - BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | - BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | -@@ -1637,25 +1744,27 @@ static int stm32_mdma_probe(struct platform_device *pdev) - } - - dmadev->irq = platform_get_irq(pdev, 0); -- if (dmadev->irq < 0) -- return dmadev->irq; -+ if (dmadev->irq < 0) { -+ ret = dmadev->irq; -+ goto err_clk; -+ } - - ret = devm_request_irq(&pdev->dev, dmadev->irq, stm32_mdma_irq_handler, - 0, dev_name(&pdev->dev), dmadev); - if (ret) { - dev_err(&pdev->dev, "failed to request IRQ\n"); -- return ret; -+ goto err_clk; - } - - ret = dmaenginem_async_device_register(dd); - if (ret) -- return ret; -+ goto err_clk; - - ret = of_dma_controller_register(of_node, stm32_mdma_of_xlate, dmadev); - if (ret < 0) { - dev_err(&pdev->dev, - "STM32 MDMA DMA OF registration failed %d\n", ret); -- goto err_unregister; -+ goto err_dmaengine; - } - - platform_set_drvdata(pdev, dmadev); -@@ -1668,7 +1777,11 @@ static int stm32_mdma_probe(struct platform_device *pdev) - - return 0; - --err_unregister: -+err_dmaengine: -+ dma_async_device_unregister(dd); -+err_clk: -+ clk_disable_unprepare(dmadev->clk); -+ - return ret; - } - -@@ -1697,7 +1810,45 @@ static int stm32_mdma_runtime_resume(struct device *dev) - } - #endif - -+#ifdef CONFIG_PM_SLEEP -+static int stm32_mdma_pw_suspend(struct device *dev) -+{ -+ struct stm32_mdma_device *dmadev = dev_get_drvdata(dev); -+ u32 ccr, id; -+ int ret; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) -+ return ret; -+ -+ for (id = 0; id < dmadev->nr_channels; id++) { -+ ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(id)); -+ if (ccr & STM32_MDMA_CCR_EN) { -+ dev_warn(dev, "Suspend is prevented by Chan %i\n", id); -+ return -EBUSY; -+ } -+ } -+ -+ pm_runtime_put_sync(dev); -+ -+ pm_runtime_force_suspend(dev); -+ return 0; -+} -+ -+static int stm32_mdma_pw_resume(struct device *dev) -+{ -+ int ret; -+ -+ ret = pm_runtime_force_resume(dev); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+#endif -+ - static const struct dev_pm_ops stm32_mdma_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(stm32_mdma_pw_suspend, stm32_mdma_pw_resume) - SET_RUNTIME_PM_OPS(stm32_mdma_runtime_suspend, - stm32_mdma_runtime_resume, NULL) - }; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h -index 8013562751a50..07f6e1136dbf8 100644 +index dd357a747780..42745f58412c 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h -@@ -258,6 +258,9 @@ struct dma_chan { - /* sysfs */ - int chan_id; - struct dma_chan_dev *dev; -+#ifdef CONFIG_DEBUG_FS -+ char *dbg_client_name; -+#endif - - struct list_head device_node; - struct dma_chan_percpu __percpu *local; -@@ -802,6 +805,10 @@ struct dma_device { - dma_cookie_t cookie, - struct dma_tx_state *txstate); - void (*device_issue_pending)(struct dma_chan *chan); -+ /* debugfs support */ -+#ifdef CONFIG_DEBUG_FS -+ void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev); -+#endif - }; - - static inline int dmaengine_slave_config(struct dma_chan *chan, -@@ -1309,9 +1316,11 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, - struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name); +@@ -1474,9 +1474,11 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, + struct device_node *np); struct dma_chan *dma_request_chan(struct device *dev, const char *name); +struct dma_chan *dma_request_chan_linked(struct device *dev, const char *name); @@ -2538,7 +1878,7 @@ index 8013562751a50..07f6e1136dbf8 100644 int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps); #else static inline struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) -@@ -1346,6 +1355,11 @@ static inline struct dma_chan *dma_request_chan(struct device *dev, +@@ -1506,6 +1508,11 @@ static inline struct dma_chan *dma_request_chan(struct device *dev, { return ERR_PTR(-ENODEV); } @@ -2550,7 +1890,7 @@ index 8013562751a50..07f6e1136dbf8 100644 static inline struct dma_chan *dma_request_chan_by_mask( const dma_cap_mask_t *mask) { -@@ -1354,6 +1368,10 @@ static inline struct dma_chan *dma_request_chan_by_mask( +@@ -1514,6 +1521,10 @@ static inline struct dma_chan *dma_request_chan_by_mask( static inline void dma_release_channel(struct dma_chan *chan) { } diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0006-ARM-5.10.10-stm32mp1-r1-DRM.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0006-ARM-5.10.10-stm32mp1-r1-DRM.patch new file mode 100644 index 0000000..14038a2 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0006-ARM-5.10.10-stm32mp1-r1-DRM.patch @@ -0,0 +1,881 @@ +From fe6c762c8d16cddae0a0fd5673f7ab8c6b06f4e5 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:01:48 +0100 +Subject: [PATCH 06/22] ARM 5.10.10-stm32mp1-r1 DRM + +--- + drivers/gpu/drm/bridge/sii902x.c | 100 +++++++++- + drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 172 ++++++++++++++---- + drivers/gpu/drm/drm_modes.c | 19 +- + .../gpu/drm/panel/panel-orisetech-otm8009a.c | 24 +-- + drivers/gpu/drm/panel/panel-raydium-rm68200.c | 17 +- + drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 3 +- + drivers/gpu/drm/stm/ltdc.c | 72 +++++--- + drivers/input/touchscreen/edt-ft5x06.c | 18 +- + drivers/input/touchscreen/goodix.c | 15 ++ + include/uapi/drm/drm_mode.h | 6 + + 10 files changed, 346 insertions(+), 100 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c +index 89558e581530..69208ead5384 100644 +--- a/drivers/gpu/drm/bridge/sii902x.c ++++ b/drivers/gpu/drm/bridge/sii902x.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -162,6 +163,11 @@ + + #define SII902X_AUDIO_PORT_INDEX 3 + ++/* CEC device */ ++#define SII902X_CEC_I2C_ADDR 0x30 ++ ++#define SII902X_CEC_SETUP 0x8e ++ + struct sii902x { + struct i2c_client *i2c; + struct regmap *regmap; +@@ -170,6 +176,7 @@ struct sii902x { + struct gpio_desc *reset_gpio; + struct i2c_mux_core *i2cmux; + struct regulator_bulk_data supplies[2]; ++ struct edid *edid; + /* + * Mutex protects audio and video functions from interfering + * each other, by keeping their i2c command sequences atomic. +@@ -280,6 +287,8 @@ static int sii902x_get_modes(struct drm_connector *connector) + + mutex_lock(&sii902x->mutex); + ++ kfree(sii902x->edid); ++ sii902x->edid = NULL; + edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]); + drm_connector_update_edid_property(connector, edid); + if (edid) { +@@ -287,7 +296,7 @@ static int sii902x_get_modes(struct drm_connector *connector) + output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI; + + num = drm_add_edid_modes(connector, edid); +- kfree(edid); ++ sii902x->edid = edid; + } + + ret = drm_display_info_set_bus_formats(&connector->display_info, +@@ -337,6 +346,7 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge) + static void sii902x_bridge_enable(struct drm_bridge *bridge) + { + struct sii902x *sii902x = bridge_to_sii902x(bridge); ++ u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI; + + mutex_lock(&sii902x->mutex); + +@@ -346,6 +356,14 @@ static void sii902x_bridge_enable(struct drm_bridge *bridge) + regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, + SII902X_SYS_CTRL_PWR_DWN, 0); + ++ if (sii902x->edid) { ++ if (drm_detect_hdmi_monitor(sii902x->edid)) ++ output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI; ++ } ++ ++ regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, ++ SII902X_SYS_CTRL_OUTPUT_MODE, output_mode); ++ + mutex_unlock(&sii902x->mutex); + } + +@@ -960,6 +978,13 @@ static int sii902x_init(struct sii902x *sii902x) + { + struct device *dev = &sii902x->i2c->dev; + unsigned int status = 0; ++ unsigned char data[2] = { SII902X_CEC_SETUP, 0}; ++ struct i2c_msg msg = { ++ .addr = SII902X_CEC_I2C_ADDR << 1, ++ .flags = 0, ++ .len = 2, ++ .buf = data, ++ }; + u8 chipid[4]; + int ret; + +@@ -982,13 +1007,22 @@ static int sii902x_init(struct sii902x *sii902x) + return -EINVAL; + } + ++ /* ++ * By default, CEC must be disabled to allow other CEC devives ++ * to bypass the bridge. ++ */ ++ ret = i2c_transfer(sii902x->i2c->adapter, &msg, 1); ++ if (ret < 0) ++ dev_warn(&sii902x->i2c->dev, "Failed to disable CEC device!\n"); ++ + /* Clear all pending interrupts */ + regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status); + regmap_write(sii902x->regmap, SII902X_INT_STATUS, status); + + if (sii902x->i2c->irq > 0) { +- regmap_write(sii902x->regmap, SII902X_INT_ENABLE, +- SII902X_HOTPLUG_EVENT); ++ regmap_update_bits(sii902x->regmap, SII902X_INT_ENABLE, ++ SII902X_HOTPLUG_EVENT, ++ SII902X_HOTPLUG_EVENT); + + ret = devm_request_threaded_irq(dev, sii902x->i2c->irq, NULL, + sii902x_interrupt, +@@ -1087,6 +1121,65 @@ static int sii902x_remove(struct i2c_client *client) + return 0; + } + ++static int sii902x_pm_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sii902x *sii902x = i2c_get_clientdata(client); ++ ++ DRM_DEBUG_DRIVER("\n"); ++ ++ if (sii902x->reset_gpio) ++ gpiod_set_value(sii902x->reset_gpio, 1); ++ ++ regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies), ++ sii902x->supplies); ++ ++ return 0; ++} ++ ++static int sii902x_pm_resume(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sii902x *sii902x = i2c_get_clientdata(client); ++ unsigned char data[2] = { SII902X_CEC_SETUP, 0}; ++ struct i2c_msg msg = { ++ .addr = SII902X_CEC_I2C_ADDR << 1, ++ .flags = 0, ++ .len = 2, ++ .buf = data, ++ }; ++ int ret; ++ ++ DRM_DEBUG_DRIVER("\n"); ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies), ++ sii902x->supplies); ++ if (ret) { ++ DRM_ERROR("regulator_bulk_enable failed\n"); ++ return ret; ++ } ++ ++ if (sii902x->reset_gpio) ++ gpiod_set_value(sii902x->reset_gpio, 0); ++ ++ regmap_write(sii902x->regmap, SII902X_REG_TPI_RQB, 0x00); ++ ++ ret = i2c_transfer(client->adapter, &msg, 1); ++ if (ret < 0) ++ DRM_ERROR("Failed to disable CEC device!\n"); ++ ++ if (client->irq > 0) ++ regmap_update_bits(sii902x->regmap, SII902X_INT_ENABLE, ++ SII902X_HOTPLUG_EVENT, ++ SII902X_HOTPLUG_EVENT); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops sii902x_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(sii902x_pm_suspend, sii902x_pm_resume) ++}; ++ + static const struct of_device_id sii902x_dt_ids[] = { + { .compatible = "sil,sii9022", }, + { } +@@ -1105,6 +1198,7 @@ static struct i2c_driver sii902x_driver = { + .driver = { + .name = "sii902x", + .of_match_table = sii902x_dt_ids, ++ .pm = &sii902x_pm_ops, + }, + .id_table = sii902x_i2c_ids, + }; +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +index 6b268f9445b3..25b63491135f 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +@@ -213,6 +213,20 @@ + + #define DSI_INT_ST0 0xbc + #define DSI_INT_ST1 0xc0 ++#define GPRXE BIT(12) ++#define GPRDE BIT(11) ++#define GPTXE BIT(10) ++#define GPWRE BIT(9) ++#define GCWRE BIT(8) ++#define DPIPLDWE BIT(7) ++#define EOTPE BIT(6) ++#define PSE BIT(5) ++#define CRCE BIT(4) ++#define ECCME BIT(3) ++#define ECCSE BIT(2) ++#define TOLPRX BIT(1) ++#define TOHSTX BIT(0) ++ + #define DSI_INT_MSK0 0xc4 + #define DSI_INT_MSK1 0xc8 + +@@ -314,9 +328,7 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, + { + struct dw_mipi_dsi *dsi = host_to_dsi(host); + const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data; +- struct drm_bridge *bridge; +- struct drm_panel *panel; +- int ret; ++ int ret = -ENODEV; + + if (device->lanes > dsi->plat_data->max_data_lanes) { + dev_err(dsi->dev, "the number of data lanes(%u) is too many\n", +@@ -329,22 +341,6 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, + dsi->format = device->format; + dsi->mode_flags = device->mode_flags; + +- ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0, +- &panel, &bridge); +- if (ret) +- return ret; +- +- if (panel) { +- bridge = drm_panel_bridge_add_typed(panel, +- DRM_MODE_CONNECTOR_DSI); +- if (IS_ERR(bridge)) +- return PTR_ERR(bridge); +- } +- +- dsi->panel_bridge = bridge; +- +- drm_bridge_add(&dsi->bridge); +- + if (pdata->host_ops && pdata->host_ops->attach) { + ret = pdata->host_ops->attach(pdata->priv_data, device); + if (ret < 0) +@@ -367,10 +363,6 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host, + return ret; + } + +- drm_of_panel_bridge_remove(host->dev->of_node, 1, 0); +- +- drm_bridge_remove(&dsi->bridge); +- + return 0; + } + +@@ -431,6 +423,42 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) + return 0; + } + ++static int dw_mipi_dsi_read_status(struct dw_mipi_dsi *dsi) ++{ ++ u32 val; ++ ++ val = dsi_read(dsi, DSI_INT_ST1); ++ ++ if (val & GPRXE) ++ DRM_DEBUG_DRIVER("DSI Generic payload receive error\n"); ++ if (val & GPRDE) ++ DRM_DEBUG_DRIVER("DSI Generic payload read error\n"); ++ if (val & GPTXE) ++ DRM_DEBUG_DRIVER("DSI Generic payload transmit error\n"); ++ if (val & GPWRE) ++ DRM_DEBUG_DRIVER("DSI Generic payload write error\n"); ++ if (val & GCWRE) ++ DRM_DEBUG_DRIVER("DSI Generic command write error\n"); ++ if (val & DPIPLDWE) ++ DRM_DEBUG_DRIVER("DSI DPI payload write error\n"); ++ if (val & EOTPE) ++ DRM_DEBUG_DRIVER("DSI EoTp error\n"); ++ if (val & PSE) ++ DRM_DEBUG_DRIVER("DSI Packet size error\n"); ++ if (val & CRCE) ++ DRM_DEBUG_DRIVER("DSI CRC error\n"); ++ if (val & ECCME) ++ DRM_DEBUG_DRIVER("DSI ECC multi-bit error\n"); ++ if (val & ECCSE) ++ DRM_DEBUG_DRIVER("DSI ECC single-bit error\n"); ++ if (val & TOLPRX) ++ DRM_DEBUG_DRIVER("DSI Timeout low-power reception\n"); ++ if (val & TOHSTX) ++ DRM_DEBUG_DRIVER("DSI Timeout high-speed transmission\n"); ++ ++ return val; ++} ++ + static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi, + const struct mipi_dsi_packet *packet) + { +@@ -460,6 +488,12 @@ static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi, + "failed to get available write payload FIFO\n"); + return ret; + } ++ ++ val = dw_mipi_dsi_read_status(dsi); ++ if (val) { ++ dev_err(dsi->dev, "dsi status error 0x%0x\n", val); ++ return -EINVAL; ++ } + } + + word = 0; +@@ -493,6 +527,12 @@ static int dw_mipi_dsi_read(struct dw_mipi_dsi *dsi, + return ret; + } + ++ val = dw_mipi_dsi_read_status(dsi); ++ if (val) { ++ dev_err(dsi->dev, "dsi status error 0x%0x\n", val); ++ return -EINVAL; ++ } ++ + val = dsi_read(dsi, DSI_GEN_PLD_DATA); + for (j = 0; j < 4 && j + i < len; j++) + buf[i + j] = val >> (8 * j); +@@ -507,6 +547,7 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, + struct dw_mipi_dsi *dsi = host_to_dsi(host); + struct mipi_dsi_packet packet; + int ret, nb_bytes; ++ int retry = 3; + + ret = mipi_dsi_create_packet(&packet, msg); + if (ret) { +@@ -518,24 +559,32 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, + if (dsi->slave) + dw_mipi_message_config(dsi->slave, msg); + +- ret = dw_mipi_dsi_write(dsi, &packet); +- if (ret) +- return ret; +- if (dsi->slave) { +- ret = dw_mipi_dsi_write(dsi->slave, &packet); ++ while (retry--) { ++ ret = dw_mipi_dsi_write(dsi, &packet); + if (ret) +- return ret; +- } ++ continue; + +- if (msg->rx_buf && msg->rx_len) { +- ret = dw_mipi_dsi_read(dsi, msg); +- if (ret) +- return ret; +- nb_bytes = msg->rx_len; +- } else { +- nb_bytes = packet.size; ++ if (dsi->slave) { ++ ret = dw_mipi_dsi_write(dsi->slave, &packet); ++ if (ret) ++ continue; ++ } ++ ++ if (msg->rx_buf && msg->rx_len) { ++ ret = dw_mipi_dsi_read(dsi, msg); ++ if (ret) ++ continue; ++ nb_bytes = msg->rx_len; ++ break; ++ } else { ++ nb_bytes = packet.size; ++ break; ++ } + } + ++ if (ret) ++ return ret; ++ + return nb_bytes; + } + +@@ -1105,6 +1154,9 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, + struct device *dev = &pdev->dev; + struct reset_control *apb_rst; + struct dw_mipi_dsi *dsi; ++ struct drm_bridge *bridge; ++ struct drm_panel *panel; ++ int i, nb_endpoints; + int ret; + + dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); +@@ -1172,8 +1224,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, + ret = mipi_dsi_host_register(&dsi->dsi_host); + if (ret) { + dev_err(dev, "Failed to register MIPI host: %d\n", ret); +- dw_mipi_dsi_debugfs_remove(dsi); +- return ERR_PTR(ret); ++ goto err_pmr_enable; + } + + dsi->bridge.driver_private = dsi; +@@ -1182,11 +1233,54 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, + dsi->bridge.of_node = pdev->dev.of_node; + #endif + ++ /* Get number of endpoints */ ++ nb_endpoints = of_graph_get_endpoint_count(pdev->dev.of_node); ++ if (!nb_endpoints) { ++ ret = -ENODEV; ++ goto err_host_reg; ++ } ++ ++ for (i = 1; i < nb_endpoints; i++) { ++ ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, i, 0, ++ &panel, &bridge); ++ if (!ret) ++ break; ++ else if (ret == -EPROBE_DEFER) ++ goto err_host_reg; ++ } ++ ++ /* check if an error is returned >> no panel or bridge detected */ ++ if (ret) ++ goto err_host_reg; ++ ++ if (panel) { ++ bridge = drm_panel_bridge_add_typed(panel, DRM_MODE_CONNECTOR_DSI); ++ if (IS_ERR(bridge)) { ++ ret = PTR_ERR(bridge); ++ goto err_host_reg; ++ } ++ } ++ ++ dsi->panel_bridge = bridge; ++ ++ drm_bridge_add(&dsi->bridge); ++ + return dsi; ++ ++err_host_reg: ++ mipi_dsi_host_unregister(&dsi->dsi_host); ++ ++err_pmr_enable: ++ pm_runtime_disable(dev); ++ dw_mipi_dsi_debugfs_remove(dsi); ++ ++ return ERR_PTR(ret); + } + + static void __dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi) + { ++ drm_bridge_remove(&dsi->bridge); ++ drm_panel_bridge_remove(dsi->panel_bridge); + mipi_dsi_host_unregister(&dsi->dsi_host); + + pm_runtime_disable(dsi->dev); +diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c +index 501b4fe55a3d..125aab6b12e8 100644 +--- a/drivers/gpu/drm/drm_modes.c ++++ b/drivers/gpu/drm/drm_modes.c +@@ -127,7 +127,7 @@ EXPORT_SYMBOL(drm_mode_probed_add); + * according to the hdisplay, vdisplay, vrefresh. + * It is based from the VESA(TM) Coordinated Video Timing Generator by + * Graham Loveridge April 9, 2003 available at +- * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls ++ * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls + * + * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. + * What I have done is to translate it by using integer calculation. +@@ -615,6 +615,15 @@ void drm_display_mode_from_videomode(const struct videomode *vm, + dmode->flags |= DRM_MODE_FLAG_DBLSCAN; + if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) + dmode->flags |= DRM_MODE_FLAG_DBLCLK; ++ if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) ++ dmode->flags |= DRM_MODE_FLAG_PPIXDATA; ++ else if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) ++ dmode->flags |= DRM_MODE_FLAG_NPIXDATA; ++ if (vm->flags & DISPLAY_FLAGS_DE_HIGH) ++ dmode->flags |= DRM_MODE_FLAG_PDE; ++ else if (vm->flags & DISPLAY_FLAGS_DE_LOW) ++ dmode->flags |= DRM_MODE_FLAG_NDE; ++ + drm_mode_set_name(dmode); + } + EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); +@@ -656,6 +665,14 @@ void drm_display_mode_to_videomode(const struct drm_display_mode *dmode, + vm->flags |= DISPLAY_FLAGS_DOUBLESCAN; + if (dmode->flags & DRM_MODE_FLAG_DBLCLK) + vm->flags |= DISPLAY_FLAGS_DOUBLECLK; ++ if (dmode->flags & DRM_MODE_FLAG_PPIXDATA) ++ vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; ++ else if (dmode->flags & DRM_MODE_FLAG_NPIXDATA) ++ vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE; ++ if (dmode->flags & DRM_MODE_FLAG_PDE) ++ vm->flags |= DISPLAY_FLAGS_DE_HIGH; ++ else if (dmode->flags & DRM_MODE_FLAG_NDE) ++ vm->flags |= DISPLAY_FLAGS_DE_LOW; + } + EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); + +diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c +index 6ac1accade80..da0970ca98f8 100644 +--- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c ++++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c +@@ -99,20 +99,6 @@ static void otm8009a_dcs_write_buf(struct otm8009a *ctx, const void *data, + dev_warn(ctx->dev, "mipi dsi dcs write buffer failed\n"); + } + +-static void otm8009a_dcs_write_buf_hs(struct otm8009a *ctx, const void *data, +- size_t len) +-{ +- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); +- +- /* data will be sent in dsi hs mode (ie. no lpm) */ +- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; +- +- otm8009a_dcs_write_buf(ctx, data, len); +- +- /* restore back the dsi lpm mode */ +- dsi->mode_flags |= MIPI_DSI_MODE_LPM; +-} +- + #define dcs_write_seq(ctx, seq...) \ + ({ \ + static const u8 d[] = { seq }; \ +@@ -400,7 +386,7 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd) + */ + data[0] = MIPI_DCS_SET_DISPLAY_BRIGHTNESS; + data[1] = bd->props.brightness; +- otm8009a_dcs_write_buf_hs(ctx, data, ARRAY_SIZE(data)); ++ otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data)); + + /* set Brightness Control & Backlight on */ + data[1] = 0x24; +@@ -412,7 +398,7 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd) + + /* Update Brightness Control & Backlight */ + data[0] = MIPI_DCS_WRITE_CONTROL_DISPLAY; +- otm8009a_dcs_write_buf_hs(ctx, data, ARRAY_SIZE(data)); ++ otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data)); + + return 0; + } +@@ -433,8 +419,10 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi) + + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) { +- dev_err(dev, "cannot get reset-gpio\n"); +- return PTR_ERR(ctx->reset_gpio); ++ ret = PTR_ERR(ctx->reset_gpio); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "cannot get reset GPIO: %d\n", ret); ++ return ret; + } + + ctx->supply = devm_regulator_get(dev, "power"); +diff --git a/drivers/gpu/drm/panel/panel-raydium-rm68200.c b/drivers/gpu/drm/panel/panel-raydium-rm68200.c +index f908eeafb1af..74fa3596618d 100644 +--- a/drivers/gpu/drm/panel/panel-raydium-rm68200.c ++++ b/drivers/gpu/drm/panel/panel-raydium-rm68200.c +@@ -82,15 +82,15 @@ struct rm68200 { + }; + + static const struct drm_display_mode default_mode = { +- .clock = 52582, ++ .clock = 54000, + .hdisplay = 720, +- .hsync_start = 720 + 38, +- .hsync_end = 720 + 38 + 8, +- .htotal = 720 + 38 + 8 + 38, ++ .hsync_start = 720 + 48, ++ .hsync_end = 720 + 48 + 9, ++ .htotal = 720 + 48 + 9 + 48, + .vdisplay = 1280, + .vsync_start = 1280 + 12, +- .vsync_end = 1280 + 12 + 4, +- .vtotal = 1280 + 12 + 4 + 12, ++ .vsync_end = 1280 + 12 + 5, ++ .vtotal = 1280 + 12 + 5 + 12, + .flags = 0, + .width_mm = 68, + .height_mm = 122, +@@ -372,7 +372,8 @@ static int rm68200_probe(struct mipi_dsi_device *dsi) + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) { + ret = PTR_ERR(ctx->reset_gpio); +- dev_err(dev, "cannot get reset GPIO: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "cannot get reset GPIO: %d\n", ret); + return ret; + } + +@@ -391,7 +392,7 @@ static int rm68200_probe(struct mipi_dsi_device *dsi) + dsi->lanes = 2; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | +- MIPI_DSI_MODE_LPM; ++ MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS; + + drm_panel_init(&ctx->panel, dev, &rm68200_drm_funcs, + DRM_MODE_CONNECTOR_DSI); +diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +index 2e1f2664495d..164f79ef6269 100644 +--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c ++++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +@@ -419,7 +419,8 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) + dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data); + if (IS_ERR(dsi->dsi)) { + ret = PTR_ERR(dsi->dsi); +- DRM_ERROR("Failed to initialize mipi dsi host: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ DRM_ERROR("Failed to initialize mipi dsi host: %d\n", ret); + goto err_dsi_probe; + } + +diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c +index 6e28f707092f..308755aa7b95 100644 +--- a/drivers/gpu/drm/stm/ltdc.c ++++ b/drivers/gpu/drm/stm/ltdc.c +@@ -724,22 +724,44 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) + { + struct drm_framebuffer *fb = state->fb; +- u32 src_w, src_h; ++ struct drm_crtc_state *crtc_state; ++ struct drm_rect *src = &state->src; ++ struct drm_rect *dst = &state->dst; + + DRM_DEBUG_DRIVER("\n"); + + if (!fb) + return 0; + +- /* convert src_ from 16:16 format */ +- src_w = state->src_w >> 16; +- src_h = state->src_h >> 16; ++ /* convert src from 16:16 format */ ++ src->x1 = state->src_x >> 16; ++ src->y1 = state->src_y >> 16; ++ src->x2 = (state->src_w >> 16) + src->x1 - 1; ++ src->y2 = (state->src_h >> 16) + src->y1 - 1; + +- /* Reject scaling */ +- if (src_w != state->crtc_w || src_h != state->crtc_h) { +- DRM_ERROR("Scaling is not supported"); ++ dst->x1 = state->crtc_x; ++ dst->y1 = state->crtc_y; ++ dst->x2 = state->crtc_w + dst->x1 - 1; ++ dst->y2 = state->crtc_h + dst->y1 - 1; ++ ++ DRM_DEBUG_DRIVER("plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n", ++ plane->base.id, fb->base.id, ++ src->x2 - src->x1 + 1, src->y2 - src->y1 + 1, ++ src->x1, src->y1, ++ dst->x2 - dst->x1 + 1, dst->y2 - dst->y1 + 1, ++ dst->x1, dst->y1); ++ ++ crtc_state = drm_atomic_get_existing_crtc_state(state->state, ++ state->crtc); ++ /* destination coordinates do not have to exceed display sizes */ ++ if (crtc_state && (crtc_state->mode.hdisplay <= dst->x2 || ++ crtc_state->mode.vdisplay <= dst->y2)) ++ return -EINVAL; ++ ++ /* source sizes do not have to exceed destination sizes */ ++ if (dst->x2 - dst->x1 < src->x2 - src->x1 || ++ dst->y2 - dst->y1 < src->y2 - src->y1) + return -EINVAL; +- } + + return 0; + } +@@ -749,44 +771,36 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, + { + struct ltdc_device *ldev = plane_to_ltdc(plane); + struct drm_plane_state *state = plane->state; ++ struct drm_rect *src = &state->src; ++ struct drm_rect *dst = &state->dst; + struct drm_framebuffer *fb = state->fb; + u32 lofs = plane->index * LAY_OFS; +- u32 x0 = state->crtc_x; +- u32 x1 = state->crtc_x + state->crtc_w - 1; +- u32 y0 = state->crtc_y; +- u32 y1 = state->crtc_y + state->crtc_h - 1; +- u32 src_x, src_y, src_w, src_h; + u32 val, pitch_in_bytes, line_length, paddr, ahbp, avbp, bpcr; + enum ltdc_pix_fmt pf; ++ struct drm_rect dr; + + if (!state->crtc || !fb) { + DRM_DEBUG_DRIVER("fb or crtc NULL"); + return; + } + +- /* convert src_ from 16:16 format */ +- src_x = state->src_x >> 16; +- src_y = state->src_y >> 16; +- src_w = state->src_w >> 16; +- src_h = state->src_h >> 16; +- +- DRM_DEBUG_DRIVER("plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n", +- plane->base.id, fb->base.id, +- src_w, src_h, src_x, src_y, +- state->crtc_w, state->crtc_h, +- state->crtc_x, state->crtc_y); ++ /* compute final coordinates of frame buffer */ ++ dr.x1 = src->x1 + dst->x1; ++ dr.y1 = src->y1 + dst->y1; ++ dr.x2 = src->x2 + dst->x1; ++ dr.y2 = src->y2 + dst->y1; + + bpcr = reg_read(ldev->regs, LTDC_BPCR); + ahbp = (bpcr & BPCR_AHBP) >> 16; + avbp = bpcr & BPCR_AVBP; + + /* Configures the horizontal start and stop position */ +- val = ((x1 + 1 + ahbp) << 16) + (x0 + 1 + ahbp); ++ val = ((dr.x2 + 1 + ahbp) << 16) + (dr.x1 + 1 + ahbp); + reg_update_bits(ldev->regs, LTDC_L1WHPCR + lofs, + LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS, val); + + /* Configures the vertical start and stop position */ +- val = ((y1 + 1 + avbp) << 16) + (y0 + 1 + avbp); ++ val = ((dr.y2 + 1 + avbp) << 16) + (dr.y1 + 1 + avbp); + reg_update_bits(ldev->regs, LTDC_L1WVPCR + lofs, + LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, val); + +@@ -805,8 +819,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, + + /* Configures the color frame buffer pitch in bytes & line length */ + pitch_in_bytes = fb->pitches[0]; +- line_length = fb->format->cpp[0] * +- (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1; ++ line_length = fb->format->cpp[0] * (dr.x2 - dr.x1 + 1) + ++ (ldev->caps.bus_width >> 3) - 1; + val = ((pitch_in_bytes << 16) | line_length); + reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs, + LXCFBLR_CFBLL | LXCFBLR_CFBP, val); +@@ -829,7 +843,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, + LXBFCR_BF2 | LXBFCR_BF1, val); + + /* Configures the frame buffer line number */ +- val = y1 - y0 + 1; ++ val = dr.y2 - dr.y1 + 1; + reg_update_bits(ldev->regs, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, val); + + /* Sets the FB address */ +diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c +index 6ff81d48da86..1643ddf5f65e 100644 +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -30,6 +30,8 @@ + #include + + #include ++#include ++#include + + #define WORK_REGISTER_THRESHOLD 0x00 + #define WORK_REGISTER_REPORT_RATE 0x08 +@@ -1074,6 +1076,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, + const struct edt_i2c_chip_data *chip_data; + struct edt_ft5x06_ts_data *tsdata; + u8 buf[2] = { 0xfc, 0x00 }; ++ struct mipi_dsi_device *panel; ++ struct device_node *np; + struct input_dev *input; + unsigned long irq_flags; + int error; +@@ -1173,7 +1177,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, + + error = edt_ft5x06_ts_identify(client, tsdata, fw_version); + if (error) { +- dev_err(&client->dev, "touchscreen probe failed\n"); ++ dev_dbg(&client->dev, "touchscreen probe failed\n"); + return error; + } + +@@ -1242,6 +1246,18 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, + if (error) + return error; + ++ np = of_parse_phandle(client->dev.of_node, "panel", 0); ++ if (np) { ++ panel = of_find_mipi_dsi_device_by_node(np); ++ of_node_put(np); ++ if (!panel) ++ return -EPROBE_DEFER; ++ ++ device_link_add(&client->dev, &panel->dev, DL_FLAG_STATELESS | ++ DL_FLAG_AUTOREMOVE_SUPPLIER); ++ put_device(&panel->dev); ++ } ++ + edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); + + dev_dbg(&client->dev, +diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c +index 6612f9e2d7e8..dee33d8dd9f6 100644 +--- a/drivers/input/touchscreen/goodix.c ++++ b/drivers/input/touchscreen/goodix.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1204,6 +1205,8 @@ static int goodix_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + struct goodix_ts_data *ts; ++ struct mipi_dsi_device *panel; ++ struct device_node *np; + int error; + + dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr); +@@ -1303,6 +1306,17 @@ static int goodix_ts_probe(struct i2c_client *client, + return error; + } + ++ np = of_parse_phandle(client->dev.of_node, "panel", 0); ++ if (np) { ++ panel = of_find_mipi_dsi_device_by_node(np); ++ of_node_put(np); ++ if (!panel) ++ return -EPROBE_DEFER; ++ device_link_add(&client->dev, &panel->dev, DL_FLAG_STATELESS | ++ DL_FLAG_AUTOREMOVE_SUPPLIER); ++ put_device(&panel->dev); ++ } ++ + return 0; + } + +@@ -1358,6 +1372,7 @@ static int __maybe_unused goodix_suspend(struct device *dev) + * sooner, delay 58ms here. + */ + msleep(58); ++ + return 0; + } + +diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h +index 863eda048265..7d845d86a474 100644 +--- a/include/uapi/drm/drm_mode.h ++++ b/include/uapi/drm/drm_mode.h +@@ -97,6 +97,12 @@ extern "C" { + #define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) + #define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + ++/* flags for polarity clock & data enable polarities */ ++#define DRM_MODE_FLAG_PPIXDATA (1 << 19) ++#define DRM_MODE_FLAG_NPIXDATA (1 << 20) ++#define DRM_MODE_FLAG_PDE (1 << 21) ++#define DRM_MODE_FLAG_NDE (1 << 22) ++ + /* Picture aspect ratio options */ + #define DRM_MODE_PICTURE_ASPECT_NONE 0 + #define DRM_MODE_PICTURE_ASPECT_4_3 1 +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0008-ARM-stm32mp1-r2-HWSPINLOCK.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0007-ARM-5.10.10-stm32mp1-r1-HWSPINLOCK.patch similarity index 87% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0008-ARM-stm32mp1-r2-HWSPINLOCK.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0007-ARM-5.10.10-stm32mp1-r1-HWSPINLOCK.patch index 1f21fa7..730272f 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0008-ARM-stm32mp1-r2-HWSPINLOCK.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0007-ARM-5.10.10-stm32mp1-r1-HWSPINLOCK.patch @@ -1,19 +1,20 @@ -From 10e0333454dbd6ccecb67ad303eae3aef707ce0b Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:43 +0200 -Subject: [PATCH 08/22] ARM-stm32mp1-r2-rc8-HWSPINLOCK +From 5c27ce1dc05fd740cc8f0f1d8072361ccab51a9f Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:02:36 +0100 +Subject: [PATCH 07/22] ARM 5.10.10-stm32mp1-r1 HWSPINLOCK +Signed-off-by: Romuald JEANNE --- - Documentation/hwspinlock.txt | 10 ++- - drivers/hwspinlock/hwspinlock_core.c | 82 ++++++++++++++++++------ + Documentation/locking/hwspinlock.rst | 10 ++- + drivers/hwspinlock/hwspinlock_core.c | 80 +++++++++++++++++++----- drivers/hwspinlock/hwspinlock_internal.h | 2 + - drivers/hwspinlock/stm32_hwspinlock.c | 62 +++++++++++------- - 4 files changed, 112 insertions(+), 44 deletions(-) + drivers/hwspinlock/stm32_hwspinlock.c | 60 +++++++++++------- + 4 files changed, 110 insertions(+), 42 deletions(-) -diff --git a/Documentation/hwspinlock.txt b/Documentation/hwspinlock.txt -index 6f03713b70039..605bd2dc8a03e 100644 ---- a/Documentation/hwspinlock.txt -+++ b/Documentation/hwspinlock.txt +diff --git a/Documentation/locking/hwspinlock.rst b/Documentation/locking/hwspinlock.rst +index 6f03713b7003..605bd2dc8a03 100644 +--- a/Documentation/locking/hwspinlock.rst ++++ b/Documentation/locking/hwspinlock.rst @@ -54,9 +54,11 @@ Should be called from a process context (might sleep). struct hwspinlock *hwspin_lock_request_specific(unsigned int id); @@ -44,7 +45,7 @@ index 6f03713b70039..605bd2dc8a03e 100644 }; diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c -index 8862445aa8580..ac76631c7059b 100644 +index fd5f5c5a5244..a2197af8973d 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -29,6 +29,8 @@ @@ -144,9 +145,9 @@ index 8862445aa8580..ac76631c7059b 100644 /* prevent underlying implementation from being removed */ if (!try_module_get(dev->driver->owner)) { -@@ -664,13 +700,18 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock) - return ret; - } +@@ -666,13 +702,18 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock) + + ret = 0; + /* update shareable refcount */ + id = hwlock_to_id(hwlock); @@ -166,7 +167,7 @@ index 8862445aa8580..ac76631c7059b 100644 return ret; } -@@ -764,9 +805,9 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id) +@@ -766,9 +807,9 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id) /* sanity check (this shouldn't happen) */ WARN_ON(hwlock_to_id(hwlock) != id); @@ -179,7 +180,7 @@ index 8862445aa8580..ac76631c7059b 100644 pr_warn("hwspinlock %u is already in use\n", id); hwlock = NULL; goto out; -@@ -799,7 +840,7 @@ int hwspin_lock_free(struct hwspinlock *hwlock) +@@ -801,7 +842,7 @@ int hwspin_lock_free(struct hwspinlock *hwlock) { struct device *dev; struct hwspinlock *tmp; @@ -188,7 +189,7 @@ index 8862445aa8580..ac76631c7059b 100644 if (!hwlock) { pr_err("invalid hwlock\n"); -@@ -810,30 +851,35 @@ int hwspin_lock_free(struct hwspinlock *hwlock) +@@ -812,28 +853,33 @@ int hwspin_lock_free(struct hwspinlock *hwlock) mutex_lock(&hwspinlock_tree_lock); /* make sure the hwspinlock is used */ @@ -205,16 +206,13 @@ index 8862445aa8580..ac76631c7059b 100644 } /* notify the underlying device that power is not needed */ - ret = pm_runtime_put(dev); - if (ret < 0) -- goto out; -+ goto unlock; -+ + pm_runtime_put(dev); + + /* update shareable refcount */ + if (radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_SHARED) && + --hwlock->refcount) + goto put; - ++ /* mark this hwspinlock as available */ - tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock), - HWSPINLOCK_UNUSED); @@ -232,7 +230,7 @@ index 8862445aa8580..ac76631c7059b 100644 return ret; } diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h -index 9eb6bd020dc70..c808e116ce3fe 100644 +index 29892767bb7a..e1f9c9600635 100644 --- a/drivers/hwspinlock/hwspinlock_internal.h +++ b/drivers/hwspinlock/hwspinlock_internal.h @@ -35,11 +35,13 @@ struct hwspinlock_ops { @@ -250,7 +248,7 @@ index 9eb6bd020dc70..c808e116ce3fe 100644 }; diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c -index c8eacf4f9692b..c7c8c4cc2c5fa 100644 +index 3ad0ce0da4d9..6c3be33f3faf 100644 --- a/drivers/hwspinlock/stm32_hwspinlock.c +++ b/drivers/hwspinlock/stm32_hwspinlock.c @@ -54,8 +54,23 @@ static const struct hwspinlock_ops stm32_hwspinlock_ops = { @@ -276,14 +274,8 @@ index c8eacf4f9692b..c7c8c4cc2c5fa 100644 + struct device *dev = &pdev->dev; struct stm32_hwspinlock *hw; void __iomem *io_base; - struct resource *res; -@@ -63,46 +78,48 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev) - int i, ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- io_base = devm_ioremap_resource(&pdev->dev, res); -+ io_base = devm_ioremap_resource(dev, res); - if (IS_ERR(io_base)) + size_t array_size; +@@ -66,41 +81,43 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev) return PTR_ERR(io_base); array_size = STM32_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock); @@ -348,7 +340,7 @@ index c8eacf4f9692b..c7c8c4cc2c5fa 100644 } static int __maybe_unused stm32_hwspinlock_runtime_suspend(struct device *dev) -@@ -137,7 +154,6 @@ MODULE_DEVICE_TABLE(of, stm32_hwpinlock_ids); +@@ -135,7 +152,6 @@ MODULE_DEVICE_TABLE(of, stm32_hwpinlock_ids); static struct platform_driver stm32_hwspinlock_driver = { .probe = stm32_hwspinlock_probe, diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0008-ARM-5.10.10-stm32mp1-r1-I2C-IIO-IRQCHIP.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0008-ARM-5.10.10-stm32mp1-r1-I2C-IIO-IRQCHIP.patch new file mode 100644 index 0000000..5f65372 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0008-ARM-5.10.10-stm32mp1-r1-I2C-IIO-IRQCHIP.patch @@ -0,0 +1,1317 @@ +From 1d88ececeebbbd2d3aa0ed971961074d1e2b71f4 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:05:39 +0100 +Subject: [PATCH 08/22] ARM 5.10.10-stm32mp1-r1 I2C-IIO-IRQCHIP + +Signed-off-by: Romuald JEANNE +--- + drivers/i2c/busses/i2c-stm32f7.c | 240 ++++++++++++++++++----------- + drivers/iio/adc/sd_adc_modulator.c | 89 +++++++++-- + drivers/iio/adc/stm32-adc-core.c | 21 ++- + drivers/iio/adc/stm32-adc.c | 29 +--- + drivers/iio/adc/stm32-dfsdm-adc.c | 105 ++++++++++++- + drivers/iio/adc/stm32-dfsdm-core.c | 91 +++++++++-- + drivers/iio/adc/stm32-dfsdm.h | 69 ++++++--- + drivers/irqchip/irq-stm32-exti.c | 83 ++++++++-- + 8 files changed, 555 insertions(+), 172 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c +index f41f51a176a1..b98ac0f4dee3 100644 +--- a/drivers/i2c/busses/i2c-stm32f7.c ++++ b/drivers/i2c/busses/i2c-stm32f7.c +@@ -51,12 +51,15 @@ + + /* STM32F7 I2C control 1 */ + #define STM32F7_I2C_CR1_PECEN BIT(23) ++#define STM32F7_I2C_CR1_ALERTEN BIT(22) + #define STM32F7_I2C_CR1_SMBHEN BIT(20) + #define STM32F7_I2C_CR1_WUPEN BIT(18) + #define STM32F7_I2C_CR1_SBC BIT(16) + #define STM32F7_I2C_CR1_RXDMAEN BIT(15) + #define STM32F7_I2C_CR1_TXDMAEN BIT(14) + #define STM32F7_I2C_CR1_ANFOFF BIT(12) ++#define STM32F7_I2C_CR1_DNF_MASK GENMASK(11, 8) ++#define STM32F7_I2C_CR1_DNF(n) (((n) & 0xf) << 8) + #define STM32F7_I2C_CR1_ERRIE BIT(7) + #define STM32F7_I2C_CR1_TCIE BIT(6) + #define STM32F7_I2C_CR1_STOPIE BIT(5) +@@ -123,6 +126,7 @@ + (((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17) + #define STM32F7_I2C_ISR_DIR BIT(16) + #define STM32F7_I2C_ISR_BUSY BIT(15) ++#define STM32F7_I2C_ISR_ALERT BIT(13) + #define STM32F7_I2C_ISR_PECERR BIT(11) + #define STM32F7_I2C_ISR_ARLO BIT(9) + #define STM32F7_I2C_ISR_BERR BIT(8) +@@ -136,6 +140,7 @@ + #define STM32F7_I2C_ISR_TXE BIT(0) + + /* STM32F7 I2C Interrupt Clear */ ++#define STM32F7_I2C_ICR_ALERTCF BIT(13) + #define STM32F7_I2C_ICR_PECCF BIT(11) + #define STM32F7_I2C_ICR_ARLOCF BIT(9) + #define STM32F7_I2C_ICR_BERRCF BIT(8) +@@ -159,10 +164,8 @@ enum { + STM32F7_I2C_MAX_SLAVE + }; + +-#define STM32F7_I2C_DNF_DEFAULT 0 +-#define STM32F7_I2C_DNF_MAX 16 ++#define STM32F7_I2C_DNF_MAX 15 + +-#define STM32F7_I2C_ANALOG_FILTER_ENABLE 1 + #define STM32F7_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ + #define STM32F7_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ + +@@ -221,8 +224,6 @@ struct stm32f7_i2c_spec { + * @clock_src: I2C clock source frequency (Hz) + * @rise_time: Rise time (ns) + * @fall_time: Fall time (ns) +- * @dnf: Digital filter coefficient (0-16) +- * @analog_filter: Analog filter delay (On/Off) + * @fmp_clr_offset: Fast Mode Plus clear register offset from set register + */ + struct stm32f7_i2c_setup { +@@ -230,8 +231,6 @@ struct stm32f7_i2c_setup { + u32 clock_src; + u32 rise_time; + u32 fall_time; +- u8 dnf; +- bool analog_filter; + u32 fmp_clr_offset; + }; + +@@ -281,6 +280,17 @@ struct stm32f7_i2c_msg { + u8 smbus_buf[I2C_SMBUS_BLOCK_MAX + 3] __aligned(4); + }; + ++/** ++ * struct stm32f7_i2c_alert - SMBus alert specific data ++ * @setup: platform data for the smbus_alert i2c client ++ * @ara: I2C slave device used to respond to the SMBus Alert with Alert ++ * Response Address ++ */ ++struct stm32f7_i2c_alert { ++ struct i2c_smbus_alert_setup setup; ++ struct i2c_client *ara; ++}; ++ + /** + * struct stm32f7_i2c_dev - private data of the controller + * @adap: I2C adapter for this controller +@@ -310,6 +320,10 @@ struct stm32f7_i2c_msg { + * @wakeup_src: boolean to know if the device is a wakeup source + * @smbus_mode: states that the controller is configured in SMBus mode + * @host_notify_client: SMBus host-notify client ++ * @alert: SMBus alert specific data ++ * @analog_filter: boolean to indicate enabling of the analog filter ++ * @dnf_dt: value of digital filter requested via dt ++ * @dnf: value of digital filter to apply + */ + struct stm32f7_i2c_dev { + struct i2c_adapter adap; +@@ -338,6 +352,10 @@ struct stm32f7_i2c_dev { + bool wakeup_src; + bool smbus_mode; + struct i2c_client *host_notify_client; ++ struct stm32f7_i2c_alert *alert; ++ bool analog_filter; ++ u32 dnf_dt; ++ u32 dnf; + }; + + /* +@@ -383,15 +401,11 @@ static struct stm32f7_i2c_spec stm32f7_i2c_specs[] = { + static const struct stm32f7_i2c_setup stm32f7_setup = { + .rise_time = STM32F7_I2C_RISE_TIME_DEFAULT, + .fall_time = STM32F7_I2C_FALL_TIME_DEFAULT, +- .dnf = STM32F7_I2C_DNF_DEFAULT, +- .analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE, + }; + + static const struct stm32f7_i2c_setup stm32mp15_setup = { + .rise_time = STM32F7_I2C_RISE_TIME_DEFAULT, + .fall_time = STM32F7_I2C_FALL_TIME_DEFAULT, +- .dnf = STM32F7_I2C_DNF_DEFAULT, +- .analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE, + .fmp_clr_offset = 0x40, + }; + +@@ -460,27 +474,28 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, + return -EINVAL; + } + +- if (setup->dnf > STM32F7_I2C_DNF_MAX) { ++ i2c_dev->dnf = DIV_ROUND_CLOSEST(i2c_dev->dnf_dt, i2cclk); ++ if (i2c_dev->dnf > STM32F7_I2C_DNF_MAX) { + dev_err(i2c_dev->dev, + "DNF out of bound %d/%d\n", +- setup->dnf, STM32F7_I2C_DNF_MAX); ++ i2c_dev->dnf * i2cclk, STM32F7_I2C_DNF_MAX * i2cclk); + return -EINVAL; + } + + /* Analog and Digital Filters */ + af_delay_min = +- (setup->analog_filter ? ++ (i2c_dev->analog_filter ? + STM32F7_I2C_ANALOG_FILTER_DELAY_MIN : 0); + af_delay_max = +- (setup->analog_filter ? ++ (i2c_dev->analog_filter ? + STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0); +- dnf_delay = setup->dnf * i2cclk; ++ dnf_delay = i2c_dev->dnf * i2cclk; + + sdadel_min = specs->hddat_min + setup->fall_time - +- af_delay_min - (setup->dnf + 3) * i2cclk; ++ af_delay_min - (i2c_dev->dnf + 3) * i2cclk; + + sdadel_max = specs->vddat_max - setup->rise_time - +- af_delay_max - (setup->dnf + 4) * i2cclk; ++ af_delay_max - (i2c_dev->dnf + 4) * i2cclk; + + scldel_min = setup->rise_time + specs->sudat_min; + +@@ -646,6 +661,7 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, + setup->speed_freq = t->bus_freq_hz; + i2c_dev->setup.rise_time = t->scl_rise_ns; + i2c_dev->setup.fall_time = t->scl_fall_ns; ++ i2c_dev->dnf_dt = t->digital_filter_width_ns; + setup->clock_src = clk_get_rate(i2c_dev->clk); + + if (!setup->clock_src) { +@@ -653,6 +669,9 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, + return -EINVAL; + } + ++ if (!of_property_read_bool(i2c_dev->dev->of_node, "i2c-digital-filter")) ++ i2c_dev->dnf_dt = 0; ++ + do { + ret = stm32f7_i2c_compute_timing(i2c_dev, setup, + &i2c_dev->timing); +@@ -674,12 +693,15 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, + return ret; + } + ++ i2c_dev->analog_filter = of_property_read_bool(i2c_dev->dev->of_node, ++ "i2c-analog-filter"); ++ + dev_dbg(i2c_dev->dev, "I2C Speed(%i), Clk Source(%i)\n", + setup->speed_freq, setup->clock_src); + dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n", + setup->rise_time, setup->fall_time); + dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n", +- (setup->analog_filter ? "On" : "Off"), setup->dnf); ++ (i2c_dev->analog_filter ? "On" : "Off"), i2c_dev->dnf); + + i2c_dev->bus_rate = setup->speed_freq; + +@@ -718,13 +740,20 @@ static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev) + timing |= STM32F7_I2C_TIMINGR_SCLL(t->scll); + writel_relaxed(timing, i2c_dev->base + STM32F7_I2C_TIMINGR); + +- /* Enable I2C */ +- if (i2c_dev->setup.analog_filter) ++ /* Configure the Analog Filter */ ++ if (i2c_dev->analog_filter) + stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, + STM32F7_I2C_CR1_ANFOFF); + else + stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, + STM32F7_I2C_CR1_ANFOFF); ++ ++ /* Program the Digital Filter */ ++ stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, ++ STM32F7_I2C_CR1_DNF_MASK); ++ stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, ++ STM32F7_I2C_CR1_DNF(i2c_dev->dnf)); ++ + stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, + STM32F7_I2C_CR1_PE); + } +@@ -1588,7 +1617,8 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) + + /* Bus error */ + if (status & STM32F7_I2C_ISR_BERR) { +- dev_err(dev, "<%s>: Bus error\n", __func__); ++ dev_err(dev, "<%s>: Bus error accessing addr 0x%x\n", ++ __func__, f7_msg->addr); + writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR); + stm32f7_i2c_release_bus(&i2c_dev->adap); + f7_msg->result = -EIO; +@@ -1596,17 +1626,26 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) + + /* Arbitration loss */ + if (status & STM32F7_I2C_ISR_ARLO) { +- dev_dbg(dev, "<%s>: Arbitration loss\n", __func__); ++ dev_dbg(dev, "<%s>: Arbitration loss accessing addr 0x%x\n", ++ __func__, f7_msg->addr); + writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR); + f7_msg->result = -EAGAIN; + } + + if (status & STM32F7_I2C_ISR_PECERR) { +- dev_err(dev, "<%s>: PEC error in reception\n", __func__); ++ dev_err(dev, "<%s>: PEC error in reception accessing addr 0x%x\n", ++ __func__, f7_msg->addr); + writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR); + f7_msg->result = -EINVAL; + } + ++ if (status & STM32F7_I2C_ISR_ALERT) { ++ dev_dbg(dev, "<%s>: SMBus alert received\n", __func__); ++ writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR); ++ i2c_handle_smbus_alert(i2c_dev->alert->ara); ++ return IRQ_HANDLED; ++ } ++ + if (!i2c_dev->slave_running) { + u32 mask; + /* Disable interrupts */ +@@ -1973,6 +2012,42 @@ static void stm32f7_i2c_disable_smbus_host(struct stm32f7_i2c_dev *i2c_dev) + } + } + ++static int stm32f7_i2c_enable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) ++{ ++ struct stm32f7_i2c_alert *alert; ++ struct i2c_adapter *adap = &i2c_dev->adap; ++ struct device *dev = i2c_dev->dev; ++ void __iomem *base = i2c_dev->base; ++ ++ alert = devm_kzalloc(dev, sizeof(*alert), GFP_KERNEL); ++ if (!alert) ++ return -ENOMEM; ++ ++ alert->ara = i2c_new_smbus_alert_device(adap, &alert->setup); ++ if (IS_ERR(alert->ara)) ++ return PTR_ERR(alert->ara); ++ ++ i2c_dev->alert = alert; ++ ++ /* Enable SMBus Alert */ ++ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_ALERTEN); ++ ++ return 0; ++} ++ ++static void stm32f7_i2c_disable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) ++{ ++ struct stm32f7_i2c_alert *alert = i2c_dev->alert; ++ void __iomem *base = i2c_dev->base; ++ ++ if (alert) { ++ /* Disable SMBus Alert */ ++ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, ++ STM32F7_I2C_CR1_ALERTEN); ++ i2c_unregister_device(alert->ara); ++ } ++} ++ + static u32 stm32f7_i2c_func(struct i2c_adapter *adap) + { + struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adap); +@@ -2164,6 +2239,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) + } + } + ++ if (of_property_read_bool(pdev->dev.of_node, "st,smbus-alert")) { ++ ret = stm32f7_i2c_enable_smbus_alert(i2c_dev); ++ if (ret) { ++ dev_err(i2c_dev->dev, ++ "failed to enable SMBus alert protocol (%d)\n", ++ ret); ++ goto i2c_disable_smbus_host; ++ } ++ } ++ + dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr); + + pm_runtime_mark_last_busy(i2c_dev->dev); +@@ -2171,6 +2256,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) + + return 0; + ++i2c_disable_smbus_host: ++ stm32f7_i2c_disable_smbus_host(i2c_dev); ++ + i2c_adapter_remove: + i2c_del_adapter(adap); + +@@ -2205,6 +2293,7 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) + { + struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + ++ stm32f7_i2c_disable_smbus_alert(i2c_dev); + stm32f7_i2c_disable_smbus_host(i2c_dev); + + i2c_del_adapter(&i2c_dev->adap); +@@ -2236,64 +2325,25 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) + return 0; + } + +-static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev) +-{ +- struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); +- +- if (!stm32f7_i2c_is_slave_registered(i2c_dev)) +- clk_disable_unprepare(i2c_dev->clk); +- +- return 0; +-} +- +-static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev) +-{ +- struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); +- int ret; +- +- if (!stm32f7_i2c_is_slave_registered(i2c_dev)) { +- ret = clk_prepare_enable(i2c_dev->clk); +- if (ret) { +- dev_err(dev, "failed to prepare_enable clock\n"); +- return ret; +- } +- } +- +- return 0; +-} +- +-#ifdef CONFIG_PM_SLEEP +-static int stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) ++static void __maybe_unused ++stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) + { +- int ret; + struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs; + +- ret = pm_runtime_get_sync(i2c_dev->dev); +- if (ret < 0) +- return ret; +- + backup_regs->cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1); + backup_regs->cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2); + backup_regs->oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1); + backup_regs->oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2); + backup_regs->tmgr = readl_relaxed(i2c_dev->base + STM32F7_I2C_TIMINGR); + stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); +- +- pm_runtime_put_sync(i2c_dev->dev); +- +- return ret; + } + +-static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) ++static void __maybe_unused ++stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) + { + u32 cr1; +- int ret; + struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs; + +- ret = pm_runtime_get_sync(i2c_dev->dev); +- if (ret < 0) +- return ret; +- + cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1); + if (cr1 & STM32F7_I2C_CR1_PE) + stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, +@@ -2309,29 +2359,49 @@ static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) + writel_relaxed(backup_regs->oar1, i2c_dev->base + STM32F7_I2C_OAR1); + writel_relaxed(backup_regs->oar2, i2c_dev->base + STM32F7_I2C_OAR2); + stm32f7_i2c_write_fm_plus_bits(i2c_dev, true); ++} + +- pm_runtime_put_sync(i2c_dev->dev); ++static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev) ++{ ++ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); + +- return ret; ++ stm32f7_i2c_regs_backup(i2c_dev); ++ ++ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) ++ clk_disable_unprepare(i2c_dev->clk); ++ ++ return 0; + } + +-static int stm32f7_i2c_suspend(struct device *dev) ++static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev) + { + struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); + int ret; + +- i2c_mark_adapter_suspended(&i2c_dev->adap); +- +- if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { +- ret = stm32f7_i2c_regs_backup(i2c_dev); +- if (ret < 0) { +- i2c_mark_adapter_resumed(&i2c_dev->adap); ++ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) { ++ ret = clk_prepare_enable(i2c_dev->clk); ++ if (ret) { ++ dev_err(dev, "failed to prepare_enable clock\n"); + return ret; + } ++ } ++ ++ stm32f7_i2c_regs_restore(i2c_dev); + ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int stm32f7_i2c_suspend(struct device *dev) ++{ ++ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); ++ ++ i2c_mark_adapter_suspended(&i2c_dev->adap); ++ ++ if (!device_may_wakeup(dev) && !device_wakeup_path(dev)) + pinctrl_pm_select_sleep_state(dev); +- pm_runtime_force_suspend(dev); +- } ++ ++ pm_runtime_force_suspend(dev); + + return 0; + } +@@ -2341,16 +2411,12 @@ static int stm32f7_i2c_resume(struct device *dev) + struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); + int ret; + +- if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { +- ret = pm_runtime_force_resume(dev); +- if (ret < 0) +- return ret; +- pinctrl_pm_select_default_state(dev); ++ ret = pm_runtime_force_resume(dev); ++ if (ret < 0) ++ return ret; + +- ret = stm32f7_i2c_regs_restore(i2c_dev); +- if (ret < 0) +- return ret; +- } ++ if (!device_may_wakeup(dev) && !device_wakeup_path(dev)) ++ pinctrl_pm_select_default_state(dev); + + i2c_mark_adapter_resumed(&i2c_dev->adap); + +diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c +index 327cc2097f6c..ceb15029673c 100644 +--- a/drivers/iio/adc/sd_adc_modulator.c ++++ b/drivers/iio/adc/sd_adc_modulator.c +@@ -9,10 +9,8 @@ + #include + #include + #include +-#include +-#include +- +-static const struct iio_info iio_sd_mod_iio_info; ++#include ++#include + + static const struct iio_chan_spec iio_sd_mod_ch = { + .type = IIO_VOLTAGE, +@@ -22,34 +20,99 @@ static const struct iio_chan_spec iio_sd_mod_ch = { + .realbits = 1, + .shift = 0, + }, ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++}; ++ ++static const struct iio_chan_spec iio_sd_mod_ch_ads = { ++ .type = IIO_VOLTAGE, ++ .indexed = 1, ++ .scan_type = { ++ .sign = 'u', ++ .realbits = 1, ++ .shift = 0, ++ }, ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .differential = 1, ++}; ++ ++struct iio_sd_mod_priv { ++ int vref_mv; ++}; ++ ++static const struct of_device_id sd_adc_of_match[] = { ++ { .compatible = "sd-modulator", .data = &iio_sd_mod_ch }, ++ { .compatible = "ads1201", .data = &iio_sd_mod_ch_ads }, ++ { } ++}; ++ ++static int iio_sd_mod_read_raw(struct iio_dev *indio_dev, ++ struct iio_chan_spec const *chan, int *val, ++ int *val2, long mask) ++{ ++ struct iio_sd_mod_priv *priv = iio_priv(indio_dev); ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_SCALE: ++ *val = priv->vref_mv; ++ *val2 = chan->scan_type.realbits; ++ return IIO_VAL_INT; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct iio_info iio_sd_mod_iio_info = { ++ .read_raw = iio_sd_mod_read_raw, + }; + + static int iio_sd_mod_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; ++ struct iio_sd_mod_priv *priv; ++ struct regulator *vref; + struct iio_dev *iio; ++ int ret; + +- iio = devm_iio_device_alloc(dev, 0); ++ iio = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!iio) + return -ENOMEM; + ++ iio->channels = (const struct iio_chan_spec *) ++ of_match_device(sd_adc_of_match, &pdev->dev)->data; ++ ++ priv = iio_priv(iio); ++ ++ iio->dev.parent = dev; ++ iio->dev.of_node = dev->of_node; + iio->name = dev_name(dev); + iio->info = &iio_sd_mod_iio_info; + iio->modes = INDIO_BUFFER_HARDWARE; +- + iio->num_channels = 1; +- iio->channels = &iio_sd_mod_ch; + +- platform_set_drvdata(pdev, iio); ++ vref = devm_regulator_get_optional(dev, "vref"); ++ if (IS_ERR(vref)) { ++ ret = PTR_ERR(vref); ++ if (ret != -ENODEV) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "vref get failed, %d\n", ret); ++ return ret; ++ } ++ } ++ ++ if (!IS_ERR(vref)) { ++ ret = regulator_get_voltage(vref); ++ if (ret < 0) { ++ dev_err(dev, "vref get failed, %d\n", ret); ++ return ret; ++ } ++ ++ priv->vref_mv = ret / 1000; ++ dev_dbg(dev, "vref+=%dmV\n", priv->vref_mv); ++ } + + return devm_iio_device_register(&pdev->dev, iio); + } + +-static const struct of_device_id sd_adc_of_match[] = { +- { .compatible = "sd-modulator" }, +- { .compatible = "ads1201" }, +- { } +-}; + MODULE_DEVICE_TABLE(of, sd_adc_of_match); + + static struct platform_driver iio_sd_mod_adc = { +diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c +index a83199b212a4..9d1ad6e38e85 100644 +--- a/drivers/iio/adc/stm32-adc-core.c ++++ b/drivers/iio/adc/stm32-adc-core.c +@@ -200,7 +200,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, + { + u32 ckmode, presc, val; + unsigned long rate; +- int i, div; ++ int i, div, duty; + + /* stm32h7 bus clock is common for all ADC instances (mandatory) */ + if (!priv->bclk) { +@@ -224,6 +224,11 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, + return -EINVAL; + } + ++ /* If duty is an error, kindly use at least /2 divider */ ++ duty = clk_get_scaled_duty_cycle(priv->aclk, 100); ++ if (duty < 0) ++ dev_warn(&pdev->dev, "adc clock duty: %d\n", duty); ++ + for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { + ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; + presc = stm32h7_adc_ckmodes_spec[i].presc; +@@ -232,6 +237,13 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, + if (ckmode) + continue; + ++ /* ++ * For proper operation, clock duty cycle range is 49% ++ * to 51%. Apply at least /2 prescaler otherwise. ++ */ ++ if (div == 1 && (duty < 49 || duty > 51)) ++ continue; ++ + if ((rate / div) <= priv->max_clk_rate) + goto out; + } +@@ -244,6 +256,10 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, + return -EINVAL; + } + ++ duty = clk_get_scaled_duty_cycle(priv->bclk, 100); ++ if (duty < 0) ++ dev_warn(&pdev->dev, "bus clock duty: %d\n", duty); ++ + for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { + ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; + presc = stm32h7_adc_ckmodes_spec[i].presc; +@@ -252,6 +268,9 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, + if (!ckmode) + continue; + ++ if (div == 1 && (duty < 49 || duty > 51)) ++ continue; ++ + if ((rate / div) <= priv->max_clk_rate) + goto out; + } +diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c +index 16c02c30dec7..c067c994dae2 100644 +--- a/drivers/iio/adc/stm32-adc.c ++++ b/drivers/iio/adc/stm32-adc.c +@@ -1353,7 +1353,7 @@ static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) + * dma cyclic transfers are used, buffer is split into two periods. + * There should be : + * - always one buffer (period) dma is working on +- * - one buffer (period) driver can push with iio_trigger_poll(). ++ * - one buffer (period) driver can push data. + */ + watermark = min(watermark, val * (unsigned)(sizeof(u16))); + adc->rx_buf_sz = min(rx_buf_sz, watermark * 2 * adc->num_conv); +@@ -1616,31 +1616,14 @@ static irqreturn_t stm32_adc_trigger_handler(int irq, void *p) + + dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi); + +- if (!adc->dma_chan) { +- /* reset buffer index */ +- adc->bufi = 0; +- iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer, +- pf->timestamp); +- } else { +- int residue = stm32_adc_dma_residue(adc); +- +- while (residue >= indio_dev->scan_bytes) { +- u16 *buffer = (u16 *)&adc->rx_buf[adc->bufi]; +- +- iio_push_to_buffers_with_timestamp(indio_dev, buffer, +- pf->timestamp); +- residue -= indio_dev->scan_bytes; +- adc->bufi += indio_dev->scan_bytes; +- if (adc->bufi >= adc->rx_buf_sz) +- adc->bufi = 0; +- } +- } +- ++ /* reset buffer index */ ++ adc->bufi = 0; ++ iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer, ++ pf->timestamp); + iio_trigger_notify_done(indio_dev->trig); + + /* re-enable eoc irq */ +- if (!adc->dma_chan) +- stm32_adc_conv_irq_enable(adc); ++ stm32_adc_conv_irq_enable(adc); + + return IRQ_HANDLED; + } +diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c +index 9234f14167b7..9d689ed9723a 100644 +--- a/drivers/iio/adc/stm32-dfsdm-adc.c ++++ b/drivers/iio/adc/stm32-dfsdm-adc.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -67,6 +68,13 @@ struct stm32_dfsdm_dev_data { + const struct regmap_config *regmap_cfg; + }; + ++struct stm32_dfsdm_sd_chan_info { ++ int scale_val; ++ int scale_val2; ++ int offset; ++ unsigned int differential; ++}; ++ + struct stm32_dfsdm_adc { + struct stm32_dfsdm *dfsdm; + const struct stm32_dfsdm_dev_data *dev_data; +@@ -79,6 +87,7 @@ struct stm32_dfsdm_adc { + struct iio_hw_consumer *hwc; + struct completion completion; + u32 *buffer; ++ struct stm32_dfsdm_sd_chan_info *sd_chan; + + /* Audio specific */ + unsigned int spi_freq; /* SPI bus clock frequency */ +@@ -1224,7 +1233,10 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, + int *val2, long mask) + { + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); +- int ret; ++ struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; ++ struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast]; ++ u32 max = flo->max << (flo->lshift - chan->scan_type.shift); ++ int ret, idx = chan->scan_index; + + switch (mask) { + case IIO_CHAN_INFO_RAW: +@@ -1260,6 +1272,39 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, + *val = adc->sample_freq; + + return IIO_VAL_INT; ++ ++ case IIO_CHAN_INFO_SCALE: ++ /* ++ * Scale is expressed in mV. ++ * When fast mode is disabled, actual resolution may be lower ++ * than 2^n, where n=realbits-1. ++ * This leads to underestimating input voltage. To ++ * compensate this deviation, the voltage reference can be ++ * corrected with a factor = realbits resolution / actual max ++ */ ++ *val = div_u64((u64)adc->sd_chan[idx].scale_val * ++ (u64)BIT(DFSDM_DATA_RES - 1), max); ++ *val2 = chan->scan_type.realbits; ++ if (adc->sd_chan[idx].differential) ++ *val *= 2; ++ return IIO_VAL_FRACTIONAL_LOG2; ++ ++ case IIO_CHAN_INFO_OFFSET: ++ /* ++ * DFSDM output data are in the range [-2^n,2^n-1], ++ * with n=realbits-1. ++ * - Differential modulator: ++ * Offset correspond to SD modulator offset. ++ * - Single ended modulator: ++ * Input is in [0V,Vref] range, where 0V corresponds to -2^n. ++ * Add 2^n to offset. (i.e. middle of input range) ++ * offset = offset(sd) * vref / res(sd) * max / vref. ++ */ ++ *val = div_u64((u64)max * adc->sd_chan[idx].offset, ++ BIT(adc->sd_chan[idx].scale_val2 - 1)); ++ if (!adc->sd_chan[idx].differential) ++ *val += max; ++ return IIO_VAL_INT; + } + + return -EINVAL; +@@ -1384,7 +1429,9 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, + * IIO_CHAN_INFO_RAW: used to compute regular conversion + * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling + */ +- ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); ++ ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | ++ BIT(IIO_CHAN_INFO_SCALE) | ++ BIT(IIO_CHAN_INFO_OFFSET); + ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | + BIT(IIO_CHAN_INFO_SAMP_FREQ); + +@@ -1394,7 +1441,7 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, + ch->scan_type.shift = 8; + } + ch->scan_type.sign = 's'; +- ch->scan_type.realbits = 24; ++ ch->scan_type.realbits = DFSDM_DATA_RES; + ch->scan_type.storagebits = 32; + + return stm32_dfsdm_chan_configure(adc->dfsdm, +@@ -1435,8 +1482,10 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) + { + struct iio_chan_spec *ch; + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); ++ struct iio_channel *channels, *chan; ++ struct stm32_dfsdm_sd_chan_info *sd_chan; + int num_ch; +- int ret, chan_idx; ++ int ret, chan_idx, val2; + + adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING; + ret = stm32_dfsdm_compute_all_osrs(indio_dev, adc->oversamp); +@@ -1460,6 +1509,21 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) + if (!ch) + return -ENOMEM; + ++ /* Get SD modulator channels */ ++ channels = iio_channel_get_all(&indio_dev->dev); ++ if (IS_ERR(channels)) { ++ dev_err(&indio_dev->dev, "Failed to get channel %ld\n", ++ PTR_ERR(channels)); ++ return PTR_ERR(channels); ++ } ++ chan = &channels[0]; ++ ++ adc->sd_chan = devm_kzalloc(&indio_dev->dev, ++ sizeof(*adc->sd_chan) * num_ch, GFP_KERNEL); ++ if (!adc->sd_chan) ++ return -ENOMEM; ++ sd_chan = adc->sd_chan; ++ + for (chan_idx = 0; chan_idx < num_ch; chan_idx++) { + ch[chan_idx].scan_index = chan_idx; + ret = stm32_dfsdm_adc_chan_init_one(indio_dev, &ch[chan_idx]); +@@ -1467,6 +1531,38 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) + dev_err(&indio_dev->dev, "Channels init failed\n"); + return ret; + } ++ ++ if (!chan->indio_dev) ++ return -EINVAL; ++ ++ ret = iio_read_channel_scale(chan, &sd_chan->scale_val, ++ &sd_chan->scale_val2); ++ if (ret < 0) { ++ dev_err(&indio_dev->dev, ++ "Failed to get channel %d scale\n", chan_idx); ++ return ret; ++ } ++ ++ if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_OFFSET)) { ++ ret = iio_read_channel_offset(chan, &sd_chan->offset, ++ &val2); ++ if (ret < 0) { ++ dev_err(&indio_dev->dev, ++ "Failed to get channel %d offset\n", ++ chan_idx); ++ return ret; ++ } ++ } ++ ++ sd_chan->differential = chan->channel->differential; ++ ++ dev_dbg(&indio_dev->dev, "Channel %d %s scale ref=%d offset=%d", ++ chan_idx, chan->channel->differential ? ++ "differential" : "single-ended", ++ sd_chan->scale_val, sd_chan->offset); ++ ++ chan++; ++ sd_chan++; + } + + indio_dev->num_channels = num_ch; +@@ -1521,6 +1617,7 @@ static const struct of_device_id stm32_dfsdm_adc_match[] = { + }, + {} + }; ++MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match); + + static int stm32_dfsdm_adc_probe(struct platform_device *pdev) + { +diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c +index 42a7377704a4..627557d8efb0 100644 +--- a/drivers/iio/adc/stm32-dfsdm-core.c ++++ b/drivers/iio/adc/stm32-dfsdm-core.c +@@ -6,6 +6,7 @@ + * Author(s): Arnaud Pouliquen for STMicroelectronics. + */ + ++#include + #include + #include + #include +@@ -20,6 +21,7 @@ + #include "stm32-dfsdm.h" + + struct stm32_dfsdm_dev_data { ++ u32 ipid; + unsigned int num_filters; + unsigned int num_channels; + const struct regmap_config *regmap_cfg; +@@ -27,8 +29,6 @@ struct stm32_dfsdm_dev_data { + + #define STM32H7_DFSDM_NUM_FILTERS 4 + #define STM32H7_DFSDM_NUM_CHANNELS 8 +-#define STM32MP1_DFSDM_NUM_FILTERS 6 +-#define STM32MP1_DFSDM_NUM_CHANNELS 8 + + static bool stm32_dfsdm_volatile_reg(struct device *dev, unsigned int reg) + { +@@ -75,8 +75,7 @@ static const struct regmap_config stm32mp1_dfsdm_regmap_cfg = { + }; + + static const struct stm32_dfsdm_dev_data stm32mp1_dfsdm_data = { +- .num_filters = STM32MP1_DFSDM_NUM_FILTERS, +- .num_channels = STM32MP1_DFSDM_NUM_CHANNELS, ++ .ipid = STM32MP15_IPIDR_NUMBER, + .regmap_cfg = &stm32mp1_dfsdm_regmap_cfg, + }; + +@@ -298,6 +297,64 @@ static const struct of_device_id stm32_dfsdm_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match); + ++static int stm32_dfsdm_config_check(struct platform_device *pdev, ++ struct dfsdm_priv *priv, ++ const struct stm32_dfsdm_dev_data *dev_data) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *child; ++ struct stm32_dfsdm *dfsdm = &priv->dfsdm; ++ const char *compat; ++ int ret, count = 0; ++ u32 id, val; ++ ++ if (!dev_data->ipid) { ++ dfsdm->num_fls = dev_data->num_filters; ++ dfsdm->num_chs = dev_data->num_channels; ++ return 0; ++ } ++ ++ ret = regmap_read(dfsdm->regmap, DFSDM_IPIDR, &val); ++ if (ret) ++ return ret; ++ ++ id = FIELD_GET(DFSDM_IPIDR_MASK, val); ++ if (id != dev_data->ipid) { ++ dev_err(&pdev->dev, "Unexpected IP version: 0x%x", id); ++ return -EINVAL; ++ } ++ ++ for_each_child_of_node(np, child) { ++ ret = of_property_read_string(child, "compatible", &compat); ++ if (ret) ++ continue; ++ count++; ++ } ++ ++ ret = regmap_read(dfsdm->regmap, DFSDM_HWCFGR, &val); ++ if (ret) ++ return ret; ++ ++ dfsdm->num_fls = FIELD_GET(DFSDM_HWCFGR_NBF_MASK, val); ++ dfsdm->num_chs = FIELD_GET(DFSDM_HWCFGR_NBT_MASK, val); ++ ++ if (count > dfsdm->num_fls) { ++ dev_err(&pdev->dev, "Unexpected child number: %d", count); ++ return -EINVAL; ++ } ++ ++ ret = regmap_read(dfsdm->regmap, DFSDM_VERR, &val); ++ if (ret) ++ return ret; ++ ++ dev_dbg(&pdev->dev, "DFSDM version: %lu.%lu. %d channels/%d filters\n", ++ FIELD_GET(DFSDM_VERR_MAJREV_MASK, val), ++ FIELD_GET(DFSDM_VERR_MINREV_MASK, val), ++ dfsdm->num_chs, dfsdm->num_fls); ++ ++ return 0; ++} ++ + static int stm32_dfsdm_probe(struct platform_device *pdev) + { + struct dfsdm_priv *priv; +@@ -314,18 +371,6 @@ static int stm32_dfsdm_probe(struct platform_device *pdev) + dev_data = of_device_get_match_data(&pdev->dev); + + dfsdm = &priv->dfsdm; +- dfsdm->fl_list = devm_kcalloc(&pdev->dev, dev_data->num_filters, +- sizeof(*dfsdm->fl_list), GFP_KERNEL); +- if (!dfsdm->fl_list) +- return -ENOMEM; +- +- dfsdm->num_fls = dev_data->num_filters; +- dfsdm->ch_list = devm_kcalloc(&pdev->dev, dev_data->num_channels, +- sizeof(*dfsdm->ch_list), +- GFP_KERNEL); +- if (!dfsdm->ch_list) +- return -ENOMEM; +- dfsdm->num_chs = dev_data->num_channels; + + ret = stm32_dfsdm_parse_of(pdev, priv); + if (ret < 0) +@@ -341,6 +386,20 @@ static int stm32_dfsdm_probe(struct platform_device *pdev) + return ret; + } + ++ ret = stm32_dfsdm_config_check(pdev, priv, dev_data); ++ if (ret < 0) ++ return ret; ++ ++ dfsdm->fl_list = devm_kcalloc(&pdev->dev, dfsdm->num_fls, ++ sizeof(*dfsdm->fl_list), GFP_KERNEL); ++ if (!dfsdm->fl_list) ++ return -ENOMEM; ++ ++ dfsdm->ch_list = devm_kcalloc(&pdev->dev, dfsdm->num_chs, ++ sizeof(*dfsdm->ch_list), GFP_KERNEL); ++ if (!dfsdm->ch_list) ++ return -ENOMEM; ++ + platform_set_drvdata(pdev, dfsdm); + + ret = stm32_dfsdm_clk_prepare_enable(dfsdm); +diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h +index 4afc1f528b78..4f230e2a7692 100644 +--- a/drivers/iio/adc/stm32-dfsdm.h ++++ b/drivers/iio/adc/stm32-dfsdm.h +@@ -13,25 +13,28 @@ + + /* + * STM32 DFSDM - global register map +- * ________________________________________________________ +- * | Offset | Registers block | +- * -------------------------------------------------------- +- * | 0x000 | CHANNEL 0 + COMMON CHANNEL FIELDS | +- * -------------------------------------------------------- +- * | 0x020 | CHANNEL 1 | +- * -------------------------------------------------------- +- * | ... | ..... | +- * -------------------------------------------------------- +- * | 0x0E0 | CHANNEL 7 | +- * -------------------------------------------------------- +- * | 0x100 | FILTER 0 + COMMON FILTER FIELDs | +- * -------------------------------------------------------- +- * | 0x200 | FILTER 1 | +- * -------------------------------------------------------- +- * | 0x300 | FILTER 2 | +- * -------------------------------------------------------- +- * | 0x400 | FILTER 3 | +- * -------------------------------------------------------- ++ * __________________________________________________________ ++ * | Offset | Registers block | ++ * ---------------------------------------------------------- ++ * | 0x000 | CHANNEL 0 + COMMON CHANNEL FIELDS | ++ * ---------------------------------------------------------- ++ * | 0x020 | CHANNEL 1 | ++ * ---------------------------------------------------------- ++ * | ... | ..... | ++ * ---------------------------------------------------------- ++ * | 0x20 x n | CHANNEL n | ++ * ---------------------------------------------------------- ++ * | 0x100 | FILTER 0 + COMMON FILTER FIELDs | ++ * ---------------------------------------------------------- ++ * | 0x200 | FILTER 1 | ++ * ---------------------------------------------------------- ++ * | | ..... | ++ * ---------------------------------------------------------- ++ * | 0x100 x m| FILTER m | ++ * ---------------------------------------------------------- ++ * ---------------------------------------------------------- ++ * | 0x7F0-7FC| Identification registers | ++ * ---------------------------------------------------------- + */ + + /* +@@ -231,6 +234,34 @@ + #define DFSDM_AWCFR_AWHTF_MASK GENMASK(15, 8) + #define DFSDM_AWCFR_AWHTF(v) FIELD_PREP(DFSDM_AWCFR_AWHTF_MASK, v) + ++/* ++ * Identification register definitions ++ */ ++#define DFSDM_HWCFGR 0x7F0 ++#define DFSDM_VERR 0x7F4 ++#define DFSDM_IPIDR 0x7F8 ++#define DFSDM_SIDR 0x7FC ++ ++/* HWCFGR: Hardware configuration register */ ++#define DFSDM_HWCFGR_NBT_SHIFT 0 ++#define DFSDM_HWCFGR_NBT_MASK GENMASK(7, 0) ++#define DFSDM_HWCFGR_NBF_SHIFT 8 ++#define DFSDM_HWCFGR_NBF_MASK GENMASK(15, 8) ++ ++/* VERR: Version register */ ++#define DFSDM_VERR_MINREV_SHIFT 0 ++#define DFSDM_VERR_MINREV_MASK GENMASK(3, 0) ++#define DFSDM_VERR_MAJREV_SHIFT 4 ++#define DFSDM_VERR_MAJREV_MASK GENMASK(7, 4) ++ ++/* IPDR: Identification register */ ++#define DFSDM_IPIDR_MASK GENMASK(31, 0) ++ ++/* SIDR: Size identification register */ ++#define DFSDM_SIDR_MASK GENMASK(31, 0) ++ ++#define STM32MP15_IPIDR_NUMBER 0x00110031 ++ + /* DFSDM filter order */ + enum stm32_dfsdm_sinc_order { + DFSDM_FASTSINC_ORDER, /* FastSinc filter type */ +diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c +index 8662d7b7b262..e1c975c27a2e 100644 +--- a/drivers/irqchip/irq-stm32-exti.c ++++ b/drivers/irqchip/irq-stm32-exti.c +@@ -193,7 +193,16 @@ static const struct stm32_desc_irq stm32mp1_desc_irq[] = { + { .exti = 23, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct }, + { .exti = 24, .irq_parent = 95, .chip = &stm32_exti_h_chip_direct }, + { .exti = 25, .irq_parent = 107, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 26, .irq_parent = 37, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 27, .irq_parent = 38, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 28, .irq_parent = 39, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 29, .irq_parent = 71, .chip = &stm32_exti_h_chip_direct }, + { .exti = 30, .irq_parent = 52, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 31, .irq_parent = 53, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 32, .irq_parent = 82, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 33, .irq_parent = 83, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 43, .irq_parent = 75, .chip = &stm32_exti_h_chip_direct }, ++ { .exti = 44, .irq_parent = 98, .chip = &stm32_exti_h_chip_direct }, + { .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, + { .exti = 48, .irq_parent = 138, .chip = &stm32_exti_h_chip_direct }, + { .exti = 50, .irq_parent = 139, .chip = &stm32_exti_h_chip_direct }, +@@ -534,6 +543,9 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) + unlock: + raw_spin_unlock(&chip_data->rlock); + ++ if (d->parent_data->chip) ++ irq_chip_set_type_parent(d, type); ++ + return err; + } + +@@ -551,6 +563,9 @@ static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on) + + raw_spin_unlock(&chip_data->rlock); + ++ if (d->parent_data->chip) ++ irq_chip_set_wake_parent(d, on); ++ + return 0; + } + +@@ -560,7 +575,13 @@ static int stm32_exti_h_set_affinity(struct irq_data *d, + if (d->parent_data->chip) + return irq_chip_set_affinity_parent(d, dest, force); + +- return -EINVAL; ++ return IRQ_SET_MASK_OK_DONE; ++} ++ ++static void stm32_exti_h_ack(struct irq_data *d) ++{ ++ if (d->parent_data->chip) ++ irq_chip_ack_parent(d); + } + + static int __maybe_unused stm32_exti_h_suspend(void) +@@ -624,6 +645,7 @@ static int stm32_exti_h_retrigger(struct irq_data *d) + static struct irq_chip stm32_exti_h_chip = { + .name = "stm32-exti-h", + .irq_eoi = stm32_exti_h_eoi, ++ .irq_ack = stm32_exti_h_ack, + .irq_mask = stm32_exti_h_mask, + .irq_unmask = stm32_exti_h_unmask, + .irq_retrigger = stm32_exti_h_retrigger, +@@ -637,8 +659,8 @@ static struct irq_chip stm32_exti_h_chip_direct = { + .name = "stm32-exti-h-direct", + .irq_eoi = irq_chip_eoi_parent, + .irq_ack = irq_chip_ack_parent, +- .irq_mask = irq_chip_mask_parent, +- .irq_unmask = irq_chip_unmask_parent, ++ .irq_mask = stm32_exti_h_mask, ++ .irq_unmask = stm32_exti_h_unmask, + .irq_retrigger = irq_chip_retrigger_hierarchy, + .irq_set_type = irq_chip_set_type_parent, + .irq_set_wake = stm32_exti_h_set_wake, +@@ -669,14 +691,28 @@ static int stm32_exti_h_domain_alloc(struct irq_domain *dm, + + irq_domain_set_hwirq_and_chip(dm, virq, hwirq, desc->chip, + chip_data); +- if (desc->irq_parent) { ++ /* ++ * EXTI 55 to 60 are mapped to PWR interrupt controller. ++ * The hwirq translation is done diferently than for GIC. ++ */ ++ if (hwirq >= 55 && hwirq <= 60) { + p_fwspec.fwnode = dm->parent->fwnode; +- p_fwspec.param_count = 3; +- p_fwspec.param[0] = GIC_SPI; +- p_fwspec.param[1] = desc->irq_parent; +- p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; ++ p_fwspec.param_count = 2; ++ p_fwspec.param[0] = hwirq - 55; ++ p_fwspec.param[1] = fwspec->param[1]; + + return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); ++ } else { ++ if (desc->irq_parent) { ++ p_fwspec.fwnode = dm->parent->fwnode; ++ p_fwspec.param_count = 3; ++ p_fwspec.param[0] = GIC_SPI; ++ p_fwspec.param[1] = desc->irq_parent; ++ p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; ++ ++ return irq_domain_alloc_irqs_parent(dm, virq, 1, ++ &p_fwspec); ++ } + } + + return 0; +@@ -841,11 +877,12 @@ static int stm32_exti_probe(struct platform_device *pdev) + { + int ret, i; + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; ++ struct device_node *child, *np = dev->of_node; + struct irq_domain *parent_domain, *domain; + struct stm32_exti_host_data *host_data; + const struct stm32_exti_drv_data *drv_data; + struct resource *res; ++ u32 nirqs; + + host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); + if (!host_data) +@@ -913,6 +950,34 @@ static int stm32_exti_probe(struct platform_device *pdev) + if (ret) + return ret; + ++ for_each_child_of_node(np, child) { ++ parent_domain = irq_find_host(of_irq_find_parent(child)); ++ if (!parent_domain) { ++ dev_err(dev, "child interrupt-parent not found\n"); ++ return -EINVAL; ++ } ++ ++ ret = of_property_read_u32(child, "st,irq-number", &nirqs); ++ if (ret || !nirqs) { ++ dev_err(dev, "Missing or bad irq-number property\n"); ++ return -EINVAL; ++ } ++ ++ domain = irq_domain_add_hierarchy(parent_domain, 0, nirqs, ++ child, ++ &stm32_exti_h_domain_ops, ++ host_data); ++ if (!domain) { ++ dev_err(dev, "Could not register exti domain\n"); ++ return -ENOMEM; ++ } ++ ++ ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, ++ domain); ++ if (ret) ++ return ret; ++ } ++ + stm32_exti_h_syscore_init(host_data); + + return 0; +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0010-ARM-stm32mp1-r2-MAILBOX-REMOTEPROC-RPMSG.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0009-ARM-5.10.10-stm32mp1-r1-MAILBOX-REMOTEPROC-RPMSG.patch similarity index 71% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0010-ARM-stm32mp1-r2-MAILBOX-REMOTEPROC-RPMSG.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0009-ARM-5.10.10-stm32mp1-r1-MAILBOX-REMOTEPROC-RPMSG.patch index 5f27021..ca45962 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0010-ARM-stm32mp1-r2-MAILBOX-REMOTEPROC-RPMSG.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0009-ARM-5.10.10-stm32mp1-r1-MAILBOX-REMOTEPROC-RPMSG.patch @@ -1,37 +1,32 @@ -From 16dc56ebda804f047d718c7531cb65fbb5176f99 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:45 +0200 -Subject: [PATCH 10/22] ARM-stm32mp1-r2-rc8-MAILBOX-REMOTEPROC-RPMSG +From 4ceafa69af22aeb262fb8d2e0e3cd845773ce0ae Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:07:25 +0100 +Subject: [PATCH 09/22] ARM 5.10.10-stm32mp1-r1 MAILBOX-REMOTEPROC-RPMSG +Signed-off-by: Romuald JEANNE --- - .../bindings/mailbox/stm32-ipcc.txt | 4 +- - .../bindings/remoteproc/rproc-srm.txt | 58 ++ - .../bindings/remoteproc/stm32-rproc.txt | 41 +- - Documentation/remoteproc.txt | 22 + - drivers/mailbox/Kconfig | 7 + - drivers/mailbox/Makefile | 2 + - drivers/mailbox/arm-smc-mailbox.c | 166 ++++ - drivers/mailbox/stm32-ipcc.c | 36 +- - drivers/remoteproc/Kconfig | 30 + - drivers/remoteproc/Makefile | 3 + - drivers/remoteproc/remoteproc_core.c | 55 +- - drivers/remoteproc/rproc_srm_core.c | 303 +++++++ - drivers/remoteproc/rproc_srm_core.h | 98 +++ - drivers/remoteproc/rproc_srm_dev.c | 744 ++++++++++++++++++ - drivers/remoteproc/stm32_rproc.c | 543 +++++++++++-- - drivers/remoteproc/tee_remoteproc.c | 379 +++++++++ - drivers/rpmsg/Kconfig | 9 + - drivers/rpmsg/Makefile | 1 + - drivers/rpmsg/rpmsg_core.c | 19 + - drivers/rpmsg/rpmsg_internal.h | 2 + - drivers/rpmsg/rpmsg_tty.c | 339 ++++++++ - drivers/rpmsg/virtio_rpmsg_bus.c | 11 + - include/linux/mailbox/arm-smccc-mbox.h | 20 + - include/linux/remoteproc.h | 2 + - include/linux/rpmsg.h | 9 + - include/linux/tee_remoteproc.h | 106 +++ - 26 files changed, 2878 insertions(+), 131 deletions(-) - create mode 100644 Documentation/devicetree/bindings/remoteproc/rproc-srm.txt + Documentation/staging/remoteproc.rst | 22 + + drivers/mailbox/Kconfig | 7 + + drivers/mailbox/Makefile | 2 + + drivers/mailbox/arm-smc-mailbox.c | 166 ++++++ + drivers/remoteproc/Kconfig | 28 + + drivers/remoteproc/Makefile | 3 + + drivers/remoteproc/remoteproc_core.c | 19 +- + drivers/remoteproc/rproc_srm_core.c | 303 ++++++++++ + drivers/remoteproc/rproc_srm_core.h | 98 ++++ + drivers/remoteproc/rproc_srm_dev.c | 744 +++++++++++++++++++++++++ + drivers/remoteproc/stm32_rproc.c | 364 ++++++++---- + drivers/remoteproc/tee_remoteproc.c | 380 +++++++++++++ + drivers/rpmsg/Kconfig | 9 + + drivers/rpmsg/Makefile | 1 + + drivers/rpmsg/rpmsg_core.c | 19 + + drivers/rpmsg/rpmsg_internal.h | 2 + + drivers/rpmsg/rpmsg_tty.c | 342 ++++++++++++ + drivers/rpmsg/virtio_rpmsg_bus.c | 11 + + include/linux/mailbox/arm-smccc-mbox.h | 20 + + include/linux/rpmsg.h | 9 + + include/linux/tee_remoteproc.h | 106 ++++ + 21 files changed, 2540 insertions(+), 115 deletions(-) create mode 100644 drivers/mailbox/arm-smc-mailbox.c create mode 100644 drivers/remoteproc/rproc_srm_core.c create mode 100644 drivers/remoteproc/rproc_srm_core.h @@ -41,159 +36,10 @@ Subject: [PATCH 10/22] ARM-stm32mp1-r2-rc8-MAILBOX-REMOTEPROC-RPMSG create mode 100644 include/linux/mailbox/arm-smccc-mbox.h create mode 100644 include/linux/tee_remoteproc.h -diff --git a/Documentation/devicetree/bindings/mailbox/stm32-ipcc.txt b/Documentation/devicetree/bindings/mailbox/stm32-ipcc.txt -index 1d2b7fee7b853..139c06a94b006 100644 ---- a/Documentation/devicetree/bindings/mailbox/stm32-ipcc.txt -+++ b/Documentation/devicetree/bindings/mailbox/stm32-ipcc.txt -@@ -14,9 +14,9 @@ Required properties: - property. Must contain the following entries: - - "rx" - - "tx" -- - "wakeup" - - interrupts: Interrupt specifiers for "rx channel occupied", "tx channel -- free" and "system wakeup". -+ free". If "wakeup-source" is set the rx interrupt is the -+ one used to wake up the system. - - #mbox-cells: Number of cells required for the mailbox specifier. Must be 1. - The data contained in the mbox specifier of the "mboxes" - property in the client node is the mailbox channel index. -diff --git a/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt -new file mode 100644 -index 0000000000000..baa6e8e135e11 ---- /dev/null -+++ b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt -@@ -0,0 +1,58 @@ -+Remoteproc System Resource Manager -+---------------------------------- -+ -+The remoteproc SRM (System Resource Manager) handles resources allocated -+to remote processors. -+This makes it possible for remote proc to reserve and initialize system -+resources for a peripheral assigned to a coprocessor. -+ -+The devices are grouped in a core node -+ -+Core -+==== -+Required properties: -+- compatible: should be "rproc-srm-core" -+ -+Dev -+=== -+Required properties: -+- compatible: should be "rproc-srm-dev" -+ -+Optional properties: -+- reg: register base address and length -+- clocks: clocks required by the coprocessor -+- clock-names: see clock-bindings.txt -+- pinctrl-0: pins configurations required by the coprocessor -+ The SRM reserves the pins for the coprocessor, which prevents the local -+ processor to use them. -+- pinctrl-names: must be "default". -+- x-supply: power supplies required by the coprocessor -+- interrupts: external interrupts configurations required by the coprocessor. -+ This is optional since the configuration is done by the coprocessor. -+ When defined, the SRM (over)writes the configuration which allows the -+ interrupt controller to check for configuration conflicts. -+- interrupt-parent: see interrupts.txt -+- interrupt-names: see interrupts.txt -+ -+Example: -+ system_resources { -+ compatible = "rproc-srm-core"; -+ -+ mmc0: sdhci@09060000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x09060000 0x100>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_pinctrl_mmc0>; -+ clock-names = "mmc", "icn"; -+ clocks = <&clk_s_c0_flexgen CLK_MMC_0>, -+ <&clk_s_c0_flexgen CLK_RX_ICN_HVA>; -+ vdda-supply = <&vdda>; -+ }; -+ -+ button { -+ compatible = "rproc-srm-dev"; -+ interrupt-parent = <&gpioa>; -+ interrupts = <5 1>; -+ interrupt-names = "gpio_key"; -+ }; -+ }; -diff --git a/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt b/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt -index 5fa915a4b7360..4cea56fbded56 100644 ---- a/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt -+++ b/Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt -@@ -4,23 +4,24 @@ This document defines the binding for the remoteproc component that loads and - boots firmwares on the ST32MP family chipset. - - Required properties: --- compatible: Must be "st,stm32mp1-m4" -+- compatible: Should be one of the following, -+ "st,stm32mp1-m4": for non-authenticated remote processor firmware. -+ "st,stm32mp1-m4_optee": for OP-TEE authenticated remote processor -+ firmware. - - reg: Address ranges of the RETRAM and MCU SRAM memories used by the - remote processor. --- resets: Reference to a reset controller asserting the remote processor. --- st,syscfg-holdboot: Reference to the system configuration which holds the -- remote processor reset hold boot -- 1st cell: phandle of syscon block -- 2nd cell: register offset containing the hold boot setting -- 3rd cell: register bitmask for the hold boot field --- st,syscfg-tz: Reference to the system configuration which holds the RCC trust -- zone mode -- 1st cell: phandle to syscon block -- 2nd cell: register offset containing the RCC trust zone mode setting -- 3rd cell: register bitmask for the RCC trust zone mode bit -+- resets: Reference to resets asserting: -+ - the remote processor -+ - the remote processor reset hold boot -+- reset-names: Name of the MCU reset -+ - must be "mcu_rst" for the remote processor reset -+ - must be "hold_boot" for the remote processor hold boot - - Optional properties: - - interrupts: Should contain the watchdog interrupt -+- wakeup-source: Flag indicating whether remoteproc can wake up the system by -+ the watchdog interrupt. Only meaningful if the "interrupts" -+ property is defined. - - mboxes: This property is required only if the rpmsg/virtio functionality - is used. List of phandle and mailbox channel specifiers: - - a channel (a) used to communicate through virtqueues with the -@@ -48,6 +49,16 @@ Optional properties: - 1st cell: phandle to syscon block - 2nd cell: register offset containing the deep sleep setting - 3rd cell: register bitmask for the deep sleep bit -+- st,syscfg-rsc-tbl: Reference to the system configuration controlling the -+ resource table address loaded by the bootloader -+ 1st cell: phandle to syscon block -+ 2nd cell: register offset containing the resource table address -+ 3rd cell: register bitmask for the resource table address -+- st,syscfg-copro-state: Reference to the system configuration which returns the -+ coprocessor state. -+ 1st cell: phandle to syscon block -+ 2nd cell: register offset containing the coprocessor state -+ 3rd cell: register bitmask for the coprocessor state - - st,auto-boot: If defined, when remoteproc is probed, it loads the default - firmware and starts the remote processor. - -@@ -57,7 +68,7 @@ Example: - reg = <0x10000000 0x40000>, - <0x30000000 0x40000>, - <0x38000000 0x10000>; -- resets = <&rcc MCU_R>; -- st,syscfg-holdboot = <&rcc 0x10C 0x1>; -- st,syscfg-tz = <&rcc 0x000 0x1>; -+ resets = <&scmi0_reset RST_SCMI0_MCU>, -+ <&scmi0_reset RST_SCMI0_MCU_HOLD_BOOT>; -+ reset-names = "mcu_rst", "hold_boot"; - }; -diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt -index 03c3d2e568b04..5b217887b99c6 100644 ---- a/Documentation/remoteproc.txt -+++ b/Documentation/remoteproc.txt +diff --git a/Documentation/staging/remoteproc.rst b/Documentation/staging/remoteproc.rst +index 9cccd3dd6a4b..c2367e3c0b19 100644 +--- a/Documentation/staging/remoteproc.rst ++++ b/Documentation/staging/remoteproc.rst @@ -357,3 +357,25 @@ Of course, RSC_VDEV resource entries are only good enough for static allocation of virtio devices. Dynamic allocations will also be made possible using the rpmsg bus (similar to how we already do dynamic allocations of @@ -221,7 +67,7 @@ index 03c3d2e568b04..5b217887b99c6 100644 +The resources handled by the SRM are defined in the DeviceTree: please read +Documentation/devicetree/bindings/remoteproc/rproc-srm.txt for details. diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index ab4eb750bbddc..7707ee26251a4 100644 +index 05b1009e2820..3d388bf2d6f6 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -16,6 +16,13 @@ config ARM_MHU @@ -239,12 +85,12 @@ index ab4eb750bbddc..7707ee26251a4 100644 tristate "i.MX Mailbox" depends on ARCH_MXC || COMPILE_TEST diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile -index c22fad6f696b7..93918a84c91b6 100644 +index 2e06e02b2e03..24841a298f4a 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o - obj-$(CONFIG_ARM_MHU) += arm_mhu.o + obj-$(CONFIG_ARM_MHU) += arm_mhu.o arm_mhu_db.o +obj-$(CONFIG_ARM_SMC_MBOX) += arm-smc-mailbox.o + @@ -253,7 +99,7 @@ index c22fad6f696b7..93918a84c91b6 100644 obj-$(CONFIG_ARMADA_37XX_RWTM_MBOX) += armada-37xx-rwtm-mailbox.o diff --git a/drivers/mailbox/arm-smc-mailbox.c b/drivers/mailbox/arm-smc-mailbox.c new file mode 100644 -index 0000000000000..a6ec56f41f7f8 +index 000000000000..a6ec56f41f7f --- /dev/null +++ b/drivers/mailbox/arm-smc-mailbox.c @@ -0,0 +1,166 @@ @@ -423,106 +269,13 @@ index 0000000000000..a6ec56f41f7f8 +MODULE_AUTHOR("Peng Fan "); +MODULE_DESCRIPTION("Generic ARM smc mailbox driver"); +MODULE_LICENSE("GPL v2"); -diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c -index 5c2d1e1f988b8..ef966887aa151 100644 ---- a/drivers/mailbox/stm32-ipcc.c -+++ b/drivers/mailbox/stm32-ipcc.c -@@ -52,7 +52,6 @@ struct stm32_ipcc { - struct clk *clk; - spinlock_t lock; /* protect access to IPCC registers */ - int irqs[IPCC_IRQ_NUM]; -- int wkp; - u32 proc_id; - u32 n_chans; - u32 xcr; -@@ -282,16 +281,9 @@ static int stm32_ipcc_probe(struct platform_device *pdev) - - /* wakeup */ - if (of_property_read_bool(np, "wakeup-source")) { -- ipcc->wkp = platform_get_irq_byname(pdev, "wakeup"); -- if (ipcc->wkp < 0) { -- if (ipcc->wkp != -EPROBE_DEFER) -- dev_err(dev, "could not get wakeup IRQ\n"); -- ret = ipcc->wkp; -- goto err_clk; -- } -- - device_set_wakeup_capable(dev, true); -- ret = dev_pm_set_dedicated_wake_irq(dev, ipcc->wkp); -+ -+ ret = dev_pm_set_wake_irq(dev, ipcc->irqs[IPCC_IRQ_RX]); - if (ret) { - dev_err(dev, "Failed to set wake up irq\n"); - goto err_init_wkp; -@@ -334,10 +326,10 @@ static int stm32_ipcc_probe(struct platform_device *pdev) - return 0; - - err_irq_wkp: -- if (ipcc->wkp) -+ if (of_property_read_bool(np, "wakeup-source")) - dev_pm_clear_wake_irq(dev); - err_init_wkp: -- device_init_wakeup(dev, false); -+ device_set_wakeup_capable(dev, false); - err_clk: - clk_disable_unprepare(ipcc->clk); - return ret; -@@ -345,27 +337,17 @@ static int stm32_ipcc_probe(struct platform_device *pdev) - - static int stm32_ipcc_remove(struct platform_device *pdev) - { -- struct stm32_ipcc *ipcc = platform_get_drvdata(pdev); -+ struct device *dev = &pdev->dev; - -- if (ipcc->wkp) -+ if (of_property_read_bool(dev->of_node, "wakeup-source")) - dev_pm_clear_wake_irq(&pdev->dev); - -- device_init_wakeup(&pdev->dev, false); -+ device_set_wakeup_capable(dev, false); - - return 0; - } - - #ifdef CONFIG_PM_SLEEP --static void stm32_ipcc_set_irq_wake(struct device *dev, bool enable) --{ -- struct stm32_ipcc *ipcc = dev_get_drvdata(dev); -- unsigned int i; -- -- if (device_may_wakeup(dev)) -- for (i = 0; i < IPCC_IRQ_NUM; i++) -- irq_set_irq_wake(ipcc->irqs[i], enable); --} -- - static int stm32_ipcc_suspend(struct device *dev) - { - struct stm32_ipcc *ipcc = dev_get_drvdata(dev); -@@ -373,8 +355,6 @@ static int stm32_ipcc_suspend(struct device *dev) - ipcc->xmr = readl_relaxed(ipcc->reg_proc + IPCC_XMR); - ipcc->xcr = readl_relaxed(ipcc->reg_proc + IPCC_XCR); - -- stm32_ipcc_set_irq_wake(dev, true); -- - return 0; - } - -@@ -382,8 +362,6 @@ static int stm32_ipcc_resume(struct device *dev) - { - struct stm32_ipcc *ipcc = dev_get_drvdata(dev); - -- stm32_ipcc_set_irq_wake(dev, false); -- - writel_relaxed(ipcc->xmr, ipcc->reg_proc + IPCC_XMR); - writel_relaxed(ipcc->xcr, ipcc->reg_proc + IPCC_XCR); - diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig -index 94afdde4bc9f1..626c1e4502f32 100644 +index d99548fb5dde..cffac49af045 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig -@@ -14,6 +14,25 @@ config REMOTEPROC +@@ -23,6 +23,25 @@ config REMOTEPROC_CDEV - if REMOTEPROC + It's safe to say N if you don't want to use this interface. +config REMOTEPROC_SRM_CORE + tristate "Remoteproc System Resource Manager core" @@ -546,18 +299,9 @@ index 94afdde4bc9f1..626c1e4502f32 100644 config IMX_REMOTEPROC tristate "IMX6/7 remoteproc support" depends on ARCH_MXC -@@ -204,6 +223,8 @@ config STM32_RPROC - depends on ARCH_STM32 - depends on REMOTEPROC - select MAILBOX -+ select REMOTEPROC_SRM_CORE -+ select REMOTEPROC_SRM_DEV - help - Say y here to support STM32 MCU processors via the - remote processor framework. -@@ -214,6 +235,15 @@ config STM32_RPROC - - This can be either built-in or a loadable module. +@@ -288,6 +307,15 @@ config TI_K3_R5_REMOTEPROC + It's safe to say N here if you're not interested in utilizing + a slave processor. + +config TEE_REMOTEPROC @@ -572,29 +316,24 @@ index 94afdde4bc9f1..626c1e4502f32 100644 endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile -index 00f09e658cb34..692a9a85963b5 100644 +index da2ace4ec86c..9f2eb094c509 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile -@@ -9,11 +9,14 @@ remoteproc-y += remoteproc_debugfs.o - remoteproc-y += remoteproc_sysfs.o +@@ -11,6 +11,9 @@ remoteproc-y += remoteproc_sysfs.o remoteproc-y += remoteproc_virtio.o remoteproc-y += remoteproc_elf_loader.o + obj-$(CONFIG_REMOTEPROC_CDEV) += remoteproc_cdev.o +obj-$(CONFIG_REMOTEPROC_SRM_CORE) += rproc_srm_core.o +obj-$(CONFIG_REMOTEPROC_SRM_DEV) += rproc_srm_dev.o - obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o - obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o - obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o - obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o - obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o +obj-$(CONFIG_TEE_REMOTEPROC) += tee_remoteproc.o - obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o - obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o - obj-$(CONFIG_QCOM_Q6V5_ADSP) += qcom_q6v5_adsp.o + obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o + obj-$(CONFIG_INGENIC_VPU_RPROC) += ingenic_rproc.o + obj-$(CONFIG_MTK_SCP) += mtk_scp.o mtk_scp_ipi.o diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c -index ce92ae227aa10..e71a27dbe5cc2 100644 +index dab2c0f5caf0..316acd156b0b 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c -@@ -34,6 +34,7 @@ +@@ -37,6 +37,7 @@ #include #include #include @@ -602,112 +341,61 @@ index ce92ae227aa10..e71a27dbe5cc2 100644 #include #include -@@ -1372,7 +1373,11 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) +@@ -1687,20 +1688,29 @@ int rproc_trigger_recovery(struct rproc *rproc) + { + const struct firmware *firmware_p; + struct device *dev = &rproc->dev; ++ bool detached; + int ret; + + ret = mutex_lock_interruptible(&rproc->lock); if (ret) return ret; -- dev_info(dev, "Booting fw image %s, size %zd\n", name, fw->size); -+ if (fw) -+ dev_info(dev, "Booting fw image %s, size %zd\n", name, -+ fw->size); -+ else -+ dev_info(dev, "Synchronizing with early booted co-processor\n"); - - /* - * if enabling an IOMMU isn't relevant for this rproc, this is -@@ -1467,6 +1472,9 @@ static int rproc_stop(struct rproc *rproc, bool crashed) - struct device *dev = &rproc->dev; - int ret; - -+ if (rproc->state == RPROC_OFFLINE) -+ return 0; ++ detached = rproc->autonomous && !atomic_read(&rproc->power); + - /* Stop any subdevices for the remote processor */ - rproc_stop_subdevices(rproc, crashed); + /* State could have changed before we got the mutex */ + if (rproc->state != RPROC_CRASHED) + goto unlock_mutex; -@@ -1667,6 +1675,13 @@ int rproc_trigger_recovery(struct rproc *rproc) - /* generate coredump */ - rproc_coredump(rproc); + dev_err(dev, "recovering %s\n", rproc->name); -+ if (!rproc->firmware) { -+ /* we don't know how to recover it, so try to shutdown it*/ ++ if (rproc->autonomous && !detached) { + mutex_unlock(&rproc->lock); + rproc_shutdown(rproc); + return 0; + } + - /* load firmware */ - ret = request_firmware(&firmware_p, rproc->firmware, dev); - if (ret < 0) { -@@ -1728,7 +1743,7 @@ static void rproc_crash_handler_work(struct work_struct *work) - */ - int rproc_boot(struct rproc *rproc) - { -- const struct firmware *firmware_p; -+ const struct firmware *firmware_p = NULL; - struct device *dev; - int ret; + ret = rproc_stop(rproc, true); +- if (ret) ++ if (ret || detached) + goto unlock_mutex; -@@ -1759,11 +1774,17 @@ int rproc_boot(struct rproc *rproc) + /* generate coredump */ +@@ -2014,6 +2024,11 @@ int rproc_add(struct rproc *rproc) + if (ret < 0) + return ret; - dev_info(dev, "powering up %s\n", rproc->name); - -- /* load firmware */ -- ret = request_firmware(&firmware_p, rproc->firmware, dev); -- if (ret < 0) { -- dev_err(dev, "request_firmware failed: %d\n", ret); -- goto downref_rproc; -+ if (!rproc->early_boot) { -+ /* load firmware */ -+ ret = request_firmware(&firmware_p, rproc->firmware, dev); -+ if (ret < 0) { -+ dev_err(dev, "request_firmware failed: %d\n", ret); -+ goto downref_rproc; -+ } -+ } else { -+ /* set firmware name to null as unknown */ -+ kfree(rproc->firmware); -+ rproc->firmware = NULL; - } - - ret = rproc_fw_boot(rproc, firmware_p); -@@ -1917,8 +1938,22 @@ int rproc_add(struct rproc *rproc) - /* create debugfs entries */ - rproc_create_debug_dir(rproc); - -- /* if rproc is marked always-on, request it to boot */ -- if (rproc->auto_boot) { + /* add resource manager device */ + ret = devm_of_platform_populate(dev->parent); + if (ret < 0) + return ret; + -+ if (rproc->early_boot) { -+ /* -+ * If rproc is marked already booted, no need to wait -+ * for firmware. -+ * Just handle associated resources and start sub devices -+ */ -+ ret = rproc_boot(rproc); -+ if (ret < 0) -+ return ret; -+ } else if (rproc->auto_boot) { -+ /* if rproc is marked always-on, request it to boot */ - ret = rproc_trigger_auto_boot(rproc); - if (ret < 0) - return ret; -@@ -2143,6 +2178,8 @@ int rproc_del(struct rproc *rproc) - list_del(&rproc->node); + /* + * Remind ourselves the remote processor has been attached to rather + * than booted by the remoteproc core. This is important because the +@@ -2297,6 +2312,8 @@ int rproc_del(struct rproc *rproc) + list_del_rcu(&rproc->node); mutex_unlock(&rproc_list_mutex); + of_platform_depopulate(rproc->dev.parent); + - device_del(&rproc->dev); + /* Ensure that no readers of rproc_list are still active */ + synchronize_rcu(); - return 0; diff --git a/drivers/remoteproc/rproc_srm_core.c b/drivers/remoteproc/rproc_srm_core.c new file mode 100644 -index 0000000000000..fc61e8b35686b +index 000000000000..fc61e8b35686 --- /dev/null +++ b/drivers/remoteproc/rproc_srm_core.c @@ -0,0 +1,303 @@ @@ -1016,7 +704,7 @@ index 0000000000000..fc61e8b35686b +MODULE_LICENSE("GPL v2"); diff --git a/drivers/remoteproc/rproc_srm_core.h b/drivers/remoteproc/rproc_srm_core.h new file mode 100644 -index 0000000000000..7dffdb38f4d46 +index 000000000000..7dffdb38f4d4 --- /dev/null +++ b/drivers/remoteproc/rproc_srm_core.h @@ -0,0 +1,98 @@ @@ -1120,7 +808,7 @@ index 0000000000000..7dffdb38f4d46 +#endif diff --git a/drivers/remoteproc/rproc_srm_dev.c b/drivers/remoteproc/rproc_srm_dev.c new file mode 100644 -index 0000000000000..6b164dad53ca1 +index 000000000000..9dad0820f263 --- /dev/null +++ b/drivers/remoteproc/rproc_srm_dev.c @@ -0,0 +1,744 @@ @@ -1788,7 +1476,7 @@ index 0000000000000..6b164dad53ca1 + + rproc_srm_dev->dev = dev; + rproc = (struct rproc *)dev_get_drvdata(dev->parent->parent); -+ rproc_srm_dev->early_boot = rproc->early_boot; ++ rproc_srm_dev->early_boot = (rproc->state == RPROC_DETACHED); + rproc_srm_dev->core = dev_get_drvdata(dev->parent); + + INIT_LIST_HEAD(&rproc_srm_dev->clk_list_head); @@ -1869,19 +1557,15 @@ index 0000000000000..6b164dad53ca1 +MODULE_DESCRIPTION("Remoteproc System Resource Manager driver - dev"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c -index 2cf4b2992bfcd..9ff1d416761b7 100644 +index d2414cc1d90d..f5a65eea9cdc 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c -@@ -15,15 +15,15 @@ - #include - #include - #include -+#include - #include +@@ -20,13 +20,11 @@ #include #include + #include +#include -+#include + #include #include "remoteproc_internal.h" @@ -1891,24 +1575,10 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 #define MBOX_NB_VQ 2 #define MBOX_NB_MBX 3 -@@ -31,9 +31,27 @@ - #define STM32_SMC_REG_WRITE 0x1 +@@ -48,6 +46,13 @@ + #define M4_STATE_STANDBY 4 + #define M4_STATE_CRASH 5 - #define STM32_MBX_VQ0 "vq0" -+#define STM32_MBX_VQ0_ID 0 - #define STM32_MBX_VQ1 "vq1" -+#define STM32_MBX_VQ1_ID 1 - #define STM32_MBX_SHUTDOWN "shutdown" - -+#define RSC_TBL_SIZE (1024) -+ -+#define COPRO_STATE_OFF 0 -+#define COPRO_STATE_INIT 1 -+#define COPRO_STATE_CRUN 2 -+#define COPRO_STATE_CSTOP 3 -+#define COPRO_STATE_STANDBY 4 -+#define COPRO_STATE_CRASH 5 -+ +/* + * Define a default index in future may come a global list of + * firmwares which list platforms and associated firmware(s) @@ -1919,98 +1589,99 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 struct stm32_syscon { struct regmap *map; u32 reg; -@@ -58,17 +76,29 @@ struct stm32_mbox { - const unsigned char name[10]; - struct mbox_chan *chan; - struct mbox_client client; -+ struct work_struct vq_work; - int vq_id; - }; +@@ -78,7 +83,7 @@ struct stm32_mbox { struct stm32_rproc { struct reset_control *rst; - struct stm32_syscon hold_boot; + struct reset_control *hold_boot; struct stm32_syscon pdds; -+ struct stm32_syscon copro_state; -+ int wdg_irq; - u32 nb_rmems; + struct stm32_syscon m4_state; + struct stm32_syscon rsctbl; +@@ -87,10 +92,17 @@ struct stm32_rproc { struct stm32_rproc_mem *rmems; struct stm32_mbox mb[MBOX_NB_MBX]; + struct workqueue_struct *workqueue; - bool secured_soc; -+ struct workqueue_struct *workqueue; + bool secured_fw; + bool fw_loaded; + struct tee_rproc *trproc; -+ void __iomem *rsc_va; -+}; -+ + void __iomem *rsc_va; + }; + +struct stm32_rproc_conf { + bool secured_fw; + struct rproc_ops *ops; - }; - ++}; ++ static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da) -@@ -91,6 +121,28 @@ static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da) + { + unsigned int i; +@@ -207,15 +219,139 @@ static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name) return -EINVAL; } -+static int stm32_rproc_da_to_pa(struct rproc *rproc, u64 da, phys_addr_t *pa) +-static int stm32_rproc_elf_load_rsc_table(struct rproc *rproc, ++static void stm32_rproc_request_shutdown(struct rproc *rproc) +{ -+ unsigned int i; + struct stm32_rproc *ddata = rproc->priv; -+ struct stm32_rproc_mem *p_mem; ++ int err, dummy_data, idx; + -+ for (i = 0; i < ddata->nb_rmems; i++) { -+ p_mem = &ddata->rmems[i]; ++ /* Request shutdown of the remote processor */ ++ if (rproc->state != RPROC_OFFLINE) { ++ idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); ++ if (idx >= 0 && ddata->mb[idx].chan) { ++ /* A dummy data is sent to allow to block on transmit. */ ++ err = mbox_send_message(ddata->mb[idx].chan, ++ &dummy_data); ++ if (err < 0) ++ dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n"); ++ } ++ } ++} + -+ if (da < p_mem->dev_addr || -+ da >= p_mem->dev_addr + p_mem->size) -+ continue; -+ *pa = da - p_mem->dev_addr + p_mem->bus_addr; -+ dev_dbg(rproc->dev.parent, "da %llx to pa %#x\n", da, *pa); -+ return 0; ++static int stm32_rproc_release(struct rproc *rproc) ++{ ++ struct stm32_rproc *ddata = rproc->priv; ++ unsigned int err = 0; ++ ++ /* To allow platform Standby power mode, set remote proc Deep Sleep. */ ++ if (ddata->pdds.map) { ++ err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg, ++ ddata->pdds.mask, 1); ++ if (err) { ++ dev_err(&rproc->dev, "failed to set pdds\n"); ++ return err; ++ } + } + -+ dev_err(rproc->dev.parent, "can't translate da %llx\n", da); ++ /* Update coprocessor state to OFF if available. */ ++ if (ddata->m4_state.map) { ++ err = regmap_update_bits(ddata->m4_state.map, ++ ddata->m4_state.reg, ++ ddata->m4_state.mask, ++ M4_STATE_OFF); ++ if (err) { ++ dev_err(&rproc->dev, "failed to set copro state\n"); ++ return err; ++ } ++ } + -+ return -EINVAL; ++ return err; +} + - static int stm32_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) - { -@@ -120,6 +172,15 @@ static int stm32_rproc_mem_release(struct rproc *rproc, - return 0; - } - -+static int stm32_rproc_elf_load_segments(struct rproc *rproc, -+ const struct firmware *fw) -+{ -+ if (!rproc->early_boot) -+ return rproc_elf_load_segments(rproc, fw); -+ -+ return 0; -+} -+ - static int stm32_rproc_of_memory_translations(struct rproc *rproc) - { - struct device *parent, *dev = rproc->dev.parent; -@@ -187,12 +248,135 @@ static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name) - return -EINVAL; - } - +static int stm32_rproc_tee_elf_sanity_check(struct rproc *rproc, + const struct firmware *fw) +{ + struct stm32_rproc *ddata = rproc->priv; + unsigned int ret = 0; + -+ if (!rproc->early_boot) { -+ ret = tee_rproc_load_fw(ddata->trproc, fw); -+ if (!ret) -+ ddata->fw_loaded = true; -+ } ++ if (rproc->state == RPROC_DETACHED) ++ return 0; ++ ++ ret = tee_rproc_load_fw(ddata->trproc, fw); ++ if (!ret) ++ ddata->fw_loaded = true; + + return ret; +} @@ -2027,17 +1698,20 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 + * else nothing done here as the firmware has been preloaded for the + * sanity check to be able to parse it for the resource table + */ -+ if (!ddata->fw_loaded && !rproc->early_boot) { -+ ret = tee_rproc_load_fw(ddata->trproc, fw); -+ if (ret) -+ return ret; -+ /* update the resource table parameters */ -+ if (rproc_tee_get_rsc_table(ddata->trproc)) { -+ /* no resource table: reset the related fields */ -+ rproc->cached_table = NULL; -+ rproc->table_ptr = NULL; -+ rproc->table_sz = 0; -+ } ++ if (ddata->fw_loaded) ++ return 0; ++ ++ ret = tee_rproc_load_fw(ddata->trproc, fw); ++ if (ret) ++ return ret; ++ ddata->fw_loaded = true; ++ ++ /* update the resource table parameters */ ++ if (rproc_tee_get_rsc_table(ddata->trproc)) { ++ /* no resource table: reset the related fields */ ++ rproc->cached_table = NULL; ++ rproc->table_ptr = NULL; ++ rproc->table_sz = 0; + } + + return 0; @@ -2045,8 +1719,10 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 + +static struct resource_table * +stm32_rproc_tee_elf_find_loaded_rsc_table(struct rproc *rproc, -+ const struct firmware *fw) -+{ + const struct firmware *fw) + { +- if (rproc_elf_load_rsc_table(rproc, fw)) +- dev_warn(&rproc->dev, "no resource table found for this firmware\n"); + struct stm32_rproc *ddata = rproc->priv; + + return tee_rproc_get_loaded_rsc_table(ddata->trproc); @@ -2056,29 +1732,21 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 +{ + struct stm32_rproc *ddata = rproc->priv; + -+ if (!rproc->early_boot) { -+ return tee_rproc_start(ddata->trproc); -+ } -+ -+ return 0; ++ return tee_rproc_start(ddata->trproc); +} -+ + ++static int stm32_rproc_tee_attach(struct rproc *rproc) ++{ ++ /* Nothing to do, remote proc already started by the secured context */ + return 0; + } + +static int stm32_rproc_tee_stop(struct rproc *rproc) +{ + struct stm32_rproc *ddata = rproc->priv; -+ int err, dummy_data, idx; ++ int err; + -+ /* request shutdown of the remote processor */ -+ if (rproc->state != RPROC_OFFLINE) { -+ idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); -+ if (idx >= 0 && ddata->mb[idx].chan) { -+ /* a dummy data is sent to allow to block on transmit */ -+ err = mbox_send_message(ddata->mb[idx].chan, -+ &dummy_data); -+ if (err < 0) -+ dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n"); -+ } -+ } ++ stm32_rproc_request_shutdown(rproc); + + err = tee_rproc_stop(ddata->trproc); + if (err) @@ -2086,159 +1754,55 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 + + ddata->fw_loaded = false; + -+ /* Reset early_boot state as we stop the co-processor */ -+ rproc->early_boot = false; -+ -+ return 0; ++ return stm32_rproc_release(rproc); +} + - static int stm32_rproc_elf_load_rsc_table(struct rproc *rproc, - const struct firmware *fw) + static int stm32_rproc_parse_memory_regions(struct rproc *rproc) { -- if (rproc_elf_load_rsc_table(rproc, fw)) -- dev_warn(&rproc->dev, "no resource table found for this firmware\n"); -+ struct resource_table *table = NULL; + struct device *dev = rproc->dev.parent; +@@ -274,12 +410,21 @@ static int stm32_rproc_parse_memory_regions(struct rproc *rproc) + + static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) + { +- int ret = stm32_rproc_parse_memory_regions(rproc); + struct stm32_rproc *ddata = rproc->priv; ++ int ret; -+ if (ddata->trproc) { -+ if (rproc_tee_get_rsc_table(ddata->trproc)) -+ goto no_rsc_table; -+ return 0; -+ } -+ -+ if (!rproc->early_boot) { -+ if (rproc_elf_load_rsc_table(rproc, fw)) -+ goto no_rsc_table; -+ -+ return 0; -+ } -+ -+ if (ddata->rsc_va) { -+ table = (struct resource_table *)ddata->rsc_va; -+ /* Assuming that the resource table fits in 1kB is fair */ -+ rproc->cached_table = kmemdup(table, RSC_TBL_SIZE, GFP_KERNEL); -+ if (!rproc->cached_table) -+ return -ENOMEM; -+ -+ rproc->table_ptr = rproc->cached_table; -+ rproc->table_sz = RSC_TBL_SIZE; -+ return 0; -+ } -+ -+no_rsc_table: -+ rproc->cached_table = NULL; -+ rproc->table_ptr = NULL; -+ rproc->table_sz = 0; -+ -+ dev_warn(&rproc->dev, "no resource table found for this firmware\n"); - return 0; - } ++ ret = stm32_rproc_parse_memory_regions(rproc); + if (ret) + return ret; -@@ -252,6 +436,36 @@ static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) - return stm32_rproc_elf_load_rsc_table(rproc, fw); - } - -+static struct resource_table * -+stm32_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, -+ const struct firmware *fw) -+{ -+ struct stm32_rproc *ddata = rproc->priv; -+ -+ if (!rproc->early_boot) -+ return rproc_elf_find_loaded_rsc_table(rproc, fw); -+ -+ return (struct resource_table *)ddata->rsc_va; -+} -+ -+static int stm32_rproc_elf_sanity_check(struct rproc *rproc, -+ const struct firmware *fw) -+{ -+ if (rproc->early_boot) -+ return 0; -+ -+ return rproc_elf_sanity_check(rproc, fw); -+} -+ -+static u32 stm32_rproc_elf_get_boot_addr(struct rproc *rproc, -+ const struct firmware *fw) -+{ -+ if (!rproc->early_boot) -+ return rproc_elf_get_boot_addr(rproc, fw); +- return stm32_rproc_elf_load_rsc_table(rproc, fw); ++ if (ddata->trproc) ++ ret = rproc_tee_get_rsc_table(ddata->trproc); ++ else ++ ret = rproc_elf_load_rsc_table(rproc, fw); ++ if (ret) ++ dev_warn(&rproc->dev, "no resource table found for this firmware\n"); + + return 0; -+} -+ + } + static irqreturn_t stm32_rproc_wdg(int irq, void *data) - { - struct rproc *rproc = data; -@@ -261,13 +475,22 @@ static irqreturn_t stm32_rproc_wdg(int irq, void *data) - return IRQ_HANDLED; - } - -+static void stm32_rproc_mb_vq_work(struct work_struct *work) -+{ -+ struct stm32_mbox *mb = container_of(work, struct stm32_mbox, vq_work); -+ struct rproc *rproc = dev_get_drvdata(mb->client.dev); -+ -+ if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE) -+ dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id); -+} -+ - static void stm32_rproc_mb_callback(struct mbox_client *cl, void *data) - { - struct rproc *rproc = dev_get_drvdata(cl->dev); - struct stm32_mbox *mb = container_of(cl, struct stm32_mbox, client); -+ struct stm32_rproc *ddata = rproc->priv; - -- if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE) -- dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id); -+ queue_work(ddata->workqueue, &mb->vq_work); - } - - static void stm32_rproc_free_mbox(struct rproc *rproc) -@@ -285,7 +508,7 @@ static void stm32_rproc_free_mbox(struct rproc *rproc) - static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = { - { - .name = STM32_MBX_VQ0, -- .vq_id = 0, -+ .vq_id = STM32_MBX_VQ0_ID, - .client = { - .rx_callback = stm32_rproc_mb_callback, - .tx_block = false, -@@ -293,7 +516,7 @@ static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = { - }, - { - .name = STM32_MBX_VQ1, -- .vq_id = 1, -+ .vq_id = STM32_MBX_VQ1_ID, - .client = { - .rx_callback = stm32_rproc_mb_callback, - .tx_block = false, -@@ -310,7 +533,7 @@ static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = { - } - }; - --static void stm32_rproc_request_mbox(struct rproc *rproc) -+static int stm32_rproc_request_mbox(struct rproc *rproc) - { - struct stm32_rproc *ddata = rproc->priv; - struct device *dev = &rproc->dev; -@@ -329,34 +552,18 @@ static void stm32_rproc_request_mbox(struct rproc *rproc) +@@ -370,8 +515,13 @@ static int stm32_rproc_request_mbox(struct rproc *rproc) ddata->mb[i].chan = mbox_request_channel_byname(cl, name); if (IS_ERR(ddata->mb[i].chan)) { -+ if (PTR_ERR(ddata->mb[i].chan) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; +- if (PTR_ERR(ddata->mb[i].chan) == -EPROBE_DEFER) ++ if (PTR_ERR(ddata->mb[i].chan) == -EPROBE_DEFER) { ++ dev_err_probe(dev->parent, ++ PTR_ERR(ddata->mb[i].chan), ++ "failed to request mailbox %s\n", ++ name); + goto err_probe; ++ } dev_warn(dev, "cannot get %s mbox\n", name); ddata->mb[i].chan = NULL; } -+ if (ddata->mb[i].vq_id >= 0) { -+ INIT_WORK(&ddata->mb[i].vq_work, -+ stm32_rproc_mb_vq_work); -+ } - } --} -- +@@ -390,30 +540,6 @@ static int stm32_rproc_request_mbox(struct rproc *rproc) + return -EPROBE_DEFER; + } + -static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold) -{ - struct stm32_rproc *ddata = rproc->priv; @@ -2259,46 +1823,54 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 - - if (err) - dev_err(&rproc->dev, "failed to set hold boot\n"); - +- - return err; -+ return 0; - } - +-} +- static void stm32_rproc_add_coredump_trace(struct rproc *rproc) -@@ -389,7 +596,7 @@ static int stm32_rproc_start(struct rproc *rproc) - stm32_rproc_add_coredump_trace(rproc); - - /* clear remote proc Deep Sleep */ -- if (ddata->pdds.map) { -+ if (ddata->pdds.map && !rproc->early_boot) { - err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg, - ddata->pdds.mask, 0); - if (err) { -@@ -398,11 +605,17 @@ static int stm32_rproc_start(struct rproc *rproc) + { + struct rproc_debug_trace *trace; +@@ -453,40 +579,34 @@ static int stm32_rproc_start(struct rproc *rproc) } } - err = stm32_rproc_set_hold_boot(rproc, false); -- if (err) -- return err; -+ /* -+ * If M4 previously started by bootloader, just guarantee holdboot -+ * is set to catch any crash. -+ */ -+ if (!rproc->early_boot) { -+ err = reset_control_deassert(ddata->hold_boot); -+ if (err) -+ return err; -+ } ++ err = reset_control_deassert(ddata->hold_boot); + if (err) + return err; + +- return stm32_rproc_set_hold_boot(rproc, true); ++ return reset_control_assert(ddata->hold_boot); + } + + static int stm32_rproc_attach(struct rproc *rproc) + { ++ struct stm32_rproc *ddata = rproc->priv; ++ + stm32_rproc_add_coredump_trace(rproc); - return stm32_rproc_set_hold_boot(rproc, true); + return reset_control_assert(ddata->hold_boot); } static int stm32_rproc_stop(struct rproc *rproc) -@@ -422,9 +635,11 @@ static int stm32_rproc_stop(struct rproc *rproc) - } - } + { + struct stm32_rproc *ddata = rproc->priv; +- int err, dummy_data, idx; ++ int err; + +- /* request shutdown of the remote processor */ +- if (rproc->state != RPROC_OFFLINE) { +- idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); +- if (idx >= 0 && ddata->mb[idx].chan) { +- /* a dummy data is sent to allow to block on transmit */ +- err = mbox_send_message(ddata->mb[idx].chan, +- &dummy_data); +- if (err < 0) +- dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n"); +- } +- } ++ stm32_rproc_request_shutdown(rproc); - err = stm32_rproc_set_hold_boot(rproc, true); - if (err) @@ -2310,46 +1882,45 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 err = reset_control_assert(ddata->rst); if (err) { -@@ -442,6 +657,21 @@ static int stm32_rproc_stop(struct rproc *rproc) - } +@@ -494,29 +614,8 @@ static int stm32_rproc_stop(struct rproc *rproc) + return err; } -+ /* update copro state to OFF */ -+ if (ddata->copro_state.map) { -+ err = regmap_update_bits(ddata->copro_state.map, -+ ddata->copro_state.reg, -+ ddata->copro_state.mask, -+ COPRO_STATE_OFF); -+ if (err) { -+ dev_err(&rproc->dev, "failed to set copro state\n"); -+ return err; -+ } -+ } -+ -+ /* Reset early_boot state as we stop the co-processor */ -+ rproc->early_boot = false; -+ - return 0; +- /* to allow platform Standby power mode, set remote proc Deep Sleep */ +- if (ddata->pdds.map) { +- err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg, +- ddata->pdds.mask, 1); +- if (err) { +- dev_err(&rproc->dev, "failed to set pdds\n"); +- return err; +- } +- } + +- /* update coprocessor state to OFF if available */ +- if (ddata->m4_state.map) { +- err = regmap_update_bits(ddata->m4_state.map, +- ddata->m4_state.reg, +- ddata->m4_state.mask, +- M4_STATE_OFF); +- if (err) { +- dev_err(&rproc->dev, "failed to set copro state\n"); +- return err; +- } +- } +- +- return 0; ++ return stm32_rproc_release(rproc); } -@@ -471,15 +701,42 @@ static struct rproc_ops st_rproc_ops = { - .start = stm32_rproc_start, - .stop = stm32_rproc_stop, - .kick = stm32_rproc_kick, -- .load = rproc_elf_load_segments, -+ .load = stm32_rproc_elf_load_segments, - .parse_fw = stm32_rproc_parse_fw, -- .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, -- .sanity_check = rproc_elf_sanity_check, -- .get_boot_addr = rproc_elf_get_boot_addr, -+ .find_loaded_rsc_table = stm32_rproc_elf_find_loaded_rsc_table, -+ .sanity_check = stm32_rproc_elf_sanity_check, -+ .get_boot_addr = stm32_rproc_elf_get_boot_addr, -+}; -+ + static void stm32_rproc_kick(struct rproc *rproc, int vqid) +@@ -553,8 +652,36 @@ static struct rproc_ops st_rproc_ops = { + .get_boot_addr = rproc_elf_get_boot_addr, + }; + +static struct rproc_ops st_rproc_tee_ops = { + .start = stm32_rproc_tee_start, + .stop = stm32_rproc_tee_stop, ++ .attach = stm32_rproc_tee_attach, + .kick = stm32_rproc_kick, + .parse_fw = stm32_rproc_parse_fw, + .find_loaded_rsc_table = stm32_rproc_tee_elf_find_loaded_rsc_table, @@ -2365,8 +1936,8 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 +static const struct stm32_rproc_conf stm32_rproc_tee_conf = { + .secured_fw = true, + .ops = &st_rproc_tee_ops, - }; - ++}; ++ static const struct of_device_id stm32_rproc_match[] = { - { .compatible = "st,stm32mp1-m4" }, + { @@ -2380,43 +1951,42 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 {}, }; MODULE_DEVICE_TABLE(of, stm32_rproc_match); -@@ -512,8 +769,10 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev) +@@ -586,21 +713,18 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev, + { + struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct rproc *rproc = platform_get_drvdata(pdev); - struct stm32_rproc *ddata = rproc->priv; - struct stm32_syscon tz; - unsigned int tzen; -+ struct stm32_syscon rsctbl; -+ phys_addr_t rsc_pa; -+ u32 rsc_da; -+ unsigned int state; int err, irq; irq = platform_get_irq(pdev, 0); -@@ -528,47 +787,90 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev) - return err; - } + if (irq == -EPROBE_DEFER) +- return -EPROBE_DEFER; ++ return dev_err_probe(dev, irq, "failed to get interrupt\n"); -+ ddata->wdg_irq = irq; -+ -+ if (of_property_read_bool(np, "wakeup-source")) { -+ device_init_wakeup(dev, true); -+ dev_pm_set_wake_irq(dev, irq); -+ } -+ + if (irq > 0) { + err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0, + dev_name(dev), pdev); +- if (err) { +- dev_err(dev, "failed to request wdg irq\n"); +- return err; +- } ++ if (err) ++ return dev_err_probe(dev, err, ++ "failed to request wdg irq\n"); + + ddata->wdg_irq = irq; + +@@ -612,36 +736,15 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev, dev_info(dev, "wdg irq registered\n"); } - ddata->rst = devm_reset_control_get_by_index(dev, 0); -+ ddata->rst = devm_reset_control_get(dev, "mcu_rst"); - if (IS_ERR(ddata->rst)) { +- if (IS_ERR(ddata->rst)) { - dev_err(dev, "failed to get mcu reset\n"); -+ if (PTR_ERR(ddata->rst) != -EPROBE_DEFER) -+ dev_err(dev, "failed to get mcu reset\n"); -+ - return PTR_ERR(ddata->rst); - } - +- return PTR_ERR(ddata->rst); +- } +- - /* - * if platform is secured the hold boot bit must be written by - * smc call and read normally. @@ -2426,97 +1996,42 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 - if (err) { - dev_err(dev, "failed to get tz syscfg\n"); - return err; -+ ddata->hold_boot = devm_reset_control_get(dev, "hold_boot"); -+ if (IS_ERR(ddata->hold_boot)) { -+ if (PTR_ERR(ddata->hold_boot) != -EPROBE_DEFER) -+ dev_err(dev, "failed to get mcu reset\n"); -+ -+ return PTR_ERR(ddata->hold_boot); - } - +- } +- - err = regmap_read(tz.map, tz.reg, &tzen); - if (err) { -- dev_err(&rproc->dev, "failed to read tzen\n"); -+ err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds); -+ if (err) -+ dev_warn(dev, "pdds not supported\n"); -+ -+ rproc->auto_boot = of_property_read_bool(np, "st,auto-boot"); -+ -+ err = stm32_rproc_of_memory_translations(rproc); -+ if (err) - return err; -+ -+ /* check if the coprocessor has been started from the bootloader */ -+ err = stm32_rproc_get_syscon(np, "st,syscfg-copro-state", -+ &ddata->copro_state); -+ if (err) { -+ /* no copro_state syscon (optional) */ -+ dev_warn(dev, "copro_state not supported\n"); -+ goto bail; - } +- dev_err(dev, "failed to read tzen\n"); +- return err; +- } - ddata->secured_soc = tzen & tz.mask; ++ ddata->rst = devm_reset_control_get(dev, "mcu_rst"); ++ if (IS_ERR(ddata->rst)) ++ return dev_err_probe(dev, PTR_ERR(ddata->rst), ++ "failed to get mcu_reset\n"); - err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot", - &ddata->hold_boot); -+ err = regmap_read(ddata->copro_state.map, ddata->copro_state.reg, -+ &state); - if (err) { +- if (err) { - dev_err(dev, "failed to get hold boot\n"); -+ dev_err(&rproc->dev, "failed to read copro state\n"); - return err; - } +- return err; +- } ++ ddata->hold_boot = devm_reset_control_get(dev, "hold_boot"); ++ if (IS_ERR(ddata->hold_boot)) ++ return dev_err_probe(dev, PTR_ERR(ddata->hold_boot), ++ "failed to get mcu reset\n"); -- err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds); -- if (err) -- dev_warn(dev, "failed to get pdds\n"); -+ if (state == COPRO_STATE_CRUN) { -+ rproc->early_boot = true; - -- rproc->auto_boot = of_property_read_bool(np, "st,auto-boot"); -+ if (stm32_rproc_get_syscon(np, "st,syscfg-rsc-tbl", &rsctbl)) { -+ /* no rsc table syscon (optional) */ -+ dev_warn(dev, "rsc tbl syscon not supported\n"); -+ goto bail; -+ } - -- return stm32_rproc_of_memory_translations(rproc); -+ err = regmap_read(rsctbl.map, rsctbl.reg, &rsc_da); -+ if (err) { -+ dev_err(&rproc->dev, "failed to read rsc tbl addr\n"); -+ return err; -+ } -+ if (!rsc_da) -+ /* no rsc table */ -+ goto bail; -+ -+ err = stm32_rproc_da_to_pa(rproc, rsc_da, &rsc_pa); -+ if (err) -+ return err; -+ -+ ddata->rsc_va = devm_ioremap_wc(dev, rsc_pa, RSC_TBL_SIZE); -+ if (IS_ERR_OR_NULL(ddata->rsc_va)) { -+ dev_err(dev, "Unable to map memory region: %pa+%zx\n", -+ &rsc_pa, RSC_TBL_SIZE); -+ ddata->rsc_va = NULL; -+ return -ENOMEM; -+ } -+ } -+bail: -+ return 0; - } - - static int stm32_rproc_probe(struct platform_device *pdev) -@@ -576,6 +878,8 @@ static int stm32_rproc_probe(struct platform_device *pdev) + err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds); + if (err) +@@ -766,6 +869,8 @@ static int stm32_rproc_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct stm32_rproc *ddata; struct device_node *np = dev->of_node; + const struct of_device_id *of_id; + const struct stm32_rproc_conf *conf; struct rproc *rproc; + unsigned int state; int ret; - -@@ -583,30 +887,69 @@ static int stm32_rproc_probe(struct platform_device *pdev) +@@ -774,12 +879,18 @@ static int stm32_rproc_probe(struct platform_device *pdev) if (ret) return ret; @@ -2531,43 +2046,26 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 if (!rproc) return -ENOMEM; - rproc->has_iommu = false; ddata = rproc->priv; +- + ddata->secured_fw = conf->secured_fw; -+ ddata->workqueue = create_workqueue(dev_name(dev)); -+ if (!ddata->workqueue) { -+ dev_err(dev, "cannot create workqueue\n"); -+ ret = -ENOMEM; -+ goto free_rproc; -+ } + rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE); - platform_set_drvdata(pdev, rproc); - - ret = stm32_rproc_parse_dt(pdev); + ret = stm32_rproc_parse_dt(pdev, ddata, &rproc->auto_boot); +@@ -820,12 +931,25 @@ static int stm32_rproc_probe(struct platform_device *pdev) if (ret) -- goto free_rproc; -+ goto free_wkq; -+ -+ if (!rproc->early_boot && !ddata->secured_fw) { -+ ret = stm32_rproc_stop(rproc); -+ if (ret) -+ goto free_wkq; -+ } + goto free_wkq; -- stm32_rproc_request_mbox(rproc); -+ ret = stm32_rproc_request_mbox(rproc); -+ if (ret) -+ goto free_wkq; -+ + if (ddata->secured_fw) { + ddata->trproc = tee_rproc_register(dev, rproc, + STM32_MP1_FW_ID); -+ if (IS_ERR_OR_NULL(ddata->trproc)) { -+ ret = -EPROBE_DEFER; ++ if (IS_ERR(ddata->trproc)) { ++ ret = PTR_ERR(ddata->trproc); ++ dev_err_probe(dev, ret, "TEE rproc device not found\n"); + goto free_mb; + } + } - ++ ret = rproc_add(rproc); if (ret) - goto free_mb; @@ -2580,38 +2078,17 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 + tee_rproc_unregister(ddata->trproc); free_mb: stm32_rproc_free_mbox(rproc); -+free_wkq: -+ destroy_workqueue(ddata->workqueue); - free_rproc: -+ if (device_may_wakeup(dev)) { -+ dev_pm_clear_wake_irq(dev); -+ device_init_wakeup(dev, false); -+ } - rproc_free(rproc); - return ret; - } -@@ -614,22 +957,70 @@ static int stm32_rproc_probe(struct platform_device *pdev) - static int stm32_rproc_remove(struct platform_device *pdev) - { - struct rproc *rproc = platform_get_drvdata(pdev); -+ struct stm32_rproc *ddata = rproc->priv; -+ struct device *dev = &pdev->dev; - - if (atomic_read(&rproc->power) > 0) + free_wkq: +@@ -851,6 +975,8 @@ static int stm32_rproc_remove(struct platform_device *pdev) rproc_shutdown(rproc); rproc_del(rproc); + if (ddata->trproc) + tee_rproc_unregister(ddata->trproc); stm32_rproc_free_mbox(rproc); -+ destroy_workqueue(ddata->workqueue); -+ -+ if (device_may_wakeup(dev)) { -+ dev_pm_clear_wake_irq(dev); -+ device_init_wakeup(dev, false); -+ } - rproc_free(rproc); + destroy_workqueue(ddata->workqueue); +@@ -863,6 +989,15 @@ static int stm32_rproc_remove(struct platform_device *pdev) return 0; } @@ -2621,52 +2098,26 @@ index 2cf4b2992bfcd..9ff1d416761b7 100644 + + if (atomic_read(&rproc->power) > 0) + dev_warn(&pdev->dev, -+ "Warning: remote fw is still running with possible side effect!!!\n"); ++ "Warning: remote fw is still running with possible side effect!!!\n"); +} + -+#ifdef CONFIG_PM_SLEEP -+static int stm32_rproc_suspend(struct device *dev) -+{ -+ struct rproc *rproc = dev_get_drvdata(dev); -+ struct stm32_rproc *ddata = rproc->priv; -+ -+ if (device_may_wakeup(dev)) -+ return enable_irq_wake(ddata->wdg_irq); -+ -+ return 0; -+} -+ -+static int stm32_rproc_resume(struct device *dev) -+{ -+ struct rproc *rproc = dev_get_drvdata(dev); -+ struct stm32_rproc *ddata = rproc->priv; -+ -+ if (device_may_wakeup(dev)) -+ return disable_irq_wake(ddata->wdg_irq); -+ -+ return 0; -+} -+#endif -+ -+static SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops, -+ stm32_rproc_suspend, stm32_rproc_resume); -+ + static int __maybe_unused stm32_rproc_suspend(struct device *dev) + { + struct rproc *rproc = dev_get_drvdata(dev); +@@ -891,6 +1026,7 @@ static SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops, static struct platform_driver stm32_rproc_driver = { .probe = stm32_rproc_probe, .remove = stm32_rproc_remove, + .shutdown = stm32_rproc_shutdown, .driver = { .name = "stm32-rproc", -+ .pm = &stm32_rproc_pm_ops, - .of_match_table = of_match_ptr(stm32_rproc_match), - }, - }; + .pm = &stm32_rproc_pm_ops, diff --git a/drivers/remoteproc/tee_remoteproc.c b/drivers/remoteproc/tee_remoteproc.c new file mode 100644 -index 0000000000000..e48887d3de7c0 +index 000000000000..67d924c95871 --- /dev/null +++ b/drivers/remoteproc/tee_remoteproc.c -@@ -0,0 +1,379 @@ +@@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) STMicroelectronics 2020 - All Rights Reserved @@ -2681,6 +2132,7 @@ index 0000000000000..e48887d3de7c0 +#include +#include +#include ++#include +#include +#include + @@ -3047,10 +2499,10 @@ index 0000000000000..e48887d3de7c0 +MODULE_AUTHOR("Arnaud Pouliquen "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig -index d0322b41eca54..88759a4c90e43 100644 +index f96716893c2a..7c8053aa968e 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig -@@ -55,4 +55,13 @@ config RPMSG_VIRTIO +@@ -64,4 +64,13 @@ config RPMSG_VIRTIO select RPMSG select VIRTIO @@ -3065,17 +2517,17 @@ index d0322b41eca54..88759a4c90e43 100644 + endmenu diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile -index 9aa859502d275..107145c6316b0 100644 +index ffe932ef6050..26a197365679 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile -@@ -5,4 +5,5 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o - obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o +@@ -7,4 +7,5 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK) += qcom_glink.o + obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o +obj-$(CONFIG_RPMSG_TTY) += rpmsg_tty.o obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c -index e330ec4dfc337..48f24503fb34e 100644 +index 91de940896e3..380500872352 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -283,6 +283,25 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, @@ -3102,10 +2554,10 @@ index e330ec4dfc337..48f24503fb34e 100644 +EXPORT_SYMBOL(rpmsg_get_buffer_size); + /* - * match an rpmsg channel with a channel info struct. + * match a rpmsg channel with a channel info struct. * this is used to make sure we're not creating rpmsg devices for channels diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h -index 3fc83cd50e98f..244292540e583 100644 +index 3fc83cd50e98..244292540e58 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h @@ -47,6 +47,7 @@ struct rpmsg_device_ops { @@ -3126,10 +2578,10 @@ index 3fc83cd50e98f..244292540e583 100644 int rpmsg_register_device(struct rpmsg_device *rpdev); diff --git a/drivers/rpmsg/rpmsg_tty.c b/drivers/rpmsg/rpmsg_tty.c new file mode 100644 -index 0000000000000..d1cccdff8ed1e +index 000000000000..b7bd1196630d --- /dev/null +++ b/drivers/rpmsg/rpmsg_tty.c -@@ -0,0 +1,339 @@ +@@ -0,0 +1,342 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved @@ -3140,6 +2592,7 @@ index 0000000000000..d1cccdff8ed1e +#include +#include +#include ++#include +#include +#include +#include @@ -3278,6 +2731,8 @@ index 0000000000000..d1cccdff8ed1e + } + } while (count > 0); + ++ tty_port_tty_wakeup(cport->port); ++ + return total; +} + @@ -3470,10 +2925,10 @@ index 0000000000000..d1cccdff8ed1e +MODULE_DESCRIPTION("virtio remote processor messaging tty driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c -index 376ebbf880d66..31b6d053f8ff0 100644 +index 7d7ed4e5cce7..b8e60b34c258 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c -@@ -175,6 +175,7 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, +@@ -181,6 +181,7 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len); @@ -3481,7 +2936,7 @@ index 376ebbf880d66..31b6d053f8ff0 100644 static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { .destroy_ept = virtio_rpmsg_destroy_ept, -@@ -184,6 +185,7 @@ static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { +@@ -190,6 +191,7 @@ static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { .trysend = virtio_rpmsg_trysend, .trysendto = virtio_rpmsg_trysendto, .trysend_offchannel = virtio_rpmsg_trysend_offchannel, @@ -3489,7 +2944,7 @@ index 376ebbf880d66..31b6d053f8ff0 100644 }; /** -@@ -699,6 +701,15 @@ static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, +@@ -705,6 +707,15 @@ static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); } @@ -3507,7 +2962,7 @@ index 376ebbf880d66..31b6d053f8ff0 100644 { diff --git a/include/linux/mailbox/arm-smccc-mbox.h b/include/linux/mailbox/arm-smccc-mbox.h new file mode 100644 -index 0000000000000..d35fb89a77f52 +index 000000000000..d35fb89a77f5 --- /dev/null +++ b/include/linux/mailbox/arm-smccc-mbox.h @@ -0,0 +1,20 @@ @@ -3531,28 +2986,8 @@ index 0000000000000..d35fb89a77f52 +}; + +#endif /* _LINUX_ARM_SMCCC_MBOX_H_ */ -diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h -index 16ad66683ad0a..221f98b73b09c 100644 ---- a/include/linux/remoteproc.h -+++ b/include/linux/remoteproc.h -@@ -481,6 +481,7 @@ struct rproc_dump_segment { - * @auto_boot: flag to indicate if remote processor should be auto-started - * @dump_segments: list of segments in the firmware - * @nb_vdev: number of vdev currently handled by rproc -+ * @early_boot: remote processor has been booted before kernel boot - */ - struct rproc { - struct list_head node; -@@ -514,6 +515,7 @@ struct rproc { - bool auto_boot; - struct list_head dump_segments; - int nb_vdev; -+ bool early_boot; - }; - - /** diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h -index 9fe156d1c018e..2af7674035aa7 100644 +index 9fe156d1c018..2af7674035aa 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -135,6 +135,7 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, @@ -3580,7 +3015,7 @@ index 9fe156d1c018e..2af7674035aa7 100644 /* use a macro to avoid include chaining to get THIS_MODULE */ diff --git a/include/linux/tee_remoteproc.h b/include/linux/tee_remoteproc.h new file mode 100644 -index 0000000000000..5d2d6ae492d0d +index 000000000000..5d2d6ae492d0 --- /dev/null +++ b/include/linux/tee_remoteproc.h @@ -0,0 +1,106 @@ diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0012-ARM-stm32mp1-r2-MEDIA-SOC-THERMAL.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0010-ARM-5.10.10-stm32mp1-r1-MEDIA-SOC-THERMAL.patch similarity index 57% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0012-ARM-stm32mp1-r2-MEDIA-SOC-THERMAL.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0010-ARM-5.10.10-stm32mp1-r1-MEDIA-SOC-THERMAL.patch index aa9a109..df1bed5 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0012-ARM-stm32mp1-r2-MEDIA-SOC-THERMAL.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0010-ARM-5.10.10-stm32mp1-r1-MEDIA-SOC-THERMAL.patch @@ -1,95 +1,46 @@ -From 1d34419db80914e8fcd39e622a56c3fdf0b2fe30 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:46 +0200 -Subject: [PATCH 12/22] ARM-stm32mp1-r2-rc8-MEDIA-SOC-THERMAL +From 88453f29216e4dc473683b0fa9fe5e3e7ae0bff2 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:11:20 +0100 +Subject: [PATCH 10/22] ARM 5.10.10-stm32mp1-r1 MEDIA-SOC-THERMAL +Signed-off-by: Romuald JEANNE --- - .../bindings/media/video-interfaces.txt | 2 + - .../bindings/soc/stm32/stm32_hdp.txt | 39 ++ - drivers/media/i2c/ov5640.c | 77 +++- - drivers/media/platform/stm32/stm32-cec.c | 10 +- - drivers/media/platform/stm32/stm32-dcmi.c | 100 +++-- - drivers/media/v4l2-core/v4l2-fwnode.c | 3 + - drivers/soc/Kconfig | 1 + - drivers/soc/Makefile | 1 + - drivers/soc/st/Kconfig | 17 + - drivers/soc/st/Makefile | 2 + - drivers/soc/st/stm32_hdp.c | 242 +++++++++++ - drivers/soc/st/stm32_pm_domain.c | 212 ++++++++++ - drivers/thermal/st/stm_thermal.c | 383 ++++++------------ - include/dt-bindings/soc/stm32-hdp.h | 108 +++++ - include/media/v4l2-fwnode.h | 2 + - 15 files changed, 882 insertions(+), 317 deletions(-) - create mode 100644 Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt + drivers/media/cec/platform/Makefile | 1 + + drivers/media/i2c/ov5640.c | 111 +++++++--- + drivers/media/platform/stm32/stm32-dcmi.c | 122 +++++++++-- + drivers/media/v4l2-core/v4l2-fwnode.c | 3 + + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/st/Kconfig | 17 ++ + drivers/soc/st/Makefile | 2 + + drivers/soc/st/stm32_hdp.c | 242 ++++++++++++++++++++++ + drivers/soc/st/stm32_pm_domain.c | 212 +++++++++++++++++++ + drivers/thermal/st/stm_thermal.c | 30 +-- + include/dt-bindings/soc/stm32-hdp.h | 108 ++++++++++ + include/media/v4l2-fwnode.h | 2 + + 13 files changed, 784 insertions(+), 68 deletions(-) create mode 100644 drivers/soc/st/Kconfig create mode 100644 drivers/soc/st/Makefile create mode 100644 drivers/soc/st/stm32_hdp.c create mode 100644 drivers/soc/st/stm32_pm_domain.c create mode 100644 include/dt-bindings/soc/stm32-hdp.h -diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt -index f884ada0bffc8..aff685a25aca9 100644 ---- a/Documentation/devicetree/bindings/media/video-interfaces.txt -+++ b/Documentation/devicetree/bindings/media/video-interfaces.txt -@@ -149,6 +149,8 @@ Optional endpoint properties - as 0 (normal). This property is valid for serial busses only. - - strobe: Whether the clock signal is used as clock (0) or strobe (1). Used - with CCP2, for instance. -+- pclk-max-frequency: maximum pixel clock frequency admissible by video -+ host interface. +diff --git a/drivers/media/cec/platform/Makefile b/drivers/media/cec/platform/Makefile +index 3a947159b25a..ea6f8ee8161c 100644 +--- a/drivers/media/cec/platform/Makefile ++++ b/drivers/media/cec/platform/Makefile +@@ -10,5 +10,6 @@ obj-$(CONFIG_CEC_MESON_AO) += meson/ + obj-$(CONFIG_CEC_SAMSUNG_S5P) += s5p/ + obj-$(CONFIG_CEC_SECO) += seco/ + obj-$(CONFIG_CEC_STI) += sti/ ++obj-$(CONFIG_CEC_STM32) += stm32/ + obj-$(CONFIG_CEC_TEGRA) += tegra/ - Example - ------- -diff --git a/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt b/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt -new file mode 100644 -index 0000000000000..e2bd82f4980eb ---- /dev/null -+++ b/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt -@@ -0,0 +1,39 @@ -+STM32 - STM32MP1- HDP Pin configuration for STM32MP1 -+======================================================= -+ -+The Hardware Debug Port (HDP) allows the observation of internal signals. By using multiplexers, -+up to 16 signals for each of 8-bit output can be observed. -+ -+Required Properties: -+ -+ - compatible: Must be "st,stm32mp1-hdp" -+ - muxing-hdp: Indicates for each HDP pins selected which HDP output among the 16 available signals you want -+ -+For each HDP pins you can select one of 16 signals which will be described in file : include/dt-bindings/soc/stm32-hdp.h -+ -+Example -+------- -+ -+In common dtsi file: -+ -+hdp: hdp@5002a000 { -+ compatible = "st,stm32mp1-hdp"; -+ reg = <0x5002a000 0x400>; -+ clocks = <&rcc HDP>; -+ clock-names = "hdp"; -+}; -+ -+In board-specific file: -+ -+In this example I've selected HDP0, HDP6 and HDP7, and for HDP0 the output signal is HDP0_GPOVAL_0, -+for HDP6 is HDP6_GPOVAL_6, and for HDP7 is HDP7_GPOVAL_7. -+ -+&hdp { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&hdp0_pins_a &hdp6_pins_a &hdp7_pins_a>; -+ pinctrl-1 = <&hdp0_pins_sleep_a &hdp6_pins_sleep_a &hdp7_pins_sleep_a>; -+ -+ muxing-hdp = <(STM32_HDP(0, HDP0_GPOVAL_0) | -+ STM32_HDP(6, HDP6_GPOVAL_6) | -+ STM32_HDP(7, HDP7_GPOVAL_7))>; -+}; diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c -index 266e947572c1e..6a1b50bec7c84 100644 +index 8f0812e85901..d7d36ad863ea 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c -@@ -63,6 +63,7 @@ +@@ -65,6 +65,7 @@ #define OV5640_REG_TIMING_VTS 0x380e #define OV5640_REG_TIMING_TC_REG20 0x3820 #define OV5640_REG_TIMING_TC_REG21 0x3821 @@ -97,7 +48,33 @@ index 266e947572c1e..6a1b50bec7c84 100644 #define OV5640_REG_AEC_CTRL00 0x3a00 #define OV5640_REG_AEC_B50_STEP 0x3a08 #define OV5640_REG_AEC_B60_STEP 0x3a0a -@@ -214,6 +215,7 @@ struct ov5640_ctrls { +@@ -98,7 +99,8 @@ + #define OV5640_REG_AVG_READOUT 0x56a1 + + enum ov5640_mode_id { +- OV5640_MODE_QCIF_176_144 = 0, ++ OV5640_MODE_QQVGA_160_120 = 0, ++ OV5640_MODE_QCIF_176_144, + OV5640_MODE_QVGA_320_240, + OV5640_MODE_VGA_640_480, + OV5640_MODE_NTSC_720_480, +@@ -113,7 +115,6 @@ enum ov5640_mode_id { + enum ov5640_frame_rate { + OV5640_15_FPS = 0, + OV5640_30_FPS, +- OV5640_60_FPS, + OV5640_NUM_FRAMERATES, + }; + +@@ -155,7 +156,6 @@ MODULE_PARM_DESC(virtual_channel, + static const int ov5640_framerates[] = { + [OV5640_15_FPS] = 15, + [OV5640_30_FPS] = 30, +- [OV5640_60_FPS] = 60, + }; + + /* regulator supplies */ +@@ -219,6 +219,7 @@ struct ov5640_ctrls { struct v4l2_ctrl *test_pattern; struct v4l2_ctrl *hflip; struct v4l2_ctrl *vflip; @@ -105,7 +82,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; struct ov5640_dev { -@@ -370,8 +372,8 @@ static const struct reg_value ov5640_setting_VGA_640_480[] = { +@@ -374,8 +375,8 @@ static const struct reg_value ov5640_setting_VGA_640_480[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, @@ -116,7 +93,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; static const struct reg_value ov5640_setting_XGA_1024_768[] = { -@@ -389,8 +391,7 @@ static const struct reg_value ov5640_setting_XGA_1024_768[] = { +@@ -393,8 +394,7 @@ static const struct reg_value ov5640_setting_XGA_1024_768[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, @@ -126,17 +103,35 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; static const struct reg_value ov5640_setting_QVGA_320_240[] = { -@@ -408,8 +409,7 @@ static const struct reg_value ov5640_setting_QVGA_320_240[] = { +@@ -412,8 +412,25 @@ static const struct reg_value ov5640_setting_QVGA_320_240[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, - {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, - {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, ++ {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0}, ++}; ++ ++static const struct reg_value ov5640_setting_QQVGA_160_120[] = { ++ {0x3c07, 0x08, 0, 0}, ++ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, ++ {0x3814, 0x31, 0, 0}, ++ {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, ++ {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, ++ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0}, ++ {0x3810, 0x00, 0, 0}, ++ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0}, ++ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0}, ++ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0}, ++ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, ++ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, + {0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0}, }; static const struct reg_value ov5640_setting_QCIF_176_144[] = { -@@ -427,8 +427,7 @@ static const struct reg_value ov5640_setting_QCIF_176_144[] = { +@@ -431,8 +448,7 @@ static const struct reg_value ov5640_setting_QCIF_176_144[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, @@ -146,7 +141,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; static const struct reg_value ov5640_setting_NTSC_720_480[] = { -@@ -446,8 +445,7 @@ static const struct reg_value ov5640_setting_NTSC_720_480[] = { +@@ -450,8 +466,7 @@ static const struct reg_value ov5640_setting_NTSC_720_480[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, @@ -156,7 +151,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; static const struct reg_value ov5640_setting_PAL_720_576[] = { -@@ -465,8 +463,7 @@ static const struct reg_value ov5640_setting_PAL_720_576[] = { +@@ -469,8 +484,7 @@ static const struct reg_value ov5640_setting_PAL_720_576[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, @@ -166,7 +161,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; static const struct reg_value ov5640_setting_720P_1280_720[] = { -@@ -484,8 +481,7 @@ static const struct reg_value ov5640_setting_720P_1280_720[] = { +@@ -488,8 +502,7 @@ static const struct reg_value ov5640_setting_720P_1280_720[] = { {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, @@ -176,7 +171,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; static const struct reg_value ov5640_setting_1080P_1920_1080[] = { -@@ -504,8 +500,8 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = { +@@ -507,8 +520,8 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, @@ -187,15 +182,15 @@ index 266e947572c1e..6a1b50bec7c84 100644 {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0}, -@@ -516,7 +512,6 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = { +@@ -519,7 +532,6 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = { {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0}, {0x3a15, 0x60, 0, 0}, {0x4407, 0x04, 0, 0}, - {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0}, - {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, + {0x4005, 0x1a, 0, 0}, }; -@@ -535,8 +530,8 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = { +@@ -538,8 +550,8 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = { {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, @@ -206,7 +201,28 @@ index 266e947572c1e..6a1b50bec7c84 100644 }; /* power-on sensor init reg table */ -@@ -1005,9 +1000,38 @@ static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor, +@@ -552,6 +564,11 @@ static const struct ov5640_mode_info ov5640_mode_init_data = { + + static const struct ov5640_mode_info + ov5640_mode_data[OV5640_NUM_MODES] = { ++ {OV5640_MODE_QQVGA_160_120, SUBSAMPLING, ++ 160, 1896, 120, 984, ++ ov5640_setting_QQVGA_160_120, ++ ARRAY_SIZE(ov5640_setting_QQVGA_160_120), ++ OV5640_30_FPS}, + {OV5640_MODE_QCIF_176_144, SUBSAMPLING, + 176, 1896, 144, 984, + ov5640_setting_QCIF_176_144, +@@ -566,7 +583,7 @@ ov5640_mode_data[OV5640_NUM_MODES] = { + 640, 1896, 480, 1080, + ov5640_setting_VGA_640_480, + ARRAY_SIZE(ov5640_setting_VGA_640_480), +- OV5640_60_FPS}, ++ OV5640_30_FPS}, + {OV5640_MODE_NTSC_720_480, SUBSAMPLING, + 720, 1896, 480, 984, + ov5640_setting_NTSC_720_480, +@@ -1018,9 +1035,38 @@ static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor, static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate) { @@ -245,7 +261,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 ov5640_calc_pclk(sensor, rate, &prediv, &mult, &sysdiv, &pll_rdiv, &bit_div, &pclk_div); -@@ -1042,6 +1066,7 @@ static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate) +@@ -1055,6 +1101,7 @@ static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate) (ilog2(pclk_div) << 4)); } @@ -253,7 +269,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 /* set JPEG framing sizes */ static int ov5640_set_jpeg_timings(struct ov5640_dev *sensor, const struct ov5640_mode_info *mode) -@@ -1065,19 +1090,20 @@ static int ov5640_set_jpeg_timings(struct ov5640_dev *sensor, +@@ -1078,19 +1125,20 @@ static int ov5640_set_jpeg_timings(struct ov5640_dev *sensor, return ov5640_write_reg16(sensor, OV5640_REG_VFIFO_VSIZE, mode->vact); } @@ -276,7 +292,22 @@ index 266e947572c1e..6a1b50bec7c84 100644 ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact); if (ret < 0) return ret; -@@ -2199,6 +2225,10 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd, +@@ -2172,12 +2220,12 @@ static int ov5640_try_frame_interval(struct ov5640_dev *sensor, + int i; + + minfps = ov5640_framerates[OV5640_15_FPS]; +- maxfps = ov5640_framerates[OV5640_60_FPS]; ++ maxfps = ov5640_framerates[OV5640_30_FPS]; + + if (fi->numerator == 0) { + fi->denominator = maxfps; + fi->numerator = 1; +- rate = OV5640_60_FPS; ++ rate = OV5640_30_FPS; + goto find_mode; + } + +@@ -2260,6 +2308,10 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd, return 0; } @@ -287,7 +318,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 static int ov5640_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) -@@ -2637,6 +2667,8 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl) +@@ -2700,6 +2752,8 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_VFLIP: ret = ov5640_set_ctrl_vflip(sensor, ctrl->val); break; @@ -296,7 +327,7 @@ index 266e947572c1e..6a1b50bec7c84 100644 default: ret = -EINVAL; break; -@@ -2704,6 +2736,9 @@ static int ov5640_init_controls(struct ov5640_dev *sensor) +@@ -2772,6 +2826,9 @@ static int ov5640_init_controls(struct ov5640_dev *sensor) V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0, V4L2_CID_POWER_LINE_FREQUENCY_50HZ); @@ -306,39 +337,8 @@ index 266e947572c1e..6a1b50bec7c84 100644 if (hdl->error) { ret = hdl->error; goto free_ctrls; -diff --git a/drivers/media/platform/stm32/stm32-cec.c b/drivers/media/platform/stm32/stm32-cec.c -index 8a86b2cc22fab..108f83c264f84 100644 ---- a/drivers/media/platform/stm32/stm32-cec.c -+++ b/drivers/media/platform/stm32/stm32-cec.c -@@ -291,7 +291,9 @@ static int stm32_cec_probe(struct platform_device *pdev) - - cec->clk_cec = devm_clk_get(&pdev->dev, "cec"); - if (IS_ERR(cec->clk_cec)) { -- dev_err(&pdev->dev, "Cannot get cec clock\n"); -+ if (PTR_ERR(cec->clk_cec) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Cannot get cec clock\n"); -+ - return PTR_ERR(cec->clk_cec); - } - -@@ -302,10 +304,14 @@ static int stm32_cec_probe(struct platform_device *pdev) - } - - cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec"); -+ if (IS_ERR(cec->clk_hdmi_cec) && -+ PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ - if (!IS_ERR(cec->clk_hdmi_cec)) { - ret = clk_prepare(cec->clk_hdmi_cec); - if (ret) { -- dev_err(&pdev->dev, "Unable to prepare hdmi-cec clock\n"); -+ dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n"); - return ret; - } - } diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c -index 9392e3409fba0..7c8256441db33 100644 +index fd1c41cba52f..60ef8a65f16c 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -95,6 +95,9 @@ enum state { @@ -351,7 +351,15 @@ index 9392e3409fba0..7c8256441db33 100644 #define TIMEOUT_MS 1000 #define OVERRUN_ERROR_THRESHOLD 3 -@@ -324,7 +327,7 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi, +@@ -157,6 +160,7 @@ struct stm32_dcmi { + struct vb2_queue queue; + + struct v4l2_fwnode_bus_parallel bus; ++ enum v4l2_mbus_type bus_type; + struct completion complete; + struct clk *mclk; + enum state state; +@@ -324,7 +328,7 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi, } /* @@ -360,7 +368,7 @@ index 9392e3409fba0..7c8256441db33 100644 * dmaengine_prep_slave_single() and dmaengine_submit() * by locking the whole DMA submission sequence */ -@@ -438,7 +441,7 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi) +@@ -438,7 +442,7 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi) } /* Abort DMA operation */ @@ -369,16 +377,31 @@ index 9392e3409fba0..7c8256441db33 100644 /* Restart capture */ if (dcmi_restart_capture(dcmi)) -@@ -733,7 +736,7 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) - if (ret < 0) { - dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync (%d)\n", - __func__, ret); -- goto err_release_buffers; -+ goto err_pm_put; - } +@@ -777,6 +781,23 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) + if (dcmi->bus.flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + val |= CR_PCKPOL; - ret = media_pipeline_start(&dcmi->vdev->entity, &dcmi->pipeline); -@@ -784,8 +787,31 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) ++ /* ++ * BT656 embedded synchronisation bus mode. ++ * ++ * Default SAV/EAV mode is supported here with default codes ++ * SAV=0xff000080 & EAV=0xff00009d. ++ * With DCMI this means LSC=SAV=0x80 & LEC=EAV=0x9d. ++ */ ++ if (dcmi->bus_type == V4L2_MBUS_BT656) { ++ val |= CR_ESS; ++ ++ /* Unmask all codes */ ++ reg_write(dcmi->regs, DCMI_ESUR, 0xffffffff);/* FEC:LEC:LSC:FSC */ ++ ++ /* Trig on LSC=0x80 & LEC=0x9d codes, ignore FSC and FEC */ ++ reg_write(dcmi->regs, DCMI_ESCR, 0xff9d80ff);/* FEC:LEC:LSC:FSC */ ++ } ++ + reg_write(dcmi->regs, DCMI_CR, val); + + /* Set crop */ +@@ -784,8 +805,31 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) dcmi_set_crop(dcmi); /* Enable jpeg capture */ @@ -412,16 +435,7 @@ index 9392e3409fba0..7c8256441db33 100644 /* Enable dcmi */ reg_set(dcmi->regs, DCMI_CR, CR_ENABLE); -@@ -837,8 +863,6 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) - - err_pm_put: - pm_runtime_put(dcmi->dev); -- --err_release_buffers: - spin_lock_irq(&dcmi->irqlock); - /* - * Return all buffers to vb2 in QUEUED state. -@@ -884,7 +908,7 @@ static void dcmi_stop_streaming(struct vb2_queue *vq) +@@ -882,7 +926,7 @@ static void dcmi_stop_streaming(struct vb2_queue *vq) /* Stop all pending DMA operations */ mutex_lock(&dcmi->dma_lock); @@ -430,7 +444,19 @@ index 9392e3409fba0..7c8256441db33 100644 mutex_unlock(&dcmi->dma_lock); pm_runtime_put(dcmi->dev); -@@ -1576,6 +1600,22 @@ static const struct dcmi_format dcmi_formats[] = { +@@ -1067,8 +1111,9 @@ static int dcmi_set_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f) + if (ret) + return ret; + +- /* Disable crop if JPEG is requested */ +- if (pix->pixelformat == V4L2_PIX_FMT_JPEG) ++ /* Disable crop if JPEG is requested or BT656 bus is selected */ ++ if (pix->pixelformat == V4L2_PIX_FMT_JPEG && ++ dcmi->bus_type != V4L2_MBUS_BT656) + dcmi->do_crop = false; + + /* pix to mbus format */ +@@ -1574,6 +1619,22 @@ static const struct dcmi_format dcmi_formats[] = { .fourcc = V4L2_PIX_FMT_JPEG, .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, .bpp = 1, @@ -453,11 +479,23 @@ index 9392e3409fba0..7c8256441db33 100644 }, }; -@@ -1747,6 +1787,15 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, +@@ -1592,6 +1653,11 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi) + if (dcmi_formats[i].mbus_code != mbus_code.code) + continue; + ++ /* Exclude JPEG if BT656 bus is selected */ ++ if (dcmi_formats[i].fourcc == V4L2_PIX_FMT_JPEG && ++ dcmi->bus_type == V4L2_MBUS_BT656) ++ continue; ++ + /* Code supported, have we got this fourcc yet? */ + for (j = 0; j < num_fmts; j++) + if (sd_fmts[j]->fourcc == +@@ -1745,6 +1811,15 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, dev_dbg(dcmi->dev, "Subdev \"%s\" bound\n", subdev->name); -+ ret = video_register_device(dcmi->vdev, VFL_TYPE_GRABBER, -1); ++ ret = video_register_device(dcmi->vdev, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(dcmi->dev, "Failed to register video device\n"); + return ret; @@ -469,7 +507,7 @@ index 9392e3409fba0..7c8256441db33 100644 /* * Link this sub-device to DCMI, it could be * a parallel camera sensor or a bridge -@@ -1759,10 +1808,11 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, +@@ -1757,10 +1832,11 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, &dcmi->vdev->entity, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); @@ -483,7 +521,7 @@ index 9392e3409fba0..7c8256441db33 100644 dev_dbg(dcmi->dev, "DCMI is now linked to \"%s\"\n", subdev->name); -@@ -1853,7 +1903,9 @@ static int dcmi_probe(struct platform_device *pdev) +@@ -1851,7 +1927,9 @@ static int dcmi_probe(struct platform_device *pdev) dcmi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(dcmi->rstc)) { @@ -494,29 +532,30 @@ index 9392e3409fba0..7c8256441db33 100644 return PTR_ERR(dcmi->rstc); } -@@ -1910,10 +1962,13 @@ static int dcmi_probe(struct platform_device *pdev) - return PTR_ERR(mclk); +@@ -1873,9 +1951,18 @@ static int dcmi_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "CSI bus not supported\n"); + return -ENODEV; } ++ ++ if (ep.bus_type == V4L2_MBUS_BT656 && ++ ep.bus.parallel.bus_width != 8) { ++ dev_err(&pdev->dev, "BT656 bus conflicts with %u bits bus width (8 bits required)\n", ++ ep.bus.parallel.bus_width); ++ return -ENODEV; ++ } ++ + dcmi->bus.flags = ep.bus.parallel.flags; + dcmi->bus.bus_width = ep.bus.parallel.bus_width; + dcmi->bus.data_shift = ep.bus.parallel.data_shift; ++ dcmi->bus_type = ep.bus_type; -- chan = dma_request_slave_channel(&pdev->dev, "tx"); -- if (!chan) { -- dev_info(&pdev->dev, "Unable to request DMA channel, defer probing\n"); -- return -EPROBE_DEFER; -+ chan = dma_request_chan(&pdev->dev, "tx"); -+ if (IS_ERR(chan)) { -+ ret = PTR_ERR(chan); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, -+ "Failed to request DMA channel: %d\n", ret); -+ return ret; - } - - spin_lock_init(&dcmi->irqlock); -@@ -1971,15 +2026,6 @@ static int dcmi_probe(struct platform_device *pdev) + irq = platform_get_irq(pdev, 0); + if (irq <= 0) +@@ -1972,15 +2059,6 @@ static int dcmi_probe(struct platform_device *pdev) } dcmi->vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT; -- ret = video_register_device(dcmi->vdev, VFL_TYPE_GRABBER, -1); +- ret = video_register_device(dcmi->vdev, VFL_TYPE_VIDEO, -1); - if (ret) { - dev_err(dcmi->dev, "Failed to register video device\n"); - goto err_media_entity_cleanup; @@ -528,7 +567,7 @@ index 9392e3409fba0..7c8256441db33 100644 /* Buffer queue */ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; -@@ -2000,7 +2046,7 @@ static int dcmi_probe(struct platform_device *pdev) +@@ -2001,7 +2079,7 @@ static int dcmi_probe(struct platform_device *pdev) ret = dcmi_graph_init(dcmi); if (ret < 0) @@ -537,7 +576,7 @@ index 9392e3409fba0..7c8256441db33 100644 /* Reset device */ ret = reset_control_assert(dcmi->rstc); -@@ -2026,7 +2072,10 @@ static int dcmi_probe(struct platform_device *pdev) +@@ -2027,7 +2105,10 @@ static int dcmi_probe(struct platform_device *pdev) return 0; err_cleanup: @@ -548,7 +587,7 @@ index 9392e3409fba0..7c8256441db33 100644 err_media_entity_cleanup: media_entity_cleanup(&dcmi->vdev->entity); err_device_release: -@@ -2048,6 +2097,7 @@ static int dcmi_remove(struct platform_device *pdev) +@@ -2049,6 +2130,7 @@ static int dcmi_remove(struct platform_device *pdev) v4l2_async_notifier_unregister(&dcmi->notifier); v4l2_async_notifier_cleanup(&dcmi->notifier); @@ -557,7 +596,7 @@ index 9392e3409fba0..7c8256441db33 100644 v4l2_device_unregister(&dcmi->v4l2_dev); media_device_cleanup(&dcmi->mdev); diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c -index 3bd1888787eb3..7f370d6b7a143 100644 +index dfc53d11053f..7d0e2f5d1700 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -356,6 +356,9 @@ v4l2_fwnode_endpoint_parse_parallel_bus(struct fwnode_handle *fwnode, @@ -571,37 +610,43 @@ index 3bd1888787eb3..7f370d6b7a143 100644 default: bus->flags = flags; diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig -index 833e04a7835c5..4ad5724f5cefd 100644 +index 425ab6f7e375..30afdfbfd9cc 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig -@@ -14,6 +14,7 @@ source "drivers/soc/qcom/Kconfig" - source "drivers/soc/renesas/Kconfig" +@@ -15,6 +15,7 @@ source "drivers/soc/renesas/Kconfig" source "drivers/soc/rockchip/Kconfig" source "drivers/soc/samsung/Kconfig" + source "drivers/soc/sifive/Kconfig" +source "drivers/soc/st/Kconfig" source "drivers/soc/sunxi/Kconfig" source "drivers/soc/tegra/Kconfig" source "drivers/soc/ti/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile -index 2ec3550035243..30d3dcabf3bb0 100644 +index 36452bed86ef..6b957db9a9bb 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile -@@ -20,6 +20,7 @@ obj-y += qcom/ - obj-y += renesas/ +@@ -21,6 +21,7 @@ obj-y += renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_SOC_SAMSUNG) += samsung/ + obj-$(CONFIG_SOC_SIFIVE) += sifive/ +obj-$(CONFIG_ARCH_STM32) += st/ obj-y += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-y += ti/ diff --git a/drivers/soc/st/Kconfig b/drivers/soc/st/Kconfig new file mode 100644 -index 0000000000000..59db031505522 +index 000000000000..8ab604999db4 --- /dev/null +++ b/drivers/soc/st/Kconfig @@ -0,0 +1,17 @@ +if ARCH_STM32 + ++config STM32_PM_DOMAINS ++ bool "STM32 PM domains" ++ depends on MACH_STM32MP157 ++ select PM_GENERIC_DOMAINS ++ default y if MACH_STM32MP157 ++ +config STM32_HDP + bool "STMicroelectronics STM32MP157 Hardware Debug Port (HDP) pin control" + depends on MACH_STM32MP157 @@ -610,24 +655,18 @@ index 0000000000000..59db031505522 + The Hardware Debug Port allows the observation of internal signals. By using multiplexers, + up to 16 signals for each of 8-bit output can be observed. + -+config STM32_PM_DOMAINS -+ bool "STM32 PM domains" -+ depends on MACH_STM32MP157 -+ select PM_GENERIC_DOMAINS -+ default y if MACH_STM32MP157 -+ +endif # ARCH_STM32 diff --git a/drivers/soc/st/Makefile b/drivers/soc/st/Makefile new file mode 100644 -index 0000000000000..0fce1db166421 +index 000000000000..85905b7688ed --- /dev/null +++ b/drivers/soc/st/Makefile @@ -0,0 +1,2 @@ -+obj-$(CONFIG_STM32_HDP) += stm32_hdp.o +obj-$(CONFIG_STM32_PM_DOMAINS) += stm32_pm_domain.o ++obj-$(CONFIG_STM32_HDP) += stm32_hdp.o diff --git a/drivers/soc/st/stm32_hdp.c b/drivers/soc/st/stm32_hdp.c new file mode 100644 -index 0000000000000..6408ac68ca5f8 +index 000000000000..47687ebd1ffd --- /dev/null +++ b/drivers/soc/st/stm32_hdp.c @@ -0,0 +1,242 @@ @@ -716,7 +755,7 @@ index 0000000000000..6408ac68ca5f8 +DEFINE_SIMPLE_ATTRIBUTE(stm32_hdp_fops, stm32_hdp_fops_get, + stm32_hdp_fops_set, "0x%llx\n"); + -+int stm32_hdp_probe(struct platform_device *pdev) ++static int stm32_hdp_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; @@ -875,7 +914,7 @@ index 0000000000000..6408ac68ca5f8 +module_platform_driver(hdp_driver); diff --git a/drivers/soc/st/stm32_pm_domain.c b/drivers/soc/st/stm32_pm_domain.c new file mode 100644 -index 0000000000000..0386624c20f2f +index 000000000000..0386624c20f2 --- /dev/null +++ b/drivers/soc/st/stm32_pm_domain.c @@ -0,0 +1,212 @@ @@ -1092,125 +1131,29 @@ index 0000000000000..0386624c20f2f +} +core_initcall(stm32_pm_domains_init); diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c -index cf9ddc52f30e1..1cecf95449c3e 100644 +index 5fd3fb8912a6..1e065a3323f9 100644 --- a/drivers/thermal/st/stm_thermal.c +++ b/drivers/thermal/st/stm_thermal.c -@@ -30,7 +30,7 @@ - #define DTS_DR_OFFSET 0x1C - #define DTS_SR_OFFSET 0x20 - #define DTS_ITENR_OFFSET 0x24 --#define DTS_CIFR_OFFSET 0x28 -+#define DTS_ICIFR_OFFSET 0x28 - - /* DTS_CFGR1 register mask definitions */ - #define HSREF_CLK_DIV_MASK GENMASK(30, 24) -@@ -51,10 +51,16 @@ - /* DTS_DR register mask definitions */ - #define TS1_MFREQ_MASK GENMASK(15, 0) - -+/* DTS_ITENR register mask definitions */ -+#define ITENR_MASK (GENMASK(2, 0) | GENMASK(6, 4)) -+ -+/* DTS_ICIFR register mask definitions */ -+#define ICIFR_MASK (GENMASK(2, 0) | GENMASK(6, 4)) -+ - /* Less significant bit position definitions */ - #define TS1_T0_POS 16 --#define TS1_SMP_TIME_POS 16 - #define TS1_HITTHD_POS 16 -+#define TS1_LITTHD_POS 0 - #define HSREF_CLK_DIV_POS 24 - - /* DTS_CFGR1 bit definitions */ -@@ -76,58 +82,37 @@ +@@ -82,8 +82,7 @@ #define ONE_MHZ 1000000 #define POLL_TIMEOUT 5000 #define STARTUP_TIME 40 --#define TS1_T0_VAL0 30 --#define TS1_T0_VAL1 130 +-#define TS1_T0_VAL0 30000 /* 30 celsius */ +-#define TS1_T0_VAL1 130000 /* 130 celsius */ +#define T0 30000 /* 30 celsius */ #define NO_HW_TRIG 0 -- --/* The Thermal Framework expects millidegrees */ --#define mcelsius(temp) ((temp) * 1000) -- --/* The Sensor expects oC degrees */ --#define celsius(temp) ((temp) / 1000) -+#define SAMPLING_TIME 15 + #define SAMPLING_TIME 15 - struct stm_thermal_sensor { - struct device *dev; - struct thermal_zone_device *th_dev; - enum thermal_device_mode mode; - struct clk *clk; -- int high_temp; -- int low_temp; -- int temp_critical; -- int temp_passive; - unsigned int low_temp_enabled; -- int num_trips; -+ unsigned int high_temp_enabled; +@@ -96,7 +95,7 @@ struct stm_thermal_sensor { + unsigned int high_temp_enabled; int irq; -- unsigned int irq_enabled; void __iomem *base; - int t0, fmt0, ramp_coeff; + int fmt0, ramp_coeff; }; --static irqreturn_t stm_thermal_alarm_irq(int irq, void *sdata) --{ -- struct stm_thermal_sensor *sensor = sdata; -- -- disable_irq_nosync(irq); -- sensor->irq_enabled = false; -- -- return IRQ_WAKE_THREAD; --} -+static int stm_enable_irq(struct stm_thermal_sensor *sensor); - - static irqreturn_t stm_thermal_alarm_irq_thread(int irq, void *sdata) - { -- u32 value; - struct stm_thermal_sensor *sensor = sdata; - -- /* read IT reason in SR and clear flags */ -- value = readl_relaxed(sensor->base + DTS_SR_OFFSET); -+ dev_dbg(sensor->dev, "sr:%d\n", -+ readl_relaxed(sensor->base + DTS_SR_OFFSET)); - -- if ((value & LOW_THRESHOLD) == LOW_THRESHOLD) -- writel_relaxed(LOW_THRESHOLD, sensor->base + DTS_CIFR_OFFSET); -+ thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED); - -- if ((value & HIGH_THRESHOLD) == HIGH_THRESHOLD) -- writel_relaxed(HIGH_THRESHOLD, sensor->base + DTS_CIFR_OFFSET); -+ stm_enable_irq(sensor); - -- thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED); -+ /* Acknoledge all DTS irqs */ -+ writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET); - - return IRQ_HANDLED; - } -@@ -160,6 +145,8 @@ static int stm_sensor_power_on(struct stm_thermal_sensor *sensor) - writel_relaxed(value, sensor->base + - DTS_CFGR1_OFFSET); - -+ sensor->mode = THERMAL_DEVICE_ENABLED; -+ - return 0; - } - -@@ -167,6 +154,8 @@ static int stm_sensor_power_off(struct stm_thermal_sensor *sensor) - { - u32 value; - -+ sensor->mode = THERMAL_DEVICE_DISABLED; -+ - /* Stop measuring */ - value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET); - value &= ~TS1_START; -@@ -232,14 +221,6 @@ static int stm_thermal_calibration(struct stm_thermal_sensor *sensor) + static int stm_enable_irq(struct stm_thermal_sensor *sensor) +@@ -243,14 +242,6 @@ static int stm_thermal_calibration(struct stm_thermal_sensor *sensor) /* Fill in DTS structure with factory sensor values */ static int stm_thermal_read_factory_settings(struct stm_thermal_sensor *sensor) { @@ -1225,7 +1168,7 @@ index cf9ddc52f30e1..1cecf95449c3e 100644 /* Retrieve fmt0 and put it on Hz */ sensor->fmt0 = ADJUST * (readl_relaxed(sensor->base + DTS_T0VALR1_OFFSET) & TS1_FMT0_MASK); -@@ -253,8 +234,8 @@ static int stm_thermal_read_factory_settings(struct stm_thermal_sensor *sensor) +@@ -264,8 +255,8 @@ static int stm_thermal_read_factory_settings(struct stm_thermal_sensor *sensor) return -EINVAL; } @@ -1236,484 +1179,43 @@ index cf9ddc52f30e1..1cecf95449c3e 100644 return 0; } -@@ -263,60 +244,16 @@ static int stm_thermal_calculate_threshold(struct stm_thermal_sensor *sensor, - int temp, u32 *th) - { +@@ -276,8 +267,7 @@ static int stm_thermal_calculate_threshold(struct stm_thermal_sensor *sensor, int freqM; -- u32 sampling_time; -- -- /* Retrieve the number of periods to sample */ -- sampling_time = (readl_relaxed(sensor->base + DTS_CFGR1_OFFSET) & -- TS1_SMP_TIME_MASK) >> TS1_SMP_TIME_POS; /* Figure out the CLK_PTAT frequency for a given temperature */ -- freqM = ((temp - sensor->t0) * sensor->ramp_coeff) -- + sensor->fmt0; -- -- dev_dbg(sensor->dev, "%s: freqM for threshold = %d Hz", -- __func__, freqM); +- freqM = ((temp - sensor->t0) * sensor->ramp_coeff) / 1000 + +- sensor->fmt0; + freqM = ((temp - T0) * sensor->ramp_coeff) / 1000 + sensor->fmt0; /* Figure out the threshold sample number */ -- *th = clk_get_rate(sensor->clk); -+ *th = clk_get_rate(sensor->clk) * SAMPLING_TIME / freqM; - if (!*th) + *th = clk_get_rate(sensor->clk) * SAMPLING_TIME / freqM; +@@ -372,7 +362,7 @@ static int stm_thermal_get_temp(void *data, int *temp) return -EINVAL; -- *th = *th / freqM; -- -- *th *= sampling_time; -- -- return 0; --} -- --static int stm_thermal_set_threshold(struct stm_thermal_sensor *sensor) --{ -- u32 value, th; -- int ret; -- -- value = readl_relaxed(sensor->base + DTS_ITR1_OFFSET); -- -- /* Erase threshold content */ -- value &= ~(TS1_LITTHD_MASK | TS1_HITTHD_MASK); -- -- /* Retrieve the sample threshold number th for a given temperature */ -- ret = stm_thermal_calculate_threshold(sensor, sensor->high_temp, &th); -- if (ret) -- return ret; -- -- value |= th & TS1_LITTHD_MASK; -- -- if (sensor->low_temp_enabled) { -- /* Retrieve the sample threshold */ -- ret = stm_thermal_calculate_threshold(sensor, sensor->low_temp, -- &th); -- if (ret) -- return ret; -- -- value |= (TS1_HITTHD_MASK & (th << TS1_HITTHD_POS)); -- } -- -- /* Write value on the Low interrupt threshold */ -- writel_relaxed(value, sensor->base + DTS_ITR1_OFFSET); -+ dev_dbg(sensor->dev, "freqM=%d Hz, threshold=0x%x", freqM, *th); - - return 0; - } -@@ -326,12 +263,10 @@ static int stm_disable_irq(struct stm_thermal_sensor *sensor) - { - u32 value; - -- /* Disable IT generation for low and high thresholds */ -+ /* Disable IT generation */ - value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET); -- writel_relaxed(value & ~(LOW_THRESHOLD | HIGH_THRESHOLD), -- sensor->base + DTS_ITENR_OFFSET); -- -- dev_dbg(sensor->dev, "%s: IT disabled on sensor side", __func__); -+ value &= ~ITENR_MASK; -+ writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET); - - return 0; - } -@@ -341,62 +276,68 @@ static int stm_enable_irq(struct stm_thermal_sensor *sensor) - { - u32 value; - -- /* -- * Code below enables High temperature threshold using a low threshold -- * sampling value -- */ -- -- /* Make sure LOW_THRESHOLD IT is clear before enabling */ -- writel_relaxed(LOW_THRESHOLD, sensor->base + DTS_CIFR_OFFSET); -+ dev_dbg(sensor->dev, "low:%d high:%d\n", sensor->low_temp_enabled, -+ sensor->high_temp_enabled); - -- /* Enable IT generation for low threshold */ -+ /* Disable IT generation for low and high thresholds */ - value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET); -- value |= LOW_THRESHOLD; -- -- /* Enable the low temperature threshold if needed */ -- if (sensor->low_temp_enabled) { -- /* Make sure HIGH_THRESHOLD IT is clear before enabling */ -- writel_relaxed(HIGH_THRESHOLD, sensor->base + DTS_CIFR_OFFSET); -+ value &= ~(LOW_THRESHOLD | HIGH_THRESHOLD); - -- /* Enable IT generation for high threshold */ -+ if (sensor->low_temp_enabled) - value |= HIGH_THRESHOLD; -- } - -- /* Enable thresholds */ -- writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET); -+ if (sensor->high_temp_enabled) -+ value |= LOW_THRESHOLD; - -- dev_dbg(sensor->dev, "%s: IT enabled on sensor side", __func__); -+ /* Enable interrupts */ -+ writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET); - - return 0; - } - --static int stm_thermal_update_threshold(struct stm_thermal_sensor *sensor) -+static int stm_thermal_set_trips(void *data, int low, int high) - { -+ struct stm_thermal_sensor *sensor = data; -+ u32 itr1, th; - int ret; - -- sensor->mode = THERMAL_DEVICE_DISABLED; -+ dev_dbg(sensor->dev, "set trips %d <--> %d\n", low, high); - -- ret = stm_sensor_power_off(sensor); -- if (ret) -- return ret; -+ /* Erase threshold content */ -+ itr1 = readl_relaxed(sensor->base + DTS_ITR1_OFFSET); -+ itr1 &= ~(TS1_LITTHD_MASK | TS1_HITTHD_MASK); - -- ret = stm_disable_irq(sensor); -- if (ret) -- return ret; -+ /* -+ * Disable low-temp if "low" is too small. As per thermal framework -+ * API, we use -INT_MAX rather than INT_MIN. -+ */ - -- ret = stm_thermal_set_threshold(sensor); -- if (ret) -- return ret; -+ if (low > -INT_MAX) { -+ sensor->low_temp_enabled = 1; -+ /* add 0.5 of hysteresis due to measurement error */ -+ ret = stm_thermal_calculate_threshold(sensor, low - 500, &th); -+ if (ret) -+ return ret; - -- ret = stm_enable_irq(sensor); -- if (ret) -- return ret; -+ itr1 |= (TS1_HITTHD_MASK & (th << TS1_HITTHD_POS)); -+ } else { -+ sensor->low_temp_enabled = 0; -+ } - -- ret = stm_sensor_power_on(sensor); -- if (ret) -- return ret; -+ /* Disable high-temp if "high" is too big. */ -+ if (high < INT_MAX) { -+ sensor->high_temp_enabled = 1; -+ ret = stm_thermal_calculate_threshold(sensor, high, &th); -+ if (ret) -+ return ret; - -- sensor->mode = THERMAL_DEVICE_ENABLED; -+ itr1 |= (TS1_LITTHD_MASK & (th << TS1_LITTHD_POS)); -+ } else { -+ sensor->high_temp_enabled = 0; -+ } -+ -+ /* Write new threshod values*/ -+ writel_relaxed(itr1, sensor->base + DTS_ITR1_OFFSET); - - return 0; - } -@@ -405,76 +346,26 @@ static int stm_thermal_update_threshold(struct stm_thermal_sensor *sensor) - static int stm_thermal_get_temp(void *data, int *temp) - { - struct stm_thermal_sensor *sensor = data; -- u32 sampling_time; -+ u32 periods; - int freqM, ret; - - if (sensor->mode != THERMAL_DEVICE_ENABLED) - return -EAGAIN; - -- /* Retrieve the number of samples */ -- ret = readl_poll_timeout(sensor->base + DTS_DR_OFFSET, freqM, -- (freqM & TS1_MFREQ_MASK), STARTUP_TIME, -- POLL_TIMEOUT); -- -+ /* Retrieve the number of periods sampled */ -+ ret = readl_relaxed_poll_timeout(sensor->base + DTS_DR_OFFSET, periods, -+ (periods & TS1_MFREQ_MASK), -+ STARTUP_TIME, POLL_TIMEOUT); - if (ret) - return ret; - -- if (!freqM) -- return -ENODATA; -- -- /* Retrieve the number of periods sampled */ -- sampling_time = (readl_relaxed(sensor->base + DTS_CFGR1_OFFSET) & -- TS1_SMP_TIME_MASK) >> TS1_SMP_TIME_POS; -- -- /* Figure out the number of samples per period */ -- freqM /= sampling_time; -- - /* Figure out the CLK_PTAT frequency */ -- freqM = clk_get_rate(sensor->clk) / freqM; -+ freqM = (clk_get_rate(sensor->clk) * SAMPLING_TIME) / periods; - if (!freqM) - return -EINVAL; - -- dev_dbg(sensor->dev, "%s: freqM=%d\n", __func__, freqM); -- /* Figure out the temperature in mili celsius */ -- *temp = mcelsius(sensor->t0 + ((freqM - sensor->fmt0) / -- sensor->ramp_coeff)); -- -- dev_dbg(sensor->dev, "%s: temperature = %d millicelsius", -- __func__, *temp); -- -- /* Update thresholds */ -- if (sensor->num_trips > 1) { -- /* Update alarm threshold value to next higher trip point */ -- if (sensor->high_temp == sensor->temp_passive && -- celsius(*temp) >= sensor->temp_passive) { -- sensor->high_temp = sensor->temp_critical; -- sensor->low_temp = sensor->temp_passive; -- sensor->low_temp_enabled = true; -- ret = stm_thermal_update_threshold(sensor); -- if (ret) -- return ret; -- } -- -- if (sensor->high_temp == sensor->temp_critical && -- celsius(*temp) < sensor->temp_passive) { -- sensor->high_temp = sensor->temp_passive; -- sensor->low_temp_enabled = false; -- ret = stm_thermal_update_threshold(sensor); -- if (ret) -- return ret; -- } -- -- /* -- * Re-enable alarm IRQ if temperature below critical -- * temperature -- */ -- if (!sensor->irq_enabled && -- (celsius(*temp) < sensor->temp_critical)) { -- sensor->irq_enabled = true; -- enable_irq(sensor->irq); -- } -- } +- *temp = (freqM - sensor->fmt0) * 1000 / sensor->ramp_coeff + sensor->t0; + *temp = (freqM - sensor->fmt0) * 1000 / sensor->ramp_coeff + T0; return 0; } -@@ -493,7 +384,7 @@ static int stm_register_irq(struct stm_thermal_sensor *sensor) - } - - ret = devm_request_threaded_irq(dev, sensor->irq, -- stm_thermal_alarm_irq, -+ NULL, - stm_thermal_alarm_irq_thread, - IRQF_ONESHOT, - dev->driver->name, sensor); -@@ -503,8 +394,6 @@ static int stm_register_irq(struct stm_thermal_sensor *sensor) - return ret; - } - -- sensor->irq_enabled = true; -- - dev_dbg(dev, "%s: thermal IRQ registered", __func__); - - return 0; -@@ -514,6 +403,8 @@ static int stm_thermal_sensor_off(struct stm_thermal_sensor *sensor) - { - int ret; - -+ stm_disable_irq(sensor); -+ - ret = stm_sensor_power_off(sensor); - if (ret) - return ret; -@@ -526,7 +417,6 @@ static int stm_thermal_sensor_off(struct stm_thermal_sensor *sensor) - static int stm_thermal_prepare(struct stm_thermal_sensor *sensor) - { - int ret; -- struct device *dev = sensor->dev; - - ret = clk_prepare_enable(sensor->clk); - if (ret) -@@ -540,26 +430,8 @@ static int stm_thermal_prepare(struct stm_thermal_sensor *sensor) - if (ret) - goto thermal_unprepare; - -- /* Set threshold(s) for IRQ */ -- ret = stm_thermal_set_threshold(sensor); -- if (ret) -- goto thermal_unprepare; -- -- ret = stm_enable_irq(sensor); -- if (ret) -- goto thermal_unprepare; -- -- ret = stm_sensor_power_on(sensor); -- if (ret) { -- dev_err(dev, "%s: failed to power on sensor\n", __func__); -- goto irq_disable; -- } -- - return 0; - --irq_disable: -- stm_disable_irq(sensor); -- - thermal_unprepare: - clk_disable_unprepare(sensor->clk); - -@@ -576,8 +448,6 @@ static int stm_thermal_suspend(struct device *dev) - if (ret) - return ret; - -- sensor->mode = THERMAL_DEVICE_DISABLED; -- - return 0; - } - -@@ -590,7 +460,12 @@ static int stm_thermal_resume(struct device *dev) - if (ret) - return ret; - -- sensor->mode = THERMAL_DEVICE_ENABLED; -+ ret = stm_sensor_power_on(sensor); -+ if (ret) -+ return ret; -+ -+ thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED); -+ stm_enable_irq(sensor); - - return 0; - } -@@ -600,6 +475,7 @@ SIMPLE_DEV_PM_OPS(stm_thermal_pm_ops, stm_thermal_suspend, stm_thermal_resume); - - static const struct thermal_zone_of_device_ops stm_tz_ops = { - .get_temp = stm_thermal_get_temp, -+ .set_trips = stm_thermal_set_trips, - }; - - static const struct of_device_id stm_thermal_of_match[] = { -@@ -612,9 +488,8 @@ static int stm_thermal_probe(struct platform_device *pdev) - { - struct stm_thermal_sensor *sensor; - struct resource *res; -- const struct thermal_trip *trip; - void __iomem *base; -- int ret, i; -+ int ret; - - if (!pdev->dev.of_node) { - dev_err(&pdev->dev, "%s: device tree node not found\n", -@@ -640,15 +515,28 @@ static int stm_thermal_probe(struct platform_device *pdev) +@@ -515,11 +505,9 @@ static int stm_thermal_probe(struct platform_device *pdev) + sensor->base = base; sensor->clk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(sensor->clk)) { +- if (IS_ERR(sensor->clk)) { - dev_err(&pdev->dev, "%s: failed to fetch PCLK clock\n", - __func__); -+ if (PTR_ERR(sensor->clk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Failed to get PCLK clock\n"); - return PTR_ERR(sensor->clk); - } - -- /* Register IRQ into GIC */ -- ret = stm_register_irq(sensor); -- if (ret) -+ stm_disable_irq(sensor); -+ -+ /* Clear irq flags */ -+ writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET); -+ -+ /* Configure and enable HW sensor */ -+ ret = stm_thermal_prepare(sensor); -+ if (ret) { -+ dev_err(&pdev->dev, "Error preprare sensor: %d\n", ret); - return ret; -+ } -+ -+ ret = stm_sensor_power_on(sensor); -+ if (ret) { -+ dev_err(&pdev->dev, "Error power on sensor: %d\n", ret); -+ return ret; -+ } - - sensor->th_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, - sensor, -@@ -661,53 +549,12 @@ static int stm_thermal_probe(struct platform_device *pdev) - return ret; - } - -- if (!sensor->th_dev->ops->get_crit_temp) { -- /* Critical point must be provided */ -- ret = -EINVAL; -- goto err_tz; +- return PTR_ERR(sensor->clk); - } -- -- ret = sensor->th_dev->ops->get_crit_temp(sensor->th_dev, -- &sensor->temp_critical); -- if (ret) { -- dev_err(&pdev->dev, -- "Not able to read critical_temp: %d\n", ret); -+ /* Register IRQ into GIC */ -+ ret = stm_register_irq(sensor); -+ if (ret) - goto err_tz; -- } -- -- sensor->temp_critical = celsius(sensor->temp_critical); -- -- /* Set thresholds for IRQ */ -- sensor->high_temp = sensor->temp_critical; -- -- trip = of_thermal_get_trip_points(sensor->th_dev); -- sensor->num_trips = of_thermal_get_ntrips(sensor->th_dev); -- -- /* Find out passive temperature if it exists */ -- for (i = (sensor->num_trips - 1); i >= 0; i--) { -- if (trip[i].type == THERMAL_TRIP_PASSIVE) { -- sensor->temp_passive = celsius(trip[i].temperature); -- /* Update high temperature threshold */ -- sensor->high_temp = sensor->temp_passive; -- } -- } -- -- /* -- * Ensure low_temp_enabled flag is disabled. -- * By disabling low_temp_enabled, low threshold IT will not be -- * configured neither enabled because it is not needed as high -- * threshold is set on the lowest temperature trip point after -- * probe. -- */ -- sensor->low_temp_enabled = false; ++ if (IS_ERR(sensor->clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(sensor->clk), ++ "Failed to get PCLK clock\n"); -- /* Configure and enable HW sensor */ -- ret = stm_thermal_prepare(sensor); -- if (ret) { -- dev_err(&pdev->dev, -- "Not able to enable sensor: %d\n", ret); -- goto err_tz; -- } -+ stm_enable_irq(sensor); - - /* - * Thermal_zone doesn't enable hwmon as default, -@@ -718,8 +565,6 @@ static int stm_thermal_probe(struct platform_device *pdev) - if (ret) - goto err_tz; - -- sensor->mode = THERMAL_DEVICE_ENABLED; -- - dev_info(&pdev->dev, "%s: Driver initialized successfully\n", - __func__); + stm_disable_irq(sensor); diff --git a/include/dt-bindings/soc/stm32-hdp.h b/include/dt-bindings/soc/stm32-hdp.h new file mode 100644 -index 0000000000000..d98665327281b +index 000000000000..d98665327281 --- /dev/null +++ b/include/dt-bindings/soc/stm32-hdp.h @@ -0,0 +1,108 @@ @@ -1826,10 +1328,10 @@ index 0000000000000..d98665327281b + +#endif /* _DT_BINDINGS_STM32_HDP_H */ diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h -index f6a7bcd131977..c3dd47f14c1ac 100644 +index ed0840f3d5df..598822e23e9e 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h -@@ -50,11 +50,13 @@ struct v4l2_fwnode_bus_mipi_csi2 { +@@ -49,11 +49,13 @@ struct v4l2_fwnode_bus_mipi_csi2 { * @flags: media bus (V4L2_MBUS_*) flags * @bus_width: bus width in bits * @data_shift: data shift in bits diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0011-ARM-5.10.10-stm32mp1-r1-MFD.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0011-ARM-5.10.10-stm32mp1-r1-MFD.patch new file mode 100644 index 0000000..9005095 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0011-ARM-5.10.10-stm32mp1-r1-MFD.patch @@ -0,0 +1,532 @@ +From 55dcc42c73d9d2c733972cd89bbbbb6d75b7d942 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:12:12 +0100 +Subject: [PATCH 11/22] ARM 5.10.10-stm32mp1-r1 MFD + +Signed-off-by: Romuald JEANNE +--- + drivers/mfd/Kconfig | 10 + + drivers/mfd/Makefile | 1 + + drivers/mfd/stm32-pwr.c | 402 +++++++++++++++++++++++++++++++ + drivers/mfd/stmfx.c | 2 - + drivers/mfd/stpmic1.c | 6 + + drivers/mfd/wm8994-core.c | 6 + + include/linux/mfd/stm32-timers.h | 1 + + 7 files changed, 426 insertions(+), 2 deletions(-) + create mode 100644 drivers/mfd/stm32-pwr.c + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 4789507f325b..2917b4466f74 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -2052,6 +2052,16 @@ config MFD_STPMIC1 + To compile this driver as a module, choose M here: the + module will be called stpmic1. + ++config MFD_STM32MP1_PWR ++ bool "STM32MP1 wake-up pins" ++ depends on MACH_STM32MP157 ++ default y ++ help ++ Select this option to enable STM32 PWR Wake-up pins driver. ++ ++ This driver provides interruptions that can be used to wake-up from ++ suspend. ++ + config MFD_STMFX + tristate "Support for STMicroelectronics Multi-Function eXpander (STMFX)" + depends on I2C +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 1780019d2474..90ffa501ae2d 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -255,6 +255,7 @@ obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o + + obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o + obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o ++obj-$(CONFIG_MFD_STM32MP1_PWR) += stm32-pwr.o + obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o + obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o + obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o +diff --git a/drivers/mfd/stm32-pwr.c b/drivers/mfd/stm32-pwr.c +new file mode 100644 +index 000000000000..5c130603d554 +--- /dev/null ++++ b/drivers/mfd/stm32-pwr.c +@@ -0,0 +1,402 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Pascal Paillet for STMicroelectronics. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NB_WAKEUPPINS 6 ++ ++#define STM32_SVC_PWR 0x82001001 ++#define STM32_WRITE 0x1 ++#define STM32_SET_BITS 0x2 ++#define STM32_CLEAR_BITS 0x3 ++ ++#define PWR_WKUP_OFFSET 0x20 ++// PWR Registers ++#define WKUPCR 0x0 ++#define WKUPFR 0x4 ++#define MPUWKUPENR 0x8 ++ ++#define WKUP_FLAGS_MASK GENMASK(5, 0) ++ ++// WKUPCR bits definition ++#define WKUP_EDGE_SHIFT 8 ++#define WKUP_PULL_SHIFT 16 ++#define WKUP_PULL_MASK GENMASK(1, 0) ++ ++enum wkup_pull_setting { ++ WKUP_NO_PULL = 0, ++ WKUP_PULL_UP, ++ WKUP_PULL_DOWN, ++ WKUP_PULL_RESERVED ++}; ++ ++#define SMC(class, op, offset, val) do { \ ++ struct arm_smccc_res res; \ ++ arm_smccc_smc(class, op, PWR_WKUP_OFFSET + (offset), val, \ ++ 0, 0, 0, 0, &res); \ ++} while (0) \ ++ ++struct stm32_pwr_data { ++ struct device *dev; ++ void __iomem *base; /* IO Memory base address */ ++ struct irq_domain *domain; /* Domain for this controller */ ++ int irq; /* Parent interrupt */ ++ u32 masked; /* IRQ is masked */ ++ u32 wake; /* IRQ is wake on */ ++ u32 pending; /* IRQ has been received while wake on*/ ++ struct gpio_desc *gpio[NB_WAKEUPPINS]; ++}; ++ ++static void stm32_pwr_irq_ack(struct irq_data *d) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ ++ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); ++ SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, BIT(d->hwirq)); ++} ++ ++static void stm32_pwr_irq_set_enable(struct irq_data *d) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ ++ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); ++ if (!(priv->masked & BIT(d->hwirq)) || (priv->wake & BIT(d->hwirq))) ++ SMC(STM32_SVC_PWR, STM32_SET_BITS, MPUWKUPENR, BIT(d->hwirq)); ++ else ++ SMC(STM32_SVC_PWR, STM32_CLEAR_BITS, MPUWKUPENR, BIT(d->hwirq)); ++} ++ ++static void stm32_pwr_irq_mask(struct irq_data *d) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ ++ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); ++ priv->masked |= BIT(d->hwirq); ++ stm32_pwr_irq_set_enable(d); ++} ++ ++static void stm32_pwr_irq_unmask(struct irq_data *d) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ ++ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); ++ priv->masked &= ~BIT(d->hwirq); ++ stm32_pwr_irq_set_enable(d); ++} ++ ++static int stm32_pwr_irq_set_wake(struct irq_data *d, unsigned int on) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ struct irq_data *parent = irq_get_irq_data(priv->irq); ++ ++ dev_dbg(priv->dev, "irq:%lu on:%d\n", d->hwirq, on); ++ if (on) { ++ priv->wake |= BIT(d->hwirq); ++ } else { ++ priv->wake &= ~BIT(d->hwirq); ++ priv->pending &= ~BIT(d->hwirq); ++ } ++ stm32_pwr_irq_set_enable(d); ++ ++ if (parent->chip && parent->chip->irq_set_wake) ++ return parent->chip->irq_set_wake(parent, on); ++ ++ return 0; ++} ++ ++static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ int pin_id = d->hwirq; ++ u32 wkupcr; ++ int en; ++ ++ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); ++ ++ en = readl_relaxed(priv->base + MPUWKUPENR) & BIT(pin_id); ++ /* reference manual request to disable the wakeup pin while ++ * changing the edge detection setting ++ */ ++ if (en) ++ stm32_pwr_irq_mask(d); ++ ++ wkupcr = readl_relaxed(priv->base + WKUPCR); ++ switch (flow_type & IRQ_TYPE_SENSE_MASK) { ++ case IRQF_TRIGGER_FALLING: ++ wkupcr |= (1 << (WKUP_EDGE_SHIFT + pin_id)); ++ break; ++ case IRQF_TRIGGER_RISING: ++ wkupcr &= ~(1 << (WKUP_EDGE_SHIFT + pin_id)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr); ++ ++ if (en) ++ stm32_pwr_irq_unmask(d); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SMP ++static int stm32_pwr_set_affinity_parent(struct irq_data *data, ++ const struct cpumask *dest, bool force) ++{ ++ struct stm32_pwr_data *priv = data->domain->host_data; ++ struct irq_data *parent = irq_get_irq_data(priv->irq); ++ ++ irq_data_update_effective_affinity(data, dest); ++ ++ if (parent->chip && parent->chip->irq_set_affinity) ++ return parent->chip->irq_set_affinity(parent, dest, force); ++ ++ return IRQ_SET_MASK_OK_DONE; ++} ++#endif ++ ++static int stm32_pwr_irq_request_resources(struct irq_data *d) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ struct gpio_desc *gpio; ++ int ret; ++ ++ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); ++ gpio = gpiod_get_index(priv->dev, "wakeup", d->hwirq, GPIOD_IN); ++ if (IS_ERR(gpio)) { ++ ret = PTR_ERR(gpio); ++ dev_err(priv->dev, "Failed to get wakeup gpio: %d", ret); ++ return ret; ++ } ++ priv->gpio[d->hwirq] = gpio; ++ return 0; ++} ++ ++static void stm32_pwr_irq_release_resources(struct irq_data *d) ++{ ++ struct stm32_pwr_data *priv = d->domain->host_data; ++ ++ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); ++ gpiod_put(priv->gpio[d->hwirq]); ++} ++ ++static struct irq_chip stm32_pwr_irq_chip = { ++ .name = "stm32-pwr-irq", ++ .irq_ack = stm32_pwr_irq_ack, ++ .irq_mask = stm32_pwr_irq_mask, ++ .irq_unmask = stm32_pwr_irq_unmask, ++ .irq_set_type = stm32_pwr_irq_set_type, ++ .irq_set_wake = stm32_pwr_irq_set_wake, ++ .irq_request_resources = stm32_pwr_irq_request_resources, ++ .irq_release_resources = stm32_pwr_irq_release_resources, ++#ifdef CONFIG_SMP ++ .irq_set_affinity = stm32_pwr_set_affinity_parent, ++#endif ++}; ++ ++static int stm32_pwr_irq_set_pull_config(struct irq_domain *d, int pin_id, ++ enum wkup_pull_setting config) ++{ ++ struct stm32_pwr_data *priv = d->host_data; ++ u32 wkupcr; ++ ++ dev_dbg(priv->dev, "irq:%d pull config:0x%x\n", pin_id, config); ++ ++ if (config >= WKUP_PULL_RESERVED) { ++ pr_err("%s: bad irq pull config\n", __func__); ++ return -EINVAL; ++ } ++ ++ wkupcr = readl_relaxed(priv->base + WKUPCR); ++ wkupcr &= ~((WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2)); ++ wkupcr |= (config & WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2); ++ ++ SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr); ++ ++ return 0; ++} ++ ++static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr, ++ const u32 *intspec, unsigned int intsize, ++ irq_hw_number_t *out_hwirq, unsigned int *out_type) ++{ ++ if (WARN_ON(intsize < 3)) { ++ pr_err("%s: bad irq config parameters\n", __func__); ++ return -EINVAL; ++ } ++ ++ *out_hwirq = intspec[0]; ++ *out_type = intspec[1] & (IRQ_TYPE_SENSE_MASK); ++ ++ return stm32_pwr_irq_set_pull_config(d, intspec[0], intspec[2]); ++} ++ ++static int stm32_pwr_alloc(struct irq_domain *d, unsigned int virq, ++ unsigned int nr_irqs, void *data) ++{ ++ struct irq_fwspec *fwspec = data; ++ irq_hw_number_t hwirq; ++ ++ hwirq = fwspec->param[0]; ++ irq_domain_set_info(d, virq, hwirq, &stm32_pwr_irq_chip, d->host_data, ++ handle_edge_irq, NULL, NULL); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops stm32_pwr_irq_domain_ops = { ++ .alloc = stm32_pwr_alloc, ++ .xlate = stm32_pwr_xlate, ++ .free = irq_domain_free_irqs_common, ++}; ++ ++/* ++ * Handler for the cascaded IRQ. ++ */ ++static void stm32_pwr_handle_irq(struct irq_desc *desc) ++{ ++ struct stm32_pwr_data *priv = irq_desc_get_handler_data(desc); ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ u32 wkupfr, wkupenr, i; ++ ++ chained_irq_enter(chip, desc); ++ ++ wkupfr = readl_relaxed(priv->base + WKUPFR); ++ wkupenr = readl_relaxed(priv->base + MPUWKUPENR); ++ ++ for (i = 0; i < NB_WAKEUPPINS; i++) { ++ if ((wkupfr & BIT(i)) && (wkupenr & BIT(i))) { ++ struct irq_desc *d; ++ ++ d = irq_to_desc(irq_find_mapping(priv->domain, i)); ++ ++ if (priv->wake & BIT(i)) { ++ dev_dbg(priv->dev, ++ "irq %d while wake enabled\n", i); ++ priv->pending |= BIT(i); ++ } ++ ++ dev_dbg(priv->dev, "handle wkup irq:%d\n", i); ++ handle_edge_irq(d); ++ } ++ } ++ chained_irq_exit(chip, desc); ++} ++ ++static int __maybe_unused stm32_pwr_suspend(struct device *dev) ++{ ++ struct stm32_pwr_data *priv = dev_get_drvdata(dev); ++ ++ pr_debug("suspend"); ++ if (priv->pending != 0) ++ return -EBUSY; ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops stm32_pwr_pm = { ++ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_pwr_suspend, NULL) ++}; ++ ++static int stm32_pwr_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct stm32_pwr_data *priv; ++ struct device_node *np = dev->of_node; ++ struct resource *res; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ priv->dev = dev; ++ dev_set_drvdata(dev, priv); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->base)) { ++ dev_err(dev, "Unable to map registers\n"); ++ return PTR_ERR(priv->base); ++ } ++ ++ /* Disable all wake-up pins */ ++ SMC(STM32_SVC_PWR, STM32_WRITE, MPUWKUPENR, 0); ++ /* Clear all interrupts flags */ ++ SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, WKUP_FLAGS_MASK); ++ ++ priv->domain = irq_domain_add_linear(np, NB_WAKEUPPINS, ++ &stm32_pwr_irq_domain_ops, priv); ++ if (!priv->domain) { ++ dev_err(dev, "%s: Unable to add irq domain!\n", __func__); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = irq_of_parse_and_map(np, 0); ++ if (ret < 0) { ++ dev_err(dev, "failed to get PWR IRQ\n"); ++ ret = priv->irq; ++ goto out_domain; ++ } ++ ++ priv->irq = ret; ++ irq_set_chained_handler_and_data(priv->irq, stm32_pwr_handle_irq, priv); ++ ++ of_node_clear_flag(np, OF_POPULATED); ++ ++ return 0; ++ ++out_domain: ++ irq_domain_remove(priv->domain); ++out: ++ return ret; ++} ++ ++static int stm32_pwr_remove(struct platform_device *pdev) ++{ ++ struct stm32_pwr_data *priv = dev_get_drvdata(&pdev->dev); ++ ++ irq_domain_remove(priv->domain); ++ return 0; ++} ++ ++static const struct of_device_id stm32_pwr_ids[] = { ++ { .compatible = "st,stm32mp1-pwr", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, stm32_pwr_ids); ++ ++static struct platform_driver stm32_pwr_driver = { ++ .probe = stm32_pwr_probe, ++ .remove = stm32_pwr_remove, ++ .driver = { ++ .name = "stm32_pwr", ++ .of_match_table = stm32_pwr_ids, ++ .pm = &stm32_pwr_pm, ++ }, ++}; ++ ++static int __init stm32_pwr_init(void) ++{ ++ return platform_driver_register(&stm32_pwr_driver); ++} ++ ++static void __exit stm32_pwr_exit(void) ++{ ++ return platform_driver_unregister(&stm32_pwr_driver); ++} ++ ++arch_initcall(stm32_pwr_init); ++module_exit(stm32_pwr_exit); +diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c +index 988e2ba6dd0f..39b2fc952b7d 100644 +--- a/drivers/mfd/stmfx.c ++++ b/drivers/mfd/stmfx.c +@@ -81,13 +81,11 @@ static struct mfd_cell stmfx_cells[] = { + .num_resources = ARRAY_SIZE(stmfx_pinctrl_resources), + }, + { +- .of_compatible = "st,stmfx-0300-idd", + .name = "stmfx-idd", + .resources = stmfx_idd_resources, + .num_resources = ARRAY_SIZE(stmfx_idd_resources), + }, + { +- .of_compatible = "st,stmfx-0300-ts", + .name = "stmfx-ts", + .resources = stmfx_ts_resources, + .num_resources = ARRAY_SIZE(stmfx_ts_resources), +diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c +index eb3da558c3fb..40eef5d18b90 100644 +--- a/drivers/mfd/stpmic1.c ++++ b/drivers/mfd/stpmic1.c +@@ -170,6 +170,9 @@ static int stpmic1_suspend(struct device *dev) + + disable_irq(pmic_dev->irq); + ++ if (device_may_wakeup(dev)) ++ enable_irq_wake(pmic_dev->irq); ++ + return 0; + } + +@@ -183,6 +186,9 @@ static int stpmic1_resume(struct device *dev) + if (ret) + return ret; + ++ if (device_may_wakeup(dev)) ++ disable_irq_wake(pmic_dev->irq); ++ + enable_irq(pmic_dev->irq); + + return 0; +diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c +index 3b2b93c5bbcb..507572b091ab 100644 +--- a/drivers/mfd/wm8994-core.c ++++ b/drivers/mfd/wm8994-core.c +@@ -185,6 +185,12 @@ static int wm8994_resume(struct device *dev) + if (!wm8994->suspended) + return 0; + ++ /* ++ * LDO1/2 minimum cycle time is 36ms according to codec specification ++ * Wait before enabling regulator to make sure we fit this requirement ++ */ ++ msleep(40); ++ + ret = regulator_bulk_enable(wm8994->num_supplies, + wm8994->supplies); + if (ret != 0) { +diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h +index f8db83aedb2b..f48f04dc4187 100644 +--- a/include/linux/mfd/stm32-timers.h ++++ b/include/linux/mfd/stm32-timers.h +@@ -31,6 +31,7 @@ + #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_DIR BIT(4) /* Counter Direction */ +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0012-ARM-5.10.10-stm32mp1-r1-MMC.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0012-ARM-5.10.10-stm32mp1-r1-MMC.patch new file mode 100644 index 0000000..a544c1d --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0012-ARM-5.10.10-stm32mp1-r1-MMC.patch @@ -0,0 +1,62 @@ +From 83c3a690670bb23a4a1fb645cf980056b4f85f4d Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:12:53 +0100 +Subject: [PATCH 12/22] ARM 5.10.10-stm32mp1-r1 MMC + +--- + drivers/mmc/core/mmc_test.c | 2 +- + drivers/mmc/host/mmci.c | 13 +++++++++---- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c +index 152e7525ed33..b1f0d04f9430 100644 +--- a/drivers/mmc/core/mmc_test.c ++++ b/drivers/mmc/core/mmc_test.c +@@ -2124,7 +2124,7 @@ static int mmc_test_rw_multiple(struct mmc_test_card *test, + if (mmc_can_erase(test->card) && + tdata->prepare & MMC_TEST_PREP_ERASE) { + ret = mmc_erase(test->card, dev_addr, +- size / 512, MMC_SECURE_ERASE_ARG); ++ size / 512, test->card->erase_arg); + if (ret) + ret = mmc_erase(test->card, dev_addr, + size / 512, MMC_ERASE_ARG); +diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c +index b5a41a7ce165..fa6d85190cdb 100644 +--- a/drivers/mmc/host/mmci.c ++++ b/drivers/mmc/host/mmci.c +@@ -1241,7 +1241,11 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) + if (!cmd->busy_timeout) + cmd->busy_timeout = 10 * MSEC_PER_SEC; + +- clks = (unsigned long long)cmd->busy_timeout * host->cclk; ++ if (cmd->busy_timeout > host->mmc->max_busy_timeout) ++ clks = (unsigned long long)host->mmc->max_busy_timeout * host->cclk; ++ else ++ clks = (unsigned long long)cmd->busy_timeout * host->cclk; ++ + do_div(clks, MSEC_PER_SEC); + writel_relaxed(clks, host->base + MMCIDATATIMER); + } +@@ -2091,14 +2095,15 @@ static int mmci_probe(struct amba_device *dev, + mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; + } + ++ /* Variants with mandatory busy timeout in HW needs R1B responses. */ ++ if (variant->busy_timeout) ++ mmc->caps |= MMC_CAP_NEED_RSP_BUSY; ++ + /* Prepare a CMD12 - needed to clear the DPSM on some variants. */ + host->stop_abort.opcode = MMC_STOP_TRANSMISSION; + host->stop_abort.arg = 0; + host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC; + +- /* We support these PM capabilities. */ +- mmc->pm_caps |= MMC_PM_KEEP_POWER; +- + /* + * We can do SGIO + */ +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0015-ARM-stm32mp1-r2-NET-TTY.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0013-ARM-5.10.10-stm32mp1-r1-NET-TTY.patch similarity index 81% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0015-ARM-stm32mp1-r2-NET-TTY.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0013-ARM-5.10.10-stm32mp1-r1-NET-TTY.patch index 60b9f51..5bdb79e 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0015-ARM-stm32mp1-r2-NET-TTY.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0013-ARM-5.10.10-stm32mp1-r1-NET-TTY.patch @@ -1,129 +1,51 @@ -From e7d39044a73d9ca89178dad8abd1477c31e4a163 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:48 +0200 -Subject: [PATCH 15/22] ARM-stm32mp1-r2-rc8-NET-TTY +From 480758c596f5d02d795cb5896c5280a6787b72d2 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:13:39 +0100 +Subject: [PATCH 13/22] ARM 5.10.10-stm32mp1-r1 NET-TTY +Signed-off-by: Romuald JEANNE --- - .../net/ethernet/stmicro/stmmac/dwmac-stm32.c | 98 +- - .../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 2 +- - .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 +- - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 29 +- - .../ethernet/stmicro/stmmac/stmmac_platform.c | 2 +- - drivers/net/phy/realtek.c | 5 + - .../broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 + - drivers/tty/serial/Kconfig | 1 + + .../net/ethernet/stmicro/stmmac/dwmac-stm32.c | 58 +- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 42 +- + drivers/net/phy/realtek.c | 13 +- drivers/tty/serial/serial_core.c | 10 + drivers/tty/serial/serial_mctrl_gpio.c | 38 + drivers/tty/serial/serial_mctrl_gpio.h | 18 + - drivers/tty/serial/stm32-usart.c | 1238 +++++++++++------ - drivers/tty/serial/stm32-usart.h | 30 +- + drivers/tty/serial/stm32-usart.c | 1250 +++++++++++------ + drivers/tty/serial/stm32-usart.h | 28 +- include/uapi/linux/serial.h | 2 + - 14 files changed, 1013 insertions(+), 468 deletions(-) + 9 files changed, 973 insertions(+), 486 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c -index 4ef041bdf6a1c..f67842bfcd5d3 100644 +index 5d4df4c5254e..ffaa434e075b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c -@@ -95,7 +95,6 @@ struct stm32_dwmac { - struct clk *syscfg_clk; +@@ -89,7 +89,6 @@ struct stm32_dwmac { + int enable_eth_ck; int eth_clk_sel_reg; int eth_ref_clk_sel_reg; - int irq_pwr_wakeup; u32 mode_reg; /* MAC glue-logic mode register */ struct regmap *regmap; u32 speed; -@@ -152,30 +151,39 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) - int ret = 0; - - if (prepare) { -- ret = clk_prepare_enable(dwmac->syscfg_clk); -- if (ret) -- return ret; -- -+ if (dwmac->syscfg_clk) { -+ ret = clk_prepare_enable(dwmac->syscfg_clk); -+ if (ret) -+ return ret; -+ } - if (dwmac->clk_eth_ck) { - ret = clk_prepare_enable(dwmac->clk_eth_ck); - if (ret) { -- clk_disable_unprepare(dwmac->syscfg_clk); -+ if (dwmac->syscfg_clk) -+ goto unprepare_syscfg; - return ret; - } - } - } else { -- clk_disable_unprepare(dwmac->syscfg_clk); -+ if (dwmac->syscfg_clk) -+ clk_disable_unprepare(dwmac->syscfg_clk); -+ - if (dwmac->clk_eth_ck) - clk_disable_unprepare(dwmac->clk_eth_ck); - } - return ret; -+ -+unprepare_syscfg: -+ clk_disable_unprepare(dwmac->syscfg_clk); -+ -+ return ret; - } - - static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) - { - struct stm32_dwmac *dwmac = plat_dat->bsp_priv; - u32 reg = dwmac->mode_reg; -- int val, ret; -+ int val; - - switch (plat_dat->interface) { - case PHY_INTERFACE_MODE_MII: -@@ -211,7 +219,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) - } - - /* Need to update PMCCLRR (clear register) */ -- ret = regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET, -+ regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET, - dwmac->ops->syscfg_eth_mask); - - /* Update PMCSETR (set register) */ -@@ -294,9 +302,8 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, +@@ -300,9 +299,7 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); struct device_node *np = dev->of_node; - int err = 0; -+ int err; - /* Gigabit Ethernet 125MHz clock selection. */ - dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel"); -@@ -308,7 +315,7 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, - /* Get ETH_CLK clocks */ - dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck"); - if (IS_ERR(dwmac->clk_eth_ck)) { -- dev_warn(dev, "No phy clock provided...\n"); -+ dev_info(dev, "No phy clock provided...\n"); - dwmac->clk_eth_ck = NULL; - } + /* Ethernet PHY have no crystal */ + dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); +@@ -334,29 +331,24 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, + if (IS_ERR(dwmac->syscfg_clk)) + dwmac->syscfg_clk = NULL; -@@ -320,38 +327,36 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, - return PTR_ERR(dwmac->clk_ethstp); - } - -- /* Clock for sysconfig */ -+ /* Optional Clock for sysconfig */ - dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk"); - if (IS_ERR(dwmac->syscfg_clk)) { -- dev_err(dev, "No syscfg clock provided...\n"); -- return PTR_ERR(dwmac->syscfg_clk); -- } -- - /* Get IRQ information early to have an ability to ask for deferred - * probe if needed before we went too far with resource allocation. - */ -- dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev, +- dwmac->irq_pwr_wakeup = platform_get_irq_byname_optional(pdev, - "stm32_pwr_wakeup"); - if (dwmac->irq_pwr_wakeup == -EPROBE_DEFER) - return -EPROBE_DEFER; @@ -132,9 +54,7 @@ index 4ef041bdf6a1c..f67842bfcd5d3 100644 - err = device_init_wakeup(&pdev->dev, true); - if (err) { - dev_err(&pdev->dev, "Failed to init wake up irq\n"); -+ err = PTR_ERR(dwmac->syscfg_clk); -+ if (err != -ENOENT) - return err; +- return err; - } - err = dev_pm_set_dedicated_wake_irq(&pdev->dev, - dwmac->irq_pwr_wakeup); @@ -143,13 +63,9 @@ index 4ef041bdf6a1c..f67842bfcd5d3 100644 - device_init_wakeup(&pdev->dev, false); - } - device_set_wakeup_enable(&pdev->dev, false); -+ dwmac->syscfg_clk = NULL; -+ err = 0; - } ++ return 0; ++} + - return err; - } - +static int stm32_dwmac_wake_init(struct device *dev, + struct stmmac_resources *stmmac_res) +{ @@ -162,15 +78,14 @@ index 4ef041bdf6a1c..f67842bfcd5d3 100644 + dev_err(dev, "Failed to set wake up irq\n"); + device_set_wakeup_capable(dev, false); + return err; -+ } + } +- return err; + + return 0; -+} -+ + } + static int stm32_dwmac_probe(struct platform_device *pdev) - { - struct plat_stmmacenet_data *plat_dat; -@@ -390,6 +395,12 @@ static int stm32_dwmac_probe(struct platform_device *pdev) +@@ -397,6 +389,12 @@ static int stm32_dwmac_probe(struct platform_device *pdev) goto err_remove_config_dt; } @@ -183,7 +98,7 @@ index 4ef041bdf6a1c..f67842bfcd5d3 100644 plat_dat->bsp_priv = dwmac; ret = stm32_dwmac_init(plat_dat); -@@ -415,14 +426,14 @@ static int stm32_dwmac_remove(struct platform_device *pdev) +@@ -422,14 +420,14 @@ static int stm32_dwmac_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); int ret = stmmac_dvr_remove(&pdev->dev); @@ -203,58 +118,41 @@ index 4ef041bdf6a1c..f67842bfcd5d3 100644 return ret; } -@@ -436,7 +447,8 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac) - return ret; - - clk_disable_unprepare(dwmac->clk_tx); -- clk_disable_unprepare(dwmac->syscfg_clk); -+ if (dwmac->syscfg_clk) -+ clk_disable_unprepare(dwmac->syscfg_clk); - if (dwmac->clk_eth_ck) - clk_disable_unprepare(dwmac->clk_eth_ck); - -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c -index f2a29a90e0854..2df6705cde6c8 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c -@@ -19,7 +19,7 @@ int dwmac4_dma_reset(void __iomem *ioaddr) - /* DMA SW reset */ - value |= DMA_BUS_MODE_SFT_RESET; - writel(value, ioaddr + DMA_BUS_MODE); -- limit = 10; -+ limit = 100; - while (limit--) { - if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)) - break; -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -index 1a768837ca728..43532e20749e8 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -@@ -706,7 +706,7 @@ static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv) - return 0; - } - -- return (riwt * 256) / (clk / 1000000); -+ return DIV_ROUND_UP(riwt * 256, clk / 1000000); - } - - static int stmmac_get_coalesce(struct net_device *dev, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -index 982be75fde833..3c99b960f660d 100644 +index b3d6d8e3f4de..9c69edc20751 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -4842,6 +4842,7 @@ int stmmac_resume(struct device *dev) - { - struct net_device *ndev = dev_get_drvdata(dev); - struct stmmac_priv *priv = netdev_priv(ndev); -+ int ret; +@@ -1533,18 +1533,18 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv, u32 queue) + stmmac_free_tx_buffer(priv, queue, i); + } - if (!netif_running(ndev)) - return 0; -@@ -4875,7 +4876,25 @@ int stmmac_resume(struct device *dev) +-/** ++/* + * stmmac_free_tx_skbufs - free TX skb buffers + * @priv: private structure + */ +-static void stmmac_free_tx_skbufs(struct stmmac_priv *priv) ++/*static void stmmac_free_tx_skbufs(struct stmmac_priv *priv) + { +- u32 tx_queue_cnt = priv->plat->tx_queues_to_use; +- u32 queue; ++ u32 tx_queue_cnt = priv->plat->tx_queues_to_use; ++ u32 queue; + +- for (queue = 0; queue < tx_queue_cnt; queue++) +- dma_free_tx_skbufs(priv, queue); +-} ++ for (queue = 0; queue < tx_queue_cnt; queue++) ++ dma_free_tx_skbufs(priv, queue); ++}*/ + + /** + * free_dma_rx_desc_resources - free RX dma desc resources +@@ -5289,8 +5289,25 @@ int stmmac_resume(struct device *dev) stmmac_reset_queues_param(priv); +- stmmac_free_tx_skbufs(priv); - stmmac_clear_descriptors(priv); + /* Stop TX/RX DMA and clear the descriptors */ + stmmac_stop_all_dma(priv); @@ -278,8 +176,8 @@ index 982be75fde833..3c99b960f660d 100644 stmmac_hw_setup(ndev, false); stmmac_init_coalesce(priv); -@@ -4896,6 +4915,14 @@ int stmmac_resume(struct device *dev) - phylink_mac_change(priv->phylink, true); +@@ -5308,6 +5325,13 @@ int stmmac_resume(struct device *dev) + netif_device_attach(ndev); return 0; +init_error: @@ -287,83 +185,61 @@ index 982be75fde833..3c99b960f660d 100644 +dma_desc_error: + if (ndev->phydev) + phy_disconnect(ndev->phydev); -+ mutex_unlock(&priv->lock); + + return -1; } EXPORT_SYMBOL_GPL(stmmac_resume); -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -index 508325cc105d5..e5d1ce84a3554 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -588,7 +588,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) - if (IS_ERR(plat->clk_ptp_ref)) { - plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk); - plat->clk_ptp_ref = NULL; -- dev_warn(&pdev->dev, "PTP uses main clock\n"); -+ dev_info(&pdev->dev, "PTP uses main clock\n"); - } else { - plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref); - dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate); diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c -index 879ca37c85081..fe26438500fcf 100644 +index 575580d3ffe0..a200019180de 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -175,6 +175,11 @@ static int rtl8211f_config_init(struct phy_device *phydev) - u16 val; +@@ -26,16 +26,11 @@ + #define RTL821x_EXT_PAGE_SELECT 0x1e + #define RTL821x_PAGE_SELECT 0x1f + +-#define RTL8211F_PHYCR1 0x18 + #define RTL8211F_INSR 0x1d + + #define RTL8211F_TX_DELAY BIT(8) + #define RTL8211F_RX_DELAY BIT(3) + +-#define RTL8211F_ALDPS_PLL_OFF BIT(1) +-#define RTL8211F_ALDPS_ENABLE BIT(2) +-#define RTL8211F_ALDPS_XTAL_OFF BIT(12) +- + #define RTL8211E_CTRL_DELAY BIT(13) + #define RTL8211E_TX_DELAY BIT(12) + #define RTL8211E_RX_DELAY BIT(11) +@@ -182,11 +177,12 @@ static int rtl8211f_config_init(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; + u16 val_txdly, val_rxdly; +- u16 val; int ret; +- val = RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_XTAL_OFF; +- phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, val, val); + /* Set green LED for Link, yellow LED for Active */ + phy_write(phydev, RTL821x_PAGE_SELECT, 0xd04); + phy_write(phydev, 0x10, 0x617f); + phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); -+ - /* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and - * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin. - */ -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -index fc12598b2dd3f..041a215aa13ed 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c -@@ -1128,7 +1128,10 @@ static int brcmf_ops_sdio_suspend(struct device *dev) - enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); - else - sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; -+ } else { -+ brcmf_sdiod_intr_unregister(sdiodev); - } -+ - if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags)) - brcmf_err("Failed to set pm_flags %x\n", sdio_flags); - return 0; -@@ -1144,6 +1147,9 @@ static int brcmf_ops_sdio_resume(struct device *dev) - if (func->num != 2) - return 0; -+ if (!sdiodev->wowl_enabled) -+ brcmf_sdiod_intr_register(sdiodev); -+ - brcmf_sdiod_freezer_off(sdiodev); - return 0; - } -diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig -index 67a9eb3f94cec..af3ebf79674fd 100644 ---- a/drivers/tty/serial/Kconfig -+++ b/drivers/tty/serial/Kconfig -@@ -1472,6 +1472,7 @@ config SERIAL_STM32 - tristate "STMicroelectronics STM32 serial port support" - select SERIAL_CORE - depends on ARCH_STM32 || COMPILE_TEST -+ select SERIAL_MCTRL_GPIO if GPIOLIB - help - This driver is for the on-chip Serial Controller on - STMicroelectronics STM32 MCUs. + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: +@@ -621,6 +617,7 @@ static struct phy_driver realtek_drvs[] = { + PHY_ID_MATCH_EXACT(0x001cc916), + .name = "RTL8211F Gigabit Ethernet", + .config_init = &rtl8211f_config_init, ++ .read_status = rtlgen_read_status, + .ack_interrupt = &rtl8211f_ack_interrupt, + .config_intr = &rtl8211f_config_intr, + .suspend = genphy_suspend, diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c -index 7c27827857363..ce7944fa3576d 100644 +index 828f9ad1be49..c8ed6756c255 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c -@@ -3102,6 +3102,16 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) +@@ -3224,6 +3224,16 @@ int uart_get_rs485_mode(struct uart_port *port) u32 rs485_delay[2]; int ret; @@ -381,7 +257,7 @@ index 7c27827857363..ce7944fa3576d 100644 rs485_delay, 2); if (!ret) { diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c -index fb4781292d409..1fc2f704769e7 100644 +index fb4781292d40..1fc2f704769e 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -299,4 +299,42 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) @@ -428,7 +304,7 @@ index fb4781292d409..1fc2f704769e7 100644 + MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h -index 1b2ff503b2c24..f2e4760ac2de1 100644 +index b134a0ffc894..fc76910fb105 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -91,6 +91,16 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios); @@ -464,7 +340,7 @@ index 1b2ff503b2c24..f2e4760ac2de1 100644 #endif diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c -index 2f72514d63edd..231fbb3684d8a 100644 +index ee6c7762d355..5694e78646eb 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -4,6 +4,7 @@ @@ -475,18 +351,14 @@ index 2f72514d63edd..231fbb3684d8a 100644 * * Inspired by st-asc.c from STMicroelectronics (c) */ -@@ -35,17 +36,19 @@ - #include - #include - -+#include "serial_mctrl_gpio.h" +@@ -34,15 +35,15 @@ + #include "serial_mctrl_gpio.h" #include "stm32-usart.h" -static void stm32_stop_tx(struct uart_port *port); -static void stm32_transmit_chars(struct uart_port *port); +static void stm32_usart_stop_tx(struct uart_port *port); +static void stm32_usart_transmit_chars(struct uart_port *port); -+static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port); static inline struct stm32_port *to_stm32_port(struct uart_port *port) { @@ -498,7 +370,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { u32 val; -@@ -54,7 +57,7 @@ static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits) +@@ -51,7 +52,7 @@ static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits) writel_relaxed(val, port->membase + reg); } @@ -507,7 +379,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { u32 val; -@@ -63,43 +66,70 @@ static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits) +@@ -60,43 +61,70 @@ static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits) writel_relaxed(val, port->membase + reg); } @@ -603,7 +475,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -@@ -107,7 +137,7 @@ static int stm32_config_rs485(struct uart_port *port, +@@ -104,7 +132,7 @@ static int stm32_config_rs485(struct uart_port *port, u32 usartdiv, baud, cr1, cr3; bool over8; @@ -612,7 +484,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 port->rs485 = *rs485conf; -@@ -125,9 +155,7 @@ static int stm32_config_rs485(struct uart_port *port, +@@ -122,9 +150,7 @@ static int stm32_config_rs485(struct uart_port *port, << USART_BRR_04_R_SHIFT; baud = DIV_ROUND_CLOSEST(port->uartclk, usartdiv); @@ -623,7 +495,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; -@@ -140,18 +168,19 @@ static int stm32_config_rs485(struct uart_port *port, +@@ -137,18 +163,19 @@ static int stm32_config_rs485(struct uart_port *port, writel_relaxed(cr3, port->membase + ofs->cr3); writel_relaxed(cr1, port->membase + ofs->cr1); } else { @@ -649,8 +521,8 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct serial_rs485 *rs485conf = &port->rs485; -@@ -167,64 +196,67 @@ static int stm32_init_rs485(struct uart_port *port, - return 0; +@@ -162,64 +189,67 @@ static int stm32_init_rs485(struct uart_port *port, + return uart_get_rs485_mode(port); } -static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, @@ -750,7 +622,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 sr |= USART_SR_DUMMY_RX; flag = TTY_NORMAL; -@@ -243,8 +275,9 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) +@@ -238,8 +268,9 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) writel_relaxed(sr & USART_SR_ERR_MASK, port->membase + ofs->icr); @@ -761,7 +633,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (sr & USART_SR_ERR_MASK) { if (sr & USART_SR_ORE) { port->icount.overrun++; -@@ -278,25 +311,115 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) +@@ -273,25 +304,140 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) uart_insert_char(port, sr, USART_SR_ORE, c, flag); } @@ -798,14 +670,14 @@ index 2f72514d63edd..231fbb3684d8a 100644 + * DMA buffer is configured in cyclic mode and handles the rollback of + * the buffer. + */ -+ if (stm32_port->state.residue > stm32_port->last_res) { ++ if (stm32_port->rx_dma_state.residue > stm32_port->last_res) { + /* Conditional first part: from last_res to end of DMA buffer */ + dma_size = stm32_port->last_res; + stm32_usart_push_buffer_dma(port, dma_size); + size = dma_size; + } + -+ dma_size = stm32_port->last_res - stm32_port->state.residue; ++ dma_size = stm32_port->last_res - stm32_port->rx_dma_state.residue; + stm32_usart_push_buffer_dma(port, dma_size); + size += dma_size; + @@ -818,15 +690,15 @@ index 2f72514d63edd..231fbb3684d8a 100644 + struct tty_port *tport = &port->state->port; + struct stm32_port *stm32_port = to_stm32_port(port); + struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; ++ enum dma_status rx_dma_status; + u32 sr; + unsigned int size; + + if (stm32_usart_rx_dma_enabled(port) || force_dma_flush) { -+ stm32_port->status = -+ dmaengine_tx_status(stm32_port->rx_ch, -+ stm32_port->rx_ch->cookie, -+ &stm32_port->state); -+ if (stm32_port->status == DMA_IN_PROGRESS) { ++ rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, ++ stm32_port->rx_ch->cookie, ++ &stm32_port->rx_dma_state); ++ if (rx_dma_status == DMA_IN_PROGRESS) { + /* Empty DMA buffer */ + size = stm32_usart_receive_chars_dma(port); + sr = readl_relaxed(port->membase + ofs->isr); @@ -857,6 +729,32 @@ index 2f72514d63edd..231fbb3684d8a 100644 + + if (size) + tty_flip_buffer_push(tport); ++} ++ ++static void stm32_usart_tx_dma_terminate(struct stm32_port *stm32_port) ++{ ++ dmaengine_terminate_async(stm32_port->tx_ch); ++ stm32_port->tx_dma_busy = false; ++} ++ ++static bool stm32_usart_tx_dma_started(struct stm32_port *stm32_port) ++{ ++ /* ++ * We cannot use the function "dmaengine_tx_status" to know the ++ * status of DMA. This function does not show if the "dma complete" ++ * callback of the DMA transaction have been called. So we prefer ++ * to use "tx_dma_busy" flag to prevent dual dma transaction at the ++ * same time. ++ */ ++ return stm32_port->tx_dma_busy; ++} ++ ++static bool stm32_usart_tx_dma_enabled(struct stm32_port *stm32_port) ++{ ++ struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; ++ ++ return !!(readl_relaxed(stm32_port->port.membase + ofs->cr3) ++ & USART_CR3_DMAT); } -static void stm32_tx_dma_complete(void *arg) @@ -868,9 +766,9 @@ index 2f72514d63edd..231fbb3684d8a 100644 + unsigned long flags; - stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); -+ dmaengine_terminate_async(stm32port->tx_ch); +- stm32port->tx_dma_busy = false; + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - stm32port->tx_dma_busy = false; ++ stm32_usart_tx_dma_terminate(stm32port); /* Let's see if we have pending data to send */ - stm32_transmit_chars(port); @@ -884,7 +782,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -@@ -305,31 +428,41 @@ static void stm32_tx_interrupt_enable(struct uart_port *port) +@@ -300,33 +446,41 @@ static void stm32_tx_interrupt_enable(struct uart_port *port) * Enables TX FIFO threashold irq when FIFO is enabled, * or TX empty irq when FIFO is disabled */ @@ -895,8 +793,9 @@ index 2f72514d63edd..231fbb3684d8a 100644 else - stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE); + stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE); -+} -+ + } + +-static void stm32_tx_interrupt_disable(struct uart_port *port) +static void stm32_usart_rx_dma_complete(void *arg) +{ + struct uart_port *port = arg; @@ -905,9 +804,8 @@ index 2f72514d63edd..231fbb3684d8a 100644 + spin_lock_irqsave(&port->lock, flags); + stm32_usart_receive_chars(port, false); + spin_unlock_irqrestore(&port->lock, flags); - } - --static void stm32_tx_interrupt_disable(struct uart_port *port) ++} ++ +static void stm32_usart_tx_interrupt_disable(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); @@ -929,13 +827,16 @@ index 2f72514d63edd..231fbb3684d8a 100644 struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct circ_buf *xmit = &port->state->xmit; - if (stm32_port->tx_dma_busy) { +- if (stm32_port->tx_dma_busy) { - stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); +- stm32_port->tx_dma_busy = false; +- } ++ if (stm32_usart_tx_dma_enabled(stm32_port)) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - stm32_port->tx_dma_busy = false; - } -@@ -344,19 +477,19 @@ static void stm32_transmit_chars_pio(struct uart_port *port) + while (!uart_circ_empty(xmit)) { + /* Check that TDR is empty before filling FIFO */ +@@ -339,24 +493,25 @@ static void stm32_transmit_chars_pio(struct uart_port *port) /* rely on TXE irq (mask or unmask) for sending remaining data */ if (uart_circ_empty(xmit)) @@ -957,9 +858,18 @@ index 2f72514d63edd..231fbb3684d8a 100644 - unsigned int count, i; + unsigned int count, i, ret; - if (stm32port->tx_dma_busy) +- if (stm32port->tx_dma_busy) ++ if (stm32_usart_tx_dma_started(stm32port)) { ++ if (!stm32_usart_tx_dma_enabled(stm32port)) ++ stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); return; -@@ -389,28 +522,36 @@ static void stm32_transmit_chars_dma(struct uart_port *port) +- +- stm32port->tx_dma_busy = true; ++ } + + count = uart_circ_chars_pending(xmit); + +@@ -384,136 +539,181 @@ static void stm32_transmit_chars_dma(struct uart_port *port) DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); @@ -970,6 +880,14 @@ index 2f72514d63edd..231fbb3684d8a 100644 - } + if (!desc) + goto fallback_err; ++ ++ /* ++ * Take "tx_dma_busy" flag. This flag will be release when ++ * dmaengine_terminate_async will be called. This flag helps ++ * transmit_chars_dma to doesn't start another dma transaction ++ * if the callback of the previous is not called. ++ */ ++ stm32port->tx_dma_busy = true; - desc->callback = stm32_tx_dma_complete; + desc->callback = stm32_usart_tx_dma_complete; @@ -980,7 +898,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 + ret = dma_submit_error(cookie); + if (ret) { + /* dma no yet started, safe to free resources */ -+ dmaengine_terminate_async(stm32port->tx_ch); ++ stm32_usart_tx_dma_terminate(stm32port); + goto fallback_err; + } @@ -1004,17 +922,32 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -@@ -418,211 +559,330 @@ static void stm32_transmit_chars(struct uart_port *port) + struct circ_buf *xmit = &port->state->xmit; ++ u32 isr; ++ int ret; if (port->x_char) { - if (stm32_port->tx_dma_busy) +- if (stm32_port->tx_dma_busy) - stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); ++ if (stm32_usart_tx_dma_started(stm32_port) && ++ stm32_usart_tx_dma_enabled(stm32_port)) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); ++ ++ /* Check that TDR is empty before filling FIFO */ ++ ret = ++ readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, ++ isr, ++ (isr & USART_SR_TXE), ++ 10, 1000); ++ if (ret) ++ dev_warn(port->dev, "1 character may be erased\n"); ++ writel_relaxed(port->x_char, port->membase + ofs->tdr); port->x_char = 0; port->icount.tx++; - if (stm32_port->tx_dma_busy) +- if (stm32_port->tx_dma_busy) - stm32_set_bits(port, ofs->cr3, USART_CR3_DMAT); ++ if (stm32_usart_tx_dma_started(stm32_port)) + stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); return; } @@ -1151,57 +1084,67 @@ index 2f72514d63edd..231fbb3684d8a 100644 else - stm32_clr_bits(port, ofs->cr3, USART_CR3_RTSE); + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_RTSE); -+ -+ mctrl_gpio_set(stm32_port->gpios, mctrl); + + mctrl_gpio_set(stm32_port->gpios, mctrl); } -static unsigned int stm32_get_mctrl(struct uart_port *port) +static unsigned int stm32_usart_get_mctrl(struct uart_port *port) { -+ struct stm32_port *stm32_port = to_stm32_port(port); -+ unsigned int ret; -+ - /* This routine is used to get signals of: DCD, DSR, RI, and CTS */ -- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; -+ ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; -+ -+ return mctrl_gpio_get(stm32_port->gpios, &ret); -+} -+ + struct stm32_port *stm32_port = to_stm32_port(port); + unsigned int ret; +@@ -524,23 +724,27 @@ static unsigned int stm32_get_mctrl(struct uart_port *port) + return mctrl_gpio_get(stm32_port->gpios, &ret); + } + +-static void stm32_enable_ms(struct uart_port *port) +static void stm32_usart_enable_ms(struct uart_port *port) -+{ -+ mctrl_gpio_enable_ms(to_stm32_port(port)->gpios); -+} -+ + { + mctrl_gpio_enable_ms(to_stm32_port(port)->gpios); + } + +-static void stm32_disable_ms(struct uart_port *port) +static void stm32_usart_disable_ms(struct uart_port *port) -+{ -+ mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); + { + mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); } /* Transmit stop */ -static void stm32_stop_tx(struct uart_port *port) +static void stm32_usart_stop_tx(struct uart_port *port) { -- stm32_tx_interrupt_disable(port); -+ struct stm32_port *stm32_port = to_stm32_port(port); + struct stm32_port *stm32_port = to_stm32_port(port); + struct serial_rs485 *rs485conf = &port->rs485; + struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -+ + +- stm32_tx_interrupt_disable(port); + stm32_usart_tx_interrupt_disable(port); -+ if (stm32_port->tx_dma_busy) { -+ dmaengine_terminate_async(stm32_port->tx_ch); ++ if (stm32_usart_tx_dma_started(stm32_port) && ++ stm32_usart_tx_dma_enabled(stm32_port)) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); -+ } + + if (rs485conf->flags & SER_RS485_ENABLED) { + if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { +@@ -554,13 +758,13 @@ static void stm32_stop_tx(struct uart_port *port) } /* There are probably characters waiting to be transmitted. */ -static void stm32_start_tx(struct uart_port *port) +static void stm32_usart_start_tx(struct uart_port *port) { + struct stm32_port *stm32_port = to_stm32_port(port); + struct serial_rs485 *rs485conf = &port->rs485; struct circ_buf *xmit = &port->state->xmit; - if (uart_circ_empty(xmit)) +- if (uart_circ_empty(xmit)) ++ if (uart_circ_empty(xmit) && !port->x_char) return; + if (rs485conf->flags & SER_RS485_ENABLED) { +@@ -573,93 +777,166 @@ static void stm32_start_tx(struct uart_port *port) + } + } + - stm32_transmit_chars(port); + stm32_usart_transmit_chars(port); +} @@ -1213,13 +1156,8 @@ index 2f72514d63edd..231fbb3684d8a 100644 + struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + + if (stm32_port->tx_ch) { -+ /* Avoid deadlock with the DMA engine callback */ -+ spin_unlock(&port->lock); -+ dmaengine_terminate_async(stm32_port->tx_ch); -+ spin_lock(&port->lock); -+ ++ stm32_usart_tx_dma_terminate(stm32_port); + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); -+ stm32_port->tx_dma_busy = false; + } } @@ -1265,14 +1203,14 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (stm32_port->cr3_irq) - stm32_set_bits(port, ofs->cr3, stm32_port->cr3_irq); + stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq); - ++ + /* + * Switch back to DMA mode (re-enable DMA request line). + * Hardware flow control is stopped when FIFO is not full any more. + */ + if (stm32_port->rx_ch) + stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR); -+ + + stm32_port->throttled = false; spin_unlock_irqrestore(&port->lock, flags); } @@ -1287,11 +1225,9 @@ index 2f72514d63edd..231fbb3684d8a 100644 - stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); - if (stm32_port->cr3_irq) - stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); -+ /* Disable DMA request line and RX DMA. */ -+ if (stm32_port->rx_ch) { ++ /* Disable DMA request line. */ ++ if (stm32_port->rx_ch) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); -+ dmaengine_terminate_sync(stm32_port->rx_ch); -+ } + stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); + if (stm32_port->cr3_irq) @@ -1301,12 +1237,11 @@ index 2f72514d63edd..231fbb3684d8a 100644 /* Handle breaks - ignored by us */ -static void stm32_break_ctl(struct uart_port *port, int break_state) +static void stm32_usart_break_ctl(struct uart_port *port, int break_state) - { - } - --static int stm32_startup(struct uart_port *port) -+static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port) +{ ++} ++ ++static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port) + { + struct stm32_port *stm32_port = to_stm32_port(port); + struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + struct dma_async_tx_descriptor *desc; @@ -1345,8 +1280,9 @@ index 2f72514d63edd..231fbb3684d8a 100644 + stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR); + + return 0; -+} -+ + } + +-static int stm32_startup(struct uart_port *port) +static int stm32_usart_startup(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); @@ -1367,7 +1303,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 /* RX FIFO Flush */ if (ofs->rqr != UNDEF_REG) - stm32_set_bits(port, ofs->rqr, USART_RQR_RXFRQ); -+ stm32_usart_set_bits(port, ofs->rqr, USART_RQR_RXFRQ); ++ writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr); - /* Tx and RX FIFO configuration */ - if (stm32_port->fifoen) { @@ -1383,7 +1319,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 + return ret; + } } -- + - /* RX FIFO enabling */ - val = stm32_port->cr1_irq | USART_CR1_RE; - if (stm32_port->fifoen) @@ -1401,34 +1337,41 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -@@ -630,6 +890,9 @@ static void stm32_shutdown(struct uart_port *port) +@@ -667,8 +944,14 @@ static void stm32_shutdown(struct uart_port *port) u32 val, isr; int ret; -+ /* Disable modem control interrupts */ -+ stm32_usart_disable_ms(port); ++ if (stm32_usart_tx_dma_enabled(stm32_port)) ++ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + ++ if (stm32_usart_tx_dma_started(stm32_port)) ++ stm32_usart_tx_dma_terminate(stm32_port); ++ + /* Disable modem control interrupts */ +- stm32_disable_ms(port); ++ stm32_usart_disable_ms(port); + val = USART_CR1_TXEIE | USART_CR1_TE; val |= stm32_port->cr1_irq | USART_CR1_RE; - val |= BIT(cfg->uart_enable_bit); -@@ -640,15 +903,24 @@ static void stm32_shutdown(struct uart_port *port) +@@ -680,15 +963,25 @@ static void stm32_shutdown(struct uart_port *port) isr, (isr & USART_SR_TC), 10, 100000); -- if (ret) -+ /* -+ * Send the TC error message only when ISR_TC is not set and -+ * data stored in TDR / TX FIFO. -+ */ -+ if (ret && !(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) - dev_err(port->dev, "transmission complete not set\n"); - -- stm32_clr_bits(port, ofs->cr1, val); ++ /* Send the TC error message only when ISR_TC is not set */ + if (ret) +- dev_err(port->dev, "transmission complete not set\n"); ++ dev_err(port->dev, "Transmission is not complete\n"); ++ ++ /* Disable RX DMA. */ ++ if (stm32_port->rx_ch) ++ dmaengine_terminate_async(stm32_port->rx_ch); ++ + /* flush RX & TX FIFO */ + if (ofs->rqr != UNDEF_REG) -+ stm32_usart_set_bits(port, ofs->rqr, -+ USART_RQR_TXFRQ | USART_RQR_RXFRQ); -+ ++ writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ, ++ port->membase + ofs->rqr); + +- stm32_clr_bits(port, ofs->cr1, val); + stm32_usart_clr_bits(port, ofs->cr1, val); free_irq(port->irq, port); @@ -1439,7 +1382,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { unsigned int bits; -@@ -678,8 +950,9 @@ static unsigned int stm32_get_databits(struct ktermios *termios) +@@ -718,8 +1011,9 @@ static unsigned int stm32_get_databits(struct ktermios *termios) return bits; } @@ -1451,7 +1394,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -@@ -688,8 +961,9 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -728,8 +1022,9 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, unsigned int baud, bits; u32 usartdiv, mantissa, fraction, oversampling; tcflag_t cflag = termios->c_cflag; @@ -1462,7 +1405,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (!stm32_port->hw_flow_control) cflag &= ~CRTSCTS; -@@ -698,26 +972,45 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -738,26 +1033,42 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, spin_lock_irqsave(&port->lock, flags); @@ -1471,12 +1414,9 @@ index 2f72514d63edd..231fbb3684d8a 100644 + (isr & USART_SR_TC), + 10, 100000); + -+ /* -+ * Send the TC error message only when ISR_TC is not set and -+ * data stored in TDR / TX FIFO. -+ */ -+ if (ret && !(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) -+ dev_err(port->dev, "transmission complete not set\n"); ++ /* Send the TC error message only when ISR_TC is not set. */ ++ if (ret) ++ dev_err(port->dev, "Transmission is not complete\n"); + /* Stop serial port and reset value */ writel_relaxed(0, port->membase + ofs->cr1); @@ -1485,8 +1425,8 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (ofs->rqr != UNDEF_REG) - stm32_set_bits(port, ofs->rqr, - USART_RQR_TXFRQ | USART_RQR_RXFRQ); -+ stm32_usart_set_bits(port, ofs->rqr, -+ USART_RQR_TXFRQ | USART_RQR_RXFRQ); ++ writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ, ++ port->membase + ofs->rqr); cr1 = USART_CR1_TE | USART_CR1_RE; if (stm32_port->fifoen) @@ -1513,7 +1453,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 stm32_port->rdr_mask = (BIT(bits) - 1); if (cflag & PARENB) { -@@ -741,7 +1034,8 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -781,7 +1092,8 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, , bits); if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch || @@ -1523,7 +1463,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (cflag & CSTOPB) bits = bits + 3; /* 1 start bit + 2 stop bits */ else -@@ -751,9 +1045,12 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -791,9 +1103,12 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, stm32_port->cr1_irq = USART_CR1_RTOIE; writel_relaxed(bits, port->membase + ofs->rtor); cr2 |= USART_CR2_RTOEN; @@ -1539,7 +1479,20 @@ index 2f72514d63edd..231fbb3684d8a 100644 } cr1 |= stm32_port->cr1_irq; -@@ -779,11 +1076,11 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -808,12 +1123,6 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, + cr3 |= USART_CR3_CTSE | USART_CR3_RTSE; + } + +- /* Handle modem control interrupts */ +- if (UART_ENABLE_MS(port, termios->c_cflag)) +- stm32_enable_ms(port); +- else +- stm32_disable_ms(port); +- + usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud); + + /* +@@ -825,11 +1134,11 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, if (usartdiv < 16) { oversampling = 8; cr1 |= USART_CR1_OVER8; @@ -1553,7 +1506,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 } mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT; -@@ -816,13 +1113,19 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -862,13 +1171,19 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= USART_SR_DUMMY_RX; @@ -1577,7 +1530,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; -@@ -836,43 +1139,55 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, +@@ -882,43 +1197,55 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, cr1 &= ~(USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK); } @@ -1641,7 +1594,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32port = container_of(port, struct stm32_port, port); -@@ -886,7 +1201,7 @@ static void stm32_pm(struct uart_port *port, unsigned int state, +@@ -932,7 +1259,7 @@ static void stm32_pm(struct uart_port *port, unsigned int state, break; case UART_PM_STATE_OFF: spin_lock_irqsave(&port->lock, flags); @@ -1650,7 +1603,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 spin_unlock_irqrestore(&port->lock, flags); pm_runtime_put_sync(port->dev); break; -@@ -894,55 +1209,98 @@ static void stm32_pm(struct uart_port *port, unsigned int state, +@@ -940,59 +1267,101 @@ static void stm32_pm(struct uart_port *port, unsigned int state, } static const struct uart_ops stm32_uart_ops = { @@ -1662,6 +1615,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 - .throttle = stm32_throttle, - .unthrottle = stm32_unthrottle, - .stop_rx = stm32_stop_rx, +- .enable_ms = stm32_enable_ms, - .break_ctl = stm32_break_ctl, - .startup = stm32_startup, - .shutdown = stm32_shutdown, @@ -1750,6 +1704,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 port->ops = &stm32_uart_ops; port->dev = &pdev->dev; port->fifosize = stm32port->info->cfg.fifosize; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); - - ret = platform_get_irq(pdev, 0); - if (ret <= 0) @@ -1758,12 +1713,14 @@ index 2f72514d63edd..231fbb3684d8a 100644 + port->rs485_config = stm32_usart_config_rs485; - port->rs485_config = stm32_config_rs485; -+ stm32_usart_init_rs485(port, pdev); - -- stm32_init_rs485(port, pdev); - +- ret = stm32_init_rs485(port, pdev); ++ ret = stm32_usart_init_rs485(port, pdev); + if (ret) + return ret; + - if (stm32port->info->cfg.has_wakeup) { -- stm32port->wakeirq = platform_get_irq(pdev, 1); +- stm32port->wakeirq = platform_get_irq_optional(pdev, 1); - if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO) - return stm32port->wakeirq ? : -ENODEV; - } @@ -1781,39 +1738,19 @@ index 2f72514d63edd..231fbb3684d8a 100644 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->membase = devm_ioremap_resource(&pdev->dev, res); -@@ -963,14 +1321,38 @@ static int stm32_init_port(struct stm32_port *stm32port, - - stm32port->port.uartclk = clk_get_rate(stm32port->clk); - if (!stm32port->port.uartclk) { -- clk_disable_unprepare(stm32port->clk); - ret = -EINVAL; -+ goto err_clk; -+ } -+ -+ stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0); -+ if (IS_ERR(stm32port->gpios)) { -+ ret = PTR_ERR(stm32port->gpios); -+ goto err_clk; +@@ -1023,7 +1392,10 @@ static int stm32_init_port(struct stm32_port *stm32port, + goto err_clk; } +- /* Both CTS/RTS gpios and "st,hw-flow-ctrl" should not be specified */ + /* + * Both CTS/RTS gpios and "st,hw-flow-ctrl" (deprecated) or "uart-has-rtscts" + * properties should not be specified. + */ -+ if (stm32port->hw_flow_control) { -+ if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) || -+ mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) { -+ dev_err(&pdev->dev, "Conflicting RTS/CTS config\n"); -+ ret = -EINVAL; -+ goto err_clk; -+ } -+ } -+ -+ return ret; -+ -+err_clk: -+ clk_disable_unprepare(stm32port->clk); -+ + if (stm32port->hw_flow_control) { + if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) || + mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) { +@@ -1041,7 +1413,7 @@ static int stm32_init_port(struct stm32_port *stm32port, return ret; } @@ -1822,15 +1759,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct device_node *np = pdev->dev.of_node; int id; -@@ -987,12 +1369,14 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) - if (WARN_ON(id >= STM32_MAX_PORTS)) - return NULL; - -- stm32_ports[id].hw_flow_control = of_property_read_bool(np, -- "st,hw-flow-ctrl"); -+ stm32_ports[id].hw_flow_control = -+ of_property_read_bool(np, "uart-has-rtscts"); - stm32_ports[id].port.line = id; +@@ -1065,6 +1437,8 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) stm32_ports[id].cr1_irq = USART_CR1_RXNEIE; stm32_ports[id].cr3_irq = 0; stm32_ports[id].last_res = RX_BUF_L; @@ -1839,7 +1768,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 return &stm32_ports[id]; } -@@ -1007,30 +1391,28 @@ static const struct of_device_id stm32_match[] = { +@@ -1079,30 +1453,28 @@ static const struct of_device_id stm32_match[] = { MODULE_DEVICE_TABLE(of, stm32_match); #endif @@ -1884,7 +1813,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 /* Configure DMA channel */ memset(&config, 0, sizeof(config)); -@@ -1040,47 +1422,23 @@ static int stm32_of_dma_rx_probe(struct stm32_port *stm32port, +@@ -1112,47 +1484,23 @@ static int stm32_of_dma_rx_probe(struct stm32_port *stm32port, ret = dmaengine_slave_config(stm32port->rx_ch, &config); if (ret < 0) { dev_err(dev, "rx dma channel config failed\n"); @@ -1943,10 +1872,12 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_usart_offsets *ofs = &stm32port->info->ofs; struct uart_port *port = &stm32port->port; -@@ -1090,19 +1448,11 @@ static int stm32_of_dma_tx_probe(struct stm32_port *stm32port, - - stm32port->tx_dma_busy = false; +@@ -1160,21 +1508,11 @@ static int stm32_of_dma_tx_probe(struct stm32_port *stm32port, + struct dma_slave_config config; + int ret; +- stm32port->tx_dma_busy = false; +- - /* Request DMA TX channel */ - stm32port->tx_ch = dma_request_slave_channel(dev, "tx"); - if (!stm32port->tx_ch) { @@ -1967,7 +1898,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 /* Configure DMA channel */ memset(&config, 0, sizeof(config)); -@@ -1112,31 +1462,20 @@ static int stm32_of_dma_tx_probe(struct stm32_port *stm32port, +@@ -1184,31 +1522,20 @@ static int stm32_of_dma_tx_probe(struct stm32_port *stm32port, ret = dmaengine_slave_config(stm32port->tx_ch, &config); if (ret < 0) { dev_err(dev, "tx dma channel config failed\n"); @@ -2003,7 +1934,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 if (!stm32port) return -ENODEV; -@@ -1146,105 +1485,145 @@ static int stm32_serial_probe(struct platform_device *pdev) +@@ -1218,105 +1545,145 @@ static int stm32_serial_probe(struct platform_device *pdev) else return -EINVAL; @@ -2014,15 +1945,15 @@ index 2f72514d63edd..231fbb3684d8a 100644 - if (stm32port->wakeirq > 0) { - ret = device_init_wakeup(&pdev->dev, true); -+ if (stm32port->wakeup_src) { -+ device_set_wakeup_capable(&pdev->dev, true); -+ ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq); - if (ret) +- if (ret) - goto err_uninit; - - ret = dev_pm_set_dedicated_wake_irq(&pdev->dev, - stm32port->wakeirq); -- if (ret) ++ if (stm32port->wakeup_src) { ++ device_set_wakeup_capable(&pdev->dev, true); ++ ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq); + if (ret) - goto err_nowup; - - device_set_wakeup_enable(&pdev->dev, false); @@ -2161,36 +2092,36 @@ index 2f72514d63edd..231fbb3684d8a 100644 - if (stm32_port->tx_ch) + if (stm32_port->tx_ch) { -+ dmaengine_terminate_async(stm32_port->tx_ch); ++ stm32_usart_tx_dma_terminate(stm32_port); + stm32_usart_of_dma_tx_remove(stm32_port, pdev); dma_release_channel(stm32_port->tx_ch); + } ++ ++ if (stm32_port->rx_ch) { ++ stm32_usart_of_dma_rx_remove(stm32_port, pdev); ++ dma_release_chan_linked(&pdev->dev, stm32_port->rx_ch); ++ } - if (stm32_port->tx_dma_buf) - dma_free_coherent(&pdev->dev, - TX_BUF_L, stm32_port->tx_buf, - stm32_port->tx_dma_buf); -+ if (stm32_port->rx_ch) { -+ stm32_usart_of_dma_rx_remove(stm32_port, pdev); -+ dma_release_chan_linked(&pdev->dev, stm32_port->rx_ch); -+ } ++ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - if (stm32_port->wakeirq > 0) { -+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); -+ + if (stm32_port->wakeup_src) { dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); } - clk_disable_unprepare(stm32_port->clk); -- ++ stm32_usart_deinit_port(stm32_port); + - err = uart_remove_one_port(&stm32_usart_driver, port); - - pm_runtime_disable(&pdev->dev); - pm_runtime_put_noidle(&pdev->dev); -+ stm32_usart_deinit_port(stm32_port); - +- - return err; + return 0; } @@ -2202,7 +2133,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; -@@ -1255,7 +1634,8 @@ static void stm32_console_putchar(struct uart_port *port, int ch) +@@ -1327,7 +1694,8 @@ static void stm32_console_putchar(struct uart_port *port, int ch) writel_relaxed(ch, port->membase + ofs->tdr); } @@ -2212,7 +2143,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct uart_port *port = &stm32_ports[co->index].port; struct stm32_port *stm32_port = to_stm32_port(port); -@@ -1279,7 +1659,7 @@ static void stm32_console_write(struct console *co, const char *s, unsigned cnt) +@@ -1351,7 +1719,7 @@ static void stm32_console_write(struct console *co, const char *s, unsigned cnt) new_cr1 |= USART_CR1_TE | BIT(cfg->uart_enable_bit); writel_relaxed(new_cr1, port->membase + ofs->cr1); @@ -2221,7 +2152,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 /* Restore interrupt state */ writel_relaxed(old_cr1, port->membase + ofs->cr1); -@@ -1289,7 +1669,7 @@ static void stm32_console_write(struct console *co, const char *s, unsigned cnt) +@@ -1361,7 +1729,7 @@ static void stm32_console_write(struct console *co, const char *s, unsigned cnt) local_irq_restore(flags); } @@ -2230,7 +2161,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct stm32_port *stm32port; int baud = 9600; -@@ -1308,7 +1688,7 @@ static int stm32_console_setup(struct console *co, char *options) +@@ -1380,7 +1748,7 @@ static int stm32_console_setup(struct console *co, char *options) * this to be called during the uart port registration when the * driver gets probed and the port should be mapped at that point. */ @@ -2239,7 +2170,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 return -ENXIO; if (options) -@@ -1320,8 +1700,8 @@ static int stm32_console_setup(struct console *co, char *options) +@@ -1392,8 +1760,8 @@ static int stm32_console_setup(struct console *co, char *options) static struct console stm32_console = { .name = STM32_SERIAL_NAME, .device = uart_console_device, @@ -2250,7 +2181,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 .flags = CON_PRINTBUFFER, .index = -1, .data = &stm32_usart_driver, -@@ -1342,60 +1722,107 @@ static struct uart_driver stm32_usart_driver = { +@@ -1414,41 +1782,72 @@ static struct uart_driver stm32_usart_driver = { .cons = STM32_SERIAL_CONSOLE, }; @@ -2315,7 +2246,6 @@ index 2f72514d63edd..231fbb3684d8a 100644 + if (ret) + return ret; + } -+ + mctrl_gpio_disable_irq_wake(stm32_port->gpios); + stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_UESM); + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE); @@ -2342,20 +2272,18 @@ index 2f72514d63edd..231fbb3684d8a 100644 + return ret; + } -- pinctrl_pm_select_sleep_state(dev); -+ /* -+ * When "no_console_suspend" is enabled, keep the pinctrl default state -+ * and rely on bootloader stage to restore this state upon resume. -+ * Otherwise, apply the idle or sleep states depending on wakeup -+ * capabilities. -+ */ -+ if (console_suspend_enabled || !uart_console(port)) { + /* + * When "no_console_suspend" is enabled, keep the pinctrl default state +@@ -1457,7 +1856,7 @@ static int __maybe_unused stm32_serial_suspend(struct device *dev) + * capabilities. + */ + if (console_suspend_enabled || !uart_console(port)) { +- if (device_may_wakeup(dev)) + if (device_may_wakeup(dev) || device_wakeup_path(dev)) -+ pinctrl_pm_select_idle_state(dev); -+ else -+ pinctrl_pm_select_sleep_state(dev); -+ } - + pinctrl_pm_select_idle_state(dev); + else + pinctrl_pm_select_sleep_state(dev); +@@ -1466,19 +1865,23 @@ static int __maybe_unused stm32_serial_suspend(struct device *dev) return 0; } @@ -2383,7 +2311,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct uart_port *port = dev_get_drvdata(dev); struct stm32_port *stm32port = container_of(port, -@@ -1406,7 +1833,7 @@ static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev) +@@ -1489,7 +1892,7 @@ static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev) return 0; } @@ -2392,7 +2320,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { struct uart_port *port = dev_get_drvdata(dev); struct stm32_port *stm32port = container_of(port, -@@ -1416,14 +1843,15 @@ static int __maybe_unused stm32_serial_runtime_resume(struct device *dev) +@@ -1499,14 +1902,15 @@ static int __maybe_unused stm32_serial_runtime_resume(struct device *dev) } static const struct dev_pm_ops stm32_serial_pm_ops = { @@ -2413,7 +2341,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 .driver = { .name = DRIVER_NAME, .pm = &stm32_serial_pm_ops, -@@ -1431,7 +1859,7 @@ static struct platform_driver stm32_serial_driver = { +@@ -1514,7 +1918,7 @@ static struct platform_driver stm32_serial_driver = { }, }; @@ -2422,7 +2350,7 @@ index 2f72514d63edd..231fbb3684d8a 100644 { static char banner[] __initdata = "STM32 USART driver initialized"; int ret; -@@ -1449,14 +1877,14 @@ static int __init usart_init(void) +@@ -1532,14 +1936,14 @@ static int __init usart_init(void) return ret; } @@ -2441,15 +2369,9 @@ index 2f72514d63edd..231fbb3684d8a 100644 MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_DESCRIPTION("STMicroelectronics STM32 serial port driver"); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h -index a175c1094dc8d..6961cd9855f68 100644 +index d4c916e78d40..f4708007ec0e 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h -@@ -1,4 +1,4 @@ --// SPDX-License-Identifier: GPL-2.0 -+/* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (C) Maxime Coquelin 2015 - * Copyright (C) STMicroelectronics SA 2017 @@ -106,7 +106,7 @@ struct stm32_usart_info stm32h7_info = { /* USART_SR (F4) / USART_ISR (F7) */ #define USART_SR_PE BIT(0) @@ -2501,10 +2423,11 @@ index a175c1094dc8d..6961cd9855f68 100644 struct stm32_port { struct uart_port port; -@@ -270,10 +262,16 @@ struct stm32_port { +@@ -269,12 +261,16 @@ struct stm32_port { + u32 cr1_irq; /* USART_CR1_RXNEIE or RTOIE */ u32 cr3_irq; /* USART_CR3_RXFTIE */ int last_res; - bool tx_dma_busy; /* dma tx busy */ +- bool tx_dma_busy; /* dma tx busy */ + bool throttled; /* port throttled */ bool hw_flow_control; bool fifoen; @@ -2513,14 +2436,14 @@ index a175c1094dc8d..6961cd9855f68 100644 + int txftcfg; /* TX FIFO threshold CFG */ + bool wakeup_src; int rdr_mask; /* receive data register mask */ -+ struct mctrl_gpios *gpios; /* modem control gpios */ -+ struct dma_tx_state state; -+ enum dma_status status; + struct mctrl_gpios *gpios; /* modem control gpios */ ++ struct dma_tx_state rx_dma_state; ++ bool tx_dma_busy; /* dma tx transaction in progress */ }; static struct stm32_port stm32_ports[STM32_MAX_PORTS]; diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h -index 93eb3c496ff1e..2d98e65d2a783 100644 +index 93eb3c496ff1..2d98e65d2a78 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -128,6 +128,8 @@ struct serial_rs485 { diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0022-ARM-stm32mp1-r2-PERF.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0014-ARM-5.10.10-stm32mp1-r1-PERF.patch similarity index 65% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0022-ARM-stm32mp1-r2-PERF.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0014-ARM-5.10.10-stm32mp1-r1-PERF.patch index 9ca6a36..dd8284c 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0022-ARM-stm32mp1-r2-PERF.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0014-ARM-5.10.10-stm32mp1-r1-PERF.patch @@ -1,28 +1,43 @@ -From 38993f1a9ca823da25a15d8c8b1bc839a0165c0a Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:56 +0200 -Subject: [PATCH 22/22] ARM-stm32mp1-r2-rc8-PERF +From f9e34d8836c280d291e1779bf50f895f55a1e8fc Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:16:53 +0100 +Subject: [PATCH 14/22] ARM 5.10.10-stm32mp1-r1 PERF --- - Documentation/perf/stm32-ddr-pmu.txt | 41 +++ - drivers/perf/Kconfig | 6 + - drivers/perf/Makefile | 1 + - drivers/perf/stm32_ddr_pmu.c | 505 +++++++++++++++++++++++++++ - 4 files changed, 553 insertions(+) - create mode 100644 Documentation/perf/stm32-ddr-pmu.txt + Documentation/admin-guide/perf/index.rst | 1 + + .../admin-guide/perf/stm32-ddr-pmu.rst | 44 ++ + drivers/perf/Kconfig | 7 + + drivers/perf/Makefile | 1 + + drivers/perf/stm32_ddr_pmu.c | 428 ++++++++++++++++++ + 5 files changed, 481 insertions(+) + create mode 100644 Documentation/admin-guide/perf/stm32-ddr-pmu.rst create mode 100644 drivers/perf/stm32_ddr_pmu.c -diff --git a/Documentation/perf/stm32-ddr-pmu.txt b/Documentation/perf/stm32-ddr-pmu.txt +diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst +index 5a8f2529a033..9f68f68be161 100644 +--- a/Documentation/admin-guide/perf/index.rst ++++ b/Documentation/admin-guide/perf/index.rst +@@ -11,6 +11,7 @@ Performance monitor support + imx-ddr + qcom_l2_pmu + qcom_l3_pmu ++ stm32-ddr-pmu + arm-ccn + arm-cmn + xgene-pmu +diff --git a/Documentation/admin-guide/perf/stm32-ddr-pmu.rst b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst new file mode 100644 -index 0000000000000..d5b35b3261bdb +index 000000000000..db647fc1acad --- /dev/null -+++ b/Documentation/perf/stm32-ddr-pmu.txt -@@ -0,0 +1,41 @@ ++++ b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst +@@ -0,0 +1,44 @@ ++======================================== +STM32 DDR Performance Monitor (DDRPERFM) +======================================== + +The DDRPERFM is the DDR Performance Monitor embedded in STM32MP1 SOC. -+See STM32MP157 reference manual RM0436 to get a description of this peripheral. ++See Documentation/arm/stm32/stm32mp157-overview.rst to get access to ++STM32MP157 reference manual RM0436 where DDRPERFM is described. + + +The five following counters are supported by stm32-ddr-pmu driver: @@ -34,6 +49,9 @@ index 0000000000000..d5b35b3261bdb + +The stm32-ddr-pmu driver relies on the perf PMU framework to expose the +counters via sysfs: ++ ++ .. code-block:: bash ++ + $ ls /sys/bus/event_source/devices/ddrperfm/events + activate_cnt idle_cnt read_cnt time_cnt write_cnt + @@ -46,7 +64,10 @@ index 0000000000000..d5b35b3261bdb +option is mandatory! + +Example: -+ $ perf stat -e ddrperfm/read_cnt/,ddrperfm/time_cnt/ -a sleep 20 ++ ++ .. code-block:: bash ++ ++ $ perf stat -e ddrperfm/read_cnt/,ddrperfm/time_cnt/ -a sleep 20 + Performance counter stats for 'system wide': + + 342541560 ddrperfm/read_cnt/ @@ -54,33 +75,29 @@ index 0000000000000..d5b35b3261bdb + + 20.021068551 seconds time elapsed + -+ -+The driver also exposes a 'bandwidth' attribute that can be used to display -+the read/write/total bandwidth achieved during the last 'perf stat' execution. -+ $ cat /sys/bus/event_source/devices/ddrperfm/bandwidth -+ Read = 403, Write = 239, Read & Write = 642 (MB/s) diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig -index 09ae8a970880f..2c50413145ab1 100644 +index 130327ff0b0e..a62a26fc516a 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig -@@ -105,6 +105,12 @@ config QCOM_L3_PMU +@@ -106,6 +106,13 @@ config QCOM_L3_PMU Adds the L3 cache PMU into the perf events subsystem for monitoring L3 cache events. +config STM32_DDR_PMU -+ bool "STM32 DDR PMU" -+ depends on MACH_STM32MP157 -+ help -+ Support for STM32 DDR performance monitor (DDRPERFM). ++ tristate "STM32 DDR PMU" ++ depends on MACH_STM32MP157 ++ default m ++ help ++ Support for STM32 DDR performance monitor (DDRPERFM). + config THUNDERX2_PMU tristate "Cavium ThunderX2 SoC PMU UNCORE" depends on ARCH_THUNDER2 && ARM64 && ACPI && NUMA diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile -index 2ebb4de178151..fd3368c1b4549 100644 +index 5365fd56f88f..7f2b7c5f9216 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile -@@ -9,6 +9,7 @@ obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o +@@ -10,6 +10,7 @@ obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o obj-$(CONFIG_HISI_PMU) += hisilicon/ obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o @@ -90,51 +107,52 @@ index 2ebb4de178151..fd3368c1b4549 100644 obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c new file mode 100644 -index 0000000000000..4f30f6f8be964 +index 000000000000..ee7a33083e02 --- /dev/null +++ b/drivers/perf/stm32_ddr_pmu.c -@@ -0,0 +1,505 @@ +@@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file is the STM32 DDR performance monitor (DDRPERFM) driver + * -+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + * Author: Gerald Baeza + */ + +#include ++#include +#include +#include +#include +#include +#include ++#include +#include +#include + -+#define POLL_MS 4000 /* The counter roll over after ~8s @533MHz */ -+#define WORD_LENGTH 4 /* Bytes */ -+#define BURST_LENGTH 8 /* Words */ ++/* ++ * The PMU is able to freeze all counters and generate an interrupt when there ++ * is a counter overflow. But, relying on this means that we lose all the ++ * events that occur between the freeze and the interrupt handler execution. ++ * So we use a polling mechanism to avoid this lose of information. ++ * The fastest counter can overflow in ~8s @533MHz (that is the maximum DDR ++ * frequency supported on STM32MP157), so we poll in 4s intervals to ensure ++ * we don't reach this limit. ++ */ ++#define POLL_MS 4000 + +#define DDRPERFM_CTL 0x000 +#define DDRPERFM_CFG 0x004 +#define DDRPERFM_STATUS 0x008 +#define DDRPERFM_CCR 0x00C -+#define DDRPERFM_IER 0x010 -+#define DDRPERFM_ISR 0x014 -+#define DDRPERFM_ICR 0x018 +#define DDRPERFM_TCNT 0x020 +#define DDRPERFM_CNT(X) (0x030 + 8 * (X)) -+#define DDRPERFM_HWCFG 0x3F0 +#define DDRPERFM_VER 0x3F4 +#define DDRPERFM_ID 0x3F8 -+#define DDRPERFM_SID 0x3FC + +#define CTL_START 0x00000001 +#define CTL_STOP 0x00000002 +#define CCR_CLEAR_ALL 0x8000000F -+#define SID_MAGIC_ID 0xA3C5DD01 -+ -+#define STRING "Read = %llu, Write = %llu, Read & Write = %llu (MB/s)\n" + +enum { + READ_CNT, @@ -148,12 +166,11 @@ index 0000000000000..4f30f6f8be964 +struct stm32_ddr_pmu { + struct pmu pmu; + void __iomem *membase; ++ struct device *dev; + struct clk *clk; -+ struct clk *clk_ddr; -+ unsigned long clk_ddr_rate; + struct hrtimer hrtimer; ++ cpumask_t pmu_cpu; + ktime_t poll_period; -+ spinlock_t lock; /* for shared registers access */ + struct perf_event *events[PMU_NR_COUNTERS]; + u64 events_cnt[PMU_NR_COUNTERS]; +}; @@ -168,98 +185,41 @@ index 0000000000000..4f30f6f8be964 + return container_of(h, struct stm32_ddr_pmu, hrtimer); +} + -+static u64 stm32_ddr_pmu_compute_bw(struct stm32_ddr_pmu *stm32_ddr_pmu, -+ int counter) -+{ -+ u64 bw = stm32_ddr_pmu->events_cnt[counter], tmp; -+ u64 div = stm32_ddr_pmu->events_cnt[TIME_CNT]; -+ u32 prediv = 1, premul = 1; -+ -+ if (bw && div) { -+ /* Maximize the dividend into 64 bits */ -+ while ((bw < 0x8000000000000000ULL) && -+ (premul < 0x40000000UL)) { -+ bw = bw << 1; -+ premul *= 2; -+ } -+ /* Minimize the dividor to fit in 32 bits */ -+ while ((div > 0xffffffffUL) && (prediv < 0x40000000UL)) { -+ div = div >> 1; -+ prediv *= 2; -+ } -+ /* Divide counter per time and multiply per DDR settings */ -+ do_div(bw, div); -+ tmp = bw * BURST_LENGTH * WORD_LENGTH; -+ tmp *= stm32_ddr_pmu->clk_ddr_rate; -+ if (tmp < bw) -+ goto error; -+ bw = tmp; -+ /* Cancel the prediv and premul factors */ -+ while (prediv > 1) { -+ bw = bw >> 1; -+ prediv /= 2; -+ } -+ while (premul > 1) { -+ bw = bw >> 1; -+ premul /= 2; -+ } -+ /* Convert MHz to Hz and B to MB, to finally get MB/s */ -+ tmp = bw * 1000000; -+ if (tmp < bw) -+ goto error; -+ bw = tmp; -+ premul = 1024 * 1024; -+ while (premul > 1) { -+ bw = bw >> 1; -+ premul /= 2; -+ } -+ } -+ return bw; -+ -+error: -+ pr_warn("stm32-ddr-pmu: overflow detected\n"); -+ return 0; -+} -+ +static void stm32_ddr_pmu_event_configure(struct perf_event *event) +{ + struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu); -+ unsigned long lock_flags, config_base = event->hw.config_base; ++ unsigned long config_base = event->hw.config_base; + u32 val; + -+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags); + writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL); + + if (config_base < TIME_CNT) { + val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG); -+ val |= (1 << config_base); ++ val |= BIT(config_base); + writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG); + } -+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags); +} + +static void stm32_ddr_pmu_event_read(struct perf_event *event) +{ + struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu); -+ unsigned long flags, config_base = event->hw.config_base; ++ unsigned long config_base = event->hw.config_base; + struct hw_perf_event *hw = &event->hw; + u64 prev_count, new_count, mask; + u32 val, offset, bit; + -+ spin_lock_irqsave(&stm32_ddr_pmu->lock, flags); -+ + writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL); + + if (config_base == TIME_CNT) { + offset = DDRPERFM_TCNT; -+ bit = 1 << 31; ++ bit = BIT(31); + } else { + offset = DDRPERFM_CNT(config_base); -+ bit = 1 << config_base; ++ bit = BIT(config_base); + } + val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_STATUS); + if (val & bit) -+ pr_warn("stm32_ddr_pmu hardware overflow\n"); ++ dev_warn(stm32_ddr_pmu->dev, "hardware counter overflow\n"); + val = readl_relaxed(stm32_ddr_pmu->membase + offset); + writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR); + writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL); @@ -271,18 +231,12 @@ index 0000000000000..4f30f6f8be964 + + mask = GENMASK_ULL(31, 0); + local64_add(val & mask, &event->count); -+ -+ if (new_count < prev_count) -+ pr_warn("STM32 DDR PMU counter saturated\n"); -+ -+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, flags); +} + +static void stm32_ddr_pmu_event_start(struct perf_event *event, int flags) +{ + struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu); + struct hw_perf_event *hw = &event->hw; -+ unsigned long lock_flags; + + if (WARN_ON_ONCE(!(hw->state & PERF_HES_STOPPED))) + return; @@ -293,37 +247,33 @@ index 0000000000000..4f30f6f8be964 + stm32_ddr_pmu_event_configure(event); + + /* Clear all counters to synchronize them, then start */ -+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags); + writel_relaxed(CCR_CLEAR_ALL, stm32_ddr_pmu->membase + DDRPERFM_CCR); + writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL); -+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags); -+ ++ local64_set(&hw->prev_count, 0); + hw->state = 0; +} + +static void stm32_ddr_pmu_event_stop(struct perf_event *event, int flags) +{ + struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu); -+ unsigned long lock_flags, config_base = event->hw.config_base; ++ unsigned long config_base = event->hw.config_base; + struct hw_perf_event *hw = &event->hw; + u32 val, bit; + + if (WARN_ON_ONCE(hw->state & PERF_HES_STOPPED)) + return; + -+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags); + writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL); + if (config_base == TIME_CNT) -+ bit = 1 << 31; ++ bit = BIT(31); + else -+ bit = 1 << config_base; ++ bit = BIT(config_base); + writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR); + if (config_base < TIME_CNT) { + val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG); + val &= ~bit; + writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG); + } -+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags); + + hw->state |= PERF_HES_STOPPED; + @@ -343,8 +293,13 @@ index 0000000000000..4f30f6f8be964 + stm32_ddr_pmu->events[config_base] = event; + + clk_enable(stm32_ddr_pmu->clk); ++ /* ++ * Pin the timer, so that the overflows are handled by the chosen ++ * event->cpu (this is the same one as presented in "cpumask" ++ * attribute). ++ */ + hrtimer_start(&stm32_ddr_pmu->hrtimer, stm32_ddr_pmu->poll_period, -+ HRTIMER_MODE_REL); ++ HRTIMER_MODE_REL_PINNED); + + stm32_ddr_pmu_event_configure(event); + @@ -360,7 +315,6 @@ index 0000000000000..4f30f6f8be964 +{ + struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu); + unsigned long config_base = event->hw.config_base; -+ bool stop = true; + int i; + + stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE); @@ -370,8 +324,9 @@ index 0000000000000..4f30f6f8be964 + + for (i = 0; i < PMU_NR_COUNTERS; i++) + if (stm32_ddr_pmu->events[i]) -+ stop = false; -+ if (stop) ++ break; ++ ++ if (i == PMU_NR_COUNTERS) + hrtimer_cancel(&stm32_ddr_pmu->hrtimer); + + clk_disable(stm32_ddr_pmu->clk); @@ -379,11 +334,15 @@ index 0000000000000..4f30f6f8be964 + +static int stm32_ddr_pmu_event_init(struct perf_event *event) +{ ++ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu); + struct hw_perf_event *hw = &event->hw; + + if (event->attr.type != event->pmu->type) + return -ENOENT; + ++ if (event->attr.config >= PMU_NR_COUNTERS) ++ return -ENOENT; ++ + if (is_sampling_event(event)) + return -EINVAL; + @@ -402,6 +361,7 @@ index 0000000000000..4f30f6f8be964 + return -EINVAL; + + hw->config_base = event->attr.config; ++ event->cpu = cpumask_first(&stm32_ddr_pmu->pmu_cpu); + + return 0; +} @@ -431,27 +391,6 @@ index 0000000000000..4f30f6f8be964 + return sprintf(buf, "config=0x%lx\n", (unsigned long)eattr->var); +} + -+static ssize_t bandwidth_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct stm32_ddr_pmu *stm32_ddr_pmu = dev_get_drvdata(dev); -+ u64 r_bw, w_bw; -+ int ret; -+ -+ if (stm32_ddr_pmu->events_cnt[TIME_CNT]) { -+ r_bw = stm32_ddr_pmu_compute_bw(stm32_ddr_pmu, READ_CNT); -+ w_bw = stm32_ddr_pmu_compute_bw(stm32_ddr_pmu, WRITE_CNT); -+ -+ ret = snprintf(buf, PAGE_SIZE, STRING, -+ r_bw, w_bw, (r_bw + w_bw)); -+ } else { -+ ret = snprintf(buf, PAGE_SIZE, "No data available\n"); -+ } -+ -+ return ret; -+} -+ +#define STM32_DDR_PMU_ATTR(_name, _func, _config) \ + (&((struct dev_ext_attribute[]) { \ + { __ATTR(_name, 0444, _func, NULL), (void *)_config } \ @@ -470,82 +409,66 @@ index 0000000000000..4f30f6f8be964 + NULL +}; + -+static DEVICE_ATTR_RO(bandwidth); -+static struct attribute *stm32_ddr_pmu_bandwidth_attrs[] = { -+ &dev_attr_bandwidth.attr, -+ NULL, -+}; -+ +static struct attribute_group stm32_ddr_pmu_event_attrs_group = { + .name = "events", + .attrs = stm32_ddr_pmu_event_attrs, +}; + -+static struct attribute_group stm32_ddr_pmu_bandwidth_attrs_group = { -+ .attrs = stm32_ddr_pmu_bandwidth_attrs, -+}; -+ +static const struct attribute_group *stm32_ddr_pmu_attr_groups[] = { + &stm32_ddr_pmu_event_attrs_group, -+ &stm32_ddr_pmu_bandwidth_attrs_group, + NULL, +}; + +static int stm32_ddr_pmu_device_probe(struct platform_device *pdev) +{ + struct stm32_ddr_pmu *stm32_ddr_pmu; ++ struct reset_control *rst; + struct resource *res; + int i, ret; -+ u32 val; + + stm32_ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(struct stm32_ddr_pmu), + GFP_KERNEL); + if (!stm32_ddr_pmu) + return -ENOMEM; + platform_set_drvdata(pdev, stm32_ddr_pmu); ++ stm32_ddr_pmu->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + stm32_ddr_pmu->membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(stm32_ddr_pmu->membase)) { -+ pr_warn("Unable to get STM32 DDR PMU membase\n"); ++ dev_err(&pdev->dev, "Unable to get membase\n"); + return PTR_ERR(stm32_ddr_pmu->membase); + } + -+ stm32_ddr_pmu->clk = devm_clk_get(&pdev->dev, "bus"); ++ stm32_ddr_pmu->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(stm32_ddr_pmu->clk)) { -+ pr_warn("Unable to get STM32 DDR PMU clock\n"); ++ dev_err(&pdev->dev, "unable to get the clock\n"); + return PTR_ERR(stm32_ddr_pmu->clk); + } + + ret = clk_prepare_enable(stm32_ddr_pmu->clk); + if (ret) { -+ pr_warn("Unable to prepare STM32 DDR PMU clock\n"); ++ dev_err(&pdev->dev, "unable to prepare the clock\n"); + return ret; + } + -+ stm32_ddr_pmu->clk_ddr = devm_clk_get(&pdev->dev, "ddr"); -+ if (IS_ERR(stm32_ddr_pmu->clk_ddr)) { -+ pr_warn("Unable to get STM32 DDR clock\n"); -+ return PTR_ERR(stm32_ddr_pmu->clk_ddr); -+ } -+ stm32_ddr_pmu->clk_ddr_rate = clk_get_rate(stm32_ddr_pmu->clk_ddr); -+ stm32_ddr_pmu->clk_ddr_rate /= 1000000; -+ + stm32_ddr_pmu->poll_period = ms_to_ktime(POLL_MS); + hrtimer_init(&stm32_ddr_pmu->hrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + stm32_ddr_pmu->hrtimer.function = stm32_ddr_pmu_poll; -+ spin_lock_init(&stm32_ddr_pmu->lock); ++ ++ /* ++ * The PMU is assigned to the cpu0 and there is no need to manage cpu ++ * hot plug migration because cpu0 is always the first/last active cpu ++ * during low power transitions. ++ */ ++ cpumask_set_cpu(0, &stm32_ddr_pmu->pmu_cpu); + + for (i = 0; i < PMU_NR_COUNTERS; i++) { + stm32_ddr_pmu->events[i] = NULL; + stm32_ddr_pmu->events_cnt[i] = 0; + } + -+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_SID); -+ if (val != SID_MAGIC_ID) -+ return -EINVAL; -+ + stm32_ddr_pmu->pmu = (struct pmu) { + .task_ctx_nr = perf_invalid_context, + .start = stm32_ddr_pmu_event_start, @@ -555,20 +478,35 @@ index 0000000000000..4f30f6f8be964 + .event_init = stm32_ddr_pmu_event_init, + .attr_groups = stm32_ddr_pmu_attr_groups, + }; -+ ret = perf_pmu_register(&stm32_ddr_pmu->pmu, "ddrperfm", -1); ++ ret = perf_pmu_register(&stm32_ddr_pmu->pmu, "stm32_ddr_pmu", -1); + if (ret) { -+ pr_warn("Unable to register STM32 DDR PMU\n"); -+ return ret; ++ dev_err(&pdev->dev, "unable to register the pmu\n"); ++ goto err_pmu_register; + } + -+ pr_info("stm32-ddr-pmu: probed (ID=0x%08x VER=0x%08x), DDR@%luMHz\n", -+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_ID), -+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_VER), -+ stm32_ddr_pmu->clk_ddr_rate); ++ rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); ++ if (IS_ERR(rst)) { ++ dev_err(&pdev->dev, "unable to get the reset\n"); ++ ret = -ENOENT; ++ goto err_get_reset; ++ } ++ reset_control_assert(rst); ++ udelay(2); ++ reset_control_deassert(rst); ++ ++ dev_info(&pdev->dev, "probed (DDRPERFM ID=0x%08x VER=0x%08x)\n", ++ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_ID), ++ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_VER)); + + clk_disable(stm32_ddr_pmu->clk); + + return 0; ++ ++err_get_reset: ++ perf_pmu_unregister(&stm32_ddr_pmu->pmu); ++err_pmu_register: ++ clk_disable_unprepare(stm32_ddr_pmu->clk); ++ return ret; +} + +static int stm32_ddr_pmu_device_remove(struct platform_device *pdev) @@ -577,6 +515,8 @@ index 0000000000000..4f30f6f8be964 + + perf_pmu_unregister(&stm32_ddr_pmu->pmu); + ++ clk_unprepare(stm32_ddr_pmu->clk); ++ + return 0; +} + diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0015-ARM-5.10.10-stm32mp1-r1-PHY-USB.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0015-ARM-5.10.10-stm32mp1-r1-PHY-USB.patch new file mode 100644 index 0000000..4311e17 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0015-ARM-5.10.10-stm32mp1-r1-PHY-USB.patch @@ -0,0 +1,1373 @@ +From 731c37c7d36e13cac98e1c872657c03613fc5259 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:14:10 +0100 +Subject: [PATCH 15/22] ARM 5.10.10-stm32mp1-r1 PHY-USB + +Signed-off-by: Romuald JEANNE +--- + drivers/phy/st/phy-stm32-usbphyc.c | 499 +++++++++++++++++++++++++---- + drivers/usb/core/hcd.c | 9 +- + drivers/usb/core/phy.c | 22 +- + drivers/usb/core/phy.h | 6 +- + drivers/usb/dwc2/core.c | 123 ++++--- + drivers/usb/dwc2/core.h | 4 + + drivers/usb/dwc2/drd.c | 21 +- + drivers/usb/dwc2/gadget.c | 5 +- + drivers/usb/dwc2/hcd.c | 6 +- + drivers/usb/dwc2/params.c | 8 + + drivers/usb/dwc2/platform.c | 47 ++- + drivers/usb/host/ehci-platform.c | 16 +- + drivers/usb/typec/stusb160x.c | 11 +- + 13 files changed, 615 insertions(+), 162 deletions(-) + +diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c +index 2b3639cba51a..5f169d5c669e 100644 +--- a/drivers/phy/st/phy-stm32-usbphyc.c ++++ b/drivers/phy/st/phy-stm32-usbphyc.c +@@ -7,8 +7,9 @@ + */ + #include + #include ++#include + #include +-#include ++#include + #include + #include + #include +@@ -17,6 +18,8 @@ + + #define STM32_USBPHYC_PLL 0x0 + #define STM32_USBPHYC_MISC 0x8 ++#define STM32_USBPHYC_MONITOR(X) (0x108 + ((X) * 0x100)) ++#define STM32_USBPHYC_TUNE(X) (0x10C + ((X) * 0x100)) + #define STM32_USBPHYC_VERSION 0x3F4 + + /* STM32_USBPHYC_PLL bit fields */ +@@ -32,19 +35,93 @@ + /* STM32_USBPHYC_MISC bit fields */ + #define SWITHOST BIT(0) + +-/* STM32_USBPHYC_VERSION bit fields */ +-#define MINREV GENMASK(3, 0) +-#define MAJREV GENMASK(7, 4) ++/* STM32_USBPHYC_MONITOR bit fields */ ++#define STM32_USBPHYC_MON_OUT GENMASK(3, 0) ++#define STM32_USBPHYC_MON_SEL GENMASK(8, 4) ++#define STM32_USBPHYC_MON_SEL_LOCKP 0x1F ++#define STM32_USBPHYC_MON_OUT_LOCKP BIT(3) ++ ++/* STM32_USBPHYC_TUNE bit fields */ ++#define INCURREN BIT(0) ++#define INCURRINT BIT(1) ++#define LFSCAPEN BIT(2) ++#define HSDRVSLEW BIT(3) ++#define HSDRVDCCUR BIT(4) ++#define HSDRVDCLEV BIT(5) ++#define HSDRVCURINCR BIT(6) ++#define FSDRVRFADJ BIT(7) ++#define HSDRVRFRED BIT(8) ++#define HSDRVCHKITRM GENMASK(12, 9) ++#define HSDRVCHKZTRM GENMASK(14, 13) ++#define OTPCOMP GENMASK(19, 15) ++#define SQLCHCTL GENMASK(21, 20) ++#define HDRXGNEQEN BIT(22) ++#define HSRXOFF GENMASK(24, 23) ++#define HSFALLPREEM BIT(25) ++#define SHTCCTCTLPROT BIT(26) ++#define STAGSEL BIT(27) ++ ++enum boosting_vals { ++ BOOST_1_MA = 1, ++ BOOST_2_MA, ++ BOOST_MAX, ++}; ++ ++enum dc_level_vals { ++ DC_MINUS_5_TO_7_MV, ++ DC_PLUS_5_TO_7_MV, ++ DC_PLUS_10_TO_14_MV, ++ DC_MAX, ++}; ++ ++enum current_trim { ++ CUR_NOMINAL, ++ CUR_PLUS_1_56_PCT, ++ CUR_PLUS_3_12_PCT, ++ CUR_PLUS_4_68_PCT, ++ CUR_PLUS_6_24_PCT, ++ CUR_PLUS_7_8_PCT, ++ CUR_PLUS_9_36_PCT, ++ CUR_PLUS_10_92_PCT, ++ CUR_PLUS_12_48_PCT, ++ CUR_PLUS_14_04_PCT, ++ CUR_PLUS_15_6_PCT, ++ CUR_PLUS_17_16_PCT, ++ CUR_PLUS_19_01_PCT, ++ CUR_PLUS_20_58_PCT, ++ CUR_PLUS_22_16_PCT, ++ CUR_PLUS_23_73_PCT, ++ CUR_MAX, ++}; ++ ++enum impedance_trim { ++ IMP_NOMINAL, ++ IMP_MINUS_2_OHMS, ++ IMP_MINUS_4_OMHS, ++ IMP_MINUS_6_OHMS, ++ IMP_MAX, ++}; ++ ++enum squelch_level { ++ SQLCH_NOMINAL, ++ SQLCH_PLUS_7_MV, ++ SQLCH_MINUS_5_MV, ++ SQLCH_PLUS_14_MV, ++ SQLCH_MAX, ++}; + +-static const char * const supplies_names[] = { +- "vdda1v1", /* 1V1 */ +- "vdda1v8", /* 1V8 */ ++enum rx_offset { ++ NO_RX_OFFSET, ++ RX_OFFSET_PLUS_5_MV, ++ RX_OFFSET_PLUS_10_MV, ++ RX_OFFSET_MINUS_5_MV, ++ RX_OFFSET_MAX, + }; + +-#define NUM_SUPPLIES ARRAY_SIZE(supplies_names) ++/* STM32_USBPHYC_VERSION bit fields */ ++#define MINREV GENMASK(3, 0) ++#define MAJREV GENMASK(7, 4) + +-#define PLL_LOCK_TIME_US 100 +-#define PLL_PWR_DOWN_TIME_US 5 + #define PLL_FVCO_MHZ 2880 + #define PLL_INFF_MIN_RATE_HZ 19200000 + #define PLL_INFF_MAX_RATE_HZ 38400000 +@@ -58,7 +135,7 @@ struct pll_params { + struct stm32_usbphyc_phy { + struct phy *phy; + struct stm32_usbphyc *usbphyc; +- struct regulator_bulk_data supplies[NUM_SUPPLIES]; ++ struct regulator *vbus; + u32 index; + bool active; + }; +@@ -70,6 +147,10 @@ struct stm32_usbphyc { + struct reset_control *rst; + struct stm32_usbphyc_phy **phys; + int nphys; ++ struct regulator *vdda1v1; ++ struct regulator *vdda1v8; ++ atomic_t n_pll_cons; ++ struct clk_hw clk48_hw; + int switch_setup; + }; + +@@ -83,6 +164,41 @@ static inline void stm32_usbphyc_clr_bits(void __iomem *reg, u32 bits) + writel_relaxed(readl_relaxed(reg) & ~bits, reg); + } + ++static int stm32_usbphyc_regulators_enable(struct stm32_usbphyc *usbphyc) ++{ ++ int ret; ++ ++ ret = regulator_enable(usbphyc->vdda1v1); ++ if (ret) ++ return ret; ++ ++ ret = regulator_enable(usbphyc->vdda1v8); ++ if (ret) ++ goto vdda1v1_disable; ++ ++ return 0; ++ ++vdda1v1_disable: ++ regulator_disable(usbphyc->vdda1v1); ++ ++ return ret; ++} ++ ++static int stm32_usbphyc_regulators_disable(struct stm32_usbphyc *usbphyc) ++{ ++ int ret; ++ ++ ret = regulator_disable(usbphyc->vdda1v8); ++ if (ret) ++ return ret; ++ ++ ret = regulator_disable(usbphyc->vdda1v1); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ + static void stm32_usbphyc_get_pll_params(u32 clk_rate, + struct pll_params *pll_params) + { +@@ -142,83 +258,106 @@ static int stm32_usbphyc_pll_init(struct stm32_usbphyc *usbphyc) + return 0; + } + +-static bool stm32_usbphyc_has_one_phy_active(struct stm32_usbphyc *usbphyc) ++static int __stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc) + { +- int i; ++ void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; ++ u32 pllen; ++ ++ stm32_usbphyc_clr_bits(pll_reg, PLLEN); + +- for (i = 0; i < usbphyc->nphys; i++) +- if (usbphyc->phys[i]->active) +- return true; ++ /* Wait for minimum width of powerdown pulse (ENABLE = Low) */ ++ if (readl_relaxed_poll_timeout(pll_reg, pllen, !(pllen & PLLEN), 5, 50)) ++ dev_err(usbphyc->dev, "PLL not reset\n"); + +- return false; ++ return stm32_usbphyc_regulators_disable(usbphyc); ++} ++ ++static int stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc) ++{ ++ /* Check if a phy port is still active or clk48 in use */ ++ if (atomic_dec_return(&usbphyc->n_pll_cons) > 0) ++ return 0; ++ ++ return __stm32_usbphyc_pll_disable(usbphyc); + } + + static int stm32_usbphyc_pll_enable(struct stm32_usbphyc *usbphyc) + { + void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; +- bool pllen = (readl_relaxed(pll_reg) & PLLEN); ++ bool pllen = readl_relaxed(pll_reg) & PLLEN; + int ret; + +- /* Check if one phy port has already configured the pll */ +- if (pllen && stm32_usbphyc_has_one_phy_active(usbphyc)) ++ /* ++ * Check if a phy port or clk48 prepare has configured the pll ++ * and ensure the PLL is enabled ++ */ ++ if (atomic_inc_return(&usbphyc->n_pll_cons) > 1 && pllen) + return 0; + + if (pllen) { +- stm32_usbphyc_clr_bits(pll_reg, PLLEN); +- /* Wait for minimum width of powerdown pulse (ENABLE = Low) */ +- udelay(PLL_PWR_DOWN_TIME_US); ++ /* ++ * PLL shouldn't be enabled without known consumer, ++ * disable it and reinit n_pll_cons ++ */ ++ dev_warn(usbphyc->dev, "PLL enabled without known consumers\n"); ++ ++ ret = __stm32_usbphyc_pll_disable(usbphyc); ++ if (ret) ++ return ret; + } + ++ ret = stm32_usbphyc_regulators_enable(usbphyc); ++ if (ret) ++ goto dec_n_pll_cons; ++ + ret = stm32_usbphyc_pll_init(usbphyc); + if (ret) +- return ret; ++ goto reg_disable; + + stm32_usbphyc_set_bits(pll_reg, PLLEN); + +- /* Wait for maximum lock time */ +- udelay(PLL_LOCK_TIME_US); +- +- if (!(readl_relaxed(pll_reg) & PLLEN)) { +- dev_err(usbphyc->dev, "PLLEN not set\n"); +- return -EIO; +- } +- + return 0; +-} + +-static int stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc) +-{ +- void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; ++reg_disable: ++ stm32_usbphyc_regulators_disable(usbphyc); + +- /* Check if other phy port active */ +- if (stm32_usbphyc_has_one_phy_active(usbphyc)) +- return 0; ++dec_n_pll_cons: ++ atomic_dec(&usbphyc->n_pll_cons); + +- stm32_usbphyc_clr_bits(pll_reg, PLLEN); +- /* Wait for minimum width of powerdown pulse (ENABLE = Low) */ +- udelay(PLL_PWR_DOWN_TIME_US); +- +- if (readl_relaxed(pll_reg) & PLLEN) { +- dev_err(usbphyc->dev, "PLL not reset\n"); +- return -EIO; +- } +- +- return 0; ++ return ret; + } + + static int stm32_usbphyc_phy_init(struct phy *phy) + { + struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); + struct stm32_usbphyc *usbphyc = usbphyc_phy->usbphyc; ++ u32 reg_mon = STM32_USBPHYC_MONITOR(usbphyc_phy->index); ++ u32 monsel = FIELD_PREP(STM32_USBPHYC_MON_SEL, ++ STM32_USBPHYC_MON_SEL_LOCKP); ++ u32 monout; + int ret; + + ret = stm32_usbphyc_pll_enable(usbphyc); + if (ret) + return ret; + ++ /* Check that PLL Lock input to PHY is High */ ++ writel_relaxed(monsel, usbphyc->base + reg_mon); ++ ret = readl_relaxed_poll_timeout(usbphyc->base + reg_mon, monout, ++ (monout & STM32_USBPHYC_MON_OUT_LOCKP), ++ 100, 1000); ++ if (ret) { ++ dev_err(usbphyc->dev, "PLL Lock input to PHY is Low (val=%x)\n", ++ (u32)(monout & STM32_USBPHYC_MON_OUT)); ++ goto pll_disable; ++ } ++ + usbphyc_phy->active = true; + + return 0; ++ ++pll_disable: ++ return stm32_usbphyc_pll_disable(usbphyc); + } + + static int stm32_usbphyc_phy_exit(struct phy *phy) +@@ -235,14 +374,20 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy) + { + struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); + +- return regulator_bulk_enable(NUM_SUPPLIES, usbphyc_phy->supplies); ++ if (usbphyc_phy->vbus) ++ return regulator_enable(usbphyc_phy->vbus); ++ ++ return 0; + } + + static int stm32_usbphyc_phy_power_off(struct phy *phy) + { + struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); + +- return regulator_bulk_disable(NUM_SUPPLIES, usbphyc_phy->supplies); ++ if (usbphyc_phy->vbus) ++ return regulator_disable(usbphyc_phy->vbus); ++ ++ return 0; + } + + static const struct phy_ops stm32_usbphyc_phy_ops = { +@@ -253,6 +398,162 @@ static const struct phy_ops stm32_usbphyc_phy_ops = { + .owner = THIS_MODULE, + }; + ++static int stm32_usbphyc_clk48_prepare(struct clk_hw *hw) ++{ ++ struct stm32_usbphyc *usbphyc = container_of(hw, struct stm32_usbphyc, ++ clk48_hw); ++ ++ return stm32_usbphyc_pll_enable(usbphyc); ++} ++ ++static void stm32_usbphyc_clk48_unprepare(struct clk_hw *hw) ++{ ++ struct stm32_usbphyc *usbphyc = container_of(hw, struct stm32_usbphyc, ++ clk48_hw); ++ ++ stm32_usbphyc_pll_disable(usbphyc); ++} ++ ++static unsigned long stm32_usbphyc_clk48_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ return 48000000; ++} ++ ++static const struct clk_ops usbphyc_clk48_ops = { ++ .prepare = stm32_usbphyc_clk48_prepare, ++ .unprepare = stm32_usbphyc_clk48_unprepare, ++ .recalc_rate = stm32_usbphyc_clk48_recalc_rate, ++}; ++ ++static void stm32_usbphyc_clk48_unregister(void *data) ++{ ++ struct stm32_usbphyc *usbphyc = data; ++ ++ of_clk_del_provider(usbphyc->dev->of_node); ++ clk_hw_unregister(&usbphyc->clk48_hw); ++} ++ ++static int stm32_usbphyc_clk48_register(struct stm32_usbphyc *usbphyc) ++{ ++ struct device_node *node = usbphyc->dev->of_node; ++ struct clk_init_data init = { }; ++ int ret = 0; ++ ++ init.name = "ck_usbo_48m"; ++ init.ops = &usbphyc_clk48_ops; ++ ++ usbphyc->clk48_hw.init = &init; ++ ++ ret = clk_hw_register(usbphyc->dev, &usbphyc->clk48_hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, ++ &usbphyc->clk48_hw); ++ if (ret) ++ clk_hw_unregister(&usbphyc->clk48_hw); ++ ++ return ret; ++} ++ ++static void stm32_usbphyc_phy_tuning(struct stm32_usbphyc *usbphyc, ++ struct device_node *np, u32 index) ++{ ++ struct device_node *tune_np; ++ u32 reg = STM32_USBPHYC_TUNE(index); ++ u32 otpcomp, val, tune = 0; ++ int ret; ++ ++ tune_np = of_parse_phandle(np, "st,phy-tuning", 0); ++ if (!tune_np) ++ return; ++ ++ /* Backup OTP compensation code */ ++ otpcomp = FIELD_GET(OTPCOMP, readl_relaxed(usbphyc->base + reg)); ++ ++ ret = of_property_read_u32(tune_np, "st,current-boost", &val); ++ if (!ret && val < BOOST_MAX) { ++ val = (val == BOOST_2_MA) ? 1 : 0; ++ tune |= INCURREN | FIELD_PREP(INCURRINT, val); ++ } else if (ret != -EINVAL) { ++ dev_warn(usbphyc->dev, ++ "phy%d: invalid st,current-boost value\n", index); ++ } ++ ++ if (!of_property_read_bool(tune_np, "st,no-lsfs-fb-cap")) ++ tune |= LFSCAPEN; ++ ++ if (of_property_read_bool(tune_np, "st,hs-slew-ctrl")) ++ tune |= HSDRVSLEW; ++ ++ ret = of_property_read_u32(tune_np, "st,hs-dc-level", &val); ++ if (!ret && val < DC_MAX) { ++ if (val == DC_MINUS_5_TO_7_MV) { ++ tune |= HSDRVDCCUR; ++ } else { ++ val = (val == DC_PLUS_10_TO_14_MV) ? 1 : 0; ++ tune |= HSDRVCURINCR | FIELD_PREP(HSDRVDCLEV, val); ++ } ++ } else if (ret != -EINVAL) { ++ dev_warn(usbphyc->dev, ++ "phy%d: invalid st,hs-dc-level value\n", index); ++ } ++ ++ if (of_property_read_bool(tune_np, "st,fs-rftime-tuning")) ++ tune |= FSDRVRFADJ; ++ ++ if (of_property_read_bool(tune_np, "st,hs-rftime-reduction")) ++ tune |= HSDRVRFRED; ++ ++ ret = of_property_read_u32(tune_np, "st,hs-current-trim", &val); ++ if (!ret && val < CUR_MAX) ++ tune |= FIELD_PREP(HSDRVCHKITRM, val); ++ else if (ret != -EINVAL) ++ dev_warn(usbphyc->dev, ++ "phy%d: invalid st,hs-current-trim value\n", index); ++ ++ ret = of_property_read_u32(tune_np, "st,hs-impedance-trim", &val); ++ if (!ret && val < IMP_MAX) ++ tune |= FIELD_PREP(HSDRVCHKZTRM, val); ++ else if (ret != -EINVAL) ++ dev_warn(usbphyc->dev, ++ "phy%d: invalid hs-impedance-trim value\n", index); ++ ++ ret = of_property_read_u32(tune_np, "st,squelch-level", &val); ++ if (!ret && val < SQLCH_MAX) ++ tune |= FIELD_PREP(SQLCHCTL, val); ++ else if (ret != -EINVAL) ++ dev_warn(usbphyc->dev, ++ "phy%d: invalid st,squelch-level value\n", index); ++ ++ if (of_property_read_bool(tune_np, "st,hs-rx-gain-eq")) ++ tune |= HDRXGNEQEN; ++ ++ ret = of_property_read_u32(tune_np, "st,hs-rx-offset", &val); ++ if (!ret && val < RX_OFFSET_MAX) ++ tune |= FIELD_PREP(HSRXOFF, val); ++ else if (ret != -EINVAL) ++ dev_warn(usbphyc->dev, ++ "phy%d: invalid st,hs-rx-offset value\n", index); ++ ++ if (of_property_read_bool(tune_np, "st,no-hs-ftime-ctrl")) ++ tune |= HSFALLPREEM; ++ ++ if (!of_property_read_bool(tune_np, "st,no-lsfs-sc")) ++ tune |= SHTCCTCTLPROT; ++ ++ if (of_property_read_bool(tune_np, "st,hs-tx-staggering")) ++ tune |= STAGSEL; ++ ++ of_node_put(tune_np); ++ ++ /* Restore OTP compensation code */ ++ tune |= FIELD_PREP(OTPCOMP, otpcomp); ++ ++ writel_relaxed(tune, usbphyc->base + reg); ++} ++ + static void stm32_usbphyc_switch_setup(struct stm32_usbphyc *usbphyc, + u32 utmi_switch) + { +@@ -313,7 +614,7 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + struct device_node *child, *np = dev->of_node; + struct resource *res; + struct phy_provider *phy_provider; +- u32 version; ++ u32 pllen, version; + int ret, port = 0; + + usbphyc = devm_kzalloc(dev, sizeof(*usbphyc), GFP_KERNEL); +@@ -328,11 +629,8 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + return PTR_ERR(usbphyc->base); + + usbphyc->clk = devm_clk_get(dev, NULL); +- if (IS_ERR(usbphyc->clk)) { +- ret = PTR_ERR(usbphyc->clk); +- dev_err(dev, "clk get failed: %d\n", ret); +- return ret; +- } ++ if (IS_ERR(usbphyc->clk)) ++ return dev_err_probe(dev, PTR_ERR(usbphyc->clk), "clk get failed\n"); + + ret = clk_prepare_enable(usbphyc->clk); + if (ret) { +@@ -345,6 +643,23 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + reset_control_assert(usbphyc->rst); + udelay(2); + reset_control_deassert(usbphyc->rst); ++ } else { ++ ret = PTR_ERR(usbphyc->rst); ++ if (ret == -EPROBE_DEFER) ++ goto clk_disable; ++ ++ stm32_usbphyc_clr_bits(usbphyc->base + STM32_USBPHYC_PLL, PLLEN); ++ } ++ ++ /* ++ * Wait for minimum width of powerdown pulse (ENABLE = Low): ++ * we have to ensure the PLL is disabled before phys initialization. ++ */ ++ if (readl_relaxed_poll_timeout(usbphyc->base + STM32_USBPHYC_PLL, ++ pllen, !(pllen & PLLEN), 5, 50)) { ++ dev_warn(usbphyc->dev, "PLL not reset\n"); ++ ret = -EPROBE_DEFER; ++ goto clk_disable; + } + + usbphyc->switch_setup = -EINVAL; +@@ -356,11 +671,26 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + goto clk_disable; + } + ++ usbphyc->vdda1v1 = devm_regulator_get(dev, "vdda1v1"); ++ if (IS_ERR(usbphyc->vdda1v1)) { ++ ret = PTR_ERR(usbphyc->vdda1v1); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get vdda1v1 supply: %d\n", ret); ++ goto clk_disable; ++ } ++ ++ usbphyc->vdda1v8 = devm_regulator_get(dev, "vdda1v8"); ++ if (IS_ERR(usbphyc->vdda1v8)) { ++ ret = PTR_ERR(usbphyc->vdda1v8); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get vdda1v8 supply: %d\n", ret); ++ goto clk_disable; ++ } ++ + for_each_child_of_node(np, child) { + struct stm32_usbphyc_phy *usbphyc_phy; + struct phy *phy; + u32 index; +- int i; + + phy = devm_phy_create(dev, child, &stm32_usbphyc_phy_ops); + if (IS_ERR(phy)) { +@@ -378,24 +708,15 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + goto put_child; + } + +- for (i = 0; i < NUM_SUPPLIES; i++) +- usbphyc_phy->supplies[i].supply = supplies_names[i]; +- +- ret = devm_regulator_bulk_get(&phy->dev, NUM_SUPPLIES, +- usbphyc_phy->supplies); +- if (ret) { +- if (ret != -EPROBE_DEFER) +- dev_err(&phy->dev, +- "failed to get regulators: %d\n", ret); +- goto put_child; +- } +- + ret = of_property_read_u32(child, "reg", &index); + if (ret || index > usbphyc->nphys) { + dev_err(&phy->dev, "invalid reg property: %d\n", ret); + goto put_child; + } + ++ /* Configure phy tuning */ ++ stm32_usbphyc_phy_tuning(usbphyc, child, index); ++ + usbphyc->phys[port] = usbphyc_phy; + phy_set_bus_width(phy, 8); + phy_set_drvdata(phy, usbphyc_phy); +@@ -405,6 +726,14 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + usbphyc->phys[port]->index = index; + usbphyc->phys[port]->active = false; + ++ usbphyc->phys[port]->vbus = devm_regulator_get_optional(&phy->dev, "vbus"); ++ if (IS_ERR(usbphyc->phys[port]->vbus)) { ++ ret = PTR_ERR(usbphyc->phys[port]->vbus); ++ if (ret == -EPROBE_DEFER) ++ goto put_child; ++ usbphyc->phys[port]->vbus = NULL; ++ } ++ + port++; + } + +@@ -416,6 +745,13 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + goto clk_disable; + } + ++ ret = stm32_usbphyc_clk48_register(usbphyc); ++ if (ret) { ++ dev_err(dev, ++ "failed to register ck_usbo_48m clock: %d\n", ret); ++ goto clk_disable; ++ } ++ + version = readl_relaxed(usbphyc->base + STM32_USBPHYC_VERSION); + dev_info(dev, "registered rev:%lu.%lu\n", + FIELD_GET(MAJREV, version), FIELD_GET(MINREV, version)); +@@ -433,12 +769,34 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) + static int stm32_usbphyc_remove(struct platform_device *pdev) + { + struct stm32_usbphyc *usbphyc = dev_get_drvdata(&pdev->dev); ++ int port; ++ ++ /* Ensure PHYs are not active, to allow PLL disabling */ ++ for (port = 0; port < usbphyc->nphys; port++) ++ if (usbphyc->phys[port]->active) ++ stm32_usbphyc_phy_exit(usbphyc->phys[port]->phy); ++ ++ stm32_usbphyc_clk48_unregister(usbphyc); + + clk_disable_unprepare(usbphyc->clk); + + return 0; + } + ++#ifdef CONFIG_PM_SLEEP ++static int stm32_usbphyc_resume(struct device *dev) ++{ ++ struct stm32_usbphyc *usbphyc = dev_get_drvdata(dev); ++ ++ if (usbphyc->switch_setup >= 0) ++ stm32_usbphyc_switch_setup(usbphyc, usbphyc->switch_setup); ++ ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(stm32_usbphyc_pm_ops, NULL, stm32_usbphyc_resume); ++ + static const struct of_device_id stm32_usbphyc_of_match[] = { + { .compatible = "st,stm32mp1-usbphyc", }, + { }, +@@ -451,6 +809,7 @@ static struct platform_driver stm32_usbphyc_driver = { + .driver = { + .of_match_table = stm32_usbphyc_of_match, + .name = "stm32-usbphyc", ++ .pm = &stm32_usbphyc_pm_ops, + } + }; + module_platform_driver(stm32_usbphyc_driver); +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 2c6b9578a7d3..7765fb216128 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -2131,7 +2131,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) + + if (!PMSG_IS_AUTO(msg)) + usb_phy_roothub_suspend(hcd->self.sysdev, +- hcd->phy_roothub); ++ hcd->phy_roothub, ++ usb_wakeup_enabled_descendants(rhdev)); + + /* Did we race with a root-hub wakeup event? */ + if (rhdev->do_remote_wakeup) { +@@ -2172,7 +2173,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) + + if (!PMSG_IS_AUTO(msg)) { + status = usb_phy_roothub_resume(hcd->self.sysdev, +- hcd->phy_roothub); ++ hcd->phy_roothub, ++ usb_wakeup_enabled_descendants(rhdev)); + if (status) + return status; + } +@@ -2217,7 +2219,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) + } + } else { + hcd->state = old_state; +- usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub); ++ usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub, ++ usb_wakeup_enabled_descendants(rhdev)); + dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", + "resume", status); + if (status != -ESHUTDOWN) +diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c +index fb1588e7c282..746615aa1b2d 100644 +--- a/drivers/usb/core/phy.c ++++ b/drivers/usb/core/phy.c +@@ -212,34 +212,36 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub) + EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off); + + int usb_phy_roothub_suspend(struct device *controller_dev, +- struct usb_phy_roothub *phy_roothub) ++ struct usb_phy_roothub *phy_roothub, ++ unsigned wakeup_enabled_descendants) + { +- usb_phy_roothub_power_off(phy_roothub); +- + /* keep the PHYs initialized so the device can wake up the system */ +- if (device_may_wakeup(controller_dev)) ++ if (device_may_wakeup(controller_dev) || wakeup_enabled_descendants) + return 0; + ++ usb_phy_roothub_power_off(phy_roothub); ++ + return usb_phy_roothub_exit(phy_roothub); + } + EXPORT_SYMBOL_GPL(usb_phy_roothub_suspend); + + int usb_phy_roothub_resume(struct device *controller_dev, +- struct usb_phy_roothub *phy_roothub) ++ struct usb_phy_roothub *phy_roothub, ++ unsigned wakeup_enabled_descendants) + { +- int err; ++ int err = 0; + + /* if the device can't wake up the system _exit was called */ +- if (!device_may_wakeup(controller_dev)) { ++ if (!device_may_wakeup(controller_dev) && !wakeup_enabled_descendants) { + err = usb_phy_roothub_init(phy_roothub); + if (err) + return err; +- } + +- err = usb_phy_roothub_power_on(phy_roothub); ++ err = usb_phy_roothub_power_on(phy_roothub); ++ } + + /* undo _init if _power_on failed */ +- if (err && !device_may_wakeup(controller_dev)) ++ if (err && !device_may_wakeup(controller_dev) && !wakeup_enabled_descendants) + usb_phy_roothub_exit(phy_roothub); + + return err; +diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h +index 20a267cd986b..3df4ddbb6046 100644 +--- a/drivers/usb/core/phy.h ++++ b/drivers/usb/core/phy.h +@@ -23,8 +23,10 @@ int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub); + void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub); + + int usb_phy_roothub_suspend(struct device *controller_dev, +- struct usb_phy_roothub *phy_roothub); ++ struct usb_phy_roothub *phy_roothub, ++ unsigned wakeup_enabled_descendants); + int usb_phy_roothub_resume(struct device *controller_dev, +- struct usb_phy_roothub *phy_roothub); ++ struct usb_phy_roothub *phy_roothub, ++ unsigned wakeup_enabled_descendants); + + #endif /* __USB_CORE_PHY_H_ */ +diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c +index fec17a2d2447..6f9236d4dd38 100644 +--- a/drivers/usb/dwc2/core.c ++++ b/drivers/usb/dwc2/core.c +@@ -83,6 +83,7 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) + gr->pcgcctl1 = dwc2_readl(hsotg, PCGCCTL1); + gr->glpmcfg = dwc2_readl(hsotg, GLPMCFG); + gr->gi2cctl = dwc2_readl(hsotg, GI2CCTL); ++ gr->ggpio = dwc2_readl(hsotg, GGPIO); + gr->pcgcctl = dwc2_readl(hsotg, PCGCTL); + + gr->valid = true; +@@ -112,21 +113,82 @@ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) + gr->valid = false; + + dwc2_writel(hsotg, 0xffffffff, GINTSTS); ++ dwc2_writel(hsotg, gr->gahbcfg, GAHBCFG); ++ dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG); + dwc2_writel(hsotg, gr->gotgctl, GOTGCTL); + dwc2_writel(hsotg, gr->gintmsk, GINTMSK); +- dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG); +- dwc2_writel(hsotg, gr->gahbcfg, GAHBCFG); + dwc2_writel(hsotg, gr->grxfsiz, GRXFSIZ); + dwc2_writel(hsotg, gr->gnptxfsiz, GNPTXFSIZ); + dwc2_writel(hsotg, gr->gdfifocfg, GDFIFOCFG); + dwc2_writel(hsotg, gr->pcgcctl1, PCGCCTL1); + dwc2_writel(hsotg, gr->glpmcfg, GLPMCFG); + dwc2_writel(hsotg, gr->pcgcctl, PCGCTL); ++ dwc2_writel(hsotg, gr->ggpio, GGPIO); + dwc2_writel(hsotg, gr->gi2cctl, GI2CCTL); + + return 0; + } + ++int dwc2_backup_registers(struct dwc2_hsotg *hsotg) ++{ ++ int ret; ++ ++ /* Backup all registers */ ++ ret = dwc2_backup_global_registers(hsotg); ++ if (ret) { ++ dev_err(hsotg->dev, "%s: failed to backup global registers\n", ++ __func__); ++ return ret; ++ } ++ ++ if (dwc2_is_host_mode(hsotg)) { ++ ret = dwc2_backup_host_registers(hsotg); ++ if (ret) { ++ dev_err(hsotg->dev, "%s: failed to backup host registers\n", ++ __func__); ++ return ret; ++ } ++ } else { ++ ret = dwc2_backup_device_registers(hsotg); ++ if (ret) { ++ dev_err(hsotg->dev, "%s: failed to backup device registers\n", ++ __func__); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++int dwc2_restore_registers(struct dwc2_hsotg *hsotg) ++{ ++ int ret; ++ ++ ret = dwc2_restore_global_registers(hsotg); ++ if (ret) { ++ dev_err(hsotg->dev, "%s: failed to restore registers\n", ++ __func__); ++ return ret; ++ } ++ if (dwc2_is_host_mode(hsotg)) { ++ ret = dwc2_restore_host_registers(hsotg); ++ if (ret) { ++ dev_err(hsotg->dev, "%s: failed to restore host registers\n", ++ __func__); ++ return ret; ++ } ++ } else { ++ ret = dwc2_restore_device_registers(hsotg, 0); ++ if (ret) { ++ dev_err(hsotg->dev, "%s: failed to restore device registers\n", ++ __func__); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + /** + * dwc2_exit_partial_power_down() - Exit controller from Partial Power Down. + * +@@ -136,7 +198,6 @@ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) + int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore) + { + u32 pcgcctl; +- int ret = 0; + + if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) + return -ENOTSUPP; +@@ -154,31 +215,11 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore) + dwc2_writel(hsotg, pcgcctl, PCGCTL); + + udelay(100); +- if (restore) { +- ret = dwc2_restore_global_registers(hsotg); +- if (ret) { +- dev_err(hsotg->dev, "%s: failed to restore registers\n", +- __func__); +- return ret; +- } +- if (dwc2_is_host_mode(hsotg)) { +- ret = dwc2_restore_host_registers(hsotg); +- if (ret) { +- dev_err(hsotg->dev, "%s: failed to restore host registers\n", +- __func__); +- return ret; +- } +- } else { +- ret = dwc2_restore_device_registers(hsotg, 0); +- if (ret) { +- dev_err(hsotg->dev, "%s: failed to restore device registers\n", +- __func__); +- return ret; +- } +- } +- } + +- return ret; ++ if (restore) ++ return dwc2_restore_registers(hsotg); ++ ++ return 0; + } + + /** +@@ -189,34 +230,14 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore) + int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg) + { + u32 pcgcctl; +- int ret = 0; ++ int ret; + + if (!hsotg->params.power_down) + return -ENOTSUPP; + +- /* Backup all registers */ +- ret = dwc2_backup_global_registers(hsotg); +- if (ret) { +- dev_err(hsotg->dev, "%s: failed to backup global registers\n", +- __func__); ++ ret = dwc2_backup_registers(hsotg); ++ if (ret) + return ret; +- } +- +- if (dwc2_is_host_mode(hsotg)) { +- ret = dwc2_backup_host_registers(hsotg); +- if (ret) { +- dev_err(hsotg->dev, "%s: failed to backup host registers\n", +- __func__); +- return ret; +- } +- } else { +- ret = dwc2_backup_device_registers(hsotg); +- if (ret) { +- dev_err(hsotg->dev, "%s: failed to backup device registers\n", +- __func__); +- return ret; +- } +- } + + /* + * Clear any pending interrupts since dwc2 will not be able to +@@ -238,7 +259,7 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg) + pcgcctl |= PCGCTL_STOPPCLK; + dwc2_writel(hsotg, pcgcctl, PCGCTL); + +- return ret; ++ return 0; + } + + /** +diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h +index 7161344c6522..80bd2900e20a 100644 +--- a/drivers/usb/dwc2/core.h ++++ b/drivers/usb/dwc2/core.h +@@ -685,6 +685,7 @@ struct dwc2_hw_params { + * @grxfsiz: Backup of GRXFSIZ register + * @gnptxfsiz: Backup of GNPTXFSIZ register + * @gi2cctl: Backup of GI2CCTL register ++ * @ggpio: Backup of GGPIO register + * @glpmcfg: Backup of GLPMCFG register + * @gdfifocfg: Backup of GDFIFOCFG register + * @pcgcctl: Backup of PCGCCTL register +@@ -701,6 +702,7 @@ struct dwc2_gregs_backup { + u32 grxfsiz; + u32 gnptxfsiz; + u32 gi2cctl; ++ u32 ggpio; + u32 glpmcfg; + u32 pcgcctl; + u32 pcgcctl1; +@@ -1329,6 +1331,8 @@ void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd); + + void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup, + int is_host); ++int dwc2_backup_registers(struct dwc2_hsotg *hsotg); ++int dwc2_restore_registers(struct dwc2_hsotg *hsotg); + int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg); + int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg); + +diff --git a/drivers/usb/dwc2/drd.c b/drivers/usb/dwc2/drd.c +index 2d4176f5788e..27202eb05bde 100644 +--- a/drivers/usb/dwc2/drd.c ++++ b/drivers/usb/dwc2/drd.c +@@ -7,6 +7,7 @@ + * Author(s): Amelie Delaunay + */ + ++#include + #include + #include + #include +@@ -25,9 +26,9 @@ static void dwc2_ovr_init(struct dwc2_hsotg *hsotg) + gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); + dwc2_writel(hsotg, gotgctl, GOTGCTL); + +- dwc2_force_mode(hsotg, false); +- + spin_unlock_irqrestore(&hsotg->lock, flags); ++ ++ dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST)); + } + + static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) +@@ -86,6 +87,19 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) + } + #endif + ++ /* ++ * In case of USB_DR_MODE_PERIPHERAL, clock is disabled at the end of ++ * the probe and enabled on udc_start. ++ * If role-switch set is called before the udc_start, we need to enable ++ * the clock to read/write GOTGCTL and GUSBCFG registers to override ++ * mode and sessions. It is the case if cable is plugged at boot. ++ */ ++ if (!hsotg->ll_hw_enabled && hsotg->clk) { ++ int ret = clk_prepare_enable(hsotg->clk); ++ if (ret) ++ return ret; ++ } ++ + spin_lock_irqsave(&hsotg->lock, flags); + + if (role == USB_ROLE_HOST) { +@@ -110,6 +124,9 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) + /* This will raise a Connector ID Status Change Interrupt */ + dwc2_force_mode(hsotg, role == USB_ROLE_HOST); + ++ if (!hsotg->ll_hw_enabled && hsotg->clk) ++ clk_disable_unprepare(hsotg->clk); ++ + dev_dbg(hsotg->dev, "%s-session valid\n", + role == USB_ROLE_NONE ? "No" : + role == USB_ROLE_HOST ? "A" : "B"); +diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c +index 0a0d11151cfb..780187454251 100644 +--- a/drivers/usb/dwc2/gadget.c ++++ b/drivers/usb/dwc2/gadget.c +@@ -3565,7 +3565,8 @@ void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) + void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) + { + /* remove the soft-disconnect and let's go */ +- dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON); ++ if (!hsotg->role_sw || (dwc2_readl(hsotg, GOTGCTL) & GOTGCTL_BSESVLD)) ++ dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON); + } + + /** +@@ -4982,7 +4983,7 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) + hsotg->gadget.speed = USB_SPEED_UNKNOWN; + spin_unlock_irqrestore(&hsotg->lock, flags); + +- for (ep = 0; ep < hsotg->num_of_eps; ep++) { ++ for (ep = 1; ep < hsotg->num_of_eps; ep++) { + if (hsotg->eps_in[ep]) + dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep); + if (hsotg->eps_out[ep]) +diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c +index e9ac215b9663..a953f7b2e3a3 100644 +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -1735,7 +1735,8 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) + * release_channel_ddma(), which is called from ep_disable when + * device disconnects + */ +- channel->qh = NULL; ++ if (hsotg->params.host_dma && hsotg->params.dma_desc_enable) ++ channel->qh = NULL; + } + /* All channels have been freed, mark them available */ + if (hsotg->params.uframe_sched) { +@@ -3611,7 +3612,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, + if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1)) + goto error; + +- if (!hsotg->flags.b.port_connect_status) { ++ if (!hsotg->flags.b.port_connect_status && ++ !dwc2_is_host_mode(hsotg)) { + /* + * The port is disconnected, which means the core is + * either in device mode or it soon will be. Just +diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c +index 267543c3dc38..92df3d620f7d 100644 +--- a/drivers/usb/dwc2/params.c ++++ b/drivers/usb/dwc2/params.c +@@ -177,7 +177,10 @@ static void dwc2_set_stm32mp15_fsotg_params(struct dwc2_hsotg *hsotg) + p->i2c_enable = false; + p->activate_stm_fs_transceiver = true; + p->activate_stm_id_vb_detection = true; ++ p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; + p->power_down = DWC2_POWER_DOWN_PARAM_NONE; ++ p->host_support_fs_ls_low_power = true; ++ p->host_ls_low_power_phy_clk = true; + } + + static void dwc2_set_stm32mp15_hsotg_params(struct dwc2_hsotg *hsotg) +@@ -189,7 +192,12 @@ static void dwc2_set_stm32mp15_hsotg_params(struct dwc2_hsotg *hsotg) + p->host_rx_fifo_size = 440; + p->host_nperio_tx_fifo_size = 256; + p->host_perio_tx_fifo_size = 256; ++ p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; + p->power_down = DWC2_POWER_DOWN_PARAM_NONE; ++ p->lpm = false; ++ p->lpm_clock_gating = false; ++ p->besl = false; ++ p->hird_threshold_en = false; + } + + const struct of_device_id dwc2_of_match_table[] = { +diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c +index 5f18acac7406..f0964babf260 100644 +--- a/drivers/usb/dwc2/platform.c ++++ b/drivers/usb/dwc2/platform.c +@@ -224,8 +224,7 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) + hsotg->reset = devm_reset_control_get_optional(hsotg->dev, "dwc2"); + if (IS_ERR(hsotg->reset)) { + ret = PTR_ERR(hsotg->reset); +- dev_err(hsotg->dev, "error getting reset control %d\n", ret); +- return ret; ++ return dev_err_probe(hsotg->dev, ret, "error getting reset control\n"); + } + + reset_control_deassert(hsotg->reset); +@@ -233,8 +232,7 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) + hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc"); + if (IS_ERR(hsotg->reset_ecc)) { + ret = PTR_ERR(hsotg->reset_ecc); +- dev_err(hsotg->dev, "error getting reset control for ecc %d\n", ret); +- return ret; ++ return dev_err_probe(hsotg->dev, ret, "error getting reset control for ecc\n"); + } + + reset_control_deassert(hsotg->reset_ecc); +@@ -283,8 +281,8 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) + /* Clock */ + hsotg->clk = devm_clk_get_optional(hsotg->dev, "otg"); + if (IS_ERR(hsotg->clk)) { +- dev_err(hsotg->dev, "cannot get otg clock\n"); +- return PTR_ERR(hsotg->clk); ++ ret = PTR_ERR(hsotg->clk); ++ return dev_err_probe(hsotg->dev, ret, "cannot get otg clock\n"); + } + + /* Regulators */ +@@ -293,12 +291,9 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) + + ret = devm_regulator_bulk_get(hsotg->dev, ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); +- if (ret) { +- if (ret != -EPROBE_DEFER) +- dev_err(hsotg->dev, "failed to request supplies: %d\n", +- ret); +- return ret; +- } ++ if (ret) ++ return dev_err_probe(hsotg->dev, ret, "failed to request supplies\n"); ++ + return 0; + } + +@@ -638,6 +633,19 @@ static int __maybe_unused dwc2_suspend(struct device *dev) + + dwc2_drd_suspend(dwc2); + ++ if (dwc2->params.power_down == DWC2_POWER_DOWN_PARAM_NONE) { ++ /* ++ * Backup host registers when power_down param is 'none', if ++ * controller power is disabled. ++ * This shouldn't be needed, when using other power_down modes. ++ */ ++ ret = dwc2_backup_registers(dwc2); ++ if (ret) { ++ dev_err(dwc2->dev, "backup regs failed %d\n", ret); ++ return ret; ++ } ++ } ++ + if (dwc2->params.activate_stm_id_vb_detection) { + unsigned long flags; + u32 ggpio, gotgctl; +@@ -675,6 +683,9 @@ static int __maybe_unused dwc2_suspend(struct device *dev) + dwc2->phy_off_for_suspend = true; + } + ++ if (device_may_wakeup(dev) || device_wakeup_path(dev)) ++ enable_irq_wake(dwc2->irq); ++ + return ret; + } + +@@ -683,6 +694,9 @@ static int __maybe_unused dwc2_resume(struct device *dev) + struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); + int ret = 0; + ++ if (device_may_wakeup(dev) || device_wakeup_path(dev)) ++ disable_irq_wake(dwc2->irq); ++ + if (dwc2->phy_off_for_suspend && dwc2->ll_hw_enabled) { + ret = __dwc2_lowlevel_hw_enable(dwc2); + if (ret) +@@ -715,8 +729,13 @@ static int __maybe_unused dwc2_resume(struct device *dev) + spin_unlock_irqrestore(&dwc2->lock, flags); + } + +- /* Need to restore FORCEDEVMODE/FORCEHOSTMODE */ +- dwc2_force_dr_mode(dwc2); ++ if (dwc2->params.power_down == DWC2_POWER_DOWN_PARAM_NONE) { ++ ret = dwc2_restore_registers(dwc2); ++ if (ret) { ++ dev_err(dwc2->dev, "restore regs failed %d\n", ret); ++ return ret; ++ } ++ } + + dwc2_drd_resume(dwc2); + +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index a48dd3fac153..5017913ce6cb 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #include "ehci.h" + +@@ -364,7 +365,9 @@ static int ehci_platform_probe(struct platform_device *dev) + if (err) + goto err_power; + +- device_wakeup_enable(hcd->self.controller); ++ if (of_property_read_bool(dev->dev.of_node, "wakeup-source")) ++ device_set_wakeup_capable(hcd->self.controller, true); ++ + device_enable_async_suspend(hcd->self.controller); + platform_set_drvdata(dev, hcd); + +@@ -400,6 +403,9 @@ static int ehci_platform_remove(struct platform_device *dev) + if (priv->quirk_poll) + quirk_poll_end(priv); + ++ if (of_property_read_bool(dev->dev.of_node, "wakeup-source")) ++ device_set_wakeup_capable(hcd->self.controller, false); ++ + usb_remove_hcd(hcd); + + if (pdata->power_off) +@@ -424,7 +430,7 @@ static int __maybe_unused ehci_platform_suspend(struct device *dev) + struct usb_ehci_pdata *pdata = dev_get_platdata(dev); + struct platform_device *pdev = to_platform_device(dev); + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); +- bool do_wakeup = device_may_wakeup(dev); ++ bool do_wakeup = device_may_wakeup(dev) || device_wakeup_path(dev); + int ret; + + if (priv->quirk_poll) +@@ -437,6 +443,9 @@ static int __maybe_unused ehci_platform_suspend(struct device *dev) + if (pdata->power_suspend) + pdata->power_suspend(pdev); + ++ if (do_wakeup) ++ enable_irq_wake(hcd->irq); ++ + return ret; + } + +@@ -448,6 +457,9 @@ static int __maybe_unused ehci_platform_resume(struct device *dev) + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + struct device *companion_dev; + ++ if (device_may_wakeup(dev) || device_wakeup_path(dev)) ++ disable_irq_wake(hcd->irq); ++ + if (pdata->power_on) { + int err = pdata->power_on(pdev); + if (err < 0) +diff --git a/drivers/usb/typec/stusb160x.c b/drivers/usb/typec/stusb160x.c +index d21750bbbb44..a7b51bf4af18 100644 +--- a/drivers/usb/typec/stusb160x.c ++++ b/drivers/usb/typec/stusb160x.c +@@ -739,10 +739,6 @@ static int stusb160x_probe(struct i2c_client *client) + typec_set_pwr_opmode(chip->port, chip->pwr_opmode); + + if (client->irq) { +- ret = stusb160x_irq_init(chip, client->irq); +- if (ret) +- goto port_unregister; +- + chip->role_sw = fwnode_usb_role_switch_get(fwnode); + if (IS_ERR(chip->role_sw)) { + ret = PTR_ERR(chip->role_sw); +@@ -752,6 +748,10 @@ static int stusb160x_probe(struct i2c_client *client) + ret); + goto port_unregister; + } ++ ++ ret = stusb160x_irq_init(chip, client->irq); ++ if (ret) ++ goto role_sw_put; + } else { + /* + * If Source or Dual power role, need to enable VDD supply +@@ -775,6 +775,9 @@ static int stusb160x_probe(struct i2c_client *client) + + return 0; + ++role_sw_put: ++ if (chip->role_sw) ++ usb_role_switch_put(chip->role_sw); + port_unregister: + typec_unregister_port(chip->port); + all_reg_disable: +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0016-ARM-5.10.10-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0016-ARM-5.10.10-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch new file mode 100644 index 0000000..b2e36c6 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0016-ARM-5.10.10-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch @@ -0,0 +1,1502 @@ +From c74780d4cb41745849aaf03a9704a96ee9ae92ba Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:16:04 +0100 +Subject: [PATCH 16/22] ARM 5.10.10-stm32mp1-r1 PINCTRL-REGULATOR-SPI + +Signed-off-by: Romuald JEANNE +--- + drivers/pinctrl/stm32/pinctrl-stm32.c | 42 ++- + drivers/pinctrl/stm32/pinctrl-stm32.h | 17 +- + drivers/pinctrl/stm32/pinctrl-stm32mp157.c | 1 + + drivers/pwm/pwm-stm32.c | 4 + + drivers/regulator/stm32-pwr.c | 85 ++++- + drivers/regulator/stpmic1_regulator.c | 182 ++++++++++- + drivers/spi/spi-stm32-qspi.c | 18 +- + drivers/spi/spi-stm32.c | 345 +++++++++++--------- + include/dt-bindings/pinctrl/stm32-pinfunc.h | 1 + + 9 files changed, 508 insertions(+), 187 deletions(-) + +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c +index 7d9bdedcd71b..a20c06b06e19 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32.c ++++ b/drivers/pinctrl/stm32/pinctrl-stm32.c +@@ -73,6 +73,7 @@ static const char * const stm32_gpio_functions[] = { + "af8", "af9", "af10", + "af11", "af12", "af13", + "af14", "af15", "analog", ++ "reserved", + }; + + struct stm32_pinctrl_group { +@@ -115,6 +116,7 @@ struct stm32_pinctrl { + u32 pkg; + u16 irqmux_map; + spinlock_t irqmux_lock; ++ u32 pin_base_shift; + }; + + static inline int stm32_gpio_pin(int gpio) +@@ -513,7 +515,7 @@ stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin) + static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, + u32 pin_num, u32 fnum) + { +- int i; ++ int i, k; + + for (i = 0; i < pctl->npins; i++) { + const struct stm32_desc_pin *pin = pctl->pins + i; +@@ -522,7 +524,10 @@ static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, + if (pin->pin.number != pin_num) + continue; + +- while (func && func->name) { ++ if (fnum == STM32_PIN_RSVD) ++ return true; ++ ++ for (k = 0; k < STM32_CONFIG_NUM; k++) { + if (func->num == fnum) + return true; + func++; +@@ -833,6 +838,11 @@ static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, + return -EINVAL; + } + ++ if (function == STM32_PIN_RSVD) { ++ dev_dbg(pctl->dev, "Reserved pins, skipping HW update.\n"); ++ return 0; ++ } ++ + bank = gpiochip_get_data(range->gc); + pin = stm32_gpio_pin(g->pin); + +@@ -1147,10 +1157,27 @@ static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + return 0; + } + ++static struct stm32_desc_pin * ++stm32_pconf_get_pin_desc_by_pin_number(struct stm32_pinctrl *pctl, ++ unsigned int pin_number) ++{ ++ struct stm32_desc_pin *pins = pctl->pins; ++ int i; ++ ++ for (i = 0; i < pctl->npins; i++) { ++ if (pins->pin.number == pin_number) ++ return pins; ++ pins++; ++ } ++ return NULL; ++} ++ + static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned int pin) + { ++ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); ++ const struct stm32_desc_pin *pin_desc; + struct pinctrl_gpio_range *range; + struct stm32_gpio_bank *bank; + int offset; +@@ -1200,7 +1227,12 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, + case 2: + drive = stm32_pconf_get_driving(bank, offset); + speed = stm32_pconf_get_speed(bank, offset); +- seq_printf(s, "%d - %s - %s - %s %s", alt, ++ pin_desc = stm32_pconf_get_pin_desc_by_pin_number(pctl, pin); ++ if (!pin_desc) ++ return; ++ ++ seq_printf(s, "%d (%s) - %s - %s - %s %s", alt, ++ pin_desc->functions[alt + 1].name, + drive ? "open drain" : "push pull", + biasing[bias], + speeds[speed], "speed"); +@@ -1404,7 +1436,8 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, + if (pctl->pkg && !(pctl->pkg & p->pkg)) + continue; + pins->pin = p->pin; +- pins->functions = p->functions; ++ memcpy((struct stm32_desc_pin *)pins->functions, p->functions, ++ STM32_CONFIG_NUM * sizeof(struct stm32_desc_function)); + pins++; + nb_pins_available++; + } +@@ -1513,6 +1546,7 @@ int stm32_pctl_probe(struct platform_device *pdev) + pctl->pctl_desc.pctlops = &stm32_pctrl_ops; + pctl->pctl_desc.pmxops = &stm32_pmx_ops; + pctl->dev = &pdev->dev; ++ pctl->pin_base_shift = pctl->match_data->pin_base_shift; + + pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc, + pctl); +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h +index b0882d120765..a7137fbff5d0 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32.h ++++ b/drivers/pinctrl/stm32/pinctrl-stm32.h +@@ -17,6 +17,8 @@ + #define STM32_PIN_GPIO 0 + #define STM32_PIN_AF(x) ((x) + 1) + #define STM32_PIN_ANALOG (STM32_PIN_AF(15) + 1) ++#define STM32_PIN_RSVD (STM32_PIN_ANALOG + 1) ++#define STM32_CONFIG_NUM (STM32_PIN_RSVD + 1) + + /* package information */ + #define STM32MP_PKG_AA BIT(0) +@@ -24,6 +26,8 @@ + #define STM32MP_PKG_AC BIT(2) + #define STM32MP_PKG_AD BIT(3) + ++#define STM32MP157_Z_BASE_SHIFT 400 ++ + struct stm32_desc_function { + const char *name; + const unsigned char num; +@@ -31,26 +35,26 @@ struct stm32_desc_function { + + struct stm32_desc_pin { + struct pinctrl_pin_desc pin; +- const struct stm32_desc_function *functions; ++ const struct stm32_desc_function functions[STM32_CONFIG_NUM]; + const unsigned int pkg; + }; + + #define STM32_PIN(_pin, ...) \ + { \ + .pin = _pin, \ +- .functions = (struct stm32_desc_function[]){ \ +- __VA_ARGS__, { } }, \ ++ .functions = { \ ++ __VA_ARGS__}, \ + } + + #define STM32_PIN_PKG(_pin, _pkg, ...) \ + { \ + .pin = _pin, \ + .pkg = _pkg, \ +- .functions = (struct stm32_desc_function[]){ \ +- __VA_ARGS__, { } }, \ ++ .functions = { \ ++ __VA_ARGS__}, \ + } + #define STM32_FUNCTION(_num, _name) \ +- { \ ++ [_num] = { \ + .num = _num, \ + .name = _name, \ + } +@@ -58,6 +62,7 @@ struct stm32_desc_pin { + struct stm32_pinctrl_match_data { + const struct stm32_desc_pin *pins; + const unsigned int npins; ++ const unsigned int pin_base_shift; + }; + + struct stm32_gpio_bank; +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c +index 2ccb99d64df8..86fe6d5ac54d 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c ++++ b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c +@@ -2328,6 +2328,7 @@ static struct stm32_pinctrl_match_data stm32mp157_match_data = { + static struct stm32_pinctrl_match_data stm32mp157_z_match_data = { + .pins = stm32mp157_z_pins, + .npins = ARRAY_SIZE(stm32mp157_z_pins), ++ .pin_base_shift = STM32MP157_Z_BASE_SHIFT, + }; + + static const struct of_device_id stm32mp157_pctrl_match[] = { +diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c +index d3be944f2ae9..13f47e25572e 100644 +--- a/drivers/pwm/pwm-stm32.c ++++ b/drivers/pwm/pwm-stm32.c +@@ -207,6 +207,10 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, + regmap_write(priv->regmap, TIM_ARR, priv->max_arr); + regmap_write(priv->regmap, TIM_PSC, psc); + ++ /* Reset input selector to its default input and disable slave mode */ ++ regmap_write(priv->regmap, TIM_TISEL, 0x0); ++ regmap_write(priv->regmap, TIM_SMCR, 0x0); ++ + /* Map TI1 or TI2 PWM input to IC1 & IC2 (or TI3/4 to IC3 & IC4) */ + regmap_update_bits(priv->regmap, + pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, +diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c +index 2a42acb7c24e..2b328b970b46 100644 +--- a/drivers/regulator/stm32-pwr.c ++++ b/drivers/regulator/stm32-pwr.c +@@ -3,12 +3,15 @@ + // Authors: Gabriel Fernandez + // Pascal Paillet . + ++#include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + #include + +@@ -24,6 +27,11 @@ + #define REG_1_1_EN BIT(30) + #define REG_1_1_RDY BIT(31) + ++#define STM32_SMC_PWR 0x82001001 ++#define STM32_WRITE 0x1 ++#define STM32_SMC_REG_SET 0x2 ++#define STM32_SMC_REG_CLEAR 0x3 ++ + /* list of supported regulators */ + enum { + PWR_REG11, +@@ -39,10 +47,18 @@ static u32 ready_mask_table[STM32PWR_REG_NUM_REGS] = { + }; + + struct stm32_pwr_reg { ++ int tzen; + void __iomem *base; + u32 ready_mask; + }; + ++#define SMC(class, op, address, val)\ ++ ({\ ++ struct arm_smccc_res res;\ ++ arm_smccc_smc(class, op, address, val,\ ++ 0, 0, 0, 0, &res);\ ++ }) ++ + static int stm32_pwr_reg_is_ready(struct regulator_dev *rdev) + { + struct stm32_pwr_reg *priv = rdev_get_drvdata(rdev); +@@ -69,9 +85,15 @@ static int stm32_pwr_reg_enable(struct regulator_dev *rdev) + int ret; + u32 val; + +- val = readl_relaxed(priv->base + REG_PWR_CR3); +- val |= rdev->desc->enable_mask; +- writel_relaxed(val, priv->base + REG_PWR_CR3); ++ if (priv->tzen) { ++ SMC(STM32_SMC_PWR, STM32_SMC_REG_SET, REG_PWR_CR3, ++ rdev->desc->enable_mask); ++ } else { ++ val = readl_relaxed(priv->base + REG_PWR_CR3); ++ val |= rdev->desc->enable_mask; ++ writel_relaxed(val, priv->base + REG_PWR_CR3); ++ } ++ + + /* use an arbitrary timeout of 20ms */ + ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, val, +@@ -88,9 +110,14 @@ static int stm32_pwr_reg_disable(struct regulator_dev *rdev) + int ret; + u32 val; + +- val = readl_relaxed(priv->base + REG_PWR_CR3); +- val &= ~rdev->desc->enable_mask; +- writel_relaxed(val, priv->base + REG_PWR_CR3); ++ if (priv->tzen) { ++ SMC(STM32_SMC_PWR, STM32_SMC_REG_CLEAR, REG_PWR_CR3, ++ rdev->desc->enable_mask); ++ } else { ++ val = readl_relaxed(priv->base + REG_PWR_CR3); ++ val &= ~rdev->desc->enable_mask; ++ writel_relaxed(val, priv->base + REG_PWR_CR3); ++ } + + /* use an arbitrary timeout of 20ms */ + ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, !val, +@@ -121,12 +148,50 @@ static const struct regulator_ops stm32_pwr_reg_ops = { + .supply_name = _supply, \ + } \ + +-static const struct regulator_desc stm32_pwr_desc[] = { ++static struct regulator_desc stm32_pwr_desc[] = { + PWR_REG(PWR_REG11, "reg11", 1100000, REG_1_1_EN, "vdd"), + PWR_REG(PWR_REG18, "reg18", 1800000, REG_1_8_EN, "vdd"), + PWR_REG(PWR_USB33, "usb33", 3300000, USB_3_3_EN, "vdd_3v3_usbfs"), + }; + ++static int is_stm32_soc_secured(struct platform_device *pdev, int *val) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct regmap *syscon; ++ u32 reg, mask; ++ int tzc_val = 0; ++ int err; ++ ++ syscon = syscon_regmap_lookup_by_phandle(np, "st,tzcr"); ++ if (IS_ERR(syscon)) { ++ if (PTR_ERR(syscon) != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "tzcr syscon required\n"); ++ return PTR_ERR(syscon); ++ } ++ ++ err = of_property_read_u32_index(np, "st,tzcr", 1, ®); ++ if (err) { ++ dev_err(&pdev->dev, "tzcr offset required !\n"); ++ return err; ++ } ++ ++ err = of_property_read_u32_index(np, "st,tzcr", 2, &mask); ++ if (err) { ++ dev_err(&pdev->dev, "tzcr mask required !\n"); ++ return err; ++ } ++ ++ err = regmap_read(syscon, reg, &tzc_val); ++ if (err) { ++ dev_err(&pdev->dev, "failed to read tzcr status !\n"); ++ return err; ++ } ++ ++ *val = tzc_val & mask; ++ ++ return 0; ++} ++ + static int stm32_pwr_regulator_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +@@ -135,6 +200,11 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) + struct regulator_dev *rdev; + struct regulator_config config = { }; + int i, ret = 0; ++ int tzen = 0; ++ ++ ret = is_stm32_soc_secured(pdev, &tzen); ++ if (ret) ++ return ret; + + base = of_iomap(np, 0); + if (!base) { +@@ -149,6 +219,7 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) + GFP_KERNEL); + if (!priv) + return -ENOMEM; ++ priv->tzen = tzen; + priv->base = base; + priv->ready_mask = ready_mask_table[i]; + config.driver_data = priv; +diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c +index cf10fdb72e32..c5337a12a61a 100644 +--- a/drivers/regulator/stpmic1_regulator.c ++++ b/drivers/regulator/stpmic1_regulator.c +@@ -2,7 +2,9 @@ + // Copyright (C) STMicroelectronics 2018 + // Author: Pascal Paillet for STMicroelectronics. + ++#include + #include ++#include + #include + #include + #include +@@ -30,10 +32,26 @@ struct stpmic1_regulator_cfg { + u8 icc_mask; + }; + ++/** ++ * struct boost_data - this structure is used as driver data for the usb boost ++ * @boost_rdev: device for boost regulator ++ * @vbus_otg_rdev: device for vbus_otg regulator ++ * @sw_out_rdev: device for sw_out regulator ++ * @occ_timeout: overcurrent detection timeout ++ */ ++struct boost_data { ++ struct regulator_dev *boost_rdev; ++ struct regulator_dev *vbus_otg_rdev; ++ struct regulator_dev *sw_out_rdev; ++ ktime_t occ_timeout; ++}; ++ + static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode); + static unsigned int stpmic1_get_mode(struct regulator_dev *rdev); + static int stpmic1_set_icc(struct regulator_dev *rdev); + static unsigned int stpmic1_map_mode(unsigned int mode); ++static int regulator_enable_boost(struct regulator_dev *rdev); ++static int regulator_disable_boost(struct regulator_dev *rdev); + + enum { + STPMIC1_BUCK1 = 0, +@@ -181,8 +199,8 @@ static const struct regulator_ops stpmic1_vref_ddr_ops = { + + static const struct regulator_ops stpmic1_boost_regul_ops = { + .is_enabled = regulator_is_enabled_regmap, +- .enable = regulator_enable_regmap, +- .disable = regulator_disable_regmap, ++ .enable = regulator_enable_boost, ++ .disable = regulator_disable_boost, + .set_over_current_protection = stpmic1_set_icc, + }; + +@@ -513,6 +531,79 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) + return IRQ_HANDLED; + } + ++static int regulator_enable_boost(struct regulator_dev *rdev) ++{ ++ struct boost_data *usb_data = rdev_get_drvdata(rdev); ++ ++ usb_data->occ_timeout = ktime_add_us(ktime_get(), 100000); ++ ++ return regulator_enable_regmap(rdev); ++} ++ ++static int regulator_disable_boost(struct regulator_dev *rdev) ++{ ++ struct boost_data *usb_data = rdev_get_drvdata(rdev); ++ ++ usb_data->occ_timeout = 0; ++ ++ return regulator_disable_regmap(rdev); ++} ++ ++static void stpmic1_reset_boost(struct boost_data *usb_data) ++{ ++ int otg_on = 0; ++ int sw_out_on = 0; ++ ++ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "reset usb boost\n"); ++ ++ /* the boost was actually disabled by the over-current protection */ ++ regulator_disable_regmap(usb_data->boost_rdev); ++ ++ if (usb_data->vbus_otg_rdev) ++ otg_on = regulator_is_enabled_regmap(usb_data->vbus_otg_rdev); ++ if (otg_on) ++ regulator_disable_regmap(usb_data->vbus_otg_rdev); ++ ++ if (usb_data->sw_out_rdev) ++ sw_out_on = regulator_is_enabled_regmap(usb_data->sw_out_rdev); ++ if (sw_out_on) ++ regulator_disable_regmap(usb_data->sw_out_rdev); ++ ++ regulator_enable_regmap(usb_data->boost_rdev); ++ ++ /* sleep at least 5ms */ ++ usleep_range(5000, 10000); ++ ++ if (otg_on) ++ regulator_enable_regmap(usb_data->vbus_otg_rdev); ++ ++ if (sw_out_on) ++ regulator_enable_regmap(usb_data->sw_out_rdev); ++ ++} ++ ++static irqreturn_t stpmic1_boost_irq_handler(int irq, void *data) ++{ ++ struct boost_data *usb_data = (struct boost_data *)data; ++ ++ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "usb boost irq handler\n"); ++ ++ /* overcurrent detected on boost after timeout */ ++ if (usb_data->occ_timeout != 0 && ++ ktime_compare(ktime_get(), usb_data->occ_timeout) > 0) { ++ /* reset usb boost and usb power switches */ ++ stpmic1_reset_boost(usb_data); ++ return IRQ_HANDLED; ++ } ++ ++ /* Send an overcurrent notification */ ++ regulator_notifier_call_chain(usb_data->boost_rdev, ++ REGULATOR_EVENT_OVER_CURRENT, ++ NULL); ++ ++ return IRQ_HANDLED; ++} ++ + #define MATCH(_name, _id) \ + [STPMIC1_##_id] = { \ + .name = #_name, \ +@@ -536,9 +627,10 @@ static struct of_regulator_match stpmic1_matches[] = { + MATCH(pwr_sw2, SW_OUT), + }; + +-static int stpmic1_regulator_register(struct platform_device *pdev, int id, +- struct of_regulator_match *match, +- const struct stpmic1_regulator_cfg *cfg) ++static struct regulator_dev * ++stpmic1_regulator_register(struct platform_device *pdev, int id, ++ struct of_regulator_match *match, ++ const struct stpmic1_regulator_cfg *cfg) + { + struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); + struct regulator_dev *rdev; +@@ -556,7 +648,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s regulator\n", + cfg->desc.name); +- return PTR_ERR(rdev); ++ return rdev; + } + + /* set mask reset */ +@@ -568,7 +660,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, + cfg->mask_reset_mask); + if (ret) { + dev_err(&pdev->dev, "set mask reset failed\n"); +- return ret; ++ return ERR_PTR(ret); + } + } + +@@ -582,15 +674,60 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, + pdev->name, rdev); + if (ret) { + dev_err(&pdev->dev, "Request IRQ failed\n"); +- return ret; ++ return ERR_PTR(ret); + } + } +- return 0; ++ ++ return rdev; ++} ++ ++static struct regulator_dev * ++stpmic1_boost_register(struct platform_device *pdev, int id, ++ struct of_regulator_match *match, ++ const struct stpmic1_regulator_cfg *cfg, ++ struct boost_data *usb_data) ++{ ++ struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); ++ struct regulator_dev *rdev; ++ struct regulator_config config = {}; ++ int ret = 0; ++ int irq; ++ ++ config.dev = &pdev->dev; ++ config.init_data = match->init_data; ++ config.of_node = match->of_node; ++ config.regmap = pmic_dev->regmap; ++ config.driver_data = (void *)usb_data; ++ ++ rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config); ++ if (IS_ERR(rdev)) { ++ dev_err(&pdev->dev, "failed to register %s regulator\n", ++ cfg->desc.name); ++ return rdev; ++ } ++ ++ /* setup an irq handler for over-current detection */ ++ irq = of_irq_get(config.of_node, 0); ++ if (irq > 0) { ++ ret = devm_request_threaded_irq(&pdev->dev, ++ irq, NULL, ++ stpmic1_boost_irq_handler, ++ IRQF_ONESHOT, pdev->name, ++ usb_data); ++ if (ret) { ++ dev_err(&pdev->dev, "Request IRQ failed\n"); ++ return ERR_PTR(ret); ++ } ++ } ++ ++ return rdev; + } + + static int stpmic1_regulator_probe(struct platform_device *pdev) + { + int i, ret; ++ struct boost_data *usb_data; ++ struct regulator_dev *rdev; + + ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches, + ARRAY_SIZE(stpmic1_matches)); +@@ -600,11 +737,30 @@ static int stpmic1_regulator_probe(struct platform_device *pdev) + return ret; + } + ++ usb_data = devm_kzalloc(&pdev->dev, sizeof(*usb_data), GFP_KERNEL); ++ if (!usb_data) ++ return -ENOMEM; ++ + for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) { +- ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], +- &stpmic1_regulator_cfgs[i]); +- if (ret < 0) +- return ret; ++ if (i == STPMIC1_BOOST) { ++ rdev = ++ stpmic1_boost_register(pdev, i, &stpmic1_matches[i], ++ &stpmic1_regulator_cfgs[i], ++ usb_data); ++ ++ usb_data->boost_rdev = rdev; ++ } else { ++ rdev = ++ stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], ++ &stpmic1_regulator_cfgs[i]); ++ ++ if (i == STPMIC1_VBUS_OTG) ++ usb_data->vbus_otg_rdev = rdev; ++ else if (i == STPMIC1_SW_OUT) ++ usb_data->sw_out_rdev = rdev; ++ } ++ if (IS_ERR(rdev)) ++ return PTR_ERR(rdev); + } + + dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n"); +diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c +index 947e6b9dc9f4..2786470a5201 100644 +--- a/drivers/spi/spi-stm32-qspi.c ++++ b/drivers/spi/spi-stm32-qspi.c +@@ -727,21 +727,31 @@ static int __maybe_unused stm32_qspi_suspend(struct device *dev) + { + pinctrl_pm_select_sleep_state(dev); + +- return 0; ++ return pm_runtime_force_suspend(dev); + } + + static int __maybe_unused stm32_qspi_resume(struct device *dev) + { + struct stm32_qspi *qspi = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = pm_runtime_force_resume(dev); ++ if (ret < 0) ++ return ret; + + pinctrl_pm_select_default_state(dev); +- clk_prepare_enable(qspi->clk); ++ ++ ret = pm_runtime_get_sync(dev); ++ if (ret < 0) { ++ pm_runtime_put_noidle(dev); ++ return ret; ++ } + + writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); + writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); + +- pm_runtime_mark_last_busy(qspi->dev); +- pm_runtime_put_autosuspend(qspi->dev); ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_put_autosuspend(dev); + + return 0; + } +diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c +index 6017209c6d2f..23bf7d6eb23c 100644 +--- a/drivers/spi/spi-stm32.c ++++ b/drivers/spi/spi-stm32.c +@@ -5,6 +5,7 @@ + // Copyright (C) 2017, STMicroelectronics - All Rights Reserved + // Author(s): Amelie Delaunay for STMicroelectronics. + ++#include + #include + #include + #include +@@ -31,8 +32,8 @@ + #define STM32F4_SPI_CR1_CPHA BIT(0) + #define STM32F4_SPI_CR1_CPOL BIT(1) + #define STM32F4_SPI_CR1_MSTR BIT(2) +-#define STM32F4_SPI_CR1_BR_SHIFT 3 + #define STM32F4_SPI_CR1_BR GENMASK(5, 3) ++#define STM32F4_SPI_CR1_BR_SHIFT 3 + #define STM32F4_SPI_CR1_SPE BIT(6) + #define STM32F4_SPI_CR1_LSBFRST BIT(7) + #define STM32F4_SPI_CR1_SSI BIT(8) +@@ -94,27 +95,22 @@ + #define STM32H7_SPI_CR1_SSI BIT(12) + + /* STM32H7_SPI_CR2 bit fields */ +-#define STM32H7_SPI_CR2_TSIZE_SHIFT 0 + #define STM32H7_SPI_CR2_TSIZE GENMASK(15, 0) ++#define STM32H7_SPI_TSIZE_MAX GENMASK(15, 0) + + /* STM32H7_SPI_CFG1 bit fields */ +-#define STM32H7_SPI_CFG1_DSIZE_SHIFT 0 + #define STM32H7_SPI_CFG1_DSIZE GENMASK(4, 0) +-#define STM32H7_SPI_CFG1_FTHLV_SHIFT 5 + #define STM32H7_SPI_CFG1_FTHLV GENMASK(8, 5) + #define STM32H7_SPI_CFG1_RXDMAEN BIT(14) + #define STM32H7_SPI_CFG1_TXDMAEN BIT(15) +-#define STM32H7_SPI_CFG1_MBR_SHIFT 28 + #define STM32H7_SPI_CFG1_MBR GENMASK(30, 28) ++#define STM32H7_SPI_CFG1_MBR_SHIFT 28 + #define STM32H7_SPI_CFG1_MBR_MIN 0 + #define STM32H7_SPI_CFG1_MBR_MAX (GENMASK(30, 28) >> 28) + + /* STM32H7_SPI_CFG2 bit fields */ +-#define STM32H7_SPI_CFG2_MIDI_SHIFT 4 + #define STM32H7_SPI_CFG2_MIDI GENMASK(7, 4) +-#define STM32H7_SPI_CFG2_COMM_SHIFT 17 + #define STM32H7_SPI_CFG2_COMM GENMASK(18, 17) +-#define STM32H7_SPI_CFG2_SP_SHIFT 19 + #define STM32H7_SPI_CFG2_SP GENMASK(21, 19) + #define STM32H7_SPI_CFG2_MASTER BIT(22) + #define STM32H7_SPI_CFG2_LSBFRST BIT(23) +@@ -130,17 +126,15 @@ + #define STM32H7_SPI_IER_EOTIE BIT(3) + #define STM32H7_SPI_IER_TXTFIE BIT(4) + #define STM32H7_SPI_IER_OVRIE BIT(6) +-#define STM32H7_SPI_IER_MODFIE BIT(9) + #define STM32H7_SPI_IER_ALL GENMASK(10, 0) + + /* STM32H7_SPI_SR bit fields */ + #define STM32H7_SPI_SR_RXP BIT(0) + #define STM32H7_SPI_SR_TXP BIT(1) + #define STM32H7_SPI_SR_EOT BIT(3) ++#define STM32H7_SPI_SR_TXTF BIT(4) + #define STM32H7_SPI_SR_OVR BIT(6) +-#define STM32H7_SPI_SR_MODF BIT(9) + #define STM32H7_SPI_SR_SUSP BIT(11) +-#define STM32H7_SPI_SR_RXPLVL_SHIFT 13 + #define STM32H7_SPI_SR_RXPLVL GENMASK(14, 13) + #define STM32H7_SPI_SR_RXWNE BIT(15) + +@@ -167,8 +161,6 @@ + #define SPI_3WIRE_TX 3 + #define SPI_3WIRE_RX 4 + +-#define SPI_1HZ_NS 1000000000 +- + /* + * use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers + * without fifo buffers. +@@ -249,7 +241,7 @@ struct stm32_spi_cfg { + int (*set_mode)(struct stm32_spi *spi, unsigned int comm_type); + void (*set_data_idleness)(struct stm32_spi *spi, u32 length); + int (*set_number_of_data)(struct stm32_spi *spi, u32 length); +- void (*transfer_one_dma_start)(struct stm32_spi *spi); ++ int (*transfer_one_dma_start)(struct stm32_spi *spi); + void (*dma_rx_cb)(void *data); + void (*dma_tx_cb)(void *data); + int (*transfer_one_irq)(struct stm32_spi *spi); +@@ -268,7 +260,6 @@ struct stm32_spi_cfg { + * @base: virtual memory area + * @clk: hw kernel clock feeding the SPI clock generator + * @clk_rate: rate of the hw kernel clock feeding the SPI clock generator +- * @rst: SPI controller reset line + * @lock: prevent I/O concurrent access + * @irq: SPI controller interrupt line + * @fifo_size: size of the embedded fifo in bytes +@@ -285,7 +276,10 @@ struct stm32_spi_cfg { + * @rx_len: number of data to be read in bytes + * @dma_tx: dma channel for TX transfer + * @dma_rx: dma channel for RX transfer ++ * @dma_completion: completion to wait for end of DMA transfer + * @phys_addr: SPI registers physical base address ++ * @xfer_completion: completion to wait for end of transfer ++ * @xfer_status: current transfer status + */ + struct stm32_spi { + struct device *dev; +@@ -294,7 +288,6 @@ struct stm32_spi { + void __iomem *base; + struct clk *clk; + u32 clk_rate; +- struct reset_control *rst; + spinlock_t lock; /* prevent I/O concurrent access */ + int irq; + unsigned int fifo_size; +@@ -313,7 +306,10 @@ struct stm32_spi { + int rx_len; + struct dma_chan *dma_tx; + struct dma_chan *dma_rx; ++ struct completion dma_completion; + dma_addr_t phys_addr; ++ struct completion xfer_completion; ++ int xfer_status; + }; + + static const struct stm32_spi_regspec stm32f4_spi_regspec = { +@@ -417,9 +413,7 @@ static int stm32h7_spi_get_bpw_mask(struct stm32_spi *spi) + stm32_spi_set_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_DSIZE); + + cfg1 = readl_relaxed(spi->base + STM32H7_SPI_CFG1); +- max_bpw = (cfg1 & STM32H7_SPI_CFG1_DSIZE) >> +- STM32H7_SPI_CFG1_DSIZE_SHIFT; +- max_bpw += 1; ++ max_bpw = FIELD_GET(STM32H7_SPI_CFG1_DSIZE, cfg1) + 1; + + spin_unlock_irqrestore(&spi->lock, flags); + +@@ -599,30 +593,30 @@ static void stm32f4_spi_read_rx(struct stm32_spi *spi) + /** + * stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register + * @spi: pointer to the spi controller data structure +- * @flush: boolean indicating that FIFO should be flushed + * + * Write in rx_buf depends on remaining bytes to avoid to write beyond + * rx_buf end. + */ +-static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush) ++static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi) + { + u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR); +- u32 rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >> +- STM32H7_SPI_SR_RXPLVL_SHIFT; ++ u32 rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr); + + while ((spi->rx_len > 0) && + ((sr & STM32H7_SPI_SR_RXP) || +- (flush && ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) { ++ ((sr & STM32H7_SPI_SR_EOT) && ++ ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) { + u32 offs = spi->cur_xferlen - spi->rx_len; + + if ((spi->rx_len >= sizeof(u32)) || +- (flush && (sr & STM32H7_SPI_SR_RXWNE))) { ++ (sr & STM32H7_SPI_SR_RXWNE)) { + u32 *rx_buf32 = (u32 *)(spi->rx_buf + offs); + + *rx_buf32 = readl_relaxed(spi->base + STM32H7_SPI_RXDR); + spi->rx_len -= sizeof(u32); + } else if ((spi->rx_len >= sizeof(u16)) || +- (flush && (rxplvl >= 2 || spi->cur_bpw > 8))) { ++ (!(sr & STM32H7_SPI_SR_RXWNE) && ++ (rxplvl >= 2 || spi->cur_bpw > 8))) { + u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs); + + *rx_buf16 = readw_relaxed(spi->base + STM32H7_SPI_RXDR); +@@ -635,12 +629,11 @@ static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush) + } + + sr = readl_relaxed(spi->base + STM32H7_SPI_SR); +- rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >> +- STM32H7_SPI_SR_RXPLVL_SHIFT; ++ rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr); + } + +- dev_dbg(spi->dev, "%s%s: %d bytes left\n", __func__, +- flush ? "(flush)" : "", spi->rx_len); ++ dev_dbg(spi->dev, "%s: %d bytes left (sr=%08x)\n", ++ __func__, spi->rx_len, sr); + } + + /** +@@ -708,12 +701,7 @@ static void stm32f4_spi_disable(struct stm32_spi *spi) + * @spi: pointer to the spi controller data structure + * + * RX-Fifo is flushed when SPI controller is disabled. To prevent any data +- * loss, use stm32h7_spi_read_rxfifo(flush) to read the remaining bytes in +- * RX-Fifo. +- * Normally, if TSIZE has been configured, we should relax the hardware at the +- * reception of the EOT interrupt. But in case of error, EOT will not be +- * raised. So the subsystem unprepare_message call allows us to properly +- * complete the transfer from an hardware point of view. ++ * loss, use stm32_spi_read_rxfifo to read the remaining bytes in RX-Fifo. + */ + static void stm32h7_spi_disable(struct stm32_spi *spi) + { +@@ -748,7 +736,7 @@ static void stm32h7_spi_disable(struct stm32_spi *spi) + } + + if (!spi->cur_usedma && spi->rx_buf && (spi->rx_len > 0)) +- stm32h7_spi_read_rxfifo(spi, true); ++ stm32h7_spi_read_rxfifo(spi); + + if (spi->cur_usedma && spi->dma_tx) + dmaengine_terminate_all(spi->dma_tx); +@@ -892,8 +880,7 @@ static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id) + struct spi_master *master = dev_id; + struct stm32_spi *spi = spi_master_get_devdata(master); + +- spi_finalize_current_transfer(master); +- stm32f4_spi_disable(spi); ++ complete(&spi->xfer_completion); + + return IRQ_HANDLED; + } +@@ -907,7 +894,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) + { + struct spi_master *master = dev_id; + struct stm32_spi *spi = spi_master_get_devdata(master); +- u32 sr, ier, mask; ++ u32 sr, ier, mask, ifcr; + unsigned long flags; + bool end = false; + +@@ -915,81 +902,78 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) + + sr = readl_relaxed(spi->base + STM32H7_SPI_SR); + ier = readl_relaxed(spi->base + STM32H7_SPI_IER); ++ ifcr = 0; + + mask = ier; +- /* EOTIE is triggered on EOT, SUSP and TXC events. */ ++ /* ++ * EOTIE enables irq from EOT, SUSP and TXC events. We need to set ++ * SUSP to acknowledge it later. TXC is automatically cleared ++ */ + mask |= STM32H7_SPI_SR_SUSP; + /* +- * When TXTF is set, DXPIE and TXPIE are cleared. So in case of +- * Full-Duplex, need to poll RXP event to know if there are remaining +- * data, before disabling SPI. ++ * DXPIE is set in Full-Duplex, one IT will be raised if TXP and RXP ++ * are set. So in case of Full-Duplex, need to poll TXP and RXP event. + */ +- if (spi->rx_buf && !spi->cur_usedma) +- mask |= STM32H7_SPI_SR_RXP; ++ if ((spi->cur_comm == SPI_FULL_DUPLEX) && (!spi->cur_usedma)) ++ mask |= STM32H7_SPI_SR_TXP | STM32H7_SPI_SR_RXP; + +- if (!(sr & mask)) { +- dev_dbg(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", +- sr, ier); ++ mask &= sr; ++ ++ if (!mask) { ++ dev_warn(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", ++ sr, ier); + spin_unlock_irqrestore(&spi->lock, flags); + return IRQ_NONE; + } + +- if (sr & STM32H7_SPI_SR_SUSP) { ++ if (mask & STM32H7_SPI_SR_SUSP) { + static DEFINE_RATELIMIT_STATE(rs, + DEFAULT_RATELIMIT_INTERVAL * 10, + 1); + if (__ratelimit(&rs)) + dev_dbg_ratelimited(spi->dev, "Communication suspended\n"); + if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) +- stm32h7_spi_read_rxfifo(spi, false); +- /* +- * If communication is suspended while using DMA, it means +- * that something went wrong, so stop the current transfer +- */ +- if (spi->cur_usedma) +- end = true; ++ stm32h7_spi_read_rxfifo(spi); ++ ifcr |= STM32H7_SPI_SR_SUSP; + } + +- if (sr & STM32H7_SPI_SR_MODF) { +- dev_warn(spi->dev, "Mode fault: transfer aborted\n"); ++ if (mask & STM32H7_SPI_SR_OVR) { ++ dev_err(spi->dev, "Overrun: RX data lost\n"); ++ spi->xfer_status = -EIO; + end = true; ++ ifcr |= STM32H7_SPI_SR_OVR; + } + +- if (sr & STM32H7_SPI_SR_OVR) { +- dev_warn(spi->dev, "Overrun: received value discarded\n"); +- if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) +- stm32h7_spi_read_rxfifo(spi, false); +- /* +- * If overrun is detected while using DMA, it means that +- * something went wrong, so stop the current transfer +- */ +- if (spi->cur_usedma) +- end = true; +- } ++ if (mask & STM32H7_SPI_SR_TXTF) ++ ifcr |= STM32H7_SPI_SR_TXTF; + +- if (sr & STM32H7_SPI_SR_EOT) { ++ if (mask & STM32H7_SPI_SR_EOT) { + if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) +- stm32h7_spi_read_rxfifo(spi, true); ++ stm32h7_spi_read_rxfifo(spi); + end = true; ++ ifcr |= STM32H7_SPI_SR_EOT; + } + +- if (sr & STM32H7_SPI_SR_TXP) ++ if (mask & STM32H7_SPI_SR_TXP) + if (!spi->cur_usedma && (spi->tx_buf && (spi->tx_len > 0))) + stm32h7_spi_write_txfifo(spi); + +- if (sr & STM32H7_SPI_SR_RXP) ++ if (mask & STM32H7_SPI_SR_RXP) + if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) +- stm32h7_spi_read_rxfifo(spi, false); +- +- writel_relaxed(sr & mask, spi->base + STM32H7_SPI_IFCR); +- +- spin_unlock_irqrestore(&spi->lock, flags); ++ stm32h7_spi_read_rxfifo(spi); + + if (end) { +- stm32h7_spi_disable(spi); +- spi_finalize_current_transfer(master); ++ /* Disable interrupts and clear status flags */ ++ writel_relaxed(0, spi->base + STM32H7_SPI_IER); ++ writel_relaxed(STM32H7_SPI_IFCR_ALL, ++ spi->base + STM32H7_SPI_IFCR); ++ ++ complete(&spi->xfer_completion); ++ } else { ++ writel_relaxed(ifcr, spi->base + STM32H7_SPI_IFCR); + } + ++ spin_unlock_irqrestore(&spi->lock, flags); + return IRQ_HANDLED; + } + +@@ -1033,6 +1017,20 @@ static int stm32_spi_prepare_msg(struct spi_master *master, + spi_dev->mode & SPI_LSB_FIRST, + spi_dev->mode & SPI_CS_HIGH); + ++ /* On STM32H7, messages should not exceed a maximum size setted ++ * afterward via the set_number_of_data function. In order to ++ * ensure that, split large messages into several messages ++ */ ++ if (spi->cfg->set_number_of_data) { ++ int ret; ++ ++ ret = spi_split_transfers_maxsize(master, msg, ++ STM32H7_SPI_TSIZE_MAX, ++ GFP_KERNEL | GFP_DMA); ++ if (ret) ++ return ret; ++ } ++ + spin_lock_irqsave(&spi->lock, flags); + + /* CPOL, CPHA and LSB FIRST bits have common register */ +@@ -1057,10 +1055,8 @@ static void stm32f4_spi_dma_tx_cb(void *data) + { + struct stm32_spi *spi = data; + +- if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { +- spi_finalize_current_transfer(spi->master); +- stm32f4_spi_disable(spi); +- } ++ if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) ++ complete(&spi->xfer_completion); + } + + /** +@@ -1073,33 +1069,25 @@ static void stm32f4_spi_dma_rx_cb(void *data) + { + struct stm32_spi *spi = data; + +- spi_finalize_current_transfer(spi->master); +- stm32f4_spi_disable(spi); ++ complete(&spi->xfer_completion); + } + + /** + * stm32h7_spi_dma_cb - dma callback + * @data: pointer to the spi controller data structure + * +- * DMA callback is called when the transfer is complete or when an error +- * occurs. If the transfer is complete, EOT flag is raised. ++ * DMA callback is called when the transfer is complete. + */ + static void stm32h7_spi_dma_cb(void *data) + { + struct stm32_spi *spi = data; + unsigned long flags; +- u32 sr; + + spin_lock_irqsave(&spi->lock, flags); + +- sr = readl_relaxed(spi->base + STM32H7_SPI_SR); ++ complete(&spi->dma_completion); + + spin_unlock_irqrestore(&spi->lock, flags); +- +- if (!(sr & STM32H7_SPI_SR_EOT)) +- dev_warn(spi->dev, "DMA error (sr=0x%08x)\n", sr); +- +- /* Now wait for EOT, or SUSP or OVR in case of error */ + } + + /** +@@ -1156,9 +1144,6 @@ static void stm32_spi_dma_config(struct stm32_spi *spi, + * stm32f4_spi_transfer_one_irq - transfer a single spi_transfer using + * interrupts + * @spi: pointer to the spi controller data structure +- * +- * It must returns 0 if the transfer is finished or 1 if the transfer is still +- * in progress. + */ + static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi) + { +@@ -1192,16 +1177,13 @@ static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi) + + spin_unlock_irqrestore(&spi->lock, flags); + +- return 1; ++ return 0; + } + + /** + * stm32h7_spi_transfer_one_irq - transfer a single spi_transfer using + * interrupts + * @spi: pointer to the spi controller data structure +- * +- * It must returns 0 if the transfer is finished or 1 if the transfer is still +- * in progress. + */ + static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) + { +@@ -1218,7 +1200,7 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) + + /* Enable the interrupts relative to the end of transfer */ + ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE | +- STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE; ++ STM32H7_SPI_IER_OVRIE; + + spin_lock_irqsave(&spi->lock, flags); + +@@ -1234,7 +1216,7 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) + + spin_unlock_irqrestore(&spi->lock, flags); + +- return 1; ++ return 0; + } + + /** +@@ -1242,8 +1224,12 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) + * transfer using DMA + * @spi: pointer to the spi controller data structure + */ +-static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) ++static int stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&spi->lock, flags); ++ + /* In DMA mode end of transfer is handled by DMA TX or RX callback. */ + if (spi->cur_comm == SPI_SIMPLEX_RX || spi->cur_comm == SPI_3WIRE_RX || + spi->cur_comm == SPI_FULL_DUPLEX) { +@@ -1256,6 +1242,10 @@ static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) + } + + stm32_spi_enable(spi); ++ ++ spin_unlock_irqrestore(&spi->lock, flags); ++ ++ return 0; + } + + /** +@@ -1263,36 +1253,48 @@ static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) + * transfer using DMA + * @spi: pointer to the spi controller data structure + */ +-static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) ++static int stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&spi->lock, flags); ++ + /* Enable the interrupts relative to the end of transfer */ + stm32_spi_set_bits(spi, STM32H7_SPI_IER, STM32H7_SPI_IER_EOTIE | + STM32H7_SPI_IER_TXTFIE | +- STM32H7_SPI_IER_OVRIE | +- STM32H7_SPI_IER_MODFIE); ++ STM32H7_SPI_IER_OVRIE); + + stm32_spi_enable(spi); + + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); ++ ++ spin_unlock_irqrestore(&spi->lock, flags); ++ ++ return 0; + } + + /** + * stm32_spi_transfer_one_dma - transfer a single spi_transfer using DMA + * @spi: pointer to the spi controller data structure + * @xfer: pointer to the spi_transfer structure +- * +- * It must returns 0 if the transfer is finished or 1 if the transfer is still +- * in progress. + */ + static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, + struct spi_transfer *xfer) + { ++ dma_async_tx_callback rx_done = NULL, tx_done = NULL; + struct dma_slave_config tx_dma_conf, rx_dma_conf; + struct dma_async_tx_descriptor *tx_dma_desc, *rx_dma_desc; + unsigned long flags; + + spin_lock_irqsave(&spi->lock, flags); + ++ if (spi->rx_buf) ++ rx_done = spi->cfg->dma_rx_cb; ++ else if (spi->tx_buf) ++ tx_done = spi->cfg->dma_tx_cb; ++ ++ reinit_completion(&spi->dma_completion); ++ + rx_dma_desc = NULL; + if (spi->rx_buf && spi->dma_rx) { + stm32_spi_dma_config(spi, &rx_dma_conf, DMA_DEV_TO_MEM); +@@ -1329,7 +1331,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, + goto dma_desc_error; + + if (rx_dma_desc) { +- rx_dma_desc->callback = spi->cfg->dma_rx_cb; ++ rx_dma_desc->callback = rx_done; + rx_dma_desc->callback_param = spi; + + if (dma_submit_error(dmaengine_submit(rx_dma_desc))) { +@@ -1343,7 +1345,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, + if (tx_dma_desc) { + if (spi->cur_comm == SPI_SIMPLEX_TX || + spi->cur_comm == SPI_3WIRE_TX) { +- tx_dma_desc->callback = spi->cfg->dma_tx_cb; ++ tx_dma_desc->callback = tx_done; + tx_dma_desc->callback_param = spi; + } + +@@ -1358,12 +1360,9 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, + stm32_spi_set_bits(spi, spi->cfg->regs->dma_tx_en.reg, + spi->cfg->regs->dma_tx_en.mask); + } +- +- spi->cfg->transfer_one_dma_start(spi); +- + spin_unlock_irqrestore(&spi->lock, flags); + +- return 1; ++ return spi->cfg->transfer_one_dma_start(spi); + + dma_submit_error: + if (spi->dma_rx) +@@ -1405,15 +1404,13 @@ static void stm32h7_spi_set_bpw(struct stm32_spi *spi) + bpw = spi->cur_bpw - 1; + + cfg1_clrb |= STM32H7_SPI_CFG1_DSIZE; +- cfg1_setb |= (bpw << STM32H7_SPI_CFG1_DSIZE_SHIFT) & +- STM32H7_SPI_CFG1_DSIZE; ++ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_DSIZE, bpw); + + spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi, spi->cur_xferlen); + fthlv = spi->cur_fthlv - 1; + + cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV; +- cfg1_setb |= (fthlv << STM32H7_SPI_CFG1_FTHLV_SHIFT) & +- STM32H7_SPI_CFG1_FTHLV; ++ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_FTHLV, fthlv); + + writel_relaxed( + (readl_relaxed(spi->base + STM32H7_SPI_CFG1) & +@@ -1431,8 +1428,7 @@ static void stm32_spi_set_mbr(struct stm32_spi *spi, u32 mbrdiv) + u32 clrb = 0, setb = 0; + + clrb |= spi->cfg->regs->br.mask; +- setb |= ((u32)mbrdiv << spi->cfg->regs->br.shift) & +- spi->cfg->regs->br.mask; ++ setb |= (mbrdiv << spi->cfg->regs->br.shift) & spi->cfg->regs->br.mask; + + writel_relaxed((readl_relaxed(spi->base + spi->cfg->regs->br.reg) & + ~clrb) | setb, +@@ -1523,8 +1519,7 @@ static int stm32h7_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type) + } + + cfg2_clrb |= STM32H7_SPI_CFG2_COMM; +- cfg2_setb |= (mode << STM32H7_SPI_CFG2_COMM_SHIFT) & +- STM32H7_SPI_CFG2_COMM; ++ cfg2_setb |= FIELD_PREP(STM32H7_SPI_CFG2_COMM, mode); + + writel_relaxed( + (readl_relaxed(spi->base + STM32H7_SPI_CFG2) & +@@ -1546,15 +1541,16 @@ static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len) + + cfg2_clrb |= STM32H7_SPI_CFG2_MIDI; + if ((len > 1) && (spi->cur_midi > 0)) { +- u32 sck_period_ns = DIV_ROUND_UP(SPI_1HZ_NS, spi->cur_speed); +- u32 midi = min((u32)DIV_ROUND_UP(spi->cur_midi, sck_period_ns), +- (u32)STM32H7_SPI_CFG2_MIDI >> +- STM32H7_SPI_CFG2_MIDI_SHIFT); ++ u32 sck_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, spi->cur_speed); ++ u32 midi = min_t(u32, ++ DIV_ROUND_UP(spi->cur_midi, sck_period_ns), ++ FIELD_GET(STM32H7_SPI_CFG2_MIDI, ++ STM32H7_SPI_CFG2_MIDI)); ++ + + dev_dbg(spi->dev, "period=%dns, midi=%d(=%dns)\n", + sck_period_ns, midi, midi * sck_period_ns); +- cfg2_setb |= (midi << STM32H7_SPI_CFG2_MIDI_SHIFT) & +- STM32H7_SPI_CFG2_MIDI; ++ cfg2_setb |= FIELD_PREP(STM32H7_SPI_CFG2_MIDI, midi); + } + + writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CFG2) & +@@ -1569,14 +1565,8 @@ static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len) + */ + static int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words) + { +- u32 cr2_clrb = 0, cr2_setb = 0; +- +- if (nb_words <= (STM32H7_SPI_CR2_TSIZE >> +- STM32H7_SPI_CR2_TSIZE_SHIFT)) { +- cr2_clrb |= STM32H7_SPI_CR2_TSIZE; +- cr2_setb = nb_words << STM32H7_SPI_CR2_TSIZE_SHIFT; +- writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CR2) & +- ~cr2_clrb) | cr2_setb, ++ if (nb_words <= STM32H7_SPI_TSIZE_MAX) { ++ writel_relaxed(FIELD_PREP(STM32H7_SPI_CR2_TSIZE, nb_words), + spi->base + STM32H7_SPI_CR2); + } else { + return -EMSGSIZE; +@@ -1675,8 +1665,16 @@ static int stm32_spi_transfer_one(struct spi_master *master, + struct spi_transfer *transfer) + { + struct stm32_spi *spi = spi_master_get_devdata(master); ++ u32 xfer_time, midi_delay_ns; ++ unsigned long timeout; + int ret; + ++ /* Don't do anything on 0 bytes transfers */ ++ if (transfer->len == 0) { ++ spi->xfer_status = 0; ++ goto finalize; ++ } ++ + spi->tx_buf = transfer->tx_buf; + spi->rx_buf = transfer->rx_buf; + spi->tx_len = spi->tx_buf ? transfer->len : 0; +@@ -1691,10 +1689,40 @@ static int stm32_spi_transfer_one(struct spi_master *master, + return ret; + } + ++ reinit_completion(&spi->xfer_completion); ++ spi->xfer_status = 0; ++ + if (spi->cur_usedma) +- return stm32_spi_transfer_one_dma(spi, transfer); ++ ret = stm32_spi_transfer_one_dma(spi, transfer); + else +- return spi->cfg->transfer_one_irq(spi); ++ ret = spi->cfg->transfer_one_irq(spi); ++ ++ if (ret) ++ return ret; ++ ++ /* Wait for transfer to complete */ ++ xfer_time = spi->cur_xferlen * 8 * MSEC_PER_SEC / spi->cur_speed; ++ midi_delay_ns = spi->cur_xferlen * 8 / spi->cur_bpw * spi->cur_midi; ++ xfer_time += DIV_ROUND_UP(midi_delay_ns, NSEC_PER_MSEC); ++ xfer_time = max(2 * xfer_time, 100U); ++ timeout = msecs_to_jiffies(xfer_time); ++ ++ timeout = wait_for_completion_timeout(&spi->xfer_completion, timeout); ++ if (timeout && spi->cur_usedma) ++ timeout = wait_for_completion_timeout(&spi->dma_completion, ++ timeout); ++ ++ if (!timeout) { ++ dev_err(spi->dev, "SPI transfer timeout (%u ms)\n", xfer_time); ++ spi->xfer_status = -ETIMEDOUT; ++ } ++ ++ spi->cfg->disable(spi); ++ ++finalize: ++ spi_finalize_current_transfer(master); ++ ++ return spi->xfer_status; + } + + /** +@@ -1831,6 +1859,7 @@ static int stm32_spi_probe(struct platform_device *pdev) + struct spi_master *master; + struct stm32_spi *spi; + struct resource *res; ++ struct reset_control *rst; + int ret; + + master = spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); +@@ -1844,6 +1873,8 @@ static int stm32_spi_probe(struct platform_device *pdev) + spi->dev = &pdev->dev; + spi->master = master; + spin_lock_init(&spi->lock); ++ init_completion(&spi->xfer_completion); ++ init_completion(&spi->dma_completion); + + spi->cfg = (const struct stm32_spi_cfg *) + of_match_device(pdev->dev.driver->of_match_table, +@@ -1892,11 +1923,19 @@ static int stm32_spi_probe(struct platform_device *pdev) + goto err_clk_disable; + } + +- spi->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); +- if (!IS_ERR(spi->rst)) { +- reset_control_assert(spi->rst); ++ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); ++ if (rst) { ++ if (IS_ERR(rst)) { ++ ret = PTR_ERR(rst); ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "reset get failed: %d\n", ++ ret); ++ goto err_clk_disable; ++ } ++ ++ reset_control_assert(rst); + udelay(2); +- reset_control_deassert(spi->rst); ++ reset_control_deassert(rst); + } + + if (spi->cfg->has_fifo) +@@ -1953,19 +1992,13 @@ static int stm32_spi_probe(struct platform_device *pdev) + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + +- ret = devm_spi_register_master(&pdev->dev, master); ++ ret = spi_register_master(master); + if (ret) { + dev_err(&pdev->dev, "spi master registration failed: %d\n", + ret); + goto err_pm_disable; + } + +- if (!master->cs_gpiods) { +- dev_err(&pdev->dev, "no CS gpios available\n"); +- ret = -EINVAL; +- goto err_pm_disable; +- } +- + dev_info(&pdev->dev, "driver initialized\n"); + + return 0; +@@ -1990,6 +2023,9 @@ static int stm32_spi_remove(struct platform_device *pdev) + struct spi_master *master = platform_get_drvdata(pdev); + struct stm32_spi *spi = spi_master_get_devdata(master); + ++ pm_runtime_get_sync(&pdev->dev); ++ ++ spi_unregister_master(master); + spi->cfg->disable(spi); + + if (master->dma_tx) +@@ -1999,7 +2035,10 @@ static int stm32_spi_remove(struct platform_device *pdev) + + clk_disable_unprepare(spi->clk); + ++ pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(&pdev->dev); ++ pm_runtime_set_suspended(&pdev->dev); ++ pm_runtime_dont_use_autosuspend(&pdev->dev); + + pinctrl_pm_select_sleep_state(&pdev->dev); + +diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h +index e6fb8ada3f4d..370a25a9366c 100644 +--- a/include/dt-bindings/pinctrl/stm32-pinfunc.h ++++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h +@@ -26,6 +26,7 @@ + #define AF14 0xf + #define AF15 0x10 + #define ANALOG 0x11 ++#define RSVD 0x12 + + /* define Pins number*/ + #define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0011-ARM-stm32mp1-r2-RESET-RTC-WATCHDOG.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0017-ARM-5.10.10-stm32mp1-r1-RESET-RTC-WATCHDOG.patch similarity index 70% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0011-ARM-stm32mp1-r2-RESET-RTC-WATCHDOG.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0017-ARM-5.10.10-stm32mp1-r1-RESET-RTC-WATCHDOG.patch index a7af3aa..acb6dea 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0011-ARM-stm32mp1-r2-RESET-RTC-WATCHDOG.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0017-ARM-5.10.10-stm32mp1-r1-RESET-RTC-WATCHDOG.patch @@ -1,139 +1,163 @@ -From 60ca74ac3c89a476b38d4f41c3bea3745779587e Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:46 +0200 -Subject: [PATCH 11/22] ARM-stm32mp1-r2-rc8-RESET-RTC-WATCHDOG +From c40d4d83b3de542be7d64b88f0c842ebecc9a6b2 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:09:52 +0100 +Subject: [PATCH 17/22] ARM 5.10.10-stm32mp1-r1 RESET-RTC-WATCHDOG +Signed-off-by: Romuald JEANNE --- - .../devicetree/bindings/rtc/st,stm32-rtc.txt | 10 +- - drivers/reset/reset-stm32mp1.c | 83 +++++--- - drivers/rtc/Kconfig | 1 + - drivers/rtc/rtc-stm32.c | 180 +++++++++++++++--- - drivers/watchdog/stm32_iwdg.c | 6 +- - include/dt-bindings/reset/stm32mp1-resets.h | 15 ++ - include/dt-bindings/rtc/rtc-stm32.h | 13 ++ - 7 files changed, 246 insertions(+), 62 deletions(-) + drivers/reset/Kconfig | 6 - + drivers/reset/Makefile | 1 - + drivers/reset/reset-stm32mp1.c | 115 ------------- + drivers/rtc/Kconfig | 1 + + drivers/rtc/rtc-stm32.c | 180 ++++++++++++++++---- + drivers/watchdog/stm32_iwdg.c | 13 +- + include/dt-bindings/reset/stm32mp1-resets.h | 15 ++ + include/dt-bindings/rtc/rtc-stm32.h | 13 ++ + 8 files changed, 183 insertions(+), 161 deletions(-) + delete mode 100644 drivers/reset/reset-stm32mp1.c create mode 100644 include/dt-bindings/rtc/rtc-stm32.h -diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt -index 130ca5b982538..bab0df81af2cc 100644 ---- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt -+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt -@@ -21,9 +21,14 @@ Required properties: - domain (RTC registers) write protection. - It is required on stm32(f4/f7/h7). +diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig +index 07d162b179fc..c3186d80c33e 100644 +--- a/drivers/reset/Kconfig ++++ b/drivers/reset/Kconfig +@@ -180,12 +180,6 @@ config RESET_SIMPLE + - Allwinner SoCs + - ZTE's zx2967 family --Optional properties (to override default rtc_ck parent clock on stm32(f4/f7/h7): -+Optional properties: -+* to override default rtc_ck parent clock on stm32(f4/f7/h7): - - assigned-clocks: reference to the rtc_ck clock entry. - - assigned-clock-parents: phandle of the new parent clock of rtc_ck. -+* to select and enable RTC Low Speed Clock Output on stm32mp1: -+- st,lsco: defines the RTC output on which RTC Low-Speed Clock is Output. The -+ valid output values are defined in . -+- pinctrl state named "default" may be defined to reserve pin for RTC output. - - Example: - -@@ -58,4 +63,7 @@ Example: - clock-names = "pclk", "rtc_ck"; - interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_NONE>, - <&exti 19 1>; -+ st,lsco = ; -+ pinctrl-0 = <&rtc_out2_rmp_pins_a>; -+ pinctrl-names = "default"; - }; +-config RESET_STM32MP157 +- bool "STM32MP157 Reset Driver" if COMPILE_TEST +- default MACH_STM32MP157 +- help +- This enables the RCC reset controller driver for STM32 MPUs. +- + config RESET_SOCFPGA + bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA + default ARCH_SOCFPGA +diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile +index 16947610cc3b..b2c9eff41d3b 100644 +--- a/drivers/reset/Makefile ++++ b/drivers/reset/Makefile +@@ -24,7 +24,6 @@ obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o + obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o + obj-$(CONFIG_RESET_SCMI) += reset-scmi.o + obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o +-obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o + obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o + obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o + obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o diff --git a/drivers/reset/reset-stm32mp1.c b/drivers/reset/reset-stm32mp1.c -index b221a28041fa0..daf0e26b27a8d 100644 +deleted file mode 100644 +index b221a28041fa..000000000000 --- a/drivers/reset/reset-stm32mp1.c -+++ b/drivers/reset/reset-stm32mp1.c -@@ -4,14 +4,21 @@ - * Author: Gabriel Fernandez for STMicroelectronics. - */ - -+#include -+#include - #include - #include - #include -+#include - #include -+#include - #include - #include -+#include - ++++ /dev/null +@@ -1,115 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * Copyright (C) STMicroelectronics 2018 - All Rights Reserved +- * Author: Gabriel Fernandez for STMicroelectronics. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- -#define CLR_OFFSET 0x4 -+#define STM32MP1_RESET_ID_MASK GENMASK(15, 0) -+ -+#define CLR_OFFSET 0x4 - - struct stm32_reset_data { - struct reset_controller_dev rcdev; -@@ -79,37 +86,57 @@ static const struct of_device_id stm32_reset_dt_ids[] = { - { /* sentinel */ }, - }; - +- +-struct stm32_reset_data { +- struct reset_controller_dev rcdev; +- void __iomem *membase; +-}; +- +-static inline struct stm32_reset_data * +-to_stm32_reset_data(struct reset_controller_dev *rcdev) +-{ +- return container_of(rcdev, struct stm32_reset_data, rcdev); +-} +- +-static int stm32_reset_update(struct reset_controller_dev *rcdev, +- unsigned long id, bool assert) +-{ +- struct stm32_reset_data *data = to_stm32_reset_data(rcdev); +- int reg_width = sizeof(u32); +- int bank = id / (reg_width * BITS_PER_BYTE); +- int offset = id % (reg_width * BITS_PER_BYTE); +- void __iomem *addr; +- +- addr = data->membase + (bank * reg_width); +- if (!assert) +- addr += CLR_OFFSET; +- +- writel(BIT(offset), addr); +- +- return 0; +-} +- +-static int stm32_reset_assert(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- return stm32_reset_update(rcdev, id, true); +-} +- +-static int stm32_reset_deassert(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- return stm32_reset_update(rcdev, id, false); +-} +- +-static int stm32_reset_status(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- struct stm32_reset_data *data = to_stm32_reset_data(rcdev); +- int reg_width = sizeof(u32); +- int bank = id / (reg_width * BITS_PER_BYTE); +- int offset = id % (reg_width * BITS_PER_BYTE); +- u32 reg; +- +- reg = readl(data->membase + (bank * reg_width)); +- +- return !!(reg & BIT(offset)); +-} +- +-static const struct reset_control_ops stm32_reset_ops = { +- .assert = stm32_reset_assert, +- .deassert = stm32_reset_deassert, +- .status = stm32_reset_status, +-}; +- +-static const struct of_device_id stm32_reset_dt_ids[] = { +- { .compatible = "st,stm32mp1-rcc"}, +- { /* sentinel */ }, +-}; +- -static int stm32_reset_probe(struct platform_device *pdev) -+static void __init stm32mp1_reset_init(struct device_node *np) - { +-{ - struct device *dev = &pdev->dev; - struct stm32_reset_data *data; - void __iomem *membase; - struct resource *res; - - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); -+ void __iomem *base; -+ const struct of_device_id *match; -+ struct stm32_reset_data *data = NULL; -+ int ret; -+ -+ base = of_iomap(np, 0); -+ if (!base) { -+ pr_err("%pOFn: unable to map resource", np); -+ of_node_put(np); -+ return; -+ } -+ -+ match = of_match_node(stm32_reset_dt_ids, np); -+ if (!match) { -+ pr_err("%s: match data not found\n", __func__); -+ goto err; -+ } -+ -+ data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) +- if (!data) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - membase = devm_ioremap_resource(dev, res); - if (IS_ERR(membase)) - return PTR_ERR(membase); -+ goto err; - +- - data->membase = membase; -+ data->membase = base; - data->rcdev.owner = THIS_MODULE; +- data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE; - data->rcdev.ops = &stm32_reset_ops; +- data->rcdev.ops = &stm32_reset_ops; - data->rcdev.of_node = dev->of_node; - - return devm_reset_controller_register(dev, &data->rcdev); -+ data->rcdev.of_node = np; -+ data->rcdev.nr_resets = STM32MP1_RESET_ID_MASK; -+ -+ ret = reset_controller_register(&data->rcdev); -+ if (!ret) -+ return; -+ -+err: -+ pr_err("stm32mp1 reset failed to initialize\n"); -+ if (data) -+ kfree(data); -+ if (base) -+ iounmap(base); -+ of_node_put(np); - } - +-} +- -static struct platform_driver stm32_reset_driver = { - .probe = stm32_reset_probe, - .driver = { @@ -143,22 +167,11 @@ index b221a28041fa0..daf0e26b27a8d 100644 -}; - -builtin_platform_driver(stm32_reset_driver); -+/* -+ * RCC reset and clock drivers bind to the same RCC node. -+ * Register RCC reset driver at init through clock of table, -+ * clock driver for RCC will register at probe time. -+ */ -+static void __init stm32mp1_reset_of_init_drv(struct device_node *np) -+{ -+ of_node_clear_flag(np, OF_POPULATED); -+ stm32mp1_reset_init(np); -+} -+OF_DECLARE_1(clk, stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_reset_of_init_drv); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig -index c5b9804140860..d590b420525ce 100644 +index 65ad9d0b47ab..f2a4d7c633c8 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig -@@ -1862,6 +1862,7 @@ config RTC_DRV_R7301 +@@ -1884,6 +1884,7 @@ config RTC_DRV_R7301 config RTC_DRV_STM32 tristate "STM32 RTC" select REGMAP_MMIO @@ -167,7 +180,7 @@ index c5b9804140860..d590b420525ce 100644 help If you say yes here you get support for the STM32 On-Chip diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c -index 2999e33a7e376..3cf51497681a4 100644 +index d774aa18f57a..7fd6347691bb 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -6,6 +6,8 @@ @@ -399,7 +412,7 @@ index 2999e33a7e376..3cf51497681a4 100644 } /* -@@ -738,13 +848,15 @@ static int stm32_rtc_probe(struct platform_device *pdev) +@@ -736,13 +846,15 @@ static int stm32_rtc_probe(struct platform_device *pdev) } else { rtc->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(rtc->pclk)) { @@ -417,7 +430,7 @@ index 2999e33a7e376..3cf51497681a4 100644 return PTR_ERR(rtc->rtc_ck); } -@@ -781,19 +893,12 @@ static int stm32_rtc_probe(struct platform_device *pdev) +@@ -779,19 +891,12 @@ static int stm32_rtc_probe(struct platform_device *pdev) } ret = device_init_wakeup(&pdev->dev, true); @@ -442,7 +455,7 @@ index 2999e33a7e376..3cf51497681a4 100644 platform_set_drvdata(pdev, rtc); -@@ -816,6 +921,21 @@ static int stm32_rtc_probe(struct platform_device *pdev) +@@ -814,6 +919,21 @@ static int stm32_rtc_probe(struct platform_device *pdev) goto err; } @@ -464,7 +477,7 @@ index 2999e33a7e376..3cf51497681a4 100644 /* * If INITS flag is reset (calendar year field set to 0x00), calendar * must be initialized -@@ -852,6 +972,9 @@ static int stm32_rtc_remove(struct platform_device *pdev) +@@ -850,6 +970,9 @@ static int stm32_rtc_remove(struct platform_device *pdev) const struct stm32_rtc_registers *regs = &rtc->data->regs; unsigned int cr; @@ -474,7 +487,7 @@ index 2999e33a7e376..3cf51497681a4 100644 /* Disable interrupts */ stm32_rtc_wpr_unlock(rtc); cr = readl_relaxed(rtc->base + regs->cr); -@@ -881,9 +1004,6 @@ static int stm32_rtc_suspend(struct device *dev) +@@ -879,9 +1002,6 @@ static int stm32_rtc_suspend(struct device *dev) if (rtc->data->has_pclk) clk_disable_unprepare(rtc->pclk); @@ -484,9 +497,9 @@ index 2999e33a7e376..3cf51497681a4 100644 return 0; } -@@ -902,15 +1022,13 @@ static int stm32_rtc_resume(struct device *dev) - if (ret < 0) +@@ -903,15 +1023,13 @@ static int stm32_rtc_resume(struct device *dev) return ret; + } - if (device_may_wakeup(dev)) - return disable_irq_wake(rtc->irq_alarm); @@ -504,31 +517,35 @@ index 2999e33a7e376..3cf51497681a4 100644 static struct platform_driver stm32_rtc_driver = { .probe = stm32_rtc_probe, diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c -index 25188d6bbe152..1b71c205cee0e 100644 +index 25188d6bbe15..a3436c296c97 100644 --- a/drivers/watchdog/stm32_iwdg.c +++ b/drivers/watchdog/stm32_iwdg.c -@@ -163,7 +163,8 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev, +@@ -162,18 +162,15 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev, + u32 ret; wdt->clk_lsi = devm_clk_get(dev, "lsi"); - if (IS_ERR(wdt->clk_lsi)) { +- if (IS_ERR(wdt->clk_lsi)) { - dev_err(dev, "Unable to get lsi clock\n"); -+ if (PTR_ERR(wdt->clk_lsi) != -EPROBE_DEFER) -+ dev_err(dev, "Unable to get lsi clock\n"); - return PTR_ERR(wdt->clk_lsi); - } +- return PTR_ERR(wdt->clk_lsi); +- } ++ if (IS_ERR(wdt->clk_lsi)) ++ return dev_err_probe(dev, PTR_ERR(wdt->clk_lsi), "Unable to get lsi clock\n"); -@@ -171,7 +172,8 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev, + /* optional peripheral clock */ if (wdt->data->has_pclk) { wdt->clk_pclk = devm_clk_get(dev, "pclk"); - if (IS_ERR(wdt->clk_pclk)) { +- if (IS_ERR(wdt->clk_pclk)) { - dev_err(dev, "Unable to get pclk clock\n"); -+ if (PTR_ERR(wdt->clk_pclk) != -EPROBE_DEFER) -+ dev_err(dev, "Unable to get pclk clock\n"); - return PTR_ERR(wdt->clk_pclk); - } +- return PTR_ERR(wdt->clk_pclk); +- } ++ if (IS_ERR(wdt->clk_pclk)) ++ return dev_err_probe(dev, PTR_ERR(wdt->clk_pclk), ++ "Unable to get pclk clock\n"); + ret = clk_prepare_enable(wdt->clk_pclk); + if (ret) { diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h -index f0c3aaef67a0a..f3a0ed3178356 100644 +index f0c3aaef67a0..f3a0ed317835 100644 --- a/include/dt-bindings/reset/stm32mp1-resets.h +++ b/include/dt-bindings/reset/stm32mp1-resets.h @@ -7,6 +7,7 @@ @@ -560,7 +577,7 @@ index f0c3aaef67a0a..f3a0ed3178356 100644 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h new file mode 100644 -index 0000000000000..4373c4dea5879 +index 000000000000..4373c4dea587 --- /dev/null +++ b/include/dt-bindings/rtc/rtc-stm32.h @@ -0,0 +1,13 @@ diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0018-ARM-5.10.10-stm32mp1-r1-SCMI.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0018-ARM-5.10.10-stm32mp1-r1-SCMI.patch new file mode 100644 index 0000000..b763a28 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0018-ARM-5.10.10-stm32mp1-r1-SCMI.patch @@ -0,0 +1,131 @@ +From 51f0826032cee1b8cb0a1597c0a8d60b0042109d Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:17:18 +0100 +Subject: [PATCH 18/22] ARM 5.10.10-stm32mp1-r1 SCMI + +--- + drivers/firmware/arm_scmi/base.c | 2 +- + drivers/firmware/arm_scmi/bus.c | 9 --------- + drivers/firmware/arm_scmi/clock.c | 2 +- + drivers/firmware/arm_scmi/common.h | 2 ++ + drivers/firmware/arm_scmi/driver.c | 10 ++++++++++ + drivers/firmware/arm_scmi/perf.c | 2 +- + drivers/firmware/arm_scmi/sensors.c | 2 +- + 7 files changed, 16 insertions(+), 13 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c +index 017e5d8bd869..a70b10ebaf45 100644 +--- a/drivers/firmware/arm_scmi/base.c ++++ b/drivers/firmware/arm_scmi/base.c +@@ -183,7 +183,7 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle, + /* Set the number of protocols to be skipped/already read */ + *num_skip = cpu_to_le32(tot_num_ret); + +- ret = scmi_do_xfer(handle, t); ++ ret = scmi_do_xfer_again(handle, t); + if (ret) + break; + +diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c +index 1377ec76a45d..8ea04b069129 100644 +--- a/drivers/firmware/arm_scmi/bus.c ++++ b/drivers/firmware/arm_scmi/bus.c +@@ -60,11 +60,6 @@ static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle) + return fn(handle); + } + +-static int scmi_protocol_dummy_init(struct scmi_handle *handle) +-{ +- return 0; +-} +- + static int scmi_dev_probe(struct device *dev) + { + struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver); +@@ -83,10 +78,6 @@ static int scmi_dev_probe(struct device *dev) + if (ret) + return ret; + +- /* Skip protocol initialisation for additional devices */ +- idr_replace(&scmi_protocols, &scmi_protocol_dummy_init, +- scmi_dev->protocol_id); +- + return scmi_drv->probe(scmi_dev); + } + +diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c +index 4645677d86f1..c348a6f2eb29 100644 +--- a/drivers/firmware/arm_scmi/clock.c ++++ b/drivers/firmware/arm_scmi/clock.c +@@ -161,7 +161,7 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, + /* Set the number of rates to be skipped/already read */ + clk_desc->rate_index = cpu_to_le32(tot_rate_cnt); + +- ret = scmi_do_xfer(handle, t); ++ ret = scmi_do_xfer_again(handle, t); + if (ret) + goto err; + +diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h +index 65063fa948d4..98e642b591c5 100644 +--- a/drivers/firmware/arm_scmi/common.h ++++ b/drivers/firmware/arm_scmi/common.h +@@ -143,6 +143,8 @@ struct scmi_xfer { + + void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer); + int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer); ++int scmi_do_xfer_again(const struct scmi_handle *handle, ++ struct scmi_xfer *xfer); + int scmi_do_xfer_with_response(const struct scmi_handle *h, + struct scmi_xfer *xfer); + int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id, +diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c +index 3dfd8b6a0ebf..479f67d2377b 100644 +--- a/drivers/firmware/arm_scmi/driver.c ++++ b/drivers/firmware/arm_scmi/driver.c +@@ -410,6 +410,16 @@ void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle, + xfer->rx.len = info->desc->max_msg_size; + } + ++int scmi_do_xfer_again(const struct scmi_handle *handle, struct scmi_xfer *xfer) ++{ ++ struct scmi_info *info = handle_to_scmi_info(handle); ++ ++ xfer->rx.len = info->desc->max_msg_size; ++ xfer->hdr.poll_completion = false; ++ ++ return scmi_do_xfer(handle, xfer); ++} ++ + #define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) + + /** +diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c +index 82fb3babff72..7bea0f6464ff 100644 +--- a/drivers/firmware/arm_scmi/perf.c ++++ b/drivers/firmware/arm_scmi/perf.c +@@ -281,7 +281,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, + /* Set the number of OPPs to be skipped/already read */ + dom_info->level_index = cpu_to_le32(tot_opp_cnt); + +- ret = scmi_do_xfer(handle, t); ++ ret = scmi_do_xfer_again(handle, t); + if (ret) + break; + +diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c +index b4232d611033..6dae881be774 100644 +--- a/drivers/firmware/arm_scmi/sensors.c ++++ b/drivers/firmware/arm_scmi/sensors.c +@@ -134,7 +134,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, + /* Set the number of sensors to be skipped/already read */ + put_unaligned_le32(desc_index, t->tx.buf); + +- ret = scmi_do_xfer(handle, t); ++ ret = scmi_do_xfer_again(handle, t); + if (ret) + break; + +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0019-ARM-5.10.10-stm32mp1-r1-SOUND.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0019-ARM-5.10.10-stm32mp1-r1-SOUND.patch new file mode 100644 index 0000000..febbf99 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0019-ARM-5.10.10-stm32mp1-r1-SOUND.patch @@ -0,0 +1,626 @@ +From f934df539b8cdfa58cb512b439749dba32a42932 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:16:24 +0100 +Subject: [PATCH 19/22] ARM 5.10.10-stm32mp1-r1 SOUND + +--- + sound/soc/codecs/Kconfig | 2 +- + sound/soc/codecs/wm8994.c | 81 ++++++++- + sound/soc/stm/stm32_i2s.c | 310 +++++++++++++++++++++++++++++----- + sound/soc/stm/stm32_sai_sub.c | 4 +- + 4 files changed, 344 insertions(+), 53 deletions(-) + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 34c6dd04b85a..3afc5d1f074d 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -1642,7 +1642,7 @@ config SND_SOC_WM8993 + depends on I2C + + config SND_SOC_WM8994 +- tristate ++ tristate "Wolfson Microelectronics WM8994 codec" + + config SND_SOC_WM8995 + tristate +diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c +index f57884113406..6d30b438ba0f 100644 +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -7,6 +7,7 @@ + * Author: Mark Brown + */ + ++#include + #include + #include + #include +@@ -838,6 +839,37 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, + return 0; + } + ++static int mclk_event(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) ++{ ++ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); ++ struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(comp); ++ int ret, mclk_id = 0; ++ ++ if (!strncmp(w->name, "MCLK2", 5)) ++ mclk_id = 1; ++ ++ switch (event) { ++ case SND_SOC_DAPM_PRE_PMU: ++ dev_dbg(comp->dev, "Enable master clock %s\n", ++ mclk_id ? "MCLK2" : "MCLK1"); ++ ++ ret = clk_prepare_enable(wm8994->mclk[mclk_id].clk); ++ if (ret < 0) { ++ dev_err(comp->dev, "Failed to enable clock: %d\n", ret); ++ return ret; ++ } ++ break; ++ case SND_SOC_DAPM_POST_PMD: ++ dev_dbg(comp->dev, "Disable master clock %s\n", ++ mclk_id ? "MCLK2" : "MCLK1"); ++ clk_disable_unprepare(wm8994->mclk[mclk_id].clk); ++ break; ++ } ++ ++ return 0; ++} ++ + static void vmid_reference(struct snd_soc_component *component) + { + struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); +@@ -1225,7 +1257,6 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, + else + adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; + +- + val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_2); + if ((val & WM8994_AIF2DACL_SRC) && + (val & WM8994_AIF2DACR_SRC)) +@@ -1847,6 +1878,16 @@ static const struct snd_soc_dapm_widget wm8994_specific_dapm_widgets[] = { + SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &wm8994_aif3adc_mux), + }; + ++static const struct snd_soc_dapm_widget wm8994_mclk1_dapm_widgets[] = { ++SND_SOC_DAPM_SUPPLY("MCLK1", SND_SOC_NOPM, 0, 0, mclk_event, ++ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), ++}; ++ ++static const struct snd_soc_dapm_widget wm8994_mclk2_dapm_widgets[] = { ++SND_SOC_DAPM_SUPPLY("MCLK2", SND_SOC_NOPM, 0, 0, mclk_event, ++ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), ++}; ++ + static const struct snd_soc_dapm_widget wm8958_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("AIF3", WM8994_POWER_MANAGEMENT_6, 5, 1, NULL, 0), + SND_SOC_DAPM_MUX("Mono PCM Out Mux", SND_SOC_NOPM, 0, 0, &mono_pcm_out_mux), +@@ -2071,10 +2112,10 @@ static const struct snd_soc_dapm_route wm8994_lateclk_intercon[] = { + }; + + static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { +- { "AIF1DACDAT", NULL, "AIF2DACDAT" }, +- { "AIF2DACDAT", NULL, "AIF1DACDAT" }, +- { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, +- { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, ++// { "AIF1DACDAT", NULL, "AIF2DACDAT" }, ++// { "AIF2DACDAT", NULL, "AIF1DACDAT" }, ++// { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, ++// { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, + { "MICBIAS1", NULL, "CLK_SYS" }, + { "MICBIAS1", NULL, "MICBIAS Supply" }, + { "MICBIAS2", NULL, "CLK_SYS" }, +@@ -2506,11 +2547,24 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, + { + struct snd_soc_component *component = dai->component; + struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); +- int ret, i; ++ int i, ret; + ++ /* ++ * Simple card provides unconditionnaly clock_id = 0. ++ * Workaround to select master clock for aif1/2 ++ */ + switch (dai->id) { + case 1: ++ if (wm8994->mclk[0].clk) ++ clk_id = WM8994_SYSCLK_MCLK1; ++ else if (wm8994->mclk[1].clk) ++ clk_id = WM8994_SYSCLK_MCLK2; ++ break; + case 2: ++ if (wm8994->mclk[1].clk) ++ clk_id = WM8994_SYSCLK_MCLK2; ++ else if (wm8994->mclk[0].clk) ++ clk_id = WM8994_SYSCLK_MCLK1; + break; + + default: +@@ -2522,6 +2576,10 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, + case WM8994_SYSCLK_MCLK1: + wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1; + ++ /* Avoid busy error on exclusive rate change request */ ++ if (!freq) ++ break; ++ + ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq); + if (ret < 0) + return ret; +@@ -2535,6 +2593,9 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, + /* TODO: Set GPIO AF */ + wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2; + ++ if (!freq) ++ break; ++ + ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq); + if (ret < 0) + return ret; +@@ -4438,6 +4499,14 @@ static int wm8994_component_probe(struct snd_soc_component *component) + ARRAY_SIZE(wm8994_snd_controls)); + snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, + ARRAY_SIZE(wm8994_specific_dapm_widgets)); ++ if (wm8994->mclk[0].clk) ++ snd_soc_dapm_new_controls(dapm, wm8994_mclk1_dapm_widgets, ++ ARRAY_SIZE(wm8994_mclk1_dapm_widgets)); ++ ++ if (wm8994->mclk[1].clk) ++ snd_soc_dapm_new_controls(dapm, wm8994_mclk2_dapm_widgets, ++ ARRAY_SIZE(wm8994_mclk2_dapm_widgets)); ++ + if (control->revision < 4) { + snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, + ARRAY_SIZE(wm8994_lateclk_revd_widgets)); +diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c +index 7c4d63c33f15..7d1672cf78cc 100644 +--- a/sound/soc/stm/stm32_i2s.c ++++ b/sound/soc/stm/stm32_i2s.c +@@ -8,6 +8,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -196,6 +197,9 @@ enum i2s_datlen { + #define STM32_I2S_IS_MASTER(x) ((x)->ms_flg == I2S_MS_MASTER) + #define STM32_I2S_IS_SLAVE(x) ((x)->ms_flg == I2S_MS_SLAVE) + ++#define STM32_I2S_NAME_LEN 32 ++#define STM32_I2S_RATE_11K 11025 ++ + /** + * struct stm32_i2s_data - private data of I2S + * @regmap_conf: I2S register map configuration pointer +@@ -206,6 +210,7 @@ enum i2s_datlen { + * @dma_data_rx: dma configuration data for tx channel + * @substream: PCM substream data pointer + * @i2sclk: kernel clock feeding the I2S clock generator ++ * @i2smclk: master clock from I2S mclk provider + * @pclk: peripheral clock driving bus interface + * @x8kclk: I2S parent clock for sampling frequencies multiple of 8kHz + * @x11kclk: I2S parent clock for sampling frequencies multiple of 11kHz +@@ -215,6 +220,9 @@ enum i2s_datlen { + * @irq_lock: prevent race condition with IRQ + * @mclk_rate: master clock frequency (Hz) + * @fmt: DAI protocol ++ * @divider: prescaler division ratio ++ * @div: prescaler div field ++ * @odd: prescaler odd field + * @refcount: keep count of opened streams on I2S + * @ms_flg: master mode flag. + */ +@@ -227,6 +235,7 @@ struct stm32_i2s_data { + struct snd_dmaengine_dai_dma_data dma_data_rx; + struct snd_pcm_substream *substream; + struct clk *i2sclk; ++ struct clk *i2smclk; + struct clk *pclk; + struct clk *x8kclk; + struct clk *x11kclk; +@@ -236,10 +245,210 @@ struct stm32_i2s_data { + spinlock_t irq_lock; /* used to prevent race condition with IRQ */ + unsigned int mclk_rate; + unsigned int fmt; ++ unsigned int divider; ++ unsigned int div; ++ bool odd; + int refcount; + int ms_flg; + }; + ++struct stm32_i2smclk_data { ++ struct clk_hw hw; ++ unsigned long freq; ++ struct stm32_i2s_data *i2s_data; ++}; ++ ++#define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw) ++ ++static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s, ++ unsigned long input_rate, ++ unsigned long output_rate) ++{ ++ unsigned int ratio, div, divider = 1; ++ bool odd; ++ ++ ratio = DIV_ROUND_CLOSEST(input_rate, output_rate); ++ ++ /* Check the parity of the divider */ ++ odd = ratio & 0x1; ++ ++ /* Compute the div prescaler */ ++ div = ratio >> 1; ++ ++ /* If div is 0 actual divider is 1 */ ++ if (div) { ++ divider = ((2 * div) + odd); ++ dev_dbg(&i2s->pdev->dev, "Divider: 2*%d(div)+%d(odd) = %d\n", ++ div, odd, divider); ++ } ++ ++ /* Division by three is not allowed by I2S prescaler */ ++ if ((div == 1 && odd) || div > I2S_CGFR_I2SDIV_MAX) { ++ dev_err(&i2s->pdev->dev, "Wrong divider setting\n"); ++ return -EINVAL; ++ } ++ ++ if (input_rate % divider) ++ dev_dbg(&i2s->pdev->dev, ++ "Rate not accurate. requested (%ld), actual (%ld)\n", ++ output_rate, input_rate / divider); ++ ++ i2s->div = div; ++ i2s->odd = odd; ++ i2s->divider = divider; ++ ++ return 0; ++} ++ ++static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s) ++{ ++ u32 cgfr, cgfr_mask; ++ ++ cgfr = I2S_CGFR_I2SDIV_SET(i2s->div) | (i2s->odd << I2S_CGFR_ODD_SHIFT); ++ cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD; ++ ++ return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, ++ cgfr_mask, cgfr); ++} ++ ++static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, ++ unsigned int rate) ++{ ++ struct platform_device *pdev = i2s->pdev; ++ struct clk *parent_clk; ++ int ret; ++ ++ if (!(rate % STM32_I2S_RATE_11K)) ++ parent_clk = i2s->x11kclk; ++ else ++ parent_clk = i2s->x8kclk; ++ ++ ret = clk_set_parent(i2s->i2sclk, parent_clk); ++ if (ret) ++ dev_err(&pdev->dev, ++ "Error %d setting i2sclk parent clock\n", ret); ++ ++ return ret; ++} ++ ++static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *prate) ++{ ++ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); ++ struct stm32_i2s_data *i2s = mclk->i2s_data; ++ int ret; ++ ++ ret = stm32_i2s_calc_clk_div(i2s, *prate, rate); ++ if (ret) ++ return ret; ++ ++ mclk->freq = *prate / i2s->divider; ++ ++ return mclk->freq; ++} ++ ++static unsigned long stm32_i2smclk_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); ++ ++ return mclk->freq; ++} ++ ++static int stm32_i2smclk_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); ++ struct stm32_i2s_data *i2s = mclk->i2s_data; ++ int ret; ++ ++ ret = stm32_i2s_calc_clk_div(i2s, parent_rate, rate); ++ if (ret) ++ return ret; ++ ++ ret = stm32_i2s_set_clk_div(i2s); ++ if (ret) ++ return ret; ++ ++ mclk->freq = rate; ++ ++ return 0; ++} ++ ++static int stm32_i2smclk_enable(struct clk_hw *hw) ++{ ++ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); ++ struct stm32_i2s_data *i2s = mclk->i2s_data; ++ ++ dev_dbg(&i2s->pdev->dev, "Enable master clock\n"); ++ ++ return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, ++ I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); ++} ++ ++static void stm32_i2smclk_disable(struct clk_hw *hw) ++{ ++ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); ++ struct stm32_i2s_data *i2s = mclk->i2s_data; ++ ++ dev_dbg(&i2s->pdev->dev, "Disable master clock\n"); ++ ++ regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0); ++} ++ ++static const struct clk_ops mclk_ops = { ++ .enable = stm32_i2smclk_enable, ++ .disable = stm32_i2smclk_disable, ++ .recalc_rate = stm32_i2smclk_recalc_rate, ++ .round_rate = stm32_i2smclk_round_rate, ++ .set_rate = stm32_i2smclk_set_rate, ++}; ++ ++static int stm32_i2s_add_mclk_provider(struct stm32_i2s_data *i2s) ++{ ++ struct clk_hw *hw; ++ struct stm32_i2smclk_data *mclk; ++ struct device *dev = &i2s->pdev->dev; ++ const char *pname = __clk_get_name(i2s->i2sclk); ++ char *mclk_name, *p, *s = (char *)pname; ++ int ret, i = 0; ++ ++ mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL); ++ if (!mclk) ++ return -ENOMEM; ++ ++ mclk_name = devm_kcalloc(dev, sizeof(char), ++ STM32_I2S_NAME_LEN, GFP_KERNEL); ++ if (!mclk_name) ++ return -ENOMEM; ++ ++ /* ++ * Forge mclk clock name from parent clock name and suffix. ++ * String after "_" char is stripped in parent name. ++ */ ++ p = mclk_name; ++ while (*s && *s != '_' && (i < (STM32_I2S_NAME_LEN - 7))) { ++ *p++ = *s++; ++ i++; ++ } ++ strcat(p, "_mclk"); ++ ++ mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0); ++ mclk->i2s_data = i2s; ++ hw = &mclk->hw; ++ ++ dev_dbg(dev, "Register master clock %s\n", mclk_name); ++ ret = devm_clk_hw_register(&i2s->pdev->dev, hw); ++ if (ret) { ++ dev_err(dev, "mclk register fails with error %d\n", ret); ++ return ret; ++ } ++ i2s->i2smclk = hw->clk; ++ ++ /* register mclk provider */ ++ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); ++} ++ + static irqreturn_t stm32_i2s_isr(int irq, void *devid) + { + struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid; +@@ -405,18 +614,46 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) + { + struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); ++ int ret = 0; + +- dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz\n", freq); ++ dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz. mode: %s, dir: %s\n", ++ freq, STM32_I2S_IS_MASTER(i2s) ? "master" : "slave", ++ dir ? "output" : "input"); + +- if ((dir == SND_SOC_CLOCK_OUT) && STM32_I2S_IS_MASTER(i2s)) { +- i2s->mclk_rate = freq; ++ /* MCLK generation is available only in master mode */ ++ if (dir == SND_SOC_CLOCK_OUT && STM32_I2S_IS_MASTER(i2s)) { ++ if (!i2s->i2smclk) { ++ dev_dbg(cpu_dai->dev, "No MCLK registered\n"); ++ return 0; ++ } + +- /* Enable master clock if master mode and mclk-fs are set */ +- return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, +- I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); ++ /* Assume shutdown if requested frequency is 0Hz */ ++ if (!freq) { ++ /* Release mclk rate only if rate was actually set */ ++ if (i2s->mclk_rate) { ++ clk_rate_exclusive_put(i2s->i2smclk); ++ i2s->mclk_rate = 0; ++ } ++ return regmap_update_bits(i2s->regmap, ++ STM32_I2S_CGFR_REG, ++ I2S_CGFR_MCKOE, 0); ++ } ++ /* If master clock is used, set parent clock now */ ++ ret = stm32_i2s_set_parent_clock(i2s, freq); ++ if (ret) ++ return ret; ++ ret = clk_set_rate_exclusive(i2s->i2smclk, freq); ++ if (ret) { ++ dev_err(cpu_dai->dev, "Could not set mclk rate\n"); ++ return ret; ++ } ++ ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, ++ I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); ++ if (!ret) ++ i2s->mclk_rate = freq; + } + +- return 0; ++ return ret; + } + + static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, +@@ -424,11 +661,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, + { + struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); + unsigned long i2s_clock_rate; +- unsigned int tmp, div, real_div, nb_bits, frame_len; ++ unsigned int nb_bits, frame_len; + unsigned int rate = params_rate(params); ++ u32 cgfr; + int ret; +- u32 cgfr, cgfr_mask; +- bool odd; + + if (!(rate % 11025)) + clk_set_parent(i2s->i2sclk, i2s->x11kclk); +@@ -449,7 +685,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, + * dsp mode : div = i2s_clk / (nb_bits x ws) + */ + if (i2s->mclk_rate) { +- tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, i2s->mclk_rate); ++ ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, ++ i2s->mclk_rate); ++ if (ret) ++ return ret; + } else { + frame_len = 32; + if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == +@@ -462,34 +701,13 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, + return ret; + + nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1); +- tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, (nb_bits * rate)); +- } +- +- /* Check the parity of the divider */ +- odd = tmp & 0x1; +- +- /* Compute the div prescaler */ +- div = tmp >> 1; +- +- cgfr = I2S_CGFR_I2SDIV_SET(div) | (odd << I2S_CGFR_ODD_SHIFT); +- cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD; +- +- real_div = ((2 * div) + odd); +- dev_dbg(cpu_dai->dev, "I2S clk: %ld, SCLK: %d\n", +- i2s_clock_rate, rate); +- dev_dbg(cpu_dai->dev, "Divider: 2*%d(div)+%d(odd) = %d\n", +- div, odd, real_div); +- +- if (((div == 1) && odd) || (div > I2S_CGFR_I2SDIV_MAX)) { +- dev_err(cpu_dai->dev, "Wrong divider setting\n"); +- return -EINVAL; ++ ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, ++ (nb_bits * rate)); ++ if (ret) ++ return ret; + } + +- if (!div && !odd) +- dev_warn(cpu_dai->dev, "real divider forced to 1\n"); +- +- ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, +- cgfr_mask, cgfr); ++ ret = stm32_i2s_set_clk_div(i2s); + if (ret < 0) + return ret; + +@@ -694,9 +912,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, + struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); + unsigned long flags; + +- regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, +- I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE); +- + clk_disable_unprepare(i2s->i2sclk); + + spin_lock_irqsave(&i2s->irq_lock, flags); +@@ -861,6 +1076,13 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, + return PTR_ERR(i2s->x11kclk); + } + ++ /* Register mclk provider if requested */ ++ if (of_find_property(np, "#clock-cells", NULL)) { ++ ret = stm32_i2s_add_mclk_provider(i2s); ++ if (ret < 0) ++ return ret; ++ } ++ + /* Get irqs */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) +@@ -906,16 +1128,16 @@ static int stm32_i2s_probe(struct platform_device *pdev) + if (!i2s) + return -ENOMEM; + +- ret = stm32_i2s_parse_dt(pdev, i2s); +- if (ret) +- return ret; +- + i2s->pdev = pdev; + i2s->ms_flg = I2S_MS_NOT_SET; + spin_lock_init(&i2s->lock_fd); + spin_lock_init(&i2s->irq_lock); + platform_set_drvdata(pdev, i2s); + ++ ret = stm32_i2s_parse_dt(pdev, i2s); ++ if (ret) ++ return ret; ++ + ret = stm32_i2s_dais_init(pdev, i2s); + if (ret) + return ret; +diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c +index 3aa1cf262402..780f48138985 100644 +--- a/sound/soc/stm/stm32_sai_sub.c ++++ b/sound/soc/stm/stm32_sai_sub.c +@@ -1294,7 +1294,7 @@ static struct snd_soc_dai_driver stm32_sai_playback_dai = { + .id = 1, /* avoid call to fmt_single_name() */ + .playback = { + .channels_min = 1, +- .channels_max = 2, ++ .channels_max = 16, + .rate_min = 8000, + .rate_max = 192000, + .rates = SNDRV_PCM_RATE_CONTINUOUS, +@@ -1312,7 +1312,7 @@ static struct snd_soc_dai_driver stm32_sai_capture_dai = { + .id = 1, /* avoid call to fmt_single_name() */ + .capture = { + .channels_min = 1, +- .channels_max = 2, ++ .channels_max = 16, + .rate_min = 8000, + .rate_max = 192000, + .rates = SNDRV_PCM_RATE_CONTINUOUS, +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0020-ARM-5.10.10-stm32mp1-r1-MISC-CPUIDLE-POWER.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0020-ARM-5.10.10-stm32mp1-r1-MISC-CPUIDLE-POWER.patch new file mode 100644 index 0000000..7ab331e --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0020-ARM-5.10.10-stm32mp1-r1-MISC-CPUIDLE-POWER.patch @@ -0,0 +1,437 @@ +From 996898e1ae8bd13f5bb6986c52bd9777b68e80fa Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:18:38 +0100 +Subject: [PATCH 20/22] ARM 5.10.10-stm32mp1-r1 MISC-CPUIDLE-POWER + +Signed-off-by: Romuald JEANNE +--- + drivers/base/power/domain.c | 4 +- + drivers/base/power/main.c | 4 +- + drivers/cpuidle/Kconfig.arm | 8 + + drivers/cpuidle/Makefile | 1 + + drivers/cpuidle/cpuidle-stm32.c | 276 ++++++++++++++++++++++++++++++++ + drivers/opp/core.c | 6 +- + include/linux/pm_wakeup.h | 10 ++ + kernel/power/suspend.c | 1 - + 8 files changed, 304 insertions(+), 6 deletions(-) + create mode 100644 drivers/cpuidle/cpuidle-stm32.c + +diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c +index 743268996336..e0894ef8457c 100644 +--- a/drivers/base/power/domain.c ++++ b/drivers/base/power/domain.c +@@ -1142,7 +1142,7 @@ static int genpd_finish_suspend(struct device *dev, bool poweroff) + if (ret) + return ret; + +- if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) ++ if (device_wakeup_path(dev) && genpd_is_active_wakeup(genpd)) + return 0; + + if (genpd->dev_ops.stop && genpd->dev_ops.start && +@@ -1196,7 +1196,7 @@ static int genpd_resume_noirq(struct device *dev) + if (IS_ERR(genpd)) + return -EINVAL; + +- if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) ++ if (device_wakeup_path(dev) && genpd_is_active_wakeup(genpd)) + return pm_generic_resume_noirq(dev); + + genpd_lock(genpd); +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index c7ac49042cee..921c5b2ec30a 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -1359,7 +1359,7 @@ static void dpm_propagate_wakeup_to_parent(struct device *dev) + + spin_lock_irq(&parent->power.lock); + +- if (dev->power.wakeup_path && !parent->power.ignore_children) ++ if (device_wakeup_path(dev) && !parent->power.ignore_children) + parent->power.wakeup_path = true; + + spin_unlock_irq(&parent->power.lock); +@@ -1627,7 +1627,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) + goto Complete; + + /* Avoid direct_complete to let wakeup_path propagate. */ +- if (device_may_wakeup(dev) || dev->power.wakeup_path) ++ if (device_may_wakeup(dev) || device_wakeup_path(dev)) + dev->power.direct_complete = false; + + if (dev->power.direct_complete) { +diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm +index 0844fadc4be8..2b8a0756e4ff 100644 +--- a/drivers/cpuidle/Kconfig.arm ++++ b/drivers/cpuidle/Kconfig.arm +@@ -91,6 +91,14 @@ config ARM_EXYNOS_CPUIDLE + help + Select this to enable cpuidle for Exynos processors. + ++config ARM_STM32_CPUIDLE ++ bool "Cpu Idle Driver for the STM32 processors" ++ depends on MACH_STM32MP157 ++ select DT_IDLE_STATES ++ select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP ++ help ++ Select this to enable cpuidle for STM32 processors. ++ + config ARM_MVEBU_V7_CPUIDLE + bool "CPU Idle Driver for mvebu v7 family processors" + depends on (ARCH_MVEBU || COMPILE_TEST) && !ARM64 +diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile +index 26bbc5e74123..cc1eccc73d65 100644 +--- a/drivers/cpuidle/Makefile ++++ b/drivers/cpuidle/Makefile +@@ -25,6 +25,7 @@ obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o + obj-$(CONFIG_ARM_PSCI_CPUIDLE_DOMAIN) += cpuidle-psci-domain.o + obj-$(CONFIG_ARM_TEGRA_CPUIDLE) += cpuidle-tegra.o + obj-$(CONFIG_ARM_QCOM_SPM_CPUIDLE) += cpuidle-qcom-spm.o ++obj-$(CONFIG_ARM_STM32_CPUIDLE) += cpuidle-stm32.o + + ############################################################################### + # MIPS drivers +diff --git a/drivers/cpuidle/cpuidle-stm32.c b/drivers/cpuidle/cpuidle-stm32.c +new file mode 100644 +index 000000000000..d3413386cc7f +--- /dev/null ++++ b/drivers/cpuidle/cpuidle-stm32.c +@@ -0,0 +1,276 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (C) STMicroelectronics 2019 ++// Author: ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "dt_idle_states.h" ++ ++#define SMC_AUTOSTOP() \ ++{ \ ++ struct arm_smccc_res res; \ ++ arm_smccc_smc(0x8200100a, 0, 0, 0, \ ++ 0, 0, 0, 0, &res); \ ++} ++ ++struct stm32_pm_domain { ++ struct device *dev; ++ struct generic_pm_domain genpd; ++ int id; ++}; ++ ++static atomic_t stm_idle_barrier; ++ ++static int stm32_enter_idle(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int index) ++{ ++ /* ++ * Call idle CPU PM enter notifier chain so that ++ * VFP and per CPU interrupt context is saved. ++ */ ++ cpu_pm_enter(); ++ ++ /* ++ * be sure that both cpu enter at the same time ++ * normally not needed is the state is declared as coupled ++ */ ++ cpuidle_coupled_parallel_barrier(dev, &stm_idle_barrier); ++ ++ /* Enter broadcast mode for periodic timers */ ++ tick_broadcast_enable(); ++ ++ /* Enter broadcast mode for one-shot timers */ ++ tick_broadcast_enter(); ++ ++ if (dev->cpu == 0) ++ cpu_cluster_pm_enter(); ++ ++ SMC_AUTOSTOP(); ++ ++ if (dev->cpu == 0) ++ cpu_cluster_pm_exit(); ++ ++ tick_broadcast_exit(); ++ ++ cpuidle_coupled_parallel_barrier(dev, &stm_idle_barrier); ++ ++ /* ++ * Call idle CPU PM exit notifier chain to restore ++ * VFP and per CPU IRQ context. ++ */ ++ cpu_pm_exit(); ++ ++ return index; ++} ++ ++static const struct of_device_id stm32_idle_state_match[] __initconst = { ++ { .compatible = "arm,idle-state", ++ .data = stm32_enter_idle }, ++ { }, ++}; ++ ++static struct cpuidle_driver stm32_idle_driver = { ++ .name = "stm32_idle", ++ .states = { ++ ARM_CPUIDLE_WFI_STATE, ++ { ++ .enter = stm32_enter_idle, ++ .exit_latency = 620, ++ .target_residency = 700, ++ .flags = /*CPUIDLE_FLAG_TIMER_STOP | */ ++ CPUIDLE_FLAG_COUPLED, ++ .name = "CStop", ++ .desc = "Clocks off", ++ }, ++ }, ++ .safe_state_index = 0, ++ .state_count = 2, ++}; ++ ++static int stm32_pd_cpuidle_off(struct generic_pm_domain *domain) ++{ ++ struct stm32_pm_domain *priv = container_of(domain, ++ struct stm32_pm_domain, ++ genpd); ++ int cpu; ++ ++ for_each_possible_cpu(cpu) { ++ struct cpuidle_device *cpuidle_dev = per_cpu(cpuidle_devices, ++ cpu); ++ ++ cpuidle_dev->states_usage[1].disable = false; ++ } ++ ++ dev_dbg(priv->dev, "%s OFF\n", domain->name); ++ ++ return 0; ++} ++ ++static int stm32_pd_cpuidle_on(struct generic_pm_domain *domain) ++{ ++ struct stm32_pm_domain *priv = container_of(domain, ++ struct stm32_pm_domain, ++ genpd); ++ int cpu; ++ ++ for_each_possible_cpu(cpu) { ++ struct cpuidle_device *cpuidle_dev = per_cpu(cpuidle_devices, ++ cpu); ++ ++ cpuidle_dev->states_usage[1].disable = true; ++ } ++ ++ dev_dbg(priv->dev, "%s ON\n", domain->name); ++ ++ return 0; ++} ++ ++static void stm32_cpuidle_domain_remove(struct stm32_pm_domain *domain) ++{ ++ int ret; ++ ++ ret = pm_genpd_remove(&domain->genpd); ++ if (ret) ++ dev_err(domain->dev, "failed to remove PM domain %s: %d\n", ++ domain->genpd.name, ret); ++} ++ ++static int stm32_cpuidle_domain_add(struct stm32_pm_domain *domain, ++ struct device *dev, ++ struct device_node *np) ++{ ++ int ret; ++ ++ domain->dev = dev; ++ domain->genpd.name = np->name; ++ domain->genpd.power_off = stm32_pd_cpuidle_off; ++ domain->genpd.power_on = stm32_pd_cpuidle_on; ++ ++ ret = pm_genpd_init(&domain->genpd, NULL, 0); ++ if (ret < 0) { ++ dev_err(domain->dev, "failed to initialise PM domain %s: %d\n", ++ np->name, ret); ++ return ret; ++ } ++ ++ ret = of_genpd_add_provider_simple(np, &domain->genpd); ++ if (ret < 0) { ++ dev_err(domain->dev, "failed to register PM domain %s: %d\n", ++ np->name, ret); ++ stm32_cpuidle_domain_remove(domain); ++ return ret; ++ } ++ ++ dev_info(domain->dev, "domain %s registered\n", np->name); ++ ++ return 0; ++} ++ ++static int stm32_cpuidle_probe(struct platform_device *pdev) ++{ ++ struct cpuidle_driver *drv; ++ struct stm32_pm_domain *domain; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct of_phandle_args child, parent; ++ struct device_node *np_child; ++ int cpu, ret; ++ ++ drv = devm_kmemdup(dev, &stm32_idle_driver, sizeof(*drv), GFP_KERNEL); ++ if (!drv) ++ return -ENOMEM; ++ ++ /* Start at index 1, index 0 standard WFI */ ++ ret = dt_init_idle_driver(drv, stm32_idle_state_match, 1); ++ if (ret < 0) ++ return ret; ++ ++ /* all the cpus of the system are coupled */ ++ ret = cpuidle_register(drv, cpu_possible_mask); ++ if (ret) ++ return ret; ++ ++ /* Declare cpuidle domain */ ++ domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL); ++ if (!domain) ++ return -ENOMEM; ++ ++ ret = stm32_cpuidle_domain_add(domain, dev, np); ++ if (ret) { ++ devm_kfree(dev, domain); ++ return ret; ++ } ++ ++ /* disable cpu idle */ ++ for_each_possible_cpu(cpu) { ++ struct cpuidle_device *cpuidle_dev = per_cpu(cpuidle_devices, ++ cpu); ++ ++ cpuidle_dev->states_usage[1].disable = true; ++ } ++ ++ /* link main cpuidle domain to consumer domain */ ++ for_each_child_of_node(np, np_child) { ++ if (!of_parse_phandle_with_args(np_child, "power-domains", ++ "#power-domain-cells", ++ 0, &child)) { ++ struct device_node *np_test = child.np; ++ ++ parent.np = np; ++ parent.args_count = 0; ++ ++ ret = of_genpd_add_subdomain(&parent, &child); ++ if (ret < 0) ++ dev_err(dev, "failed to add Sub PM domain %d\n", ++ ret); ++ ++ dev_dbg(dev, "%s, add sub cpuidle of %s, with child %s\n", ++ __func__, np->name, np_test->name); ++ ++ pm_runtime_put(dev); ++ } ++ } ++ ++ dev_info(dev, "cpuidle domain probed\n"); ++ ++ return 0; ++} ++ ++int stm32_cpuidle_remove(struct platform_device *pdev) ++{ ++ cpuidle_unregister(&stm32_idle_driver); ++ return 0; ++} ++ ++static const struct of_device_id stm32_cpuidle_of_match[] = { ++ { ++ .compatible = "stm32,cpuidle", ++ }, ++}; ++ ++static struct platform_driver stm32_cpuidle_driver = { ++ .probe = stm32_cpuidle_probe, ++ .remove = stm32_cpuidle_remove, ++ .driver = { ++ .name = "stm32_cpuidle", ++ .owner = THIS_MODULE, ++ .of_match_table = stm32_cpuidle_of_match, ++ }, ++}; ++ ++module_platform_driver(stm32_cpuidle_driver); ++ ++MODULE_AUTHOR("<>"); ++MODULE_DESCRIPTION("STM32 cpu idle driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/opp/core.c b/drivers/opp/core.c +index 903b465c8568..dbcce5de9346 100644 +--- a/drivers/opp/core.c ++++ b/drivers/opp/core.c +@@ -1608,9 +1608,13 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev, + struct opp_table *opp_table; + + opp_table = dev_pm_opp_get_opp_table(dev); +- if (IS_ERR(opp_table)) ++ ++ if (PTR_ERR(opp_table) == -EPROBE_DEFER) + return opp_table; + ++ if (!opp_table) ++ return ERR_PTR(-ENOMEM); ++ + /* Make sure there are no concurrent readers while updating opp_table */ + WARN_ON(!list_empty(&opp_table->opp_list)); + +diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h +index aa3da6611533..196a157456aa 100644 +--- a/include/linux/pm_wakeup.h ++++ b/include/linux/pm_wakeup.h +@@ -84,6 +84,11 @@ static inline bool device_may_wakeup(struct device *dev) + return dev->power.can_wakeup && !!dev->power.wakeup; + } + ++static inline bool device_wakeup_path(struct device *dev) ++{ ++ return dev->power.wakeup_path; ++} ++ + static inline void device_set_wakeup_path(struct device *dev) + { + dev->power.wakeup_path = true; +@@ -174,6 +179,11 @@ static inline bool device_may_wakeup(struct device *dev) + return dev->power.can_wakeup && dev->power.should_wakeup; + } + ++static inline bool device_wakeup_path(struct device *dev) ++{ ++ return false; ++} ++ + static inline void device_set_wakeup_path(struct device *dev) {} + + static inline void __pm_stay_awake(struct wakeup_source *ws) {} +diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c +index 32391acc806b..dc800d4f5b9f 100644 +--- a/kernel/power/suspend.c ++++ b/kernel/power/suspend.c +@@ -34,7 +34,6 @@ + #include "power.h" + + const char * const pm_labels[] = { +- [PM_SUSPEND_TO_IDLE] = "freeze", + [PM_SUSPEND_STANDBY] = "standby", + [PM_SUSPEND_MEM] = "mem", + }; +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0021-ARM-5.10.10-stm32mp1-r1-DEVICETREE.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0021-ARM-5.10.10-stm32mp1-r1-DEVICETREE.patch new file mode 100644 index 0000000..81d157e --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0021-ARM-5.10.10-stm32mp1-r1-DEVICETREE.patch @@ -0,0 +1,8742 @@ +From f539f59331650f195c24a84b2a99f5f8109c0e38 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:03:16 +0100 +Subject: [PATCH 21/22] ARM 5.10.10-stm32mp1-r1 DEVICETREE + +--- + .../bindings/connector/usb-connector.yaml | 24 + + .../bindings/cpufreq/stm32-cpufreq.txt | 61 ++ + .../devicetree/bindings/dma/st,stm32-dma.yaml | 54 ++ + .../bindings/dma/st,stm32-mdma.yaml | 12 +- + .../devicetree/bindings/hwlock/hwlock.txt | 27 +- + .../bindings/hwlock/st,stm32-hwspinlock.yaml | 4 +- + .../devicetree/bindings/i2c/st,stm32-i2c.yaml | 12 + + .../iio/adc/sigma-delta-modulator.yaml | 3 + + .../bindings/iio/adc/st,stm32-dfsdm-adc.yaml | 7 +- + .../interrupt-controller/st,stm32-exti.yaml | 19 + + .../bindings/media/st,stm32-dcmi.yaml | 38 + + .../bindings/media/video-interfaces.txt | 2 + + .../bindings/mfd/st,stm32-timers.yaml | 6 +- + .../bindings/mfd/st,stm32mp1-pwr.txt | 57 ++ + .../bindings/perf/stm32-ddr-pmu.yaml | 44 ++ + .../bindings/phy/phy-stm32-usbphyc.txt | 73 -- + .../bindings/phy/phy-stm32-usbphyc.yaml | 179 +++++ + .../bindings/pinctrl/st,stm32-pinctrl.yaml | 8 + + .../bindings/remoteproc/rproc-srm.txt | 58 ++ + .../bindings/remoteproc/st,stm32-rproc.yaml | 51 +- + .../devicetree/bindings/serial/rs485.yaml | 16 + + .../bindings/serial/st,stm32-uart.yaml | 75 +- + .../bindings/soc/stm32/stm32_hdp.txt | 39 + + .../bindings/sound/st,stm32-adfsdm.txt | 63 -- + .../bindings/sound/st,stm32-i2s.yaml | 4 + + .../bindings/sound/st,stm32-sai.txt | 107 --- + .../bindings/sound/st,stm32-sai.yaml | 200 +++++ + .../devicetree/bindings/usb/dwc2.yaml | 4 + + .../devicetree/bindings/usb/generic-ehci.yaml | 5 + + .../devicetree/bindings/usb/st,stusb160x.yaml | 87 +++ + arch/arm/boot/dts/Makefile | 48 ++ + arch/arm/boot/dts/stm32429i-eval.dts | 1 + + arch/arm/boot/dts/stm32f746.dtsi | 4 + + arch/arm/boot/dts/stm32h743.dtsi | 4 + + .../boot/dts/stm32mp15-m4-srm-pinctrl.dtsi | 524 +++++++++++++ + arch/arm/boot/dts/stm32mp15-m4-srm.dtsi | 442 +++++++++++ + arch/arm/boot/dts/stm32mp15-no-scmi.dtsi | 157 ++++ + arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 228 +++++- + arch/arm/boot/dts/stm32mp151.dtsi | 627 +++++++++++----- + arch/arm/boot/dts/stm32mp153.dtsi | 8 +- + arch/arm/boot/dts/stm32mp157.dtsi | 3 +- + arch/arm/boot/dts/stm32mp157a-dk1.dts | 2 +- + arch/arm/boot/dts/stm32mp157a-ed1.dts | 32 + + arch/arm/boot/dts/stm32mp157a-ev1.dts | 88 +++ + .../boot/dts/stm32mp157c-dk2-a7-examples.dts | 60 ++ + .../boot/dts/stm32mp157c-dk2-m4-examples.dts | 129 ++++ + arch/arm/boot/dts/stm32mp157c-dk2.dts | 68 +- + arch/arm/boot/dts/stm32mp157c-ed1.dts | 368 +--------- + .../boot/dts/stm32mp157c-ev1-a7-examples.dts | 57 ++ + .../boot/dts/stm32mp157c-ev1-m4-examples.dts | 146 ++++ + arch/arm/boot/dts/stm32mp157c-ev1.dts | 330 +-------- + arch/arm/boot/dts/stm32mp157d-dk1.dts | 28 + + arch/arm/boot/dts/stm32mp157d-ed1.dts | 33 + + arch/arm/boot/dts/stm32mp157d-ev1.dts | 88 +++ + .../boot/dts/stm32mp157f-dk2-a7-examples.dts | 60 ++ + .../boot/dts/stm32mp157f-dk2-m4-examples.dts | 129 ++++ + arch/arm/boot/dts/stm32mp157f-dk2.dts | 157 ++++ + arch/arm/boot/dts/stm32mp157f-ed1.dts | 37 + + .../boot/dts/stm32mp157f-ev1-a7-examples.dts | 57 ++ + .../boot/dts/stm32mp157f-ev1-m4-examples.dts | 146 ++++ + arch/arm/boot/dts/stm32mp157f-ev1.dts | 89 +++ + arch/arm/boot/dts/stm32mp15xa.dtsi | 13 + + arch/arm/boot/dts/stm32mp15xc.dtsi | 6 +- + arch/arm/boot/dts/stm32mp15xd.dtsi | 42 ++ + arch/arm/boot/dts/stm32mp15xf.dtsi | 20 + + arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 122 +++- + arch/arm/boot/dts/stm32mp15xx-edx.dtsi | 413 +++++++++++ + arch/arm/boot/dts/stm32mp15xx-evx.dtsi | 686 ++++++++++++++++++ + 68 files changed, 5596 insertions(+), 1195 deletions(-) + create mode 100644 Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt + create mode 100644 Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt + create mode 100644 Documentation/devicetree/bindings/perf/stm32-ddr-pmu.yaml + delete mode 100644 Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt + create mode 100644 Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml + create mode 100644 Documentation/devicetree/bindings/remoteproc/rproc-srm.txt + create mode 100644 Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt + delete mode 100644 Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt + delete mode 100644 Documentation/devicetree/bindings/sound/st,stm32-sai.txt + create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-sai.yaml + create mode 100644 Documentation/devicetree/bindings/usb/st,stusb160x.yaml + create mode 100644 arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp15-m4-srm.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp15-no-scmi.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp157a-ed1.dts + create mode 100644 arch/arm/boot/dts/stm32mp157a-ev1.dts + create mode 100644 arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157d-dk1.dts + create mode 100644 arch/arm/boot/dts/stm32mp157d-ed1.dts + create mode 100644 arch/arm/boot/dts/stm32mp157d-ev1.dts + create mode 100644 arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157f-dk2.dts + create mode 100644 arch/arm/boot/dts/stm32mp157f-ed1.dts + create mode 100644 arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157f-ev1.dts + create mode 100644 arch/arm/boot/dts/stm32mp15xa.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp15xd.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp15xf.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp15xx-edx.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp15xx-evx.dtsi + +diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml +index 728f82db073d..ccf6eb22ba05 100644 +--- a/Documentation/devicetree/bindings/connector/usb-connector.yaml ++++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml +@@ -93,6 +93,24 @@ properties: + - device + - dual + ++ typec-power-opmode: ++ description: Determines the power operation mode that the Type C connector ++ will support and will advertise through CC pins when it has no power ++ delivery support. ++ - "default" corresponds to default USB voltage and current defined by the ++ USB 2.0 and USB 3.2 specifications, 5V 500mA for USB 2.0 ports and ++ 5V 900mA or 1500mA for USB 3.2 ports in single-lane or dual-lane ++ operation respectively. ++ - "1.5A" and "3.0A", 5V 1.5A and 5V 3.0A respectively, as defined in USB ++ Type-C Cable and Connector specification, when Power Delivery is not ++ supported. ++ allOf: ++ - $ref: /schemas/types.yaml#definitions/string ++ enum: ++ - default ++ - 1.5A ++ - 3.0A ++ + # The following are optional properties for "usb-c-connector" with power + # delivery support. + source-pdos: +@@ -173,6 +191,12 @@ allOf: + type: + const: micro + ++anyOf: ++ - not: ++ required: ++ - typec-power-opmode ++ - new-source-frs-typec-current ++ + additionalProperties: true + + examples: +diff --git a/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt +new file mode 100644 +index 000000000000..1292eb2612a0 +--- /dev/null ++++ b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt +@@ -0,0 +1,61 @@ ++STM32 CPUFreq and OPP bindings ++============================== ++ ++STM32 CPUFreq driver needs to read chip information from the SoC to list ++available OPPs. Then it depends on cpufreq-dt bindings. ++ ++Required properties: ++-------------------- ++- clocks: Phandle to the cpu clock "cpu". ++- clocks-name: Should contain "cpu". ++- nvmem-cells: Phandle to nvmem cell that contains "part_number". ++- nvmem-cell-names: Must be "part_number". ++- operating-points-v2: Phandle to operating points table. See ../power/opp.txt ++ for more details. ++ ++Optional properties: ++-------------------- ++See cpufreq-dt.txt for optional properties. ++ ++Examples: ++--------- ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <0>; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ nvmem-cells = <&part_number_otp>; ++ nvmem-cell-names = "part_number"; ++ }; ++ ++ cpu1: cpu@1 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <1>; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ }; ++ ++ cpu0_opp_table: cpu0-opp-table { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-650000000 { ++ opp-hz = /bits/ 64 <650000000>; ++ opp-microvolt = <1200000>; ++ opp-supported-hw = <0x1>; ++ }; ++ opp-800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1350000>; ++ opp-supported-hw = <0x2>; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml +index 2a5325f480f6..99351fe0fa17 100644 +--- a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml ++++ b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml +@@ -40,6 +40,21 @@ description: | + 0x0: FIFO mode with threshold selectable with bit 0-1 + 0x1: Direct mode: each DMA request immediately initiates a transfer + from/to the memory, FIFO is bypassed. ++ -bit 4: alternative DMA request/acknowledge protocol ++ 0x0: Use standard DMA ACK management, where ACK signal is maintained ++ up to the removal of request and transfer completion ++ 0x1: Use alternative DMA ACK management, where ACK de-assertion does ++ not wait for the de-assertion of the REQuest, ACK is only managed ++ by transfer completion. This must only be used on channels ++ managing transfers for STM32 USART/UART. ++ -bit 30-29: indicated SRAM Buffer size in (2^order)*PAGE_SIZE. ++ Order is given by those 2 bits starting at 0. ++ Valid only whether Intermediate M2M transfer is set. ++ For cyclic, whether Intermediate M2M transfer is chosen, any value can be set: ++ SRAM buffer size will rely on period size and not on this DT value. ++ -bit 31: Intermediate M2M transfer from/to DDR to/from SRAM throughout MDMA ++ 0: MDMA not used to generate an intermediate M2M transfer ++ 1: MDMA used to generate an intermediate M2M transfer. + + + maintainers: +@@ -75,6 +90,35 @@ properties: + description: if defined, it indicates that the controller + supports memory-to-memory transfer + ++ dmas: ++ description: A list of eight dma specifiers, one for each entry in dma-names. ++ Refer to stm32-mdma.yaml for more details. ++ items: ++ - description: DMA channel 0 connected to the MDMA channel specified ++ - description: DMA channel 1 connected to the MDMA channel specified ++ - description: DMA channel 2 connected to the MDMA channel specified ++ - description: DMA channel 3 connected to the MDMA channel specified ++ - description: DMA channel 4 connected to the MDMA channel specified ++ - description: DMA channel 5 connected to the MDMA channel specified ++ - description: DMA channel 6 connected to the MDMA channel specified ++ - description: DMA channel 7 connected to the MDMA channel specified ++ ++ dma-names: ++ description: Represents each STM32 DMA channel connected to a STM32 MDMA one. ++ items: ++ - const: ch0 ++ - const: ch1 ++ - const: ch2 ++ - const: ch3 ++ - const: ch4 ++ - const: ch5 ++ - const: ch6 ++ - const: ch7 ++ ++ memory-region: ++ description: Phandle to a node describing memory to be used for M2M intermediate transfer ++ between DMA and MDMA. ++ + required: + - compatible + - reg +@@ -104,6 +148,16 @@ examples: + st,mem2mem; + resets = <&rcc 150>; + dma-requests = <8>; ++ dmas = <&mdma1 8 0x3 0x1200000a 0x40026408 0x00000020 1>, ++ <&mdma1 9 0x3 0x1200000a 0x40026408 0x00000800 1>, ++ <&mdma1 10 0x3 0x1200000a 0x40026408 0x00200000 1>, ++ <&mdma1 11 0x3 0x1200000a 0x40026408 0x08000000 1>, ++ <&mdma1 12 0x3 0x1200000a 0x4002640C 0x00000020 1>, ++ <&mdma1 13 0x3 0x1200000a 0x4002640C 0x00000800 1>, ++ <&mdma1 14 0x3 0x1200000a 0x4002640C 0x00200000 1>, ++ <&mdma1 15 0x3 0x1200000a 0x4002640C 0x08000000 1>; ++ dma-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6", "ch7"; ++ memory-region = <&sram_dmapool>; + }; + + ... +diff --git a/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml +index c30be840be1c..c4bb58014374 100644 +--- a/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml ++++ b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml +@@ -10,8 +10,8 @@ description: | + The STM32 MDMA is a general-purpose direct memory access controller capable of + supporting 64 independent DMA channels with 256 HW requests. + DMA clients connected to the STM32 MDMA controller must use the format +- described in the dma.txt file, using a five-cell specifier for each channel: +- a phandle to the MDMA controller plus the following five integer cells: ++ described in the dma.txt file, using a six-cell specifier for each channel: ++ a phandle to the MDMA controller plus the following six integer cells: + 1. The request line number + 2. The priority level + 0x0: Low +@@ -48,6 +48,10 @@ description: | + if no HW ack signal is used by the MDMA client + 5. A 32bit mask specifying the value to be written to acknowledge the request + if no HW ack signal is used by the MDMA client ++ 6. A bitfield value specifying if the MDMA client wants to generate M2M transfer ++ with HW trigger (1) or not (0). This bitfield should be only enabled for ++ M2M transfer triggered by STM32 DMA client. The memory devices involved in this ++ kind of transfer are SRAM and DDR. + + maintainers: + - Amelie Delaunay +@@ -57,7 +61,7 @@ allOf: + + properties: + "#dma-cells": +- const: 5 ++ const: 6 + + compatible: + const: st,stm32h7-mdma +@@ -97,7 +101,7 @@ examples: + interrupts = <122>; + clocks = <&timer_clk>; + resets = <&rcc 992>; +- #dma-cells = <5>; ++ #dma-cells = <6>; + dma-channels = <16>; + dma-requests = <32>; + st,ahb-addr-masks = <0x20000000>, <0x00000000>; +diff --git a/Documentation/devicetree/bindings/hwlock/hwlock.txt b/Documentation/devicetree/bindings/hwlock/hwlock.txt +index 085d1f5c916a..e98088a409ba 100644 +--- a/Documentation/devicetree/bindings/hwlock/hwlock.txt ++++ b/Documentation/devicetree/bindings/hwlock/hwlock.txt +@@ -13,7 +13,7 @@ hwlock providers: + + Required properties: + - #hwlock-cells: Specifies the number of cells needed to represent a +- specific lock. ++ specific lock. Shall be 1 or 2 (see hwlocks below). + + hwlock users: + ============= +@@ -27,6 +27,11 @@ Required properties: + #hwlock-cells. The list can have just a single hwlock + or multiple hwlocks, with each hwlock represented by + a phandle and a corresponding args specifier. ++ If #hwlock-cells is 1, all of the locks are exclusive ++ (cannot be used by several users). ++ If #hwlock-cells is 2, the value of the second cell ++ defines whether the lock is for exclusive usage (0) or ++ shared (1) i.e. can be used by several users. + + Optional properties: + - hwlock-names: List of hwlock name strings defined in the same order +@@ -46,14 +51,22 @@ of length 1. + ... + }; + +-2. Example of a node using multiple specific hwlocks: ++2. Example of nodes using multiple and shared specific hwlocks: + +-The following example has a node requesting two hwlocks, a hwlock within +-the hwlock device node 'hwlock1' with #hwlock-cells value of 1, and another +-hwlock within the hwlock device node 'hwlock2' with #hwlock-cells value of 2. ++The following example has a nodeA requesting two hwlocks: ++- an exclusive one (#hwlock-cells = 1) within the hwlock device node 'hwlock1' ++- a shared one (#hwlock-cells = 2, second cell = 1) within the hwlock device ++ node 'hwlock2'. ++The shared lock is also be used by nodeB. + +- node { ++ nodeA { + ... +- hwlocks = <&hwlock1 2>, <&hwlock2 0 3>; ++ hwlocks = <&hwlock1 2>, <&hwlock2 0 1>; + ... + }; ++ ++ nodeB { ++ ... ++ hwlocks = <&hwlock2 0 1>; ++ ... ++ }; +\ No newline at end of file +diff --git a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml +index 47cf9c8d97e9..539a1dc052b7 100644 +--- a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml ++++ b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml +@@ -12,7 +12,7 @@ maintainers: + + properties: + "#hwlock-cells": +- const: 1 ++ const: 2 + + compatible: + const: st,stm32-hwspinlock +@@ -41,7 +41,7 @@ examples: + #include + hwspinlock@4c000000 { + compatible = "st,stm32-hwspinlock"; +- #hwlock-cells = <1>; ++ #hwlock-cells = <2>; + reg = <0x4c000000 0x400>; + clocks = <&rcc HSEM>; + clock-names = "hsem"; +diff --git a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml +index d747f4990ad8..9f0b098e899a 100644 +--- a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml ++++ b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml +@@ -20,6 +20,13 @@ allOf: + - st,stm32mp15-i2c + then: + properties: ++ i2c-analog-filter: true ++ ++ i2c-digital-filter: true ++ ++ i2c-digital-filter-width-ns: ++ default: 0 ++ + i2c-scl-rising-time-ns: + default: 25 + +@@ -36,6 +43,11 @@ allOf: + minItems: 3 + maxItems: 3 + ++ st,smbus-alert: ++ description: Enable the SMBus-Alert via SMBA pin, note SMBA pin ++ must also be configured via pinctrl. ++ type: boolean ++ + - if: + properties: + compatible: +diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml +index a390343d0c2a..bf5d71fb60da 100644 +--- a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml ++++ b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml +@@ -21,6 +21,9 @@ properties: + '#io-channel-cells': + const: 0 + ++ vref-supply: ++ description: Phandle to the vref input analog reference voltage. ++ + required: + - compatible + - '#io-channel-cells' +diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml +index d61bc011e820..6f2398cdc82d 100644 +--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml ++++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml +@@ -199,8 +199,6 @@ patternProperties: + description: + From common IIO binding. Used to pipe external sigma delta + modulator or internal ADC output to DFSDM channel. +- This is not required for "st,stm32-dfsdm-pdm" compatibility as +- PDM microphone is binded in Audio DT node. + + required: + - io-channels +@@ -235,6 +233,10 @@ patternProperties: + description: child node + + properties: ++ compatible: ++ enum: ++ - st,stm32h7-dfsdm-dai ++ + "#sound-dai-cells": + const: 0 + +@@ -244,6 +246,7 @@ patternProperties: + modulator or internal ADC output to DFSDM channel. + + required: ++ - compatible + - "#sound-dai-cells" + - io-channels + +diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml +index 2a5b29567926..8e4093cbc9b5 100644 +--- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml ++++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml +@@ -39,6 +39,25 @@ properties: + description: + Interrupts references to primary interrupt controller + ++patternProperties: ++ '^exti[0-9a-f]*$': ++ type: object ++ properties: ++ interrupt-controller: true ++ "#interrupt-cells": ++ const: 2 ++ ++ st,irq-number: ++ description: ++ Interrupt number mapped on the parent. ++ $ref: "/schemas/types.yaml#/definitions/uint32" ++ ++ required: ++ - "#interrupt-cells" ++ - interrupt-controller ++ - st,irq-number ++ - interrupt-parent ++ + required: + - "#interrupt-cells" + - compatible +diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml +index 3fe778cb5cc3..c18574bb3e81 100644 +--- a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml ++++ b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml +@@ -44,6 +44,43 @@ properties: + bindings defined in + Documentation/devicetree/bindings/media/video-interfaces.txt. + ++ properties: ++ endpoint: ++ type: object ++ ++ properties: ++ bus-type: ++ enum: [5, 6] ++ default: 5 ++ ++ bus-width: ++ enum: [8, 10, 12, 14] ++ default: 8 ++ ++ remote-endpoint: true ++ ++ allOf: ++ - if: ++ properties: ++ bus-type: ++ const: 6 ++ ++ then: ++ properties: ++ hsync-active: false ++ vsync-active: false ++ bus-width: ++ enum: [8] ++ ++ required: ++ - remote-endpoint ++ - bus-type ++ - pclk-sample ++ ++ unevaluatedProperties: false ++ ++ additionalProperties: false ++ + required: + - compatible + - reg +@@ -75,6 +112,7 @@ examples: + port { + dcmi_0: endpoint { + remote-endpoint = <&ov5640_0>; ++ bus-type = <5>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; +diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt +index 3920f25a9123..5d63c4de8783 100644 +--- a/Documentation/devicetree/bindings/media/video-interfaces.txt ++++ b/Documentation/devicetree/bindings/media/video-interfaces.txt +@@ -513,6 +513,8 @@ Optional endpoint properties + as 0 (normal). This property is valid for serial busses only. + - strobe: Whether the clock signal is used as clock (0) or strobe (1). Used + with CCP2, for instance. ++- pclk-max-frequency: maximum pixel clock frequency admissible by video ++ host interface. + + Example + ------- +diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml +index f212fc6e1661..0f16c8864a87 100644 +--- a/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml ++++ b/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml +@@ -131,7 +131,7 @@ additionalProperties: false + examples: + - | + #include +- timers2: timers@40000000 { ++ timers2: timer@40000000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; +@@ -149,9 +149,9 @@ examples: + #pwm-cells = <3>; + st,breakinput = <0 1 5>; + }; +- timer@0 { ++ timer@1 { + compatible = "st,stm32-timer-trigger"; +- reg = <0>; ++ reg = <1>; + }; + counter { + compatible = "st,stm32-timer-counter"; +diff --git a/Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt b/Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt +new file mode 100644 +index 000000000000..eb622387bb65 +--- /dev/null ++++ b/Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt +@@ -0,0 +1,57 @@ ++STMicroelectronics STM32MP1 Power Management Controller ++======================================================= ++ ++The PWR IP is responsible for handling the power related resources such as ++clocks, power supplies and resets. It provides 6 wake-up pins that are handled ++by an interrupt-controller. Wake-up pin can be used to wake-up from STANDBY SoC state. ++ ++Required properties: ++- compatible should be: "st,stm32mp1-pwr" ++- reg: should be register base and length as documented in the ++ datasheet ++- interrupts: contains the reference to the gic wake-up pin interrupt ++- interrupt-controller; Enable interrupt controller for wake-up pins. ++- #interrupt-cells = <3> ++- wakeup-gpios: contains a list of GPIO spec describing each wake-up pin. ++ ++Optional Properties: ++- pwr-supply: main soc power supply ++ ++Interrupt consumers have to specify 3 cells: ++ - cell 1: wake-up pin id from 0 to 5 ++ - cell 2: IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_RISING ++ - cell 3: Pull config: 0 = No Pull, 1=Pull Up, 2=Pull Down ++ ++ ++Example: ++ ++ pwr: pwr@50001000 { ++ compatible = "st,stm32mp1-pwr", "simple-mfd"; ++ reg = <0x50001000 0x400>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ ++ wakeup-gpios = <&gpioa 0 0>, <&gpioa 2 0>, ++ <&gpioc 13 0>, <&gpioi 8 0>, ++ <&gpioi 11 0>, <&gpioc 1 0>; ++ ++ pwr-supply = <&vdd>; ++ }; ++ ++ ++Example of interrupt user: ++gpio_keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ button@4 { ++ label = "WakeUp4"; ++ linux,code = ; ++ interrupt-parent = <&pwr>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING 1>; ++ wakeup-source; ++ }; ++}; ++ +diff --git a/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.yaml +new file mode 100644 +index 000000000000..085f2886e580 +--- /dev/null ++++ b/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.yaml +@@ -0,0 +1,44 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/perf/stm32-ddr-pmu.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++maintainers: ++ - Gerald Baeza ++ ++title: STMicroelectronics STM32 DDR Performance Monitor (DDRPERFM) bindings ++ ++properties: ++ compatible: ++ const: st,stm32-ddr-pmu ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - resets ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ ++ ddrperfm: perf@5a007000 { ++ compatible = "st,stm32-ddr-pmu"; ++ reg = <0x5a007000 0x400>; ++ clocks = <&rcc DDRPERFM>; ++ resets = <&rcc DDRPERFM_R>; ++ }; ++... +diff --git a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt +deleted file mode 100644 +index 725ae71ae653..000000000000 +--- a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt ++++ /dev/null +@@ -1,73 +0,0 @@ +-STMicroelectronics STM32 USB HS PHY controller +- +-The STM32 USBPHYC block contains a dual port High Speed UTMI+ PHY and a UTMI +-switch. It controls PHY configuration and status, and the UTMI+ switch that +-selects either OTG or HOST controller for the second PHY port. It also sets +-PLL configuration. +- +-USBPHYC +- |_ PLL +- | +- |_ PHY port#1 _________________ HOST controller +- | _ | +- | / 1|________________| +- |_ PHY port#2 ----| |________________ +- | \_0| | +- |_ UTMI switch_______| OTG controller +- +- +-Phy provider node +-================= +- +-Required properties: +-- compatible: must be "st,stm32mp1-usbphyc" +-- reg: address and length of the usb phy control register set +-- clocks: phandle + clock specifier for the PLL phy clock +-- #address-cells: number of address cells for phys sub-nodes, must be <1> +-- #size-cells: number of size cells for phys sub-nodes, must be <0> +- +-Optional properties: +-- assigned-clocks: phandle + clock specifier for the PLL phy clock +-- assigned-clock-parents: the PLL phy clock parent +-- resets: phandle + reset specifier +- +-Required nodes: one sub-node per port the controller provides. +- +-Phy sub-nodes +-============== +- +-Required properties: +-- reg: phy port index +-- phy-supply: phandle to the regulator providing 3V3 power to the PHY, +- see phy-bindings.txt in the same directory. +-- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY +-- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY +-- #phy-cells: see phy-bindings.txt in the same directory, must be <0> for PHY +- port#1 and must be <1> for PHY port#2, to select USB controller +- +- +-Example: +- usbphyc: usb-phy@5a006000 { +- compatible = "st,stm32mp1-usbphyc"; +- reg = <0x5a006000 0x1000>; +- clocks = <&rcc_clk USBPHY_K>; +- resets = <&rcc_rst USBPHY_R>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- usbphyc_port0: usb-phy@0 { +- reg = <0>; +- phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18> +- #phy-cells = <0>; +- }; +- +- usbphyc_port1: usb-phy@1 { +- reg = <1>; +- phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18> +- #phy-cells = <1>; +- }; +- }; +diff --git a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml +new file mode 100644 +index 000000000000..35460bb9f513 +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml +@@ -0,0 +1,179 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: "http://devicetree.org/schemas/phy/phy-stm32-usbphyc.yaml#" ++$schema: "http://devicetree.org/meta-schemas/core.yaml#" ++ ++title: STMicroelectronics STM32 USB HS PHY controller binding ++ ++description: ++ ++ The STM32 USBPHYC block contains a dual port High Speed UTMI+ PHY and a UTMI ++ switch. It controls PHY configuration and status, and the UTMI+ switch that ++ selects either OTG or HOST controller for the second PHY port. It also sets ++ PLL configuration. ++ ++ USBPHYC ++ |_ PLL ++ | ++ |_ PHY port#1 _________________ HOST controller ++ | __ | ++ | / 1|________________| ++ |_ PHY port#2 ----| |________________ ++ | \_0| | ++ |_ UTMI switch_______| OTG controller ++ ++maintainers: ++ - Amelie Delaunay ++ ++properties: ++ compatible: ++ enum: ++ - st,stm32mp1-usbphyc ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ '#address-cells': ++ const: 1 ++ ++ '#size-cells': ++ const: 0 ++ ++ vdda1v1-supply: ++ description: regulator providing 1V1 power supply to the PLL block ++ ++ vdda1v8-supply: ++ description: regulator providing 1V8 power supply to the PLL block ++ ++ '#clock-cells': ++ description: number of clock cells for ck_usbo_48m consumer ++ const: 0 ++ ++#Required child nodes: ++ ++patternProperties: ++ "^usb-phy@[0|1]$": ++ type: object ++ description: ++ Each port the controller provides must be represented as a sub-node. ++ ++ properties: ++ reg: ++ description: phy port index. ++ maxItems: 1 ++ ++ phy-supply: ++ description: regulator providing 3V3 power supply to the PHY. ++ ++ vbus-supply: ++ description: regulator providing 5V Vbus to the USB connector. ++ ++ st,phy-tuning: ++ $ref: /schemas/types.yaml#definitions/phandle ++ description: ++ It can be necessary to adjust the PHY settings to compensate parasitics, which can be due ++ to USB connector/receptacle, routing, ESD protection component,... Here is the list of ++ all optional parameters to tune the interface of the PHY (HS for High-Speed, FS for Full- ++ Speed, LS for Low-Speed) ++ * st,current-boost, <1> current boosting of 1mA ++ <2> current boosting of 2mA ++ * st,no-lsfs-fb-cap, disables the LS/FS feedback capacitor ++ * st,hs-slew-ctrl, slows the HS driver slew rate by 10% ++ * st,hs-dc-level, <0> decreases the HS driver DC level by 5 to 7mV ++ <1> increases the HS driver DC level by 5 to 7mV ++ <2> increases the HS driver DC level by 10 to 14mV ++ * st,fs-rftime-tuning, enables the FS rise/fall tuning option ++ * st,hs-rftime-reduction, enables the HS rise/fall reduction feature ++ * st,hs-current-trim, controls HS driver current trimming for choke ++ * st,hs-impedance-trim, controls HS driver impedance tuning for choke ++ * st,squelch-level, adjusts the squelch DC threshold value ++ * st,hs-rx-gain-eq, enables the HS Rx gain equalizer ++ * st,hs-rx-offset, adjusts the HS Rx offset ++ * st,no-hs-ftime-ctrl, disables the HS fall time control of single ended signals ++ during pre-emphasis ++ * st,no-lsfs-sc, disables the short circuit protection in LS/FS driver ++ * st,hs-tx-staggering, enables the basic staggering in HS Tx mode ++ ++ '#phy-cells': ++ enum: [ 0x0, 0x1 ] ++ ++ allOf: ++ - if: ++ properties: ++ reg: ++ const: 0 ++ then: ++ properties: ++ '#phy-cells': ++ const: 0 ++ else: ++ properties: ++ '#phy-cells': ++ const: 1 ++ description: ++ The value is used to select UTMI switch output. ++ 0 for OTG controller and 1 for Host controller. ++ ++ required: ++ - reg ++ - phy-supply ++ - '#phy-cells' ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - '#address-cells' ++ - '#size-cells' ++ - vdda1v1-supply ++ - vdda1v8-supply ++ - '#clock-cells' ++ - usb-phy@0 ++ - usb-phy@1 ++ ++examples: ++ - | ++ #include ++ #include ++ ++ usb_phy_tuning: usb-phy-tuning { ++ st,hs-dc-level = <2>; ++ st,fs-rftime-tuning; ++ st,hs-rftime-reduction; ++ st,hs-current-trim = <15>; ++ st,hs-impedance-trim = <1>; ++ st,squelch-level = <3>; ++ st,hs-rx-offset = <2>; ++ st,no-lsfs-sc; ++ }; ++ ++ usbphyc: usbphyc@5a006000 { ++ compatible = "st,stm32mp1-usbphyc"; ++ reg = <0x5a006000 0x1000>; ++ clocks = <&rcc_clk USBPHY_K>; ++ resets = <&rcc_rst USBPHY_R>; ++ vdda1v1-supply = <®11>; ++ vdda1v8-supply = <®18>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <0>; ++ ++ usbphyc_port0: usb-phy@0 { ++ reg = <0>; ++ phy-supply = <&vdd_usb>; ++ #phy-cells = <0>; ++ st,phy-tuning = <&usb_phy_tuning>; ++ }; ++ ++ usbphyc_port1: usb-phy@1 { ++ reg = <1>; ++ phy-supply = <&vdd_usb>; ++ #phy-cells = <1>; ++ st,phy-tuning = <&usb_phy_tuning>; ++ }; ++ }; ++... +diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +index 72877544ca78..f67e2e7079f5 100644 +--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml ++++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +@@ -139,9 +139,13 @@ patternProperties: + * ... + * 16 : Alternate Function 15 + * 17 : Analog ++ * 18 : Reserved + To simplify the usage, macro is available to generate "pinmux" field. + This macro is available here: + - include/dt-bindings/pinctrl/stm32-pinfunc.h ++ Setting the pinmux's function to the Reserved (RSVD) value is used to inform ++ the driver that it shall not apply the mux setting. This can be used to ++ reserve some pins, for example to a co-processor not running Linux. + Some examples of using macro: + /* GPIO A9 set as alernate function 2 */ + ... { +@@ -155,6 +159,10 @@ patternProperties: + ... { + pinmux = ; + }; ++ /* GPIO A9 reserved for co-processor */ ++ ... { ++ pinmux = ; ++ }; + + bias-disable: + type: boolean +diff --git a/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt +new file mode 100644 +index 000000000000..baa6e8e135e1 +--- /dev/null ++++ b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt +@@ -0,0 +1,58 @@ ++Remoteproc System Resource Manager ++---------------------------------- ++ ++The remoteproc SRM (System Resource Manager) handles resources allocated ++to remote processors. ++This makes it possible for remote proc to reserve and initialize system ++resources for a peripheral assigned to a coprocessor. ++ ++The devices are grouped in a core node ++ ++Core ++==== ++Required properties: ++- compatible: should be "rproc-srm-core" ++ ++Dev ++=== ++Required properties: ++- compatible: should be "rproc-srm-dev" ++ ++Optional properties: ++- reg: register base address and length ++- clocks: clocks required by the coprocessor ++- clock-names: see clock-bindings.txt ++- pinctrl-0: pins configurations required by the coprocessor ++ The SRM reserves the pins for the coprocessor, which prevents the local ++ processor to use them. ++- pinctrl-names: must be "default". ++- x-supply: power supplies required by the coprocessor ++- interrupts: external interrupts configurations required by the coprocessor. ++ This is optional since the configuration is done by the coprocessor. ++ When defined, the SRM (over)writes the configuration which allows the ++ interrupt controller to check for configuration conflicts. ++- interrupt-parent: see interrupts.txt ++- interrupt-names: see interrupts.txt ++ ++Example: ++ system_resources { ++ compatible = "rproc-srm-core"; ++ ++ mmc0: sdhci@09060000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x09060000 0x100>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_pinctrl_mmc0>; ++ clock-names = "mmc", "icn"; ++ clocks = <&clk_s_c0_flexgen CLK_MMC_0>, ++ <&clk_s_c0_flexgen CLK_RX_ICN_HVA>; ++ vdda-supply = <&vdda>; ++ }; ++ ++ button { ++ compatible = "rproc-srm-dev"; ++ interrupt-parent = <&gpioa>; ++ interrupts = <5 1>; ++ interrupt-names = "gpio_key"; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml +index 4ffa25268fcc..7180d545ab80 100644 +--- a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml ++++ b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml +@@ -16,7 +16,9 @@ maintainers: + + properties: + compatible: +- const: st,stm32mp1-m4 ++ enum: ++ - st,stm32mp1-m4 ++ - st,stm32mp1-m4_optee + + reg: + description: +@@ -25,24 +27,13 @@ properties: + maxItems: 3 + + resets: +- maxItems: 1 +- +- st,syscfg-holdboot: +- description: remote processor reset hold boot +- - Phandle of syscon block. +- - The offset of the hold boot setting register. +- - The field mask of the hold boot. +- $ref: "/schemas/types.yaml#/definitions/phandle-array" +- maxItems: 1 ++ maxItems: 2 + +- st,syscfg-tz: +- description: +- Reference to the system configuration which holds the RCC trust zone mode +- - Phandle of syscon block. +- - The offset of the RCC trust zone mode register. +- - The field mask of the RCC trust zone mode. +- $ref: "/schemas/types.yaml#/definitions/phandle-array" +- maxItems: 1 ++ reset-names: ++ items: ++ - const: mcu_rst ++ - const: hold_boot ++ maxItems: 2 + + interrupts: + description: Should contain the WWDG1 watchdog reset interrupt +@@ -91,9 +82,19 @@ properties: + $ref: "/schemas/types.yaml#/definitions/phandle-array" + description: | + Reference to the system configuration which holds the remote +- 1st cell: phandle to syscon block +- 2nd cell: register offset containing the deep sleep setting +- 3rd cell: register bitmask for the deep sleep bit ++ maxItems: 1 ++ ++ st,syscfg-m4-state: ++ $ref: "/schemas/types.yaml#/definitions/phandle-array" ++ description: | ++ Reference to the tamp register which exposes the Cortex-M4 state. ++ maxItems: 1 ++ ++ st,syscfg-rsc-tbl: ++ $ref: "/schemas/types.yaml#/definitions/phandle-array" ++ description: | ++ Reference to the tamp register which references the Cortex-M4 ++ resource table address. + maxItems: 1 + + st,auto-boot: +@@ -107,7 +108,6 @@ required: + - reg + - resets + - st,syscfg-holdboot +- - st,syscfg-tz + + additionalProperties: false + +@@ -119,9 +119,12 @@ examples: + reg = <0x10000000 0x40000>, + <0x30000000 0x40000>, + <0x38000000 0x10000>; +- resets = <&rcc MCU_R>; ++ resets = <&scmi0_reset RST_SCMI0_MCU>, ++ <&scmi0_reset RST_SCMI0_MCU_HOLD_BOOT>; ++ reset-names = "mcu_rst", "hold_boot"; + st,syscfg-holdboot = <&rcc 0x10C 0x1>; +- st,syscfg-tz = <&rcc 0x000 0x1>; ++ st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; ++ st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; + }; + + ... +diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml +index 0c9fa694f85c..a2ac9de2d85e 100644 +--- a/Documentation/devicetree/bindings/serial/rs485.yaml ++++ b/Documentation/devicetree/bindings/serial/rs485.yaml +@@ -29,6 +29,22 @@ properties: + default: 0 + maximum: 1000 + ++ rs485-rts-delay-ns: ++ description: This property is used to define delays lower than 1ms. ++ prop-encoded-array ++ $ref: /schemas/types.yaml#/definitions/uint32-array ++ items: ++ items: ++ - description: Delay between rts signal and beginning of data sent in ++ nanoseconds. It corresponds to the delay before sending data. ++ default: 0 ++ maximum: 1000 ++ - description: Delay between end of data sent and rts signal in nanoseconds. ++ It corresponds to the delay after sending data and actual release ++ of the line. ++ default: 0 ++ maximum: 1000 ++ + rs485-rts-active-low: + description: drive RTS low when sending (default is high). + $ref: /schemas/types.yaml#/definitions/flag +diff --git a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml +index 06d5f251ec88..d2df06f4d8f9 100644 +--- a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml ++++ b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml +@@ -9,9 +9,6 @@ maintainers: + + title: STMicroelectronics STM32 USART bindings + +-allOf: +- - $ref: rs485.yaml +- + properties: + compatible: + enum: +@@ -50,26 +47,54 @@ properties: + minItems: 1 + maxItems: 2 + +- cts-gpios: +- maxItems: 1 +- +- rts-gpios: +- maxItems: 1 ++# cts-gpios and rts-gpios properties can be used instead of 'uart-has-rtscts' ++# or 'st,hw-flow-ctrl' (deprecated) for making use of any gpio pins for flow ++# control instead of dedicated pins. ++# ++# It should be noted that both cts-gpios/rts-gpios and 'uart-has-rtscts' or ++# 'st,hw-flow-ctrl' (deprecated) properties cannot co-exist in a design. ++ cts-gpios: true ++ rts-gpios: true + + wakeup-source: true + + rs485-rts-delay: true ++ rs485-rts-delay-ns: true + rs485-rts-active-low: true + linux,rs485-enabled-at-boot-time: true + rs485-rx-during-tx: true + +-if: +- required: +- - st,hw-flow-ctrl +-then: +- properties: +- cts-gpios: false +- rts-gpios: false ++ st,rx-fifo-threshold-bytes: ++ description: RX FIFO threshold configuration in bytes. ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ enum: [1, 2, 4, 8, 12, 14, 16] ++ default: 8 ++ ++ st,tx-fifo-threshold-bytes: ++ description: TX FIFO threshold configuration in bytes. ++ If value is set to 1, TX FIFO threshold is disabled. ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ enum: [1, 2, 4, 8, 12, 14, 16] ++ default: 8 ++ ++allOf: ++ - $ref: rs485.yaml ++ ++ - if: ++ required: ++ - st,hw-flow-ctrl ++ then: ++ properties: ++ cts-gpios: false ++ rts-gpios: false ++ ++ - if: ++ required: ++ - st,stm32h7-uart ++ then: ++ properties: ++ st,rx-fifo-threshold-bytes: false ++ st,tx-fifo-threshold-bytes: false + + required: + - compatible +@@ -82,6 +107,26 @@ additionalProperties: false + examples: + - | + #include ++ ++ usart4: serial@40004c00 { ++ compatible = "st,stm32-uart"; ++ reg = <0x40004c00 0x400>; ++ interrupts = <52>; ++ clocks = <&clk_pclk1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_usart4>; ++ }; ++ ++ usart2: serial@40004400 { ++ compatible = "st,stm32-uart"; ++ reg = <0x40004400 0x400>; ++ interrupts = <38>; ++ clocks = <&clk_pclk1>; ++ st,hw-flow-ctrl; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_usart2 &pinctrl_usart2_rtscts>; ++ }; ++ + usart1: serial@40011000 { + compatible = "st,stm32-uart"; + reg = <0x40011000 0x400>; +diff --git a/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt b/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt +new file mode 100644 +index 000000000000..e2bd82f4980e +--- /dev/null ++++ b/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt +@@ -0,0 +1,39 @@ ++STM32 - STM32MP1- HDP Pin configuration for STM32MP1 ++======================================================= ++ ++The Hardware Debug Port (HDP) allows the observation of internal signals. By using multiplexers, ++up to 16 signals for each of 8-bit output can be observed. ++ ++Required Properties: ++ ++ - compatible: Must be "st,stm32mp1-hdp" ++ - muxing-hdp: Indicates for each HDP pins selected which HDP output among the 16 available signals you want ++ ++For each HDP pins you can select one of 16 signals which will be described in file : include/dt-bindings/soc/stm32-hdp.h ++ ++Example ++------- ++ ++In common dtsi file: ++ ++hdp: hdp@5002a000 { ++ compatible = "st,stm32mp1-hdp"; ++ reg = <0x5002a000 0x400>; ++ clocks = <&rcc HDP>; ++ clock-names = "hdp"; ++}; ++ ++In board-specific file: ++ ++In this example I've selected HDP0, HDP6 and HDP7, and for HDP0 the output signal is HDP0_GPOVAL_0, ++for HDP6 is HDP6_GPOVAL_6, and for HDP7 is HDP7_GPOVAL_7. ++ ++&hdp { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&hdp0_pins_a &hdp6_pins_a &hdp7_pins_a>; ++ pinctrl-1 = <&hdp0_pins_sleep_a &hdp6_pins_sleep_a &hdp7_pins_sleep_a>; ++ ++ muxing-hdp = <(STM32_HDP(0, HDP0_GPOVAL_0) | ++ STM32_HDP(6, HDP6_GPOVAL_6) | ++ STM32_HDP(7, HDP7_GPOVAL_7))>; ++}; +diff --git a/Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt b/Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt +deleted file mode 100644 +index 864f5b00b031..000000000000 +--- a/Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt ++++ /dev/null +@@ -1,63 +0,0 @@ +-STMicroelectronics Audio Digital Filter Sigma Delta modulators(DFSDM) +- +-The DFSDM allows PDM microphones capture through SPI interface. The Audio +-interface is seems as a sub block of the DFSDM device. +-For details on DFSDM bindings refer to ../iio/adc/st,stm32-dfsdm-adc.txt +- +-Required properties: +- - compatible: "st,stm32h7-dfsdm-dai". +- +- - #sound-dai-cells : Must be equal to 0 +- +- - io-channels : phandle to iio dfsdm instance node. +- +-Example of a sound card using audio DFSDM node. +- +- sound_card { +- compatible = "audio-graph-card"; +- +- dais = <&cpu_port>; +- }; +- +- dfsdm: dfsdm@40017000 { +- compatible = "st,stm32h7-dfsdm"; +- reg = <0x40017000 0x400>; +- clocks = <&rcc DFSDM1_CK>; +- clock-names = "dfsdm"; +- #interrupt-cells = <1>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- dfsdm_adc0: filter@0 { +- compatible = "st,stm32-dfsdm-dmic"; +- reg = <0>; +- interrupts = <110>; +- dmas = <&dmamux1 101 0x400 0x00>; +- dma-names = "rx"; +- st,adc-channels = <1>; +- st,adc-channel-names = "dmic0"; +- st,adc-channel-types = "SPI_R"; +- st,adc-channel-clk-src = "CLKOUT"; +- st,filter-order = <5>; +- +- dfsdm_dai0: dfsdm-dai { +- compatible = "st,stm32h7-dfsdm-dai"; +- #sound-dai-cells = <0>; +- io-channels = <&dfsdm_adc0 0>; +- cpu_port: port { +- dfsdm_endpoint: endpoint { +- remote-endpoint = <&dmic0_endpoint>; +- }; +- }; +- }; +- }; +- +- dmic0: dmic@0 { +- compatible = "dmic-codec"; +- #sound-dai-cells = <0>; +- port { +- dmic0_endpoint: endpoint { +- remote-endpoint = <&dfsdm_endpoint>; +- }; +- }; +- }; +diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml +index f32410890589..6feb5a09c184 100644 +--- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml ++++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml +@@ -54,6 +54,10 @@ properties: + resets: + maxItems: 1 + ++ "#clock-cells": ++ description: Configure the I2S device as MCLK clock provider. ++ const: 0 ++ + required: + - compatible + - "#sound-dai-cells" +diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt +deleted file mode 100644 +index c42b91e525fa..000000000000 +--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt ++++ /dev/null +@@ -1,107 +0,0 @@ +-STMicroelectronics STM32 Serial Audio Interface (SAI). +- +-The SAI interface (Serial Audio Interface) offers a wide set of audio protocols +-as I2S standards, LSB or MSB-justified, PCM/DSP, TDM, and AC'97. +-The SAI contains two independent audio sub-blocks. Each sub-block has +-its own clock generator and I/O lines controller. +- +-Required properties: +- - compatible: Should be "st,stm32f4-sai" or "st,stm32h7-sai" +- - reg: Base address and size of SAI common register set. +- - clocks: Must contain phandle and clock specifier pairs for each entry +- in clock-names. +- - clock-names: Must contain "pclk" "x8k" and "x11k" +- "pclk": Clock which feeds the peripheral bus interface. +- Mandatory for "st,stm32h7-sai" compatible. +- Not used for "st,stm32f4-sai" compatible. +- "x8k": SAI parent clock for sampling rates multiple of 8kHz. +- "x11k": SAI parent clock for sampling rates multiple of 11.025kHz. +- - interrupts: cpu DAI interrupt line shared by SAI sub-blocks +- +-Optional properties: +- - resets: Reference to a reset controller asserting the SAI +- +-SAI subnodes: +-Two subnodes corresponding to SAI sub-block instances A et B can be defined. +-Subnode can be omitted for unsused sub-block. +- +-SAI subnodes required properties: +- - compatible: Should be "st,stm32-sai-sub-a" or "st,stm32-sai-sub-b" +- for SAI sub-block A or B respectively. +- - reg: Base address and size of SAI sub-block register set. +- - clocks: Must contain one phandle and clock specifier pair +- for sai_ck which feeds the internal clock generator. +- If the SAI shares a master clock, with another SAI set as MCLK +- clock provider, SAI provider phandle must be specified here. +- - clock-names: Must contain "sai_ck". +- Must also contain "MCLK", if SAI shares a master clock, +- with a SAI set as MCLK clock provider. +- - dmas: see Documentation/devicetree/bindings/dma/st,stm32-dma.yaml +- - dma-names: identifier string for each DMA request line +- "tx": if sai sub-block is configured as playback DAI +- "rx": if sai sub-block is configured as capture DAI +- - pinctrl-names: should contain only value "default" +- - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +- +-SAI subnodes Optional properties: +- - st,sync: specify synchronization mode. +- By default SAI sub-block is in asynchronous mode. +- This property sets SAI sub-block as slave of another SAI sub-block. +- Must contain the phandle and index of the sai sub-block providing +- the synchronization. +- - st,iec60958: support S/PDIF IEC6958 protocol for playback +- IEC60958 protocol is not available for capture. +- By default, custom protocol is assumed, meaning that protocol is +- configured according to protocol defined in related DAI link node, +- such as i2s, left justified, right justified, dsp and pdm protocols. +- Note: ac97 protocol is not supported by SAI driver +- - #clock-cells: should be 0. This property must be present if the SAI device +- is a master clock provider, according to clocks bindings, described in +- Documentation/devicetree/bindings/clock/clock-bindings.txt. +- +-The device node should contain one 'port' child node with one child 'endpoint' +-node, according to the bindings defined in Documentation/devicetree/bindings/ +-graph.txt. +- +-Example: +-sound_card { +- compatible = "audio-graph-card"; +- dais = <&sai1b_port>; +-}; +- +-sai1: sai1@40015800 { +- compatible = "st,stm32h7-sai"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 0x40015800 0x400>; +- reg = <0x40015800 0x4>; +- clocks = <&rcc SAI1_CK>, <&rcc PLL1_Q>, <&rcc PLL2_P>; +- clock-names = "pclk", "x8k", "x11k"; +- interrupts = <87>; +- +- sai1a: audio-controller@40015804 { +- compatible = "st,stm32-sai-sub-a"; +- reg = <0x4 0x1C>; +- clocks = <&rcc SAI1_CK>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 1 87 0x400 0x0>; +- dma-names = "tx"; +- pinctrl-names = "default"; +- pinctrl-0 = <&pinctrl_sai1a>; +- +- sai1b_port: port { +- cpu_endpoint: endpoint { +- remote-endpoint = <&codec_endpoint>; +- format = "i2s"; +- }; +- }; +- }; +-}; +- +-audio-codec { +- codec_port: port { +- codec_endpoint: endpoint { +- remote-endpoint = <&cpu_endpoint>; +- }; +- }; +-}; +diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml +new file mode 100644 +index 000000000000..6ad48c7681c1 +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml +@@ -0,0 +1,200 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/st,stm32-sai.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: STMicroelectronics STM32 Serial Audio Interface (SAI) ++ ++maintainers: ++ - Olivier Moysan ++ ++description: ++ The SAI interface (Serial Audio Interface) offers a wide set of audio ++ protocols as I2S standards, LSB or MSB-justified, PCM/DSP, TDM, and AC'97. ++ The SAI contains two independent audio sub-blocks. Each sub-block has ++ its own clock generator and I/O lines controller. ++ ++properties: ++ compatible: ++ enum: ++ - st,stm32f4-sai ++ - st,stm32h7-sai ++ ++ reg: ++ items: ++ - description: Base address and size of SAI common register set. ++ - description: Base address and size of SAI identification register set. ++ minItems: 1 ++ maxItems: 2 ++ ++ ranges: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++ "#address-cells": ++ const: 1 ++ ++ "#size-cells": ++ const: 1 ++ ++ clocks: ++ maxItems: 3 ++ ++ clock-names: ++ maxItems: 3 ++ ++required: ++ - compatible ++ - reg ++ - ranges ++ - "#address-cells" ++ - "#size-cells" ++ - clocks ++ - clock-names ++ ++patternProperties: ++ "^audio-controller@[0-9a-f]+$": ++ type: object ++ description: ++ Two subnodes corresponding to SAI sub-block instances A et B ++ can be defined. Subnode can be omitted for unsused sub-block. ++ ++ properties: ++ compatible: ++ description: Compatible for SAI sub-block A or B. ++ pattern: "st,stm32-sai-sub-[ab]" ++ ++ "#sound-dai-cells": ++ const: 0 ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: sai_ck clock feeding the internal clock generator. ++ - description: MCLK clock from a SAI set as master clock provider. ++ minItems: 1 ++ maxItems: 2 ++ ++ clock-names: ++ items: ++ - const: sai_ck ++ - const: MCLK ++ minItems: 1 ++ maxItems: 2 ++ ++ dmas: ++ maxItems: 1 ++ ++ dma-names: ++ description: | ++ rx: SAI sub-block is configured as a capture DAI. ++ tx: SAI sub-block is configured as a playback DAI. ++ enum: [ rx, tx ] ++ ++ st,sync: ++ description: ++ Configure the SAI sub-block as slave of another SAI sub-block. ++ By default SAI sub-block is in asynchronous mode. ++ Must contain the phandle and index of the SAI sub-block providing ++ the synchronization. ++ allOf: ++ - $ref: /schemas/types.yaml#definitions/phandle-array ++ - maxItems: 1 ++ ++ st,iec60958: ++ description: ++ If set, support S/PDIF IEC6958 protocol for playback. ++ IEC60958 protocol is not available for capture. ++ By default, custom protocol is assumed, meaning that protocol is ++ configured according to protocol defined in related DAI link node, ++ such as i2s, left justified, right justified, dsp and pdm protocols. ++ allOf: ++ - $ref: /schemas/types.yaml#definitions/flag ++ ++ "#clock-cells": ++ description: Configure the SAI device as master clock provider. ++ const: 0 ++ ++ required: ++ - compatible ++ - "#sound-dai-cells" ++ - reg ++ - clocks ++ - clock-names ++ - dmas ++ - dma-names ++ ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: st,stm32f4-sai ++ ++ - then: ++ properties: ++ clocks: ++ items: ++ - description: x8k, SAI parent clock for sampling rates multiple of 8kHz. ++ - description: x11k, SAI parent clock for sampling rates multiple of 11.025kHz. ++ ++ clock-names: ++ items: ++ - const: x8k ++ - const: x11k ++ ++ - else: ++ properties: ++ clocks: ++ items: ++ - description: pclk feeds the peripheral bus interface. ++ - description: x8k, SAI parent clock for sampling rates multiple of 8kHz. ++ - description: x11k, SAI parent clock for sampling rates multiple of 11.025kHz. ++ ++ clock-names: ++ items: ++ - const: pclk ++ - const: x8k ++ - const: x11k ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ sai2: sai@4400b000 { ++ compatible = "st,stm32h7-sai"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x4400b000 0x400>; ++ reg = <0x4400b000 0x4>, <0x4400b3f0 0x10>; ++ clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; ++ clock-names = "pclk", "x8k", "x11k"; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>; ++ pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>; ++ status = "okay"; ++ ++ sai2a: audio-controller@4400b004 { ++ #sound-dai-cells = <0>; ++ compatible = "st,stm32-sai-sub-a"; ++ reg = <0x4 0x1c>; ++ dmas = <&dmamux1 89 0x400 0x01>; ++ dma-names = "tx"; ++ clocks = <&rcc SAI2_K>; ++ clock-names = "sai_ck"; ++ status = "okay"; ++ }; ++ }; ++ ++... +diff --git a/Documentation/devicetree/bindings/usb/dwc2.yaml b/Documentation/devicetree/bindings/usb/dwc2.yaml +index e5ee51b7b470..5dbe0b723667 100644 +--- a/Documentation/devicetree/bindings/usb/dwc2.yaml ++++ b/Documentation/devicetree/bindings/usb/dwc2.yaml +@@ -129,6 +129,10 @@ properties: + description: If present indicates that we need to reset the PHY when we + detect a wakeup. This is due to a hardware errata. + ++ wakeup-source: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: If present indicates this device has wakeup capabilities ++ + required: + - compatible + - reg +diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml +index 247ef00381ea..e7647bd1195c 100644 +--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml ++++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml +@@ -91,6 +91,11 @@ properties: + iommus: + maxItems: 1 + ++ wakeup-source: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ Indicate this device has wakeup capabilities. ++ + required: + - compatible + - reg +diff --git a/Documentation/devicetree/bindings/usb/st,stusb160x.yaml b/Documentation/devicetree/bindings/usb/st,stusb160x.yaml +new file mode 100644 +index 000000000000..9a51efa9d101 +--- /dev/null ++++ b/Documentation/devicetree/bindings/usb/st,stusb160x.yaml +@@ -0,0 +1,87 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: "http://devicetree.org/schemas/usb/st,stusb160x.yaml#" ++$schema: "http://devicetree.org/meta-schemas/core.yaml#" ++ ++title: STMicroelectronics STUSB160x Type-C controller bindings ++ ++maintainers: ++ - Amelie Delaunay ++ ++properties: ++ compatible: ++ enum: ++ - st,stusb1600 ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ vdd-supply: ++ description: main power supply (4.1V-22V) ++ ++ vsys-supply: ++ description: low power supply (3.0V-5.5V) ++ ++ vconn-supply: ++ description: power supply (2.7V-5.5V) used to supply VConn on CC pin in ++ source or dual power role ++ ++ connector: ++ type: object ++ ++ allOf: ++ - $ref: ../connector/usb-connector.yaml ++ ++ properties: ++ compatible: ++ const: usb-c-connector ++ ++ power-role: true ++ ++ typec-power-opmode: true ++ ++ required: ++ - compatible ++ ++required: ++ - compatible ++ - reg ++ - connector ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ i2c4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ typec: stusb1600@28 { ++ compatible = "st,stusb1600"; ++ reg = <0x28>; ++ vdd-supply = <&vbus_drd>; ++ vsys-supply = <&vdd_usb>; ++ interrupts = <11 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-parent = <&gpioi>; ++ ++ typec_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ power-role = "dual"; ++ data-role = "dual"; ++ typec-power-opmode = "default"; ++ ++ port { ++ typec_con_ep: endpoint { ++ remote-endpoint = <&usbotg_hs_ep>; ++ }; ++ }; ++ }; ++ }; ++ }; ++... +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index ce66ffd5a1bb..4c3ba0468276 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -1,4 +1,36 @@ + # SPDX-License-Identifier: GPL-2.0 ++ ++# board-specific dtc flags ++DTC_FLAGS_stm32mp157c-dk2 += -@ ++DTC_FLAGS_stm32f429-disco += -@ ++DTC_FLAGS_stm32f469-disco += -@ ++DTC_FLAGS_stm32f746-disco += -@ ++DTC_FLAGS_stm32f769-disco += -@ ++DTC_FLAGS_stm32429i-eval += -@ ++DTC_FLAGS_stm32746g-eval += -@ ++DTC_FLAGS_stm32h743i-eval += -@ ++DTC_FLAGS_stm32h743i-disco += -@ ++DTC_FLAGS_stm32mp157a-dk1 += -@ ++DTC_FLAGS_stm32mp157d-dk1 += -@ ++DTC_FLAGS_stm32mp157c-dk2 += -@ ++DTC_FLAGS_stm32mp157f-dk2 += -@ ++DTC_FLAGS_stm32mp157c-dk2-a7-examples += -@ ++DTC_FLAGS_stm32mp157c-dk2-m4-examples += -@ ++DTC_FLAGS_stm32mp157f-dk2-a7-examples += -@ ++DTC_FLAGS_stm32mp157f-dk2-m4-examples += -@ ++DTC_FLAGS_stm32mp157a-ed1 += -@ ++DTC_FLAGS_stm32mp157c-ed1 += -@ ++DTC_FLAGS_stm32mp157d-ed1 += -@ ++DTC_FLAGS_stm32mp157f-ed1 += -@ ++DTC_FLAGS_stm32mp157a-ev1 += -@ ++DTC_FLAGS_stm32mp157c-ev1 += -@ ++DTC_FLAGS_stm32mp157d-ev1 += -@ ++DTC_FLAGS_stm32mp157f-ev1 += -@ ++DTC_FLAGS_stm32mp157c-ev1-a7-examples += -@ ++DTC_FLAGS_stm32mp157c-ev1-m4-examples += -@ ++DTC_FLAGS_stm32mp157f-ev1-a7-examples += -@ ++DTC_FLAGS_stm32mp157f-ev1-m4-examples += -@ ++ + dtb-$(CONFIG_ARCH_ALPINE) += \ + alpine-db.dtb + dtb-$(CONFIG_MACH_ARTPEC6) += \ +@@ -1063,12 +1095,28 @@ dtb-$(CONFIG_ARCH_STM32) += \ + stm32mp157a-avenger96.dtb \ + stm32mp157a-dhcor-avenger96.dtb \ + stm32mp157a-dk1.dtb \ ++ stm32mp157d-dk1.dtb \ + stm32mp157a-iot-box.dtb \ + stm32mp157a-stinger96.dtb \ + stm32mp157c-dhcom-pdk2.dtb \ + stm32mp157c-dk2.dtb \ ++ stm32mp157c-dk2-a7-examples.dtb \ ++ stm32mp157c-dk2-m4-examples.dtb \ ++ stm32mp157f-dk2.dtb \ ++ stm32mp157f-dk2-a7-examples.dtb \ ++ stm32mp157f-dk2-m4-examples.dtb \ ++ stm32mp157a-ed1.dtb \ + stm32mp157c-ed1.dtb \ ++ stm32mp157d-ed1.dtb \ ++ stm32mp157f-ed1.dtb \ ++ stm32mp157a-ev1.dtb \ + stm32mp157c-ev1.dtb \ ++ stm32mp157c-ev1-a7-examples.dtb \ ++ stm32mp157c-ev1-m4-examples.dtb \ ++ stm32mp157d-ev1.dtb \ ++ stm32mp157f-ev1.dtb \ ++ stm32mp157f-ev1-a7-examples.dtb \ ++ stm32mp157f-ev1-m4-examples.dtb \ + stm32mp157c-lxa-mc1.dtb \ + stm32mp157c-odyssey.dtb + dtb-$(CONFIG_MACH_SUN4I) += \ +diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts +index 67e7648de41e..7e10ae744c9d 100644 +--- a/arch/arm/boot/dts/stm32429i-eval.dts ++++ b/arch/arm/boot/dts/stm32429i-eval.dts +@@ -188,6 +188,7 @@ + port { + dcmi_0: endpoint { + remote-endpoint = <&ov2640_0>; ++ bus-type = <5>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; +diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi +index 640ff54ed00c..2e69f1bb84ef 100644 +--- a/arch/arm/boot/dts/stm32f746.dtsi ++++ b/arch/arm/boot/dts/stm32f746.dtsi +@@ -349,6 +349,7 @@ + clocks = <&rcc 1 CLK_I2C1>; + #address-cells = <1>; + #size-cells = <0>; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -361,6 +362,7 @@ + clocks = <&rcc 1 CLK_I2C2>; + #address-cells = <1>; + #size-cells = <0>; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -373,6 +375,7 @@ + clocks = <&rcc 1 CLK_I2C3>; + #address-cells = <1>; + #size-cells = <0>; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -385,6 +388,7 @@ + clocks = <&rcc 1 CLK_I2C4>; + #address-cells = <1>; + #size-cells = <0>; ++ i2c-analog-filter; + status = "disabled"; + }; + +diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi +index 7febe19e780d..078b078297ae 100644 +--- a/arch/arm/boot/dts/stm32h743.dtsi ++++ b/arch/arm/boot/dts/stm32h743.dtsi +@@ -144,6 +144,7 @@ + <32>; + resets = <&rcc STM32H7_APB1L_RESET(I2C1)>; + clocks = <&rcc I2C1_CK>; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -156,6 +157,7 @@ + <34>; + resets = <&rcc STM32H7_APB1L_RESET(I2C2)>; + clocks = <&rcc I2C2_CK>; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -168,6 +170,7 @@ + <73>; + resets = <&rcc STM32H7_APB1L_RESET(I2C3)>; + clocks = <&rcc I2C3_CK>; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -401,6 +404,7 @@ + <96>; + resets = <&rcc STM32H7_APB4_RESET(I2C4)>; + clocks = <&rcc I2C4_CK>; ++ i2c-analog-filter; + status = "disabled"; + }; + +diff --git a/arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi +new file mode 100644 +index 000000000000..b4030e5c9422 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi +@@ -0,0 +1,524 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Fabien Dessenne for STMicroelectronics. ++ */ ++ ++&pinctrl { ++ m4_adc1_in6_pins_a: m4-adc1-in6 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_adc12_ain_pins_a: m4-adc12-ain-0 { ++ pins { ++ pinmux = , /* ADC1 in13 */ ++ , /* ADC1 in6 */ ++ , /* ADC2 in2 */ ++ ; /* ADC2 in6 */ ++ }; ++ }; ++ ++ m4_adc12_usb_pwr_pins_a: m4-adc12-usb-pwr-pins-0 { ++ pins { ++ pinmux = , /* ADC12 in18 */ ++ ; /* ADC12 in19 */ ++ }; ++ }; ++ ++ m4_cec_pins_a: m4-cec-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_cec_pins_b: m4-cec-1 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_dac_ch1_pins_a: m4-dac-ch1 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_dac_ch2_pins_a: m4-dac-ch2 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_dcmi_pins_a: m4-dcmi-0 { ++ pins { ++ pinmux = ,/* DCMI_HSYNC */ ++ ,/* DCMI_VSYNC */ ++ ,/* DCMI_PIXCLK */ ++ ,/* DCMI_D0 */ ++ ,/* DCMI_D1 */ ++ ,/* DCMI_D2 */ ++ ,/* DCMI_D3 */ ++ ,/* DCMI_D4 */ ++ ,/* DCMI_D5 */ ++ ,/* DCMI_D6 */ ++ ,/* DCMI_D7 */ ++ ,/* DCMI_D8 */ ++ ,/* DCMI_D9 */ ++ ,/* DCMI_D10 */ ++ ;/* DCMI_D11 */ ++ }; ++ }; ++ ++ m4_dfsdm_clkout_pins_a: m4-dfsdm-clkout-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_CKOUT */ ++ }; ++ }; ++ ++ m4_dfsdm_data1_pins_a: m4-dfsdm-data1-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_DATA1 */ ++ }; ++ }; ++ ++ m4_dfsdm_data3_pins_a: m4-dfsdm-data3-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_DATA3 */ ++ }; ++ }; ++ ++ m4_ethernet0_rgmii_pins_a: m4-rgmii-0 { ++ pins { ++ pinmux = , /* ETH_RGMII_CLK125 */ ++ , /* ETH_RGMII_GTX_CLK */ ++ , /* ETH_RGMII_TXD0 */ ++ , /* ETH_RGMII_TXD1 */ ++ , /* ETH_RGMII_TXD2 */ ++ , /* ETH_RGMII_TXD3 */ ++ , /* ETH_RGMII_TX_CTL */ ++ , /* ETH_MDC */ ++ , /* ETH_MDIO */ ++ , /* ETH_RGMII_RXD0 */ ++ , /* ETH_RGMII_RXD1 */ ++ , /* ETH_RGMII_RXD2 */ ++ , /* ETH_RGMII_RXD3 */ ++ , /* ETH_RGMII_RX_CLK */ ++ ; /* ETH_RGMII_RX_CTL */ ++ }; ++ }; ++ ++ m4_fmc_pins_a: m4-fmc-0 { ++ pins { ++ pinmux = , /* FMC_NOE */ ++ , /* FMC_NWE */ ++ , /* FMC_A16_FMC_CLE */ ++ , /* FMC_A17_FMC_ALE */ ++ , /* FMC_D0 */ ++ , /* FMC_D1 */ ++ , /* FMC_D2 */ ++ , /* FMC_D3 */ ++ , /* FMC_D4 */ ++ , /* FMC_D5 */ ++ , /* FMC_D6 */ ++ , /* FMC_D7 */ ++ , /* FMC_NE2_FMC_NCE */ ++ ; /* FMC_NWAIT */ ++ }; ++ }; ++ ++ m4_hdp0_pins_a: m4-hdp0-0 { ++ pins { ++ pinmux = ; /* HDP0 */ ++ }; ++ }; ++ ++ m4_hdp6_pins_a: m4-hdp6-0 { ++ pins { ++ pinmux = ; /* HDP6 */ ++ }; ++ }; ++ ++ m4_hdp7_pins_a: m4-hdp7-0 { ++ pins { ++ pinmux = ; /* HDP7 */ ++ }; ++ }; ++ ++ m4_i2c1_pins_a: m4-i2c1-0 { ++ pins { ++ pinmux = , /* I2C1_SCL */ ++ ; /* I2C1_SDA */ ++ }; ++ }; ++ ++ m4_i2c2_pins_a: m4-i2c2-0 { ++ pins { ++ pinmux = , /* I2C2_SCL */ ++ ; /* I2C2_SDA */ ++ }; ++ }; ++ ++ m4_i2c5_pins_a: m4-i2c5-0 { ++ pins { ++ pinmux = , /* I2C5_SCL */ ++ ; /* I2C5_SDA */ ++ }; ++ }; ++ ++ m4_i2s2_pins_a: m4-i2s2-0 { ++ pins { ++ pinmux = , /* I2S2_SDO */ ++ , /* I2S2_WS */ ++ ; /* I2S2_CK */ ++ }; ++ }; ++ ++ m4_ltdc_pins_a: m4-ltdc-a-0 { ++ pins { ++ pinmux = , /* LCD_CLK */ ++ , /* LCD_HSYNC */ ++ , /* LCD_VSYNC */ ++ , /* LCD_DE */ ++ , /* LCD_R0 */ ++ , /* LCD_R1 */ ++ , /* LCD_R2 */ ++ , /* LCD_R3 */ ++ , /* LCD_R4 */ ++ , /* LCD_R5 */ ++ , /* LCD_R6 */ ++ , /* LCD_R7 */ ++ , /* LCD_G0 */ ++ , /* LCD_G1 */ ++ , /* LCD_G2 */ ++ , /* LCD_G3 */ ++ , /* LCD_G4 */ ++ , /* LCD_G5 */ ++ , /* LCD_G6 */ ++ , /* LCD_G7 */ ++ , /* LCD_B0 */ ++ , /* LCD_B1 */ ++ , /* LCD_B2 */ ++ , /* LCD_B3 */ ++ , /* LCD_B4 */ ++ , /* LCD_B5 */ ++ , /* LCD_B6 */ ++ ; /* LCD_B7 */ ++ }; ++ }; ++ ++ m4_ltdc_pins_b: m4-ltdc-b-0 { ++ pins { ++ pinmux = , /* LCD_CLK */ ++ , /* LCD_HSYNC */ ++ , /* LCD_VSYNC */ ++ , /* LCD_DE */ ++ , /* LCD_R0 */ ++ , /* LCD_R1 */ ++ , /* LCD_R2 */ ++ , /* LCD_R3 */ ++ , /* LCD_R4 */ ++ , /* LCD_R5 */ ++ , /* LCD_R6 */ ++ , /* LCD_R7 */ ++ , /* LCD_G0 */ ++ , /* LCD_G1 */ ++ , /* LCD_G2 */ ++ , /* LCD_G3 */ ++ , /* LCD_G4 */ ++ , /* LCD_G5 */ ++ , /* LCD_G6 */ ++ , /* LCD_G7 */ ++ , /* LCD_B0 */ ++ , /* LCD_B1 */ ++ , /* LCD_B2 */ ++ , /* LCD_B3 */ ++ , /* LCD_B4 */ ++ , /* LCD_B5 */ ++ , /* LCD_B6 */ ++ ; /* LCD_B7 */ ++ }; ++ }; ++ ++ m4_m_can1_pins_a: m4-m-can1-0 { ++ pins { ++ pinmux = , /* CAN1_TX */ ++ ; /* CAN1_RX */ ++ }; ++ }; ++ ++ m4_pwm1_pins_a: m4-pwm1-0 { ++ pins { ++ pinmux = , /* TIM1_CH1 */ ++ , /* TIM1_CH2 */ ++ ; /* TIM1_CH4 */ ++ }; ++ }; ++ ++ m4_pwm2_pins_a: m4-pwm2-0 { ++ pins { ++ pinmux = ; /* TIM2_CH4 */ ++ }; ++ }; ++ ++ m4_pwm3_pins_a: m4-pwm3-0 { ++ pins { ++ pinmux = ; /* TIM3_CH2 */ ++ }; ++ }; ++ ++ m4_pwm4_pins_a: m4-pwm4-0 { ++ pins { ++ pinmux = , /* TIM4_CH3 */ ++ ; /* TIM4_CH4 */ ++ }; ++ }; ++ ++ m4_pwm4_pins_b: m4-pwm4-1 { ++ pins { ++ pinmux = ; /* TIM4_CH2 */ ++ }; ++ }; ++ ++ m4_pwm5_pins_a: m4-pwm5-0 { ++ pins { ++ pinmux = ; /* TIM5_CH2 */ ++ }; ++ }; ++ ++ m4_pwm8_pins_a: m4-pwm8-0 { ++ pins { ++ pinmux = ; /* TIM8_CH4 */ ++ }; ++ }; ++ ++ m4_pwm12_pins_a: m4-pwm12-0 { ++ pins { ++ pinmux = ; /* TIM12_CH1 */ ++ }; ++ }; ++ ++ m4_qspi_bk1_pins_a: m4-qspi-bk1-0 { ++ pins { ++ pinmux = , /* QSPI_BK1_IO0 */ ++ , /* QSPI_BK1_IO1 */ ++ , /* QSPI_BK1_IO2 */ ++ , /* QSPI_BK1_IO3 */ ++ ; /* QSPI_BK1_NCS */ ++ }; ++ }; ++ ++ m4_qspi_bk2_pins_a: m4-qspi-bk2-0 { ++ pins { ++ pinmux = , /* QSPI_BK2_IO0 */ ++ , /* QSPI_BK2_IO1 */ ++ , /* QSPI_BK2_IO2 */ ++ , /* QSPI_BK2_IO3 */ ++ ; /* QSPI_BK2_NCS */ ++ }; ++ }; ++ ++ m4_qspi_clk_pins_a: m4-qspi-clk-0 { ++ pins { ++ pinmux = ; /* QSPI_CLK */ ++ }; ++ }; ++ ++ m4_rtc_out2_rmp_pins_a: m4-rtc-out2-rmp-pins-0 { ++ pins { ++ pinmux = ; /* RTC_OUT2_RMP */ ++ }; ++ }; ++ ++ m4_sai2a_pins_a: m4-sai2a-0 { ++ pins { ++ pinmux = , /* SAI2_SCK_A */ ++ , /* SAI2_SD_A */ ++ , /* SAI2_FS_A */ ++ ; /* SAI2_MCLK_A */ ++ }; ++ }; ++ ++ m4_sai2b_pins_a: m4-sai2b-0 { ++ pins { ++ pinmux = , /* SAI2_SCK_B */ ++ , /* SAI2_FS_B */ ++ , /* SAI2_MCLK_B */ ++ ; /* SAI2_SD_B */ ++ }; ++ }; ++ ++ m4_sai2b_pins_b: m4-sai2b-2 { ++ pins { ++ pinmux = ; /* SAI2_SD_B */ ++ }; ++ }; ++ ++ m4_sai4a_pins_a: m4-sai4a-0 { ++ pins { ++ pinmux = ; /* SAI4_SD_A */ ++ }; ++ }; ++ ++ m4_sdmmc1_b4_pins_a: m4-sdmmc1-b4-0 { ++ pins { ++ pinmux = , /* SDMMC1_D0 */ ++ , /* SDMMC1_D1 */ ++ , /* SDMMC1_D2 */ ++ , /* SDMMC1_D3 */ ++ , /* SDMMC1_CMD */ ++ ; /* SDMMC1_CK */ ++ }; ++ }; ++ ++ m4_sdmmc1_dir_pins_a: m4-sdmmc1-dir-0 { ++ pins { ++ pinmux = , /* SDMMC1_D0DIR */ ++ , /* SDMMC1_D123DIR */ ++ , /* SDMMC1_CDIR */ ++ ; /* SDMMC1_CKIN */ ++ }; ++ }; ++ ++ m4_sdmmc2_b4_pins_a: m4-sdmmc2-b4-0 { ++ pins { ++ pinmux = , /* SDMMC2_D0 */ ++ , /* SDMMC2_D1 */ ++ , /* SDMMC2_D2 */ ++ , /* SDMMC2_D3 */ ++ , /* SDMMC2_CMD */ ++ ; /* SDMMC2_CK */ ++ }; ++ }; ++ ++ m4_sdmmc2_b4_pins_b: m4-sdmmc2-b4-1 { ++ pins { ++ pinmux = , /* SDMMC2_D0 */ ++ , /* SDMMC2_D1 */ ++ , /* SDMMC2_D2 */ ++ , /* SDMMC2_D3 */ ++ , /* SDMMC2_CMD */ ++ ; /* SDMMC2_CK */ ++ }; ++ }; ++ ++ m4_sdmmc2_d47_pins_a: m4-sdmmc2-d47-0 { ++ pins { ++ pinmux = , /* SDMMC2_D4 */ ++ , /* SDMMC2_D5 */ ++ , /* SDMMC2_D6 */ ++ ; /* SDMMC2_D7 */ ++ }; ++ }; ++ ++ m4_sdmmc3_b4_pins_a: m4-sdmmc3-b4-0 { ++ pins { ++ pinmux = , /* SDMMC3_D0 */ ++ , /* SDMMC3_D1 */ ++ , /* SDMMC3_D2 */ ++ , /* SDMMC3_D3 */ ++ , /* SDMMC3_CMD */ ++ ; /* SDMMC3_CK */ ++ }; ++ }; ++ ++ m4_spdifrx_pins_a: m4-spdifrx-0 { ++ pins { ++ pinmux = ; /* SPDIF_IN1 */ ++ }; ++ }; ++ ++ m4_spi4_pins_a: m4-spi4-0 { ++ pins { ++ pinmux = , /* SPI4_SCK */ ++ , /* SPI4_MOSI */ ++ ; /* SPI4_MISO */ ++ }; ++ }; ++ ++ m4_spi5_pins_a: m4-spi5-0 { ++ pins { ++ pinmux = , /* SPI5_SCK */ ++ , /* SPI5_MOSI */ ++ ; /* SPI5_MISO */ ++ }; ++ }; ++ ++ m4_stusb1600_pins_a: m4-stusb1600-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_uart4_pins_a: m4-uart4-0 { ++ pins { ++ pinmux = , /* UART4_TX */ ++ ; /* UART4_RX */ ++ }; ++ }; ++ ++ m4_uart7_pins_a: m4-uart7-0 { ++ pins { ++ pinmux = , /* USART7_TX */ ++ ; /* USART7_RX */ ++ }; ++ }; ++ ++ m4_usart2_pins_a: m4-usart2-0 { ++ pins { ++ pinmux = , /* USART2_TX */ ++ , /* USART2_RTS */ ++ , /* USART2_RX */ ++ ; /* USART2_CTS_NSS */ ++ }; ++ }; ++ ++ m4_usart3_pins_a: m4-usart3-0 { ++ pins { ++ pinmux = , /* USART3_TX */ ++ , /* USART3_RTS */ ++ , /* USART3_RX */ ++ ; /* USART3_CTS_NSS */ ++ }; ++ }; ++ ++ m4_usart3_pins_b: m4-usart3-1 { ++ pins { ++ pinmux = , /* USART3_TX */ ++ , /* USART3_RTS */ ++ , /* USART3_RX */ ++ ; /* USART3_CTS_NSS */ ++ }; ++ }; ++ ++ m4_usbotg_hs_pins_a: m4-usbotg_hs-0 { ++ pins { ++ pinmux = ; /* OTG_ID */ ++ }; ++ }; ++ ++ m4_usbotg_fs_dp_dm_pins_a: m4-usbotg-fs-dp-dm-0 { ++ pins { ++ pinmux = , /* OTG_FS_DM */ ++ ; /* OTG_FS_DP */ ++ }; ++ }; ++}; ++ ++&pinctrl_z { ++ m4_i2c4_pins_a: m4-i2c4-0 { ++ pins { ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ ++ }; ++ }; ++ ++ m4_spi1_pins_a: m4-spi1-0 { ++ pins { ++ pinmux = , /* SPI1_SCK */ ++ , /* SPI1_MOSI */ ++ ; /* SPI1_MISO */ ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp15-m4-srm.dtsi b/arch/arm/boot/dts/stm32mp15-m4-srm.dtsi +new file mode 100644 +index 000000000000..60454aee4123 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15-m4-srm.dtsi +@@ -0,0 +1,442 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Fabien Dessenne for STMicroelectronics. ++ */ ++ ++&m4_rproc { ++ m4_system_resources { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ m4_timers2: timer@40000000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40000000 0x400>; ++ clocks = <&rcc TIM2_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers3: timer@40001000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40001000 0x400>; ++ clocks = <&rcc TIM3_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers4: timer@40002000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40002000 0x400>; ++ clocks = <&rcc TIM4_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers5: timer@40003000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40003000 0x400>; ++ clocks = <&rcc TIM5_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers6: timer@40004000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40004000 0x400>; ++ clocks = <&rcc TIM6_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers7: timer@40005000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40005000 0x400>; ++ clocks = <&rcc TIM7_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers12: timer@40006000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40006000 0x400>; ++ clocks = <&rcc TIM12_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers13: timer@40007000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40007000 0x400>; ++ clocks = <&rcc TIM13_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers14: timer@40008000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40008000 0x400>; ++ clocks = <&rcc TIM14_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_lptimer1: timer@40009000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40009000 0x400>; ++ clocks = <&rcc LPTIM1_K>; ++ clock-names = "mux"; ++ status = "disabled"; ++ }; ++ m4_spi2: spi@4000b000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4000b000 0x400>; ++ clocks = <&rcc SPI2_K>; ++ status = "disabled"; ++ }; ++ m4_i2s2: audio-controller@4000b000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4000b000 0x400>; ++ status = "disabled"; ++ }; ++ m4_spi3: spi@4000c000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4000c000 0x400>; ++ clocks = <&rcc SPI3_K>; ++ status = "disabled"; ++ }; ++ m4_i2s3: audio-controller@4000c000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4000c000 0x400>; ++ status = "disabled"; ++ }; ++ m4_spdifrx: audio-controller@4000d000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4000d000 0x400>; ++ clocks = <&rcc SPDIF_K>; ++ clock-names = "kclk"; ++ status = "disabled"; ++ }; ++ m4_usart2: serial@4000e000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4000e000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <27 1>; ++ clocks = <&rcc USART2_K>; ++ status = "disabled"; ++ }; ++ m4_usart3: serial@4000f000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4000f000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <28 1>; ++ clocks = <&rcc USART3_K>; ++ status = "disabled"; ++ }; ++ m4_uart4: serial@40010000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40010000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <30 1>; ++ clocks = <&rcc UART4_K>; ++ status = "disabled"; ++ }; ++ m4_uart5: serial@40011000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40011000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <31 1>; ++ clocks = <&rcc UART5_K>; ++ status = "disabled"; ++ }; ++ m4_i2c1: i2c@40012000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40012000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <21 1>; ++ clocks = <&rcc I2C1_K>; ++ status = "disabled"; ++ }; ++ m4_i2c2: i2c@40013000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40013000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <22 1>; ++ clocks = <&rcc I2C2_K>; ++ status = "disabled"; ++ }; ++ m4_i2c3: i2c@40014000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40014000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <23 1>; ++ clocks = <&rcc I2C3_K>; ++ status = "disabled"; ++ }; ++ m4_i2c5: i2c@40015000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40015000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <25 1>; ++ clocks = <&rcc I2C5_K>; ++ status = "disabled"; ++ }; ++ m4_cec: cec@40016000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40016000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <69 1>; ++ clocks = <&rcc CEC_K>, <&scmi0_clk CK_SCMI0_LSE>; ++ clock-names = "cec", "hdmi-cec"; ++ status = "disabled"; ++ }; ++ m4_dac: dac@40017000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40017000 0x400>; ++ clocks = <&rcc DAC12>; ++ clock-names = "pclk"; ++ status = "disabled"; ++ }; ++ m4_uart7: serial@40018000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40018000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <32 1>; ++ clocks = <&rcc UART7_K>; ++ status = "disabled"; ++ }; ++ m4_uart8: serial@40019000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x40019000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <33 1>; ++ clocks = <&rcc UART8_K>; ++ status = "disabled"; ++ }; ++ m4_timers1: timer@44000000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44000000 0x400>; ++ clocks = <&rcc TIM1_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers8: timer@44001000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44001000 0x400>; ++ clocks = <&rcc TIM8_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_usart6: serial@44003000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44003000 0x400>; ++ interrupt-parent = <&exti>; ++ interrupts = <29 1>; ++ clocks = <&rcc USART6_K>; ++ status = "disabled"; ++ }; ++ m4_spi1: spi@44004000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44004000 0x400>; ++ clocks = <&rcc SPI1_K>; ++ status = "disabled"; ++ }; ++ m4_i2s1: audio-controller@44004000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44004000 0x400>; ++ status = "disabled"; ++ }; ++ m4_spi4: spi@44005000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44005000 0x400>; ++ clocks = <&rcc SPI4_K>; ++ status = "disabled"; ++ }; ++ m4_timers15: timer@44006000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44006000 0x400>; ++ clocks = <&rcc TIM15_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers16: timer@44007000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44007000 0x400>; ++ clocks = <&rcc TIM16_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_timers17: timer@44008000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44008000 0x400>; ++ clocks = <&rcc TIM17_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ }; ++ m4_spi5: spi@44009000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x44009000 0x400>; ++ clocks = <&rcc SPI5_K>; ++ status = "disabled"; ++ }; ++ m4_sai1: sai@4400a000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4400a000 0x4>; ++ clocks = <&rcc SAI1_K>; ++ clock-names = "sai_ck"; ++ status = "disabled"; ++ }; ++ m4_sai2: sai@4400b000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4400b000 0x4>; ++ clocks = <&rcc SAI2_K>; ++ clock-names = "sai_ck"; ++ status = "disabled"; ++ }; ++ m4_sai3: sai@4400c000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4400c000 0x4>; ++ clocks = <&rcc SAI3_K>; ++ clock-names = "sai_ck"; ++ status = "disabled"; ++ }; ++ m4_dfsdm: dfsdm@4400d000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4400d000 0x800>; ++ clocks = <&rcc DFSDM_K>, <&rcc ADFSDM_K>; ++ clock-names = "dfsdm", "audio"; ++ status = "disabled"; ++ }; ++ m4_m_can1: can@4400e000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4400e000 0x400>, <0x44011000 0x2800>; ++ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; ++ clock-names = "hclk", "cclk"; ++ status = "disabled"; ++ }; ++ m4_m_can2: can@4400f000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4400f000 0x400>, <0x44011000 0x2800>; ++ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; ++ clock-names = "hclk", "cclk"; ++ status = "disabled"; ++ }; ++ m4_dma1: dma@48000000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x48000000 0x400>; ++ clocks = <&rcc DMA1>; ++ status = "disabled"; ++ }; ++ m4_dma2: dma@48001000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x48001000 0x400>; ++ clocks = <&rcc DMA2>; ++ status = "disabled"; ++ }; ++ m4_dmamux1: dma-router@48002000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x48002000 0x1c>; ++ clocks = <&rcc DMAMUX>; ++ status = "disabled"; ++ }; ++ m4_adc: adc@48003000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x48003000 0x400>; ++ clocks = <&rcc ADC12>, <&rcc ADC12_K>; ++ clock-names = "bus", "adc"; ++ status = "disabled"; ++ }; ++ m4_sdmmc3: sdmmc@48004000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x48004000 0x400>, <0x48005000 0x400>; ++ clocks = <&rcc SDMMC3_K>; ++ status = "disabled"; ++ }; ++ m4_usbotg_hs: usb-otg@49000000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x49000000 0x10000>; ++ clocks = <&rcc USBO_K>; ++ clock-names = "otg"; ++ status = "disabled"; ++ }; ++ m4_hash2: hash@4c002000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4c002000 0x400>; ++ clocks = <&rcc HASH2>; ++ status = "disabled"; ++ }; ++ m4_rng2: rng@4c003000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4c003000 0x400>; ++ clocks = <&rcc RNG2_K>; ++ status = "disabled"; ++ }; ++ m4_crc2: crc@4c004000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4c004000 0x400>; ++ clocks = <&rcc CRC2>; ++ status = "disabled"; ++ }; ++ m4_cryp2: cryp@4c005000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4c005000 0x400>; ++ clocks = <&rcc CRYP2>; ++ status = "disabled"; ++ }; ++ m4_dcmi: dcmi@4c006000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x4c006000 0x400>; ++ clocks = <&rcc DCMI>; ++ clock-names = "mclk"; ++ status = "disabled"; ++ }; ++ m4_lptimer2: timer@50021000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x50021000 0x400>; ++ clocks = <&rcc LPTIM2_K>; ++ clock-names = "mux"; ++ status = "disabled"; ++ }; ++ m4_lptimer3: timer@50022000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x50022000 0x400>; ++ clocks = <&rcc LPTIM3_K>; ++ clock-names = "mux"; ++ status = "disabled"; ++ }; ++ m4_lptimer4: timer@50023000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x50023000 0x400>; ++ clocks = <&rcc LPTIM4_K>; ++ clock-names = "mux"; ++ status = "disabled"; ++ }; ++ m4_lptimer5: timer@50024000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x50024000 0x400>; ++ clocks = <&rcc LPTIM5_K>; ++ clock-names = "mux"; ++ status = "disabled"; ++ }; ++ m4_sai4: sai@50027000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x50027000 0x4>; ++ clocks = <&rcc SAI4_K>; ++ clock-names = "sai_ck"; ++ status = "disabled"; ++ }; ++ m4_qspi: qspi@58003000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; ++ clocks = <&rcc QSPI_K>; ++ status = "disabled"; ++ }; ++ m4_ethernet0: ethernet@5800a000 { ++ compatible = "rproc-srm-dev"; ++ reg = <0x5800a000 0x2000>; ++ clock-names = "stmmaceth", ++ "mac-clk-tx", ++ "mac-clk-rx", ++ "ethstp", ++ "syscfg-clk"; ++ clocks = <&rcc ETHMAC>, ++ <&rcc ETHTX>, ++ <&rcc ETHRX>, ++ <&rcc ETHSTP>, ++ <&rcc SYSCFG>; ++ status = "disabled"; ++ }; ++ }; ++}; ++ +diff --git a/arch/arm/boot/dts/stm32mp15-no-scmi.dtsi b/arch/arm/boot/dts/stm32mp15-no-scmi.dtsi +new file mode 100644 +index 000000000000..94a10b86a179 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15-no-scmi.dtsi +@@ -0,0 +1,157 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved ++ * Author: Gabriel Fernandez for STMicroelectronics. ++ */ ++ ++/ { ++ ++ clocks { ++ clk_hse: clk-hse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ }; ++ ++ clk_hsi: clk-hsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <64000000>; ++ }; ++ ++ clk_lse: clk-lse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ }; ++ ++ clk_lsi: clk-lsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32000>; ++ }; ++ ++ clk_csi: clk-csi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <4000000>; ++ }; ++ }; ++ ++ cpus { ++ cpu0: cpu@0 { ++ clocks = <&rcc CK_MPU>; ++ }; ++ ++ cpu1: cpu@1 { ++ clocks = <&rcc CK_MPU>; ++ }; ++ }; ++ ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&rcc>; ++ offset = <0x404>; ++ mask = <0x1>; ++ }; ++ ++ soc { ++ m_can1: can@4400e000 { ++ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; ++ }; ++ ++ m_can2: can@4400f000 { ++ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; ++ }; ++ ++ cryp1: cryp@54001000 { ++ clocks = <&rcc CRYP1>; ++ resets = <&rcc CRYP1_R>; ++ }; ++ ++ dsi: dsi@5a000000 { ++ clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>; ++ }; ++ }; ++ ++ ahb { ++ m4_rproc: m4@10000000 { ++ resets = <&rcc MCU_R>, <&rcc MCU_HOLD_BOOT_R>; ++ ++ m4_system_resources { ++ m4_cec: cec@40016000 { ++ clocks = <&rcc CEC_K>, <&rcc CK_LSE>; ++ }; ++ ++ m4_m_can1: can@4400e000 { ++ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; ++ }; ++ ++ m4_m_can2: can@4400f000 { ++ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; ++ }; ++ }; ++ }; ++ }; ++ ++ firmware { ++ /delete-node/ scmi0; ++ /delete-node/ scmi1; ++ }; ++ /delete-node/ sram@2ffff000; ++}; ++ ++&cec { ++ clocks = <&rcc CEC_K>, <&clk_lse>; ++}; ++ ++&gpioz { ++ clocks = <&rcc GPIOZ>; ++}; ++ ++&hash1 { ++ clocks = <&rcc HASH1>; ++ resets = <&rcc HASH1_R>; ++}; ++ ++&i2c4 { ++ clocks = <&rcc I2C4_K>; ++ resets = <&rcc I2C4_R>; ++}; ++ ++&i2c6 { ++ clocks = <&rcc I2C6_K>; ++ resets = <&rcc I2C6_R>; ++}; ++ ++&iwdg2 { ++ clocks = <&rcc IWDG2>, <&rcc CK_LSI>; ++}; ++ ++&mdma1 { ++ clocks = <&rcc MDMA>; ++ resets = <&rcc MDMA_R>; ++}; ++ ++&rcc { ++ compatible = "st,stm32mp1-rcc", "syscon"; ++ clocks = <&clk_hse>, <&clk_hsi>, <&clk_csi>, <&clk_lse>, <&clk_lsi>; ++}; ++ ++&rng1 { ++ clocks = <&rcc RNG1_K>; ++ resets = <&rcc RNG1_R>; ++}; ++ ++&rtc { ++ clocks = <&rcc RTCAPB>, <&rcc RTC>; ++}; ++ ++&spi6 { ++ clocks = <&rcc SPI6_K>; ++ resets = <&rcc SPI6_R>; ++}; ++ ++&usart1 { ++ clocks = <&rcc USART1_K>; ++}; +diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +index d84686e00370..a0b76e238c18 100644 +--- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi ++++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +@@ -118,6 +118,45 @@ + }; + }; + ++ dfsdm_clkout_pins_a: dfsdm-clkout-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_CKOUT */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ dfsdm_clkout_sleep_pins_a: dfsdm-clkout-sleep-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_CKOUT */ ++ }; ++ }; ++ ++ dfsdm_data1_pins_a: dfsdm-data1-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_DATA1 */ ++ }; ++ }; ++ ++ dfsdm_data1_sleep_pins_a: dfsdm-data1-sleep-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_DATA1 */ ++ }; ++ }; ++ ++ dfsdm_data3_pins_a: dfsdm-data3-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_DATA3 */ ++ }; ++ }; ++ ++ dfsdm_data3_sleep_pins_a: dfsdm-data3-sleep-pins-0 { ++ pins { ++ pinmux = ; /* DFSDM_DATA3 */ ++ }; ++ }; ++ + ethernet0_rgmii_pins_a: rgmii-0 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ +@@ -349,6 +388,51 @@ + }; + }; + ++ hdp0_pins_a: hdp0-0 { ++ pins { ++ pinmux = ; /* HDP0 */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <2>; ++ }; ++ }; ++ ++ hdp0_pins_sleep_a: hdp0-sleep-0 { ++ pins { ++ pinmux = ; /* HDP0 */ ++ }; ++ }; ++ ++ hdp6_pins_a: hdp6-0 { ++ pins { ++ pinmux = ; /* HDP6 */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <2>; ++ }; ++ }; ++ ++ hdp6_pins_sleep_a: hdp6-sleep-0 { ++ pins { ++ pinmux = ; /* HDP6 */ ++ }; ++ }; ++ ++ hdp7_pins_a: hdp7-0 { ++ pins { ++ pinmux = ; /* HDP7 */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <2>; ++ }; ++ }; ++ ++ hdp7_pins_sleep_a: hdp7-sleep-0 { ++ pins { ++ pinmux = ; /* HDP7 */ ++ }; ++ }; ++ + i2c1_pins_a: i2c1-0 { + pins { + pinmux = , /* I2C1_SCL */ +@@ -1051,6 +1135,12 @@ + }; + }; + ++ rtc_out2_rmp_pins_a: rtc-out2-rmp-pins-0 { ++ pins { ++ pinmux = ; /* RTC_OUT2_RMP */ ++ }; ++ }; ++ + sai2a_pins_a: sai2a-0 { + pins { + pinmux = , /* SAI2_SCK_A */ +@@ -1147,7 +1237,7 @@ + }; + }; + +- sai2b_pins_c: sai2a-4 { ++ sai2b_pins_c: sai2b-4 { + pins1 { + pinmux = ; /* SAI2_SD_B */ + bias-disable; +@@ -1591,6 +1681,73 @@ + }; + }; + ++ spi4_pins_a: spi4-0 { ++ pins { ++ pinmux = , /* SPI4_SCK */ ++ ; /* SPI4_MOSI */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ pins2 { ++ pinmux = ; /* SPI4_MISO */ ++ bias-disable; ++ }; ++ }; ++ ++ spi4_pins_b: spi4-1 { ++ pins1 { ++ pinmux = , /* SPI4_SCK */ ++ ; /* SPI4_MOSI */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ ++ pins2 { ++ pinmux = ; /* SPI4_MISO */ ++ bias-disable; ++ }; ++ }; ++ ++ spi4_sleep_pins_b: spi4-sleep-1 { ++ pins { ++ pinmux = , /* SPI4_SCK */ ++ , /* SPI4_MISO */ ++ ; /* SPI4_MOSI */ ++ }; ++ }; ++ ++ spi5_pins_a: spi5-0 { ++ pins1 { ++ pinmux = , /* SPI5_SCK */ ++ ; /* SPI5_MOSI */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ ++ pins2 { ++ pinmux = ; /* SPI5_MISO */ ++ bias-disable; ++ }; ++ }; ++ ++ spi5_sleep_pins_a: spi5-sleep-0 { ++ pins { ++ pinmux = , /* SPI5_SCK */ ++ , /* SPI5_MISO */ ++ ; /* SPI5_MOSI */ ++ }; ++ }; ++ ++ stusb1600_pins_a: stusb1600-0 { ++ pins { ++ pinmux = ; ++ bias-pull-up; ++ }; ++ }; ++ + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ +@@ -1605,20 +1762,20 @@ + }; + + uart4_idle_pins_a: uart4-idle-0 { +- pins1 { +- pinmux = ; /* UART4_TX */ +- }; +- pins2 { +- pinmux = ; /* UART4_RX */ +- bias-disable; +- }; ++ pins1 { ++ pinmux = ; /* UART4_TX */ ++ }; ++ pins2 { ++ pinmux = ; /* UART4_RX */ ++ bias-disable; ++ }; + }; + + uart4_sleep_pins_a: uart4-sleep-0 { +- pins { ++ pins { + pinmux = , /* UART4_TX */ + ; /* UART4_RX */ +- }; ++ }; + }; + + uart4_pins_b: uart4-1 { +@@ -1684,7 +1841,7 @@ + }; + pins2 { + pinmux = ; /* UART7_RX */ +- bias-disable; ++ bias-pull-up; + }; + }; + +@@ -1694,7 +1851,7 @@ + }; + pins2 { + pinmux = ; /* UART7_RX */ +- bias-disable; ++ bias-pull-up; + }; + }; + +@@ -1726,20 +1883,6 @@ + }; + }; + +- spi4_pins_a: spi4-0 { +- pins { +- pinmux = , /* SPI4_SCK */ +- ; /* SPI4_MOSI */ +- bias-disable; +- drive-push-pull; +- slew-rate = <1>; +- }; +- pins2 { +- pinmux = ; /* SPI4_MISO */ +- bias-disable; +- }; +- }; +- + usart2_pins_a: usart2-0 { + pins1 { + pinmux = , /* USART2_TX */ +@@ -1806,10 +1949,15 @@ + usart2_idle_pins_c: usart2-idle-2 { + pins1 { + pinmux = , /* USART2_TX */ +- , /* USART2_RTS */ + ; /* USART2_CTS_NSS */ + }; + pins2 { ++ pinmux = ; /* USART2_RTS */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <3>; ++ }; ++ pins3 { + pinmux = ; /* USART2_RX */ + bias-disable; + }; +@@ -1855,10 +2003,15 @@ + usart3_idle_pins_b: usart3-idle-1 { + pins1 { + pinmux = , /* USART3_TX */ +- , /* USART3_RTS */ + ; /* USART3_CTS_NSS */ + }; + pins2 { ++ pinmux = ; /* USART3_RTS */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins3 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; +@@ -1884,19 +2037,24 @@ + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ +- bias-disable; ++ bias-pull-up; + }; + }; + + usart3_idle_pins_c: usart3-idle-2 { + pins1 { + pinmux = , /* USART3_TX */ +- , /* USART3_RTS */ + ; /* USART3_CTS_NSS */ + }; + pins2 { +- pinmux = ; /* USART3_RX */ ++ pinmux = ; /* USART3_RTS */ + bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins3 { ++ pinmux = ; /* USART3_RX */ ++ bias-pull-up; + }; + }; + +@@ -1970,4 +2128,12 @@ + bias-disable; + }; + }; ++ ++ spi1_sleep_pins_a: spi1-sleep-0 { ++ pins { ++ pinmux = , /* SPI1_SCK */ ++ , /* SPI1_MISO */ ++ ; /* SPI1_MOSI */ ++ }; ++ }; + }; +diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi +index 84757901cd8d..ca71139f3ad4 100644 +--- a/arch/arm/boot/dts/stm32mp151.dtsi ++++ b/arch/arm/boot/dts/stm32mp151.dtsi +@@ -5,7 +5,10 @@ + */ + #include + #include ++#include + #include ++#include ++ + + / { + #address-cells = <1>; +@@ -17,9 +20,14 @@ + + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; +- clock-frequency = <650000000>; + device_type = "cpu"; + reg = <0>; ++ clocks = <&scmi0_clk CK_SCMI0_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ nvmem-cells = <&part_number_otp>; ++ nvmem-cell-names = "part_number"; ++ #cooling-cells = <2>; + }; + }; + +@@ -30,6 +38,61 @@ + interrupt-parent = <&intc>; + }; + ++ cpu0_opp_table: cpu0-opp-table { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ }; ++ ++ scmi_sram: sram@2ffff000 { ++ compatible = "mmio-sram"; ++ reg = <0x2ffff000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x2ffff000 0x1000>; ++ ++ scmi0_shm: scmi_shm@0 { ++ reg = <0 0x80>; ++ }; ++ ++ scmi1_shm: scmi_shm@200 { ++ reg = <0x200 0x80>; ++ }; ++ }; ++ ++ firmware { ++ scmi0: scmi0 { ++ compatible = "arm,scmi-smc"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ arm,smc-id = <0x82002000>; ++ shmem = <&scmi0_shm>; ++ ++ scmi0_clk: protocol@14 { ++ reg = <0x14>; ++ #clock-cells = <1>; ++ }; ++ ++ scmi0_reset: protocol@16 { ++ reg = <0x16>; ++ #reset-cells = <1>; ++ }; ++ }; ++ ++ scmi1: scmi1 { ++ compatible = "arm,scmi-smc"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ arm,smc-id = <0x82002001>; ++ shmem = <&scmi1_shm>; ++ status = "disabled"; ++ ++ scmi1_clk: protocol@14 { ++ reg = <0x14>; ++ #clock-cells = <1>; ++ }; ++ }; ++ }; ++ + psci { + compatible = "arm,psci-1.0"; + method = "smc"; +@@ -50,38 +113,7 @@ + , + ; + interrupt-parent = <&intc>; +- }; +- +- clocks { +- clk_hse: clk-hse { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <24000000>; +- }; +- +- clk_hsi: clk-hsi { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <64000000>; +- }; +- +- clk_lse: clk-lse { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <32768>; +- }; +- +- clk_lsi: clk-lsi { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <32000>; +- }; +- +- clk_csi: clk-csi { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <4000000>; +- }; ++ always-on; + }; + + thermal-zones { +@@ -91,12 +123,6 @@ + thermal-sensors = <&dts>; + + trips { +- cpu_alert1: cpu-alert1 { +- temperature = <85000>; +- hysteresis = <0>; +- type = "passive"; +- }; +- + cpu-crit { + temperature = <120000>; + hysteresis = <0>; +@@ -115,6 +141,26 @@ + status = "disabled"; + }; + ++ pm_domain { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stm32mp157c-pd"; ++ ++ pd_core_ret: core-ret-power-domain@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ #power-domain-cells = <0>; ++ label = "CORE-RETENTION"; ++ ++ pd_core: core-power-domain@2 { ++ reg = <2>; ++ #power-domain-cells = <0>; ++ label = "CORE"; ++ }; ++ }; ++ }; ++ + soc { + compatible = "simple-bus"; + #address-cells = <1>; +@@ -122,6 +168,14 @@ + interrupt-parent = <&intc>; + ranges; + ++ sram: sram@10000000 { ++ compatible = "mmio-sram"; ++ reg = <0x10000000 0x60000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x10000000 0x60000>; ++ }; ++ + timers2: timer@40000000 { + #address-cells = <1>; + #size-cells = <0>; +@@ -129,11 +183,11 @@ + reg = <0x40000000 0x400>; + clocks = <&rcc TIM2_K>; + clock-names = "int"; +- dmas = <&dmamux1 18 0x400 0x1>, +- <&dmamux1 19 0x400 0x1>, +- <&dmamux1 20 0x400 0x1>, +- <&dmamux1 21 0x400 0x1>, +- <&dmamux1 22 0x400 0x1>; ++ dmas = <&dmamux1 18 0x400 0x80000001>, ++ <&dmamux1 19 0x400 0x80000001>, ++ <&dmamux1 20 0x400 0x80000001>, ++ <&dmamux1 21 0x400 0x80000001>, ++ <&dmamux1 22 0x400 0x80000001>; + dma-names = "ch1", "ch2", "ch3", "ch4", "up"; + status = "disabled"; + +@@ -162,12 +216,12 @@ + reg = <0x40001000 0x400>; + clocks = <&rcc TIM3_K>; + clock-names = "int"; +- dmas = <&dmamux1 23 0x400 0x1>, +- <&dmamux1 24 0x400 0x1>, +- <&dmamux1 25 0x400 0x1>, +- <&dmamux1 26 0x400 0x1>, +- <&dmamux1 27 0x400 0x1>, +- <&dmamux1 28 0x400 0x1>; ++ dmas = <&dmamux1 23 0x400 0x80000001>, ++ <&dmamux1 24 0x400 0x80000001>, ++ <&dmamux1 25 0x400 0x80000001>, ++ <&dmamux1 26 0x400 0x80000001>, ++ <&dmamux1 27 0x400 0x80000001>, ++ <&dmamux1 28 0x400 0x80000001>; + dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; + status = "disabled"; + +@@ -196,10 +250,10 @@ + reg = <0x40002000 0x400>; + clocks = <&rcc TIM4_K>; + clock-names = "int"; +- dmas = <&dmamux1 29 0x400 0x1>, +- <&dmamux1 30 0x400 0x1>, +- <&dmamux1 31 0x400 0x1>, +- <&dmamux1 32 0x400 0x1>; ++ dmas = <&dmamux1 29 0x400 0x80000001>, ++ <&dmamux1 30 0x400 0x80000001>, ++ <&dmamux1 31 0x400 0x80000001>, ++ <&dmamux1 32 0x400 0x80000001>; + dma-names = "ch1", "ch2", "ch3", "ch4"; + status = "disabled"; + +@@ -228,12 +282,12 @@ + reg = <0x40003000 0x400>; + clocks = <&rcc TIM5_K>; + clock-names = "int"; +- dmas = <&dmamux1 55 0x400 0x1>, +- <&dmamux1 56 0x400 0x1>, +- <&dmamux1 57 0x400 0x1>, +- <&dmamux1 58 0x400 0x1>, +- <&dmamux1 59 0x400 0x1>, +- <&dmamux1 60 0x400 0x1>; ++ dmas = <&dmamux1 55 0x400 0x80000001>, ++ <&dmamux1 56 0x400 0x80000001>, ++ <&dmamux1 57 0x400 0x80000001>, ++ <&dmamux1 58 0x400 0x80000001>, ++ <&dmamux1 59 0x400 0x80000001>, ++ <&dmamux1 60 0x400 0x80000001>; + dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; + status = "disabled"; + +@@ -262,7 +316,7 @@ + reg = <0x40004000 0x400>; + clocks = <&rcc TIM6_K>; + clock-names = "int"; +- dmas = <&dmamux1 69 0x400 0x1>; ++ dmas = <&dmamux1 69 0x400 0x80000001>; + dma-names = "up"; + status = "disabled"; + +@@ -280,7 +334,7 @@ + reg = <0x40005000 0x400>; + clocks = <&rcc TIM7_K>; + clock-names = "int"; +- dmas = <&dmamux1 70 0x400 0x1>; ++ dmas = <&dmamux1 70 0x400 0x80000001>; + dma-names = "up"; + status = "disabled"; + +@@ -362,8 +416,11 @@ + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x40009000 0x400>; ++ interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM1_K>; + clock-names = "mux"; ++ power-domains = <&pd_core>; ++ wakeup-source; + status = "disabled"; + + pwm { +@@ -382,6 +439,11 @@ + compatible = "st,stm32-lptimer-counter"; + status = "disabled"; + }; ++ ++ timer { ++ compatible = "st,stm32-lptimer-timer"; ++ status = "disabled"; ++ }; + }; + + spi2: spi@4000b000 { +@@ -392,9 +454,10 @@ + interrupts = ; + clocks = <&rcc SPI2_K>; + resets = <&rcc SPI2_R>; +- dmas = <&dmamux1 39 0x400 0x05>, +- <&dmamux1 40 0x400 0x05>; ++ dmas = <&dmamux1 39 0x400 0x01>, ++ <&dmamux1 40 0x400 0x01>; + dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -417,9 +480,10 @@ + interrupts = ; + clocks = <&rcc SPI3_K>; + resets = <&rcc SPI3_R>; +- dmas = <&dmamux1 61 0x400 0x05>, +- <&dmamux1 62 0x400 0x05>; ++ dmas = <&dmamux1 61 0x400 0x01>, ++ <&dmamux1 62 0x400 0x01>; + dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -450,32 +514,52 @@ + usart2: serial@4000e000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000e000 0x400>; +- interrupts = ; ++ interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART2_K>; ++ wakeup-source; ++ power-domains = <&pd_core>; ++ dmas = <&dmamux1 43 0x400 0x15>, ++ <&dmamux1 44 0x400 0x11>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; +- interrupts = ; ++ interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART3_K>; ++ wakeup-source; ++ power-domains = <&pd_core>; ++ dmas = <&dmamux1 45 0x400 0x15>, ++ <&dmamux1 46 0x400 0x11>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; +- interrupts = ; ++ interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART4_K>; ++ wakeup-source; ++ power-domains = <&pd_core>; ++ dmas = <&dmamux1 63 0x400 0x15>, ++ <&dmamux1 64 0x400 0x11>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; +- interrupts = ; ++ interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART5_K>; ++ wakeup-source; ++ power-domains = <&pd_core>; ++ dmas = <&dmamux1 65 0x400 0x15>, ++ <&dmamux1 66 0x400 0x11>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + +@@ -483,14 +567,19 @@ + compatible = "st,stm32mp15-i2c"; + reg = <0x40012000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; ++ interrupts-extended = <&exti 21 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C1_K>; + resets = <&rcc I2C1_R>; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&dmamux1 33 0x400 0x80000001>, ++ <&dmamux1 34 0x400 0x80000001>; ++ dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + st,syscfg-fmp = <&syscfg 0x4 0x1>; + wakeup-source; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -498,14 +587,19 @@ + compatible = "st,stm32mp15-i2c"; + reg = <0x40013000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; ++ interrupts-extended = <&exti 22 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C2_K>; + resets = <&rcc I2C2_R>; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&dmamux1 35 0x400 0x80000001>, ++ <&dmamux1 36 0x400 0x80000001>; ++ dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + st,syscfg-fmp = <&syscfg 0x4 0x2>; + wakeup-source; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -513,14 +607,19 @@ + compatible = "st,stm32mp15-i2c"; + reg = <0x40014000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; ++ interrupts-extended = <&exti 23 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C3_K>; + resets = <&rcc I2C3_R>; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&dmamux1 73 0x400 0x80000001>, ++ <&dmamux1 74 0x400 0x80000001>; ++ dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + st,syscfg-fmp = <&syscfg 0x4 0x4>; + wakeup-source; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -528,14 +627,19 @@ + compatible = "st,stm32mp15-i2c"; + reg = <0x40015000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; ++ interrupts-extended = <&exti 25 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C5_K>; + resets = <&rcc I2C5_R>; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&dmamux1 115 0x400 0x80000001>, ++ <&dmamux1 116 0x400 0x80000001>; ++ dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + st,syscfg-fmp = <&syscfg 0x4 0x10>; + wakeup-source; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -543,7 +647,7 @@ + compatible = "st,stm32-cec"; + reg = <0x40016000 0x400>; + interrupts = ; +- clocks = <&rcc CEC_K>, <&clk_lse>; ++ clocks = <&rcc CEC_K>, <&scmi0_clk CK_SCMI0_LSE>; + clock-names = "cec", "hdmi-cec"; + status = "disabled"; + }; +@@ -575,16 +679,26 @@ + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; +- interrupts = ; ++ interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART7_K>; ++ wakeup-source; ++ power-domains = <&pd_core>; ++ dmas = <&dmamux1 79 0x400 0x15>, ++ <&dmamux1 80 0x400 0x11>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; +- interrupts = ; ++ interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART8_K>; ++ wakeup-source; ++ power-domains = <&pd_core>; ++ dmas = <&dmamux1 81 0x400 0x15>, ++ <&dmamux1 82 0x400 0x11>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + +@@ -595,13 +709,13 @@ + reg = <0x44000000 0x400>; + clocks = <&rcc TIM1_K>; + clock-names = "int"; +- dmas = <&dmamux1 11 0x400 0x1>, +- <&dmamux1 12 0x400 0x1>, +- <&dmamux1 13 0x400 0x1>, +- <&dmamux1 14 0x400 0x1>, +- <&dmamux1 15 0x400 0x1>, +- <&dmamux1 16 0x400 0x1>, +- <&dmamux1 17 0x400 0x1>; ++ dmas = <&dmamux1 11 0x400 0x80000001>, ++ <&dmamux1 12 0x400 0x80000001>, ++ <&dmamux1 13 0x400 0x80000001>, ++ <&dmamux1 14 0x400 0x80000001>, ++ <&dmamux1 15 0x400 0x80000001>, ++ <&dmamux1 16 0x400 0x80000001>, ++ <&dmamux1 17 0x400 0x80000001>; + dma-names = "ch1", "ch2", "ch3", "ch4", + "up", "trig", "com"; + status = "disabled"; +@@ -631,13 +745,13 @@ + reg = <0x44001000 0x400>; + clocks = <&rcc TIM8_K>; + clock-names = "int"; +- dmas = <&dmamux1 47 0x400 0x1>, +- <&dmamux1 48 0x400 0x1>, +- <&dmamux1 49 0x400 0x1>, +- <&dmamux1 50 0x400 0x1>, +- <&dmamux1 51 0x400 0x1>, +- <&dmamux1 52 0x400 0x1>, +- <&dmamux1 53 0x400 0x1>; ++ dmas = <&dmamux1 47 0x400 0x80000001>, ++ <&dmamux1 48 0x400 0x80000001>, ++ <&dmamux1 49 0x400 0x80000001>, ++ <&dmamux1 50 0x400 0x80000001>, ++ <&dmamux1 51 0x400 0x80000001>, ++ <&dmamux1 52 0x400 0x80000001>, ++ <&dmamux1 53 0x400 0x80000001>; + dma-names = "ch1", "ch2", "ch3", "ch4", + "up", "trig", "com"; + status = "disabled"; +@@ -663,8 +777,13 @@ + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; +- interrupts = ; ++ interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART6_K>; ++ wakeup-source; ++ power-domains = <&pd_core>; ++ dmas = <&dmamux1 71 0x400 0x15>, ++ <&dmamux1 72 0x400 0x11>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + +@@ -676,9 +795,10 @@ + interrupts = ; + clocks = <&rcc SPI1_K>; + resets = <&rcc SPI1_R>; +- dmas = <&dmamux1 37 0x400 0x05>, +- <&dmamux1 38 0x400 0x05>; ++ dmas = <&dmamux1 37 0x400 0x01>, ++ <&dmamux1 38 0x400 0x01>; + dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -701,9 +821,10 @@ + interrupts = ; + clocks = <&rcc SPI4_K>; + resets = <&rcc SPI4_R>; +- dmas = <&dmamux1 83 0x400 0x05>, +- <&dmamux1 84 0x400 0x05>; ++ dmas = <&dmamux1 83 0x400 0x01>, ++ <&dmamux1 84 0x400 0x01>; + dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -714,10 +835,10 @@ + reg = <0x44006000 0x400>; + clocks = <&rcc TIM15_K>; + clock-names = "int"; +- dmas = <&dmamux1 105 0x400 0x1>, +- <&dmamux1 106 0x400 0x1>, +- <&dmamux1 107 0x400 0x1>, +- <&dmamux1 108 0x400 0x1>; ++ dmas = <&dmamux1 105 0x400 0x80000001>, ++ <&dmamux1 106 0x400 0x80000001>, ++ <&dmamux1 107 0x400 0x80000001>, ++ <&dmamux1 108 0x400 0x80000001>; + dma-names = "ch1", "up", "trig", "com"; + status = "disabled"; + +@@ -741,8 +862,8 @@ + reg = <0x44007000 0x400>; + clocks = <&rcc TIM16_K>; + clock-names = "int"; +- dmas = <&dmamux1 109 0x400 0x1>, +- <&dmamux1 110 0x400 0x1>; ++ dmas = <&dmamux1 109 0x400 0x80000001>, ++ <&dmamux1 110 0x400 0x80000001>; + dma-names = "ch1", "up"; + status = "disabled"; + +@@ -765,8 +886,8 @@ + reg = <0x44008000 0x400>; + clocks = <&rcc TIM17_K>; + clock-names = "int"; +- dmas = <&dmamux1 111 0x400 0x1>, +- <&dmamux1 112 0x400 0x1>; ++ dmas = <&dmamux1 111 0x400 0x80000001>, ++ <&dmamux1 112 0x400 0x80000001>; + dma-names = "ch1", "up"; + status = "disabled"; + +@@ -791,9 +912,10 @@ + interrupts = ; + clocks = <&rcc SPI5_K>; + resets = <&rcc SPI5_R>; +- dmas = <&dmamux1 85 0x400 0x05>, +- <&dmamux1 86 0x400 0x05>; ++ dmas = <&dmamux1 85 0x400 0x01>, ++ <&dmamux1 86 0x400 0x01>; + dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -811,7 +933,7 @@ + #sound-dai-cells = <0>; + + compatible = "st,stm32-sai-sub-a"; +- reg = <0x4 0x1c>; ++ reg = <0x4 0x20>; + clocks = <&rcc SAI1_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 87 0x400 0x01>; +@@ -821,7 +943,7 @@ + sai1b: audio-controller@4400a024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI1_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 88 0x400 0x01>; +@@ -842,7 +964,7 @@ + sai2a: audio-controller@4400b004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; +- reg = <0x4 0x1c>; ++ reg = <0x4 0x20>; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 89 0x400 0x01>; +@@ -852,7 +974,7 @@ + sai2b: audio-controller@4400b024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 90 0x400 0x01>; +@@ -873,7 +995,7 @@ + sai3a: audio-controller@4400c004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; +- reg = <0x04 0x1c>; ++ reg = <0x04 0x20>; + clocks = <&rcc SAI3_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 113 0x400 0x01>; +@@ -883,7 +1005,7 @@ + sai3b: audio-controller@4400c024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI3_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 114 0x400 0x01>; +@@ -977,6 +1099,15 @@ + #dma-cells = <4>; + st,mem2mem; + dma-requests = <8>; ++ dmas = <&mdma1 0 0x3 0x1200000a 0x48000008 0x00000020 1>, ++ <&mdma1 1 0x3 0x1200000a 0x48000008 0x00000800 1>, ++ <&mdma1 2 0x3 0x1200000a 0x48000008 0x00200000 1>, ++ <&mdma1 3 0x3 0x1200000a 0x48000008 0x08000000 1>, ++ <&mdma1 4 0x3 0x1200000a 0x4800000C 0x00000020 1>, ++ <&mdma1 5 0x3 0x1200000a 0x4800000C 0x00000800 1>, ++ <&mdma1 6 0x3 0x1200000a 0x4800000C 0x00200000 1>, ++ <&mdma1 7 0x3 0x1200000a 0x4800000C 0x08000000 1>; ++ dma-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6", "ch7"; + }; + + dma2: dma-controller@48001000 { +@@ -995,11 +1126,20 @@ + #dma-cells = <4>; + st,mem2mem; + dma-requests = <8>; ++ dmas = <&mdma1 8 0x3 0x1200000a 0x48001008 0x00000020 1>, ++ <&mdma1 9 0x3 0x1200000a 0x48001008 0x00000800 1>, ++ <&mdma1 10 0x3 0x1200000a 0x48001008 0x00200000 1>, ++ <&mdma1 11 0x3 0x1200000a 0x48001008 0x08000000 1>, ++ <&mdma1 12 0x3 0x1200000a 0x4800100C 0x00000020 1>, ++ <&mdma1 13 0x3 0x1200000a 0x4800100C 0x00000800 1>, ++ <&mdma1 14 0x3 0x1200000a 0x4800100C 0x00200000 1>, ++ <&mdma1 15 0x3 0x1200000a 0x4800100C 0x08000000 1>; ++ dma-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6", "ch7"; + }; + + dmamux1: dma-router@48002000 { + compatible = "st,stm32h7-dmamux"; +- reg = <0x48002000 0x1c>; ++ reg = <0x48002000 0x40>; + #dma-cells = <3>; + dma-requests = <128>; + dma-masters = <&dma1 &dma2>; +@@ -1028,7 +1168,7 @@ + reg = <0x0>; + interrupt-parent = <&adc>; + interrupts = <0>; +- dmas = <&dmamux1 9 0x400 0x01>; ++ dmas = <&dmamux1 9 0x400 0x80000001>; + dma-names = "rx"; + status = "disabled"; + }; +@@ -1039,7 +1179,7 @@ + reg = <0x100>; + interrupt-parent = <&adc>; + interrupts = <1>; +- dmas = <&dmamux1 10 0x400 0x01>; ++ dmas = <&dmamux1 10 0x400 0x80000001>; + dma-names = "rx"; + status = "disabled"; + }; +@@ -1047,7 +1187,7 @@ + + sdmmc3: sdmmc@48004000 { + compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x10153180>; ++ arm,primecell-periphid = <0x00253180>; + reg = <0x48004000 0x400>; + interrupts = ; + interrupt-names = "cmd_irq"; +@@ -1067,27 +1207,37 @@ + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; +- interrupts = ; +- g-rx-fifo-size = <256>; ++ interrupts-extended = <&exti 44 IRQ_TYPE_LEVEL_HIGH>; ++ g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; +- g-tx-fifo-size = <128 128 64 64 64 64 32 32>; ++ g-tx-fifo-size = <256 16 16 16 16 16 16 16>; + dr_mode = "otg"; + usb33d-supply = <&usb33>; ++ power-domains = <&pd_core>; ++ wakeup-source; + status = "disabled"; + }; + ++ hsem: hwspinlock@4c000000 { ++ compatible = "st,stm32-hwspinlock"; ++ #hwlock-cells = <2>; ++ reg = <0x4c000000 0x400>; ++ clocks = <&rcc HSEM>; ++ clock-names = "hsem"; ++ }; ++ + ipcc: mailbox@4c001000 { + compatible = "st,stm32mp1-ipcc"; + #mbox-cells = <1>; + reg = <0x4c001000 0x400>; + st,proc-id = <0>; + interrupts-extended = +- <&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, +- <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, +- <&exti 61 1>; +- interrupt-names = "rx", "tx", "wakeup"; ++ <&exti 61 1>, ++ <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "rx", "tx"; + clocks = <&rcc IPCC>; + wakeup-source; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -1098,21 +1248,30 @@ + resets = <&rcc CAMITF_R>; + clocks = <&rcc DCMI>; + clock-names = "mclk"; +- dmas = <&dmamux1 75 0x400 0x0d>; ++ dmas = <&dmamux1 75 0x400 0xe0000001>; + dma-names = "tx"; + status = "disabled"; + }; + + rcc: rcc@50000000 { +- compatible = "st,stm32mp1-rcc", "syscon"; ++ compatible = "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; ++ interrupts = ; ++ ++ clock-names = "hse", "hsi", "csi", "lse", "lsi"; ++ clocks = <&scmi0_clk CK_SCMI0_HSE>, ++ <&scmi0_clk CK_SCMI0_HSI>, ++ <&scmi0_clk CK_SCMI0_CSI>, ++ <&scmi0_clk CK_SCMI0_LSE>, ++ <&scmi0_clk CK_SCMI0_LSI>; + }; + + pwr_regulators: pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; ++ st,tzcr = <&rcc 0x0 0x1>; + + reg11: reg11 { + regulator-name = "reg11"; +@@ -1138,11 +1297,38 @@ + reg = <0x50001014 0x4>; + }; + ++ pwr_irq: pwr@50001020 { ++ compatible = "st,stm32mp1-pwr"; ++ reg = <0x50001020 0x100>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ ++ wakeup-gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>, ++ <&gpioa 2 GPIO_ACTIVE_HIGH>, ++ <&gpioc 13 GPIO_ACTIVE_HIGH>, ++ <&gpioi 8 GPIO_ACTIVE_HIGH>, ++ <&gpioi 11 GPIO_ACTIVE_HIGH>, ++ <&gpioc 1 GPIO_ACTIVE_HIGH>; ++ }; ++ + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp1-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; ++ hwlocks = <&hsem 1 1>; ++ ++ /* exti_pwr is an extra interrupt controller used for ++ * EXTI 55 to 60. It's mapped on pwr interrupt ++ * controller. ++ */ ++ exti_pwr: exti-pwr { ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&pwr_irq>; ++ st,irq-number = <6>; ++ }; + }; + + syscfg: syscon@50020000 { +@@ -1156,8 +1342,11 @@ + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x50021000 0x400>; ++ interrupts-extended = <&exti 48 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM2_K>; + clock-names = "mux"; ++ power-domains = <&pd_core>; ++ wakeup-source; + status = "disabled"; + + pwm { +@@ -1176,6 +1365,11 @@ + compatible = "st,stm32-lptimer-counter"; + status = "disabled"; + }; ++ ++ timer { ++ compatible = "st,stm32-lptimer-timer"; ++ status = "disabled"; ++ }; + }; + + lptimer3: timer@50022000 { +@@ -1183,8 +1377,11 @@ + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x50022000 0x400>; ++ interrupts-extended = <&exti 50 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM3_K>; + clock-names = "mux"; ++ power-domains = <&pd_core>; ++ wakeup-source; + status = "disabled"; + + pwm { +@@ -1198,13 +1395,21 @@ + reg = <2>; + status = "disabled"; + }; ++ ++ timer { ++ compatible = "st,stm32-lptimer-timer"; ++ status = "disabled"; ++ }; + }; + + lptimer4: timer@50023000 { + compatible = "st,stm32-lptimer"; + reg = <0x50023000 0x400>; ++ interrupts-extended = <&exti 52 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM4_K>; + clock-names = "mux"; ++ power-domains = <&pd_core>; ++ wakeup-source; + status = "disabled"; + + pwm { +@@ -1212,13 +1417,21 @@ + #pwm-cells = <3>; + status = "disabled"; + }; ++ ++ timer { ++ compatible = "st,stm32-lptimer-timer"; ++ status = "disabled"; ++ }; + }; + + lptimer5: timer@50024000 { + compatible = "st,stm32-lptimer"; + reg = <0x50024000 0x400>; ++ interrupts-extended = <&exti 53 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM5_K>; + clock-names = "mux"; ++ power-domains = <&pd_core>; ++ wakeup-source; + status = "disabled"; + + pwm { +@@ -1226,6 +1439,11 @@ + #pwm-cells = <3>; + status = "disabled"; + }; ++ ++ timer { ++ compatible = "st,stm32-lptimer-timer"; ++ status = "disabled"; ++ }; + }; + + vrefbuf: vrefbuf@50025000 { +@@ -1250,7 +1468,7 @@ + sai4a: audio-controller@50027004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; +- reg = <0x04 0x1c>; ++ reg = <0x04 0x20>; + clocks = <&rcc SAI4_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 99 0x400 0x01>; +@@ -1260,7 +1478,7 @@ + sai4b: audio-controller@50027024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI4_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 100 0x400 0x01>; +@@ -1278,13 +1496,21 @@ + status = "disabled"; + }; + ++ hdp: hdp@5002a000 { ++ compatible = "st,stm32mp1-hdp"; ++ reg = <0x5002a000 0x400>; ++ clocks = <&rcc HDP>; ++ clock-names = "hdp"; ++ status = "disabled"; ++ }; ++ + hash1: hash@54002000 { + compatible = "st,stm32f756-hash"; + reg = <0x54002000 0x400>; + interrupts = ; +- clocks = <&rcc HASH1>; +- resets = <&rcc HASH1_R>; +- dmas = <&mdma1 31 0x10 0x1000A02 0x0 0x0>; ++ clocks = <&scmi0_clk CK_SCMI0_HASH1>; ++ resets = <&scmi0_reset RST_SCMI0_HASH1>; ++ dmas = <&mdma1 31 0x2 0x1000A02 0x0 0x0 0x0>; + dma-names = "in"; + dma-maxburst = <2>; + status = "disabled"; +@@ -1293,8 +1519,8 @@ + rng1: rng@54003000 { + compatible = "st,stm32-rng"; + reg = <0x54003000 0x400>; +- clocks = <&rcc RNG1_K>; +- resets = <&rcc RNG1_R>; ++ clocks = <&scmi0_clk CK_SCMI0_RNG1>; ++ resets = <&scmi0_reset RST_SCMI0_RNG1>; + status = "disabled"; + }; + +@@ -1303,8 +1529,8 @@ + reg = <0x58000000 0x1000>; + interrupts = ; + clocks = <&rcc MDMA>; +- resets = <&rcc MDMA_R>; +- #dma-cells = <5>; ++ resets = <&scmi0_reset RST_SCMI0_MDMA>; ++ #dma-cells = <6>; + dma-channels = <32>; + dma-requests = <48>; + }; +@@ -1335,9 +1561,9 @@ + <4 0x09010000 0x1000>, + <4 0x09020000 0x1000>; + interrupts = ; +- dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>, +- <&mdma1 20 0x2 0x12000a08 0x0 0x0>, +- <&mdma1 21 0x2 0x12000a0a 0x0 0x0>; ++ dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0 0x0>, ++ <&mdma1 20 0x2 0x12000a08 0x0 0x0 0x0>, ++ <&mdma1 21 0x2 0x12000a0a 0x0 0x0 0x0>; + dma-names = "tx", "rx", "ecc"; + status = "disabled"; + }; +@@ -1348,8 +1574,8 @@ + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = ; +- dmas = <&mdma1 22 0x10 0x100002 0x0 0x0>, +- <&mdma1 22 0x10 0x100008 0x0 0x0>; ++ dmas = <&mdma1 22 0x2 0x100002 0x0 0x0 0x0>, ++ <&mdma1 22 0x2 0x100008 0x0 0x0 0x0>; + dma-names = "tx", "rx"; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; +@@ -1360,7 +1586,7 @@ + + sdmmc1: sdmmc@58005000 { + compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x10153180>; ++ arm,primecell-periphid = <0x00253180>; + reg = <0x58005000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; +@@ -1375,7 +1601,7 @@ + + sdmmc2: sdmmc@58007000 { + compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x10153180>; ++ arm,primecell-periphid = <0x00253180>; + reg = <0x58007000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; +@@ -1405,8 +1631,10 @@ + compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; + reg = <0x5800a000 0x2000>; + reg-names = "stmmaceth"; +- interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; +- interrupt-names = "macirq"; ++ interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, ++ <&exti 70 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "macirq", ++ "eth_wake_irq"; + clock-names = "stmmaceth", + "mac-clk-tx", + "mac-clk-rx", +@@ -1423,6 +1651,7 @@ + snps,en-tx-lpi-clockgating; + snps,axi-config = <&stmmac_axi_config_0>; + snps,tso; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -1440,8 +1669,10 @@ + reg = <0x5800d000 0x1000>; + clocks = <&rcc USBH>; + resets = <&rcc USBH_R>; +- interrupts = ; ++ interrupts-extended = <&exti 43 IRQ_TYPE_LEVEL_HIGH>; + companion = <&usbh_ohci>; ++ power-domains = <&pd_core>; ++ wakeup-source; + status = "disabled"; + }; + +@@ -1464,7 +1695,7 @@ + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; +- clocks = <&rcc IWDG2>, <&rcc CK_LSI>; ++ clocks = <&rcc IWDG2>, <&scmi0_clk CK_SCMI0_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; +@@ -1472,10 +1703,13 @@ + usbphyc: usbphyc@5a006000 { + #address-cells = <1>; + #size-cells = <0>; ++ #clock-cells = <0>; + compatible = "st,stm32mp1-usbphyc"; + reg = <0x5a006000 0x1000>; + clocks = <&rcc USBPHY_K>; + resets = <&rcc USBPHY_R>; ++ vdda1v1-supply = <®11>; ++ vdda1v8-supply = <®18>; + status = "disabled"; + + usbphyc_port0: usb-phy@0 { +@@ -1489,11 +1723,21 @@ + }; + }; + ++ ddrperfm: perf@5a007000 { ++ compatible = "st,stm32-ddr-pmu"; ++ reg = <0x5a007000 0x400>; ++ clocks = <&rcc DDRPERFM>; ++ resets = <&rcc DDRPERFM_R>; ++ }; ++ + usart1: serial@5c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x5c000000 0x400>; +- interrupts = ; +- clocks = <&rcc USART1_K>; ++ interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&scmi0_clk CK_SCMI0_USART1>; ++ resets = <&scmi0_reset RST_SCMI0_USART1>; ++ wakeup-source; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -1503,11 +1747,12 @@ + compatible = "st,stm32h7-spi"; + reg = <0x5c001000 0x400>; + interrupts = ; +- clocks = <&rcc SPI6_K>; +- resets = <&rcc SPI6_R>; +- dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>, +- <&mdma1 35 0x0 0x40002 0x0 0x0>; ++ clocks = <&scmi0_clk CK_SCMI0_SPI6>; ++ resets = <&scmi0_reset RST_SCMI0_SPI6>; ++ dmas = <&mdma1 34 0x0 0x40008 0x0 0x0 0x0>, ++ <&mdma1 35 0x0 0x40002 0x0 0x0 0x0>; + dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + status = "disabled"; + }; + +@@ -1515,23 +1760,29 @@ + compatible = "st,stm32mp15-i2c"; + reg = <0x5c002000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; +- clocks = <&rcc I2C4_K>; +- resets = <&rcc I2C4_R>; ++ interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&scmi0_clk CK_SCMI0_I2C4>; ++ resets = <&scmi0_reset RST_SCMI0_I2C4>; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&mdma1 36 0x0 0x40008 0x0 0x0 0>, ++ <&mdma1 37 0x0 0x40002 0x0 0x0 0>; ++ dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + st,syscfg-fmp = <&syscfg 0x4 0x8>; + wakeup-source; ++ i2c-analog-filter; + status = "disabled"; + }; + + rtc: rtc@5c004000 { + compatible = "st,stm32mp1-rtc"; + reg = <0x5c004000 0x400>; +- clocks = <&rcc RTCAPB>, <&rcc RTC>; ++ clocks = <&scmi0_clk CK_SCMI0_RTCAPB>, ++ <&scmi0_clk CK_SCMI0_RTC>; + clock-names = "pclk", "rtc_ck"; +- interrupts = ; ++ interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + +@@ -1540,26 +1791,37 @@ + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; ++ part_number_otp: part_number_otp@4 { ++ reg = <0x4 0x1>; ++ }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; ++ ethernet_mac_address: mac@e4 { ++ reg = <0xe4 0x6>; ++ }; + }; + + i2c6: i2c@5c009000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x5c009000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; +- clocks = <&rcc I2C6_K>; +- resets = <&rcc I2C6_R>; ++ interrupts-extended = <&exti 54 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&scmi0_clk CK_SCMI0_I2C6>; ++ resets = <&scmi0_reset RST_SCMI0_I2C6>; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&mdma1 38 0x0 0x40008 0x0 0x0 0>, ++ <&mdma1 39 0x0 0x40002 0x0 0x0 0>; ++ dma-names = "rx", "tx"; ++ power-domains = <&pd_core>; + st,syscfg-fmp = <&syscfg 0x4 0x20>; + wakeup-source; ++ i2c-analog-filter; + status = "disabled"; + }; + +@@ -1574,6 +1836,7 @@ + ranges = <0 0x50002000 0xa400>; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; ++ hwlocks = <&hsem 0 1>; + pins-are-numbered; + + gpioa: gpio@50002000 { +@@ -1706,6 +1969,7 @@ + pins-are-numbered; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; ++ hwlocks = <&hsem 0 1>; + + gpioz: gpio@54004000 { + gpio-controller; +@@ -1713,12 +1977,30 @@ + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 0x400>; +- clocks = <&rcc GPIOZ>; ++ clocks = <&scmi0_clk CK_SCMI0_GPIOZ>; + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; + }; + }; ++ ++ tamp: tamp@5c00a000 { ++ compatible = "simple-bus", "syscon", "simple-mfd"; ++ reg = <0x5c00a000 0x400>; ++ ++ reboot-mode { ++ compatible = "syscon-reboot-mode"; ++ offset = <0x150>; /* reg20 */ ++ mask = <0xff>; ++ mode-normal = <0>; ++ mode-fastboot = <0x1>; ++ mode-recovery = <0x2>; ++ mode-stm32cubeprogrammer = <0x3>; ++ mode-ums_mmc0 = <0x10>; ++ mode-ums_mmc1 = <0x11>; ++ mode-ums_mmc2 = <0x12>; ++ }; ++ }; + }; + + mlahb: ahb { +@@ -1735,11 +2017,18 @@ + reg = <0x10000000 0x40000>, + <0x30000000 0x40000>, + <0x38000000 0x10000>; +- resets = <&rcc MCU_R>; +- st,syscfg-holdboot = <&rcc 0x10C 0x1>; +- st,syscfg-tz = <&rcc 0x000 0x1>; ++ resets = <&scmi0_reset RST_SCMI0_MCU>, ++ <&scmi0_reset RST_SCMI0_MCU_HOLD_BOOT>; ++ reset-names = "mcu_rst", "hold_boot"; + st,syscfg-pdds = <&pwr_mcu 0x0 0x1>; ++ st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; ++ st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; + status = "disabled"; ++ ++ m4_system_resources { ++ compatible = "rproc-srm-core"; ++ status = "disabled"; ++ }; + }; + }; + }; +diff --git a/arch/arm/boot/dts/stm32mp153.dtsi b/arch/arm/boot/dts/stm32mp153.dtsi +index 1c1889b194cf..cf16b843c6b5 100644 +--- a/arch/arm/boot/dts/stm32mp153.dtsi ++++ b/arch/arm/boot/dts/stm32mp153.dtsi +@@ -10,9 +10,11 @@ + cpus { + cpu1: cpu@1 { + compatible = "arm,cortex-a7"; +- clock-frequency = <650000000>; + device_type = "cpu"; + reg = <1>; ++ clocks = <&scmi0_clk CK_SCMI0_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + }; + +@@ -30,7 +32,7 @@ + interrupts = , + ; + interrupt-names = "int0", "int1"; +- clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; ++ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; + clock-names = "hclk", "cclk"; + bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; + status = "disabled"; +@@ -43,7 +45,7 @@ + interrupts = , + ; + interrupt-names = "int0", "int1"; +- clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; ++ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; + clock-names = "hclk", "cclk"; + bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; + status = "disabled"; +diff --git a/arch/arm/boot/dts/stm32mp157.dtsi b/arch/arm/boot/dts/stm32mp157.dtsi +index 54e73ccea446..8a34964b9d79 100644 +--- a/arch/arm/boot/dts/stm32mp157.dtsi ++++ b/arch/arm/boot/dts/stm32mp157.dtsi +@@ -20,7 +20,8 @@ + dsi: dsi@5a000000 { + compatible = "st,stm32-dsi"; + reg = <0x5a000000 0x800>; +- clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>; ++ phy-dsi-supply = <®18>; ++ clocks = <&rcc DSI_K>, <&scmi0_clk CK_SCMI0_HSE>, <&rcc DSI_PX>; + clock-names = "pclk", "ref", "px_clk"; + resets = <&rcc DSI_R>; + reset-names = "apb"; +diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts +index 4c8be9c8eb20..f415e581a63c 100644 +--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts ++++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts +@@ -7,6 +7,7 @@ + /dts-v1/; + + #include "stm32mp157.dtsi" ++#include "stm32mp15xa.dtsi" + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxac-pinctrl.dtsi" + #include "stm32mp15xx-dkx.dtsi" +@@ -16,7 +17,6 @@ + compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; + + aliases { +- ethernet0 = ðernet0; + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; +diff --git a/arch/arm/boot/dts/stm32mp157a-ed1.dts b/arch/arm/boot/dts/stm32mp157a-ed1.dts +new file mode 100644 +index 000000000000..0213ca5c17fa +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157a-ed1.dts +@@ -0,0 +1,32 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xa.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157A eval daughter"; ++ compatible = "st,stm32mp157a-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ reserved-memory { ++ gpu_reserved: gpu@f6000000 { ++ reg = <0xf6000000 0x8000000>; ++ no-map; ++ }; ++ }; ++}; ++ ++&gpu { ++ contiguous-area = <&gpu_reserved>; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157a-ev1.dts b/arch/arm/boot/dts/stm32mp157a-ev1.dts +new file mode 100644 +index 000000000000..11bd88a82f05 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157a-ev1.dts +@@ -0,0 +1,88 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157a-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157A eval daughter on eval mother"; ++ compatible = "st,stm32mp157a-ev1", "st,stm32mp157a-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ }; ++}; ++ ++<dc { ++ status = "okay"; ++ ++ port { ++ ltdc_ep0_out: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&dsi_in>; ++ }; ++ }; ++}; ++ ++&dsi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ dsi_in: endpoint { ++ remote-endpoint = <<dc_ep0_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ dsi_out: endpoint { ++ remote-endpoint = <&dsi_panel_in>; ++ }; ++ }; ++ }; ++ ++ panel_dsi: panel-dsi@0 { ++ compatible = "raydium,rm68200"; ++ reg = <0>; ++ reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; ++ backlight = <&panel_backlight>; ++ power-supply = <&v3v3>; ++ status = "okay"; ++ ++ port { ++ dsi_panel_in: endpoint { ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c2 { ++ gt9147: goodix_ts@5d { ++ compatible = "goodix,gt9147"; ++ reg = <0x5d>; ++ panel = <&panel_dsi>; ++ pinctrl-0 = <&goodix_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ interrupts = <14 IRQ_TYPE_EDGE_RISING>; ++ interrupt-parent = <&stmfx_pinctrl>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts b/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts +new file mode 100644 +index 000000000000..372ceb2c7128 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts +@@ -0,0 +1,60 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157c-dk2.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157C-DK2 configured to run Linux A7 examples"; ++ compatible = "st,stm32mp157c-dk2-a7-examples", "st,stm32mp157c-dk2", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "okay"; ++ ++ adc2: adc@100 { ++ /* Set IRQ mode as example. DMA is the preferred mode, yet. */ ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ }; ++}; ++ ++&i2c5 { ++ status = "okay"; ++}; ++ ++&timers1 { ++ status = "okay"; ++}; ++ ++&timers3 { ++ status = "okay"; ++}; ++ ++&timers4 { ++ status = "okay"; ++}; ++ ++&timers5 { ++ status = "okay"; ++}; ++ ++&timers6 { ++ status = "okay"; ++}; ++ ++&timers12 { ++ status = "okay"; ++}; ++ ++&uart7 { ++ status = "okay"; ++}; ++ ++&usart3 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts b/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts +new file mode 100644 +index 000000000000..14eac740d4e3 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts +@@ -0,0 +1,129 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157c-dk2.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157C-DK2 configured to run M4 examples"; ++ compatible = "st,stm32mp157c-dk2-m4-examples", "st,stm32mp157c-dk2", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "disabled"; ++}; ++ ++&dac { ++ status = "disabled"; ++}; ++ ++&dma2 { ++ status = "disabled"; ++}; ++ ++&dmamux1 { ++ dma-masters = <&dma1>; ++ dma-channels = <8>; ++}; ++ ++&m4_adc { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_dac { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_dma2 { ++ status = "okay"; ++}; ++ ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ ++&m4_hash2 { ++ status = "okay"; ++}; ++ ++&m4_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_i2c5_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_rng2 { ++ status = "okay"; ++}; ++ ++&m4_rproc { ++ m4_system_resources { ++ status = "okay"; ++ ++ button { ++ compatible = "rproc-srm-dev"; ++ interrupt-parent = <&gpioa>; ++ interrupts = <14 2>; ++ interrupt-names = "irq"; ++ status = "okay"; ++ }; ++ ++ m4_led: m4_led { ++ compatible = "rproc-srm-dev"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_leds_orange_pins>; ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&m4_spi4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_spi4_pins_a>; ++ status = "okay"; ++}; ++ ++ ++&m4_timers2 { ++ status = "okay"; ++}; ++ ++&m4_timers1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_pwm1_pins_a_ch1>; ++ status = "okay"; ++}; ++ ++&m4_uart7 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_uart7_pins_a>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ m4_leds_orange_pins: m4-leds-orange-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_pwm1_pins_a_ch1: m4-pwm1-0-ch1 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++}; ++ ++&timers1 { ++ status = "disabled"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts +index 045636555ddd..1c894f288c66 100644 +--- a/arch/arm/boot/dts/stm32mp157c-dk2.dts ++++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts +@@ -11,13 +11,13 @@ + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxac-pinctrl.dtsi" + #include "stm32mp15xx-dkx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + + aliases { +- ethernet0 = ðernet0; + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; +@@ -27,11 +27,19 @@ + chosen { + stdout-path = "serial0:115200n8"; + }; ++ ++ wifi_pwrseq: wifi-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpioh 4 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&cryp1 { ++ status = "okay"; + }; + + &dsi { + status = "okay"; +- phy-dsi-supply = <®18>; + + ports { + port@0 { +@@ -49,7 +57,7 @@ + }; + }; + +- panel@0 { ++ panel_otm8009a: panel-otm8009a@0 { + compatible = "orisetech,otm8009a"; + reg = <0>; + reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; +@@ -65,6 +73,18 @@ + }; + + &i2c1 { ++ touchscreen@2a { ++ compatible = "focaltech,ft6236"; ++ reg = <0x2a>; ++ interrupts = <2 2>; ++ interrupt-parent = <&gpiof>; ++ interrupt-controller; ++ touchscreen-size-x = <480>; ++ touchscreen-size-y = <800>; ++ panel = <&panel_otm8009a>; ++ vcc-supply = <&v3v3>; ++ status = "okay"; ++ }; + touchscreen@38 { + compatible = "focaltech,ft6236"; + reg = <0x38>; +@@ -73,6 +93,8 @@ + interrupt-controller; + touchscreen-size-x = <480>; + touchscreen-size-y = <800>; ++ panel = <&panel_otm8009a>; ++ vcc-supply = <&v3v3>; + status = "okay"; + }; + }; +@@ -88,10 +110,48 @@ + }; + }; + ++&rtc { ++ st,lsco = ; ++ pinctrl-0 = <&rtc_out2_rmp_pins_a>; ++ pinctrl-names = "default"; ++}; ++ ++/* Wifi */ ++&sdmmc2 { ++ arm,primecell-periphid = <0x10153180>; ++ pinctrl-names = "default", "opendrain", "sleep"; ++ pinctrl-0 = <&sdmmc2_b4_pins_a>; ++ pinctrl-1 = <&sdmmc2_b4_od_pins_a>; ++ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>; ++ non-removable; ++ st,neg-edge; ++ bus-width = <4>; ++ vmmc-supply = <&v3v3>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ brcmf: bcrmf@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; ++ ++/* Bluetooth */ + &usart2 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&usart2_pins_c>; + pinctrl-1 = <&usart2_sleep_pins_c>; + pinctrl-2 = <&usart2_idle_pins_c>; +- status = "disabled"; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ shutdown-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>; ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <3000000>; ++ vbat-supply = <&v3v3>; ++ vddio-supply = <&v3v3>; ++ }; + }; +diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts +index 2e77ccec3fc1..d2c24803b99e 100644 +--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts ++++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + /dts-v1/; + +@@ -9,8 +9,7 @@ + #include "stm32mp15xc.dtsi" + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxaa-pinctrl.dtsi" +-#include +-#include ++#include "stm32mp15xx-edx.dtsi" + + / { + model = "STMicroelectronics STM32MP157C eval daughter"; +@@ -20,373 +19,18 @@ + stdout-path = "serial0:115200n8"; + }; + +- memory@c0000000 { +- device_type = "memory"; +- reg = <0xC0000000 0x40000000>; +- }; +- + reserved-memory { +- #address-cells = <1>; +- #size-cells = <1>; +- ranges; +- +- mcuram2: mcuram2@10000000 { +- compatible = "shared-dma-pool"; +- reg = <0x10000000 0x40000>; +- no-map; +- }; +- +- vdev0vring0: vdev0vring0@10040000 { +- compatible = "shared-dma-pool"; +- reg = <0x10040000 0x1000>; +- no-map; +- }; +- +- vdev0vring1: vdev0vring1@10041000 { +- compatible = "shared-dma-pool"; +- reg = <0x10041000 0x1000>; +- no-map; +- }; +- +- vdev0buffer: vdev0buffer@10042000 { +- compatible = "shared-dma-pool"; +- reg = <0x10042000 0x4000>; ++ gpu_reserved: gpu@f6000000 { ++ reg = <0xf6000000 0x8000000>; + no-map; + }; +- +- mcuram: mcuram@30000000 { +- compatible = "shared-dma-pool"; +- reg = <0x30000000 0x40000>; +- no-map; +- }; +- +- retram: retram@38000000 { +- compatible = "shared-dma-pool"; +- reg = <0x38000000 0x10000>; +- no-map; +- }; +- +- gpu_reserved: gpu@e8000000 { +- reg = <0xe8000000 0x8000000>; +- no-map; +- }; +- }; +- +- aliases { +- serial0 = &uart4; +- }; +- +- sd_switch: regulator-sd_switch { +- compatible = "regulator-gpio"; +- regulator-name = "sd_switch"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <2900000>; +- regulator-type = "voltage"; +- regulator-always-on; +- +- gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; +- gpios-states = <0>; +- states = <1800000 0x1>, +- <2900000 0x0>; +- }; +- +- vin: vin { +- compatible = "regulator-fixed"; +- regulator-name = "vin"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- regulator-always-on; +- }; +-}; +- +-&adc { +- /* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */ +- pinctrl-0 = <&adc1_in6_pins_a>; +- pinctrl-names = "default"; +- vdd-supply = <&vdd>; +- vdda-supply = <&vdda>; +- vref-supply = <&vdda>; +- status = "disabled"; +- adc1: adc@0 { +- st,adc-channels = <0 1 6>; +- /* 16.5 ck_cycles sampling time */ +- st,min-sample-time-nsecs = <400>; +- status = "okay"; +- }; +-}; +- +-&dac { +- pinctrl-names = "default"; +- pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; +- vref-supply = <&vdda>; +- status = "disabled"; +- dac1: dac@1 { +- status = "okay"; +- }; +- dac2: dac@2 { +- status = "okay"; + }; + }; + +-&dts { ++&cryp1 { + status = "okay"; + }; + + &gpu { + contiguous-area = <&gpu_reserved>; + }; +- +-&i2c4 { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&i2c4_pins_a>; +- pinctrl-1 = <&i2c4_sleep_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- clock-frequency = <400000>; +- status = "okay"; +- /* spare dmas for other usage */ +- /delete-property/dmas; +- /delete-property/dma-names; +- +- pmic: stpmic@33 { +- compatible = "st,stpmic1"; +- reg = <0x33>; +- interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; +- interrupt-controller; +- #interrupt-cells = <2>; +- status = "okay"; +- +- regulators { +- compatible = "st,stpmic1-regulators"; +- buck1-supply = <&vin>; +- buck2-supply = <&vin>; +- buck3-supply = <&vin>; +- buck4-supply = <&vin>; +- ldo1-supply = <&v3v3>; +- ldo2-supply = <&v3v3>; +- ldo3-supply = <&vdd_ddr>; +- ldo4-supply = <&vin>; +- ldo5-supply = <&v3v3>; +- ldo6-supply = <&v3v3>; +- vref_ddr-supply = <&vin>; +- boost-supply = <&vin>; +- pwr_sw1-supply = <&bst_out>; +- pwr_sw2-supply = <&bst_out>; +- +- vddcore: buck1 { +- regulator-name = "vddcore"; +- regulator-min-microvolt = <1200000>; +- regulator-max-microvolt = <1350000>; +- regulator-always-on; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- vdd_ddr: buck2 { +- regulator-name = "vdd_ddr"; +- regulator-min-microvolt = <1350000>; +- regulator-max-microvolt = <1350000>; +- regulator-always-on; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- vdd: buck3 { +- regulator-name = "vdd"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- st,mask-reset; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- v3v3: buck4 { +- regulator-name = "v3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- regulator-over-current-protection; +- regulator-initial-mode = <0>; +- }; +- +- vdda: ldo1 { +- regulator-name = "vdda"; +- regulator-min-microvolt = <2900000>; +- regulator-max-microvolt = <2900000>; +- interrupts = ; +- }; +- +- v2v8: ldo2 { +- regulator-name = "v2v8"; +- regulator-min-microvolt = <2800000>; +- regulator-max-microvolt = <2800000>; +- interrupts = ; +- }; +- +- vtt_ddr: ldo3 { +- regulator-name = "vtt_ddr"; +- regulator-min-microvolt = <500000>; +- regulator-max-microvolt = <750000>; +- regulator-always-on; +- regulator-over-current-protection; +- }; +- +- vdd_usb: ldo4 { +- regulator-name = "vdd_usb"; +- interrupts = ; +- }; +- +- vdd_sd: ldo5 { +- regulator-name = "vdd_sd"; +- regulator-min-microvolt = <2900000>; +- regulator-max-microvolt = <2900000>; +- interrupts = ; +- regulator-boot-on; +- }; +- +- v1v8: ldo6 { +- regulator-name = "v1v8"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <1800000>; +- interrupts = ; +- }; +- +- vref_ddr: vref_ddr { +- regulator-name = "vref_ddr"; +- regulator-always-on; +- }; +- +- bst_out: boost { +- regulator-name = "bst_out"; +- interrupts = ; +- }; +- +- vbus_otg: pwr_sw1 { +- regulator-name = "vbus_otg"; +- interrupts = ; +- }; +- +- vbus_sw: pwr_sw2 { +- regulator-name = "vbus_sw"; +- interrupts = ; +- regulator-active-discharge = <1>; +- }; +- }; +- +- onkey { +- compatible = "st,stpmic1-onkey"; +- interrupts = , ; +- interrupt-names = "onkey-falling", "onkey-rising"; +- power-off-time-sec = <10>; +- status = "okay"; +- }; +- +- watchdog { +- compatible = "st,stpmic1-wdt"; +- status = "disabled"; +- }; +- }; +-}; +- +-&ipcc { +- status = "okay"; +-}; +- +-&iwdg2 { +- timeout-sec = <32>; +- status = "okay"; +-}; +- +-&m4_rproc { +- memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, +- <&vdev0vring1>, <&vdev0buffer>; +- mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; +- mbox-names = "vq0", "vq1", "shutdown"; +- interrupt-parent = <&exti>; +- interrupts = <68 1>; +- status = "okay"; +-}; +- +-&pwr_regulators { +- vdd-supply = <&vdd>; +- vdd_3v3_usbfs-supply = <&vdd_usb>; +-}; +- +-&rng1 { +- status = "okay"; +-}; +- +-&rtc { +- status = "okay"; +-}; +- +-&sdmmc1 { +- pinctrl-names = "default", "opendrain", "sleep"; +- pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; +- pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; +- pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; +- cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; +- disable-wp; +- st,sig-dir; +- st,neg-edge; +- st,use-ckin; +- bus-width = <4>; +- vmmc-supply = <&vdd_sd>; +- vqmmc-supply = <&sd_switch>; +- sd-uhs-sdr12; +- sd-uhs-sdr25; +- sd-uhs-sdr50; +- sd-uhs-ddr50; +- status = "okay"; +-}; +- +-&sdmmc2 { +- pinctrl-names = "default", "opendrain", "sleep"; +- pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; +- pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; +- pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; +- non-removable; +- no-sd; +- no-sdio; +- st,neg-edge; +- bus-width = <8>; +- vmmc-supply = <&v3v3>; +- vqmmc-supply = <&vdd>; +- mmc-ddr-3_3v; +- status = "okay"; +-}; +- +-&timers6 { +- status = "okay"; +- /* spare dmas for other usage */ +- /delete-property/dmas; +- /delete-property/dma-names; +- timer@5 { +- status = "okay"; +- }; +-}; +- +-&uart4 { +- pinctrl-names = "default", "sleep", "idle"; +- pinctrl-0 = <&uart4_pins_a>; +- pinctrl-1 = <&uart4_sleep_pins_a>; +- pinctrl-2 = <&uart4_idle_pins_a>; +- status = "okay"; +-}; +- +-&usbotg_hs { +- vbus-supply = <&vbus_otg>; +-}; +- +-&usbphyc_port0 { +- phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; +-}; +- +-&usbphyc_port1 { +- phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; +-}; +diff --git a/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts +new file mode 100644 +index 000000000000..8a4eda70d452 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157c-ev1.dts" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157C-EV1 configured to run Linux A7 examples"; ++ compatible = "st,stm32mp157c-ev1-a7-examples", "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; ++ ++ test_keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ autorepeat; ++ status = "okay"; ++ /* gpio needs vdd core in retention for wakeup */ ++ power-domains = <&pd_core_ret>; ++ ++ button@1 { ++ label = "PA13"; ++ linux,code = ; ++ interrupts-extended = <&gpioa 13 IRQ_TYPE_EDGE_FALLING>; ++ status = "okay"; ++ wakeup-source; ++ }; ++ }; ++}; ++ ++&adc { ++ status = "okay"; ++}; ++ ++&dac { ++ status = "okay"; ++}; ++ ++&timers2 { ++ status = "okay"; ++}; ++ ++&timers8 { ++ status = "okay"; ++}; ++ ++&timers12 { ++ status = "okay"; ++}; ++ ++&usart3 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts +new file mode 100644 +index 000000000000..b1bb38efbfa8 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts +@@ -0,0 +1,146 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157c-ev1.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157C-EV1 configured to run M4 examples"; ++ compatible = "st,stm32mp157c-ev1-m4-examples", "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "disabled"; ++}; ++ ++&dac { ++ status = "disabled"; ++}; ++ ++&dcmi { ++ status = "disabled"; ++}; ++ ++&dma2 { ++ status = "disabled"; ++}; ++ ++&dmamux1 { ++ dma-masters = <&dma1>; ++ dma-channels = <8>; ++}; ++ ++&fmc { ++ status = "disabled"; ++}; ++ ++&i2c5 { ++ status = "disabled"; ++}; ++ ++&m4_adc { ++ vref-supply = <&vdda>; ++ status = "okay"; ++}; ++ ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ ++&m4_dac { ++ vref-supply = <&vdda>; ++ status = "okay"; ++}; ++ ++&m4_dma2 { ++ status = "okay"; ++}; ++ ++&m4_hash2 { ++ status = "okay"; ++}; ++ ++&m4_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_i2c5_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_qspi { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_qspi_clk_pins_a &m4_qspi_bk1_pins_a ++ &m4_qspi_bk2_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_rproc { ++ m4_system_resources { ++ status = "okay"; ++ ++ /* button { ++ compatible = "rproc-srm-dev"; ++ interrupt-parent = <&gpioa>; ++ interrupts = <14 2>; ++ interrupt-names = "irq"; ++ status = "okay"; ++ };*/ ++ ++ m4_led: m4_led { ++ compatible = "rproc-srm-dev"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_leds_orange_pins>; ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&m4_rng2 { ++ status = "okay"; ++}; ++ ++&m4_spi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_spi1_pins_a>; ++ status = "okay"; ++}; ++ ++ ++&m4_timers2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_pwm2_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_usart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_usart3_pins_a>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ m4_leds_orange_pins: m4-leds-orange-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "disabled"; ++}; ++ ++&sai2b { ++ status = "disabled"; ++}; ++ ++&timers2 { ++ status = "disabled"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts +index a55e80ce2602..e84897ef4443 100644 +--- a/arch/arm/boot/dts/stm32mp157c-ev1.dts ++++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts +@@ -1,13 +1,12 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + /dts-v1/; + + #include "stm32mp157c-ed1.dts" +-#include +-#include ++#include "stm32mp15xx-evx.dtsi" + + / { + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; +@@ -20,89 +19,29 @@ + aliases { + serial0 = &uart4; + serial1 = &usart3; +- ethernet0 = ðernet0; + }; +- +- clocks { +- clk_ext_camera: clk-ext-camera { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <24000000>; +- }; +- }; +- +- joystick { +- compatible = "gpio-keys"; +- pinctrl-0 = <&joystick_pins>; +- pinctrl-names = "default"; +- button-0 { +- label = "JoySel"; +- linux,code = ; +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <0 IRQ_TYPE_EDGE_RISING>; +- }; +- button-1 { +- label = "JoyDown"; +- linux,code = ; +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <1 IRQ_TYPE_EDGE_RISING>; +- }; +- button-2 { +- label = "JoyLeft"; +- linux,code = ; +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <2 IRQ_TYPE_EDGE_RISING>; +- }; +- button-3 { +- label = "JoyRight"; +- linux,code = ; +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <3 IRQ_TYPE_EDGE_RISING>; +- }; +- button-4 { +- label = "JoyUp"; +- linux,code = ; +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <4 IRQ_TYPE_EDGE_RISING>; +- }; +- }; +- +- panel_backlight: panel-backlight { +- compatible = "gpio-backlight"; +- gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; +- default-on; +- status = "okay"; +- }; +-}; +- +-&cec { +- pinctrl-names = "default"; +- pinctrl-0 = <&cec_pins_a>; +- status = "okay"; + }; + +-&dcmi { ++<dc { + status = "okay"; +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&dcmi_pins_a>; +- pinctrl-1 = <&dcmi_sleep_pins_a>; + + port { +- dcmi_0: endpoint { +- remote-endpoint = <&ov5640_0>; +- bus-width = <8>; +- hsync-active = <0>; +- vsync-active = <0>; +- pclk-sample = <1>; ++ ltdc_ep0_out: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&dsi_in>; + }; + }; + }; + + &dsi { +- phy-dsi-supply = <®18>; ++ #address-cells = <1>; ++ #size-cells = <0>; + status = "okay"; + + ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ + port@0 { + reg = <0>; + dsi_in: endpoint { +@@ -118,7 +57,7 @@ + }; + }; + +- panel-dsi@0 { ++ panel_dsi: panel-dsi@0 { + compatible = "raydium,rm68200"; + reg = <0>; + reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; +@@ -134,243 +73,16 @@ + }; + }; + +-ðernet0 { +- status = "okay"; +- pinctrl-0 = <ðernet0_rgmii_pins_a>; +- pinctrl-1 = <ðernet0_rgmii_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- phy-mode = "rgmii-id"; +- max-speed = <1000>; +- phy-handle = <&phy0>; +- +- mdio0 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "snps,dwmac-mdio"; +- phy0: ethernet-phy@0 { +- reg = <0>; +- }; +- }; +-}; +- +-&fmc { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&fmc_pins_a>; +- pinctrl-1 = <&fmc_sleep_pins_a>; +- status = "okay"; +- +- nand-controller@4,0 { +- status = "okay"; +- +- nand@0 { +- reg = <0>; +- nand-on-flash-bbt; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +- }; +-}; +- + &i2c2 { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&i2c2_pins_a>; +- pinctrl-1 = <&i2c2_sleep_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- status = "okay"; +- +- ov5640: camera@3c { +- compatible = "ovti,ov5640"; +- reg = <0x3c>; +- clocks = <&clk_ext_camera>; +- clock-names = "xclk"; +- DOVDD-supply = <&v2v8>; +- powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; +- reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; +- rotation = <180>; +- status = "okay"; +- +- port { +- ov5640_0: endpoint { +- remote-endpoint = <&dcmi_0>; +- bus-width = <8>; +- data-shift = <2>; /* lines 9:2 are used */ +- hsync-active = <0>; +- vsync-active = <0>; +- pclk-sample = <1>; +- }; +- }; +- }; +- +- stmfx: stmfx@42 { +- compatible = "st,stmfx-0300"; +- reg = <0x42>; +- interrupts = <8 IRQ_TYPE_EDGE_RISING>; +- interrupt-parent = <&gpioi>; +- vdd-supply = <&v3v3>; +- +- stmfx_pinctrl: pinctrl { +- compatible = "st,stmfx-0300-pinctrl"; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- gpio-ranges = <&stmfx_pinctrl 0 0 24>; +- +- joystick_pins: joystick-pins { +- pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; +- bias-pull-down; +- }; +- }; +- }; +-}; +- +-&i2c5 { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&i2c5_pins_a>; +- pinctrl-1 = <&i2c5_sleep_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- status = "okay"; +-}; +- +-<dc { +- status = "okay"; +- +- port { +- ltdc_ep0_out: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&dsi_in>; +- }; +- }; +-}; +- +-&m_can1 { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&m_can1_pins_a>; +- pinctrl-1 = <&m_can1_sleep_pins_a>; +- status = "okay"; +-}; +- +-&qspi { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; +- pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; +- reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- +- flash0: mx66l51235l@0 { +- compatible = "jedec,spi-nor"; +- reg = <0>; +- spi-rx-bus-width = <4>; +- spi-max-frequency = <108000000>; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +- +- flash1: mx66l51235l@1 { +- compatible = "jedec,spi-nor"; +- reg = <1>; +- spi-rx-bus-width = <4>; +- spi-max-frequency = <108000000>; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +-}; +- +-&sdmmc3 { +- pinctrl-names = "default", "opendrain", "sleep"; +- pinctrl-0 = <&sdmmc3_b4_pins_a>; +- pinctrl-1 = <&sdmmc3_b4_od_pins_a>; +- pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; +- broken-cd; +- st,neg-edge; +- bus-width = <4>; +- vmmc-supply = <&v3v3>; +- status = "disabled"; +-}; +- +-&spi1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi1_pins_a>; +- status = "disabled"; +-}; +- +-&timers2 { +- /* spare dmas for other usage (un-delete to enable pwm capture) */ +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm2_pins_a>; +- pinctrl-1 = <&pwm2_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@1 { ++ gt9147: goodix_ts@5d { ++ compatible = "goodix,gt9147"; ++ reg = <0x5d>; ++ panel = <&panel_dsi>; ++ pinctrl-0 = <&goodix_pins>; ++ pinctrl-names = "default"; + status = "okay"; +- }; +-}; + +-&timers8 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm8_pins_a>; +- pinctrl-1 = <&pwm8_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@7 { +- status = "okay"; ++ interrupts = <14 IRQ_TYPE_EDGE_RISING>; ++ interrupt-parent = <&stmfx_pinctrl>; + }; + }; +- +-&timers12 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm12_pins_a>; +- pinctrl-1 = <&pwm12_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@11 { +- status = "okay"; +- }; +-}; +- +-&usart3 { +- pinctrl-names = "default", "sleep", "idle"; +- pinctrl-0 = <&usart3_pins_b>; +- pinctrl-1 = <&usart3_sleep_pins_b>; +- pinctrl-2 = <&usart3_idle_pins_b>; +- /* +- * HW flow control USART3_RTS is optional, and isn't default wired to +- * the connector. SB23 needs to be soldered in order to use it, and R77 +- * (ETH_CLK) should be removed. +- */ +- uart-has-rtscts; +- status = "disabled"; +-}; +- +-&usbh_ehci { +- phys = <&usbphyc_port0>; +- status = "okay"; +-}; +- +-&usbotg_hs { +- pinctrl-0 = <&usbotg_hs_pins_a>; +- pinctrl-names = "default"; +- phys = <&usbphyc_port1 0>; +- phy-names = "usb2-phy"; +- status = "okay"; +-}; +- +-&usbphyc { +- status = "okay"; +-}; +diff --git a/arch/arm/boot/dts/stm32mp157d-dk1.dts b/arch/arm/boot/dts/stm32mp157d-dk1.dts +new file mode 100644 +index 000000000000..bcc012cfff7c +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157d-dk1.dts +@@ -0,0 +1,28 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xd.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157D-DK1 Discovery Board"; ++ compatible = "st,stm32mp157d-dk1", "st,stm32mp157"; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157d-ed1.dts b/arch/arm/boot/dts/stm32mp157d-ed1.dts +new file mode 100644 +index 000000000000..5aa383d3b585 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157d-ed1.dts +@@ -0,0 +1,33 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xd.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157D eval daughter"; ++ compatible = "st,stm32mp157d-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ reserved-memory { ++ gpu_reserved: gpu@f6000000 { ++ reg = <0xf6000000 0x8000000>; ++ no-map; ++ }; ++ }; ++}; ++ ++&gpu { ++ contiguous-area = <&gpu_reserved>; ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157d-ev1.dts b/arch/arm/boot/dts/stm32mp157d-ev1.dts +new file mode 100644 +index 000000000000..5cb08c707990 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157d-ev1.dts +@@ -0,0 +1,88 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157d-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157D eval daughter on eval mother"; ++ compatible = "st,stm32mp157d-ev1", "st,stm32mp157d-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ }; ++}; ++ ++<dc { ++ status = "okay"; ++ ++ port { ++ ltdc_ep0_out: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&dsi_in>; ++ }; ++ }; ++}; ++ ++&dsi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ dsi_in: endpoint { ++ remote-endpoint = <<dc_ep0_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ dsi_out: endpoint { ++ remote-endpoint = <&dsi_panel_in>; ++ }; ++ }; ++ }; ++ ++ panel_dsi: panel-dsi@0 { ++ compatible = "raydium,rm68200"; ++ reg = <0>; ++ reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; ++ backlight = <&panel_backlight>; ++ power-supply = <&v3v3>; ++ status = "okay"; ++ ++ port { ++ dsi_panel_in: endpoint { ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c2 { ++ gt9147: goodix_ts@5d { ++ compatible = "goodix,gt9147"; ++ reg = <0x5d>; ++ panel = <&panel_dsi>; ++ pinctrl-0 = <&goodix_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ interrupts = <14 IRQ_TYPE_EDGE_RISING>; ++ interrupt-parent = <&stmfx_pinctrl>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts b/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts +new file mode 100644 +index 000000000000..8dcb52fedb22 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts +@@ -0,0 +1,60 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157f-dk2.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157F-DK2 configured to run Linux A7 examples"; ++ compatible = "st,stm32mp157f-dk2-a7-examples", "st,stm32mp157f-dk2", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "okay"; ++ ++ adc2: adc@100 { ++ /* Set IRQ mode as example. DMA is the preferred mode, yet. */ ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ }; ++}; ++ ++&i2c5 { ++ status = "okay"; ++}; ++ ++&timers1 { ++ status = "okay"; ++}; ++ ++&timers3 { ++ status = "okay"; ++}; ++ ++&timers4 { ++ status = "okay"; ++}; ++ ++&timers5 { ++ status = "okay"; ++}; ++ ++&timers6 { ++ status = "okay"; ++}; ++ ++&timers12 { ++ status = "okay"; ++}; ++ ++&uart7 { ++ status = "okay"; ++}; ++ ++&usart3 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts b/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts +new file mode 100644 +index 000000000000..72652299743b +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts +@@ -0,0 +1,129 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157f-dk2.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157F-DK2 configured to run M4 examples"; ++ compatible = "st,stm32mp157f-dk2-m4-examples", "st,stm32mp157f-dk2", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "disabled"; ++}; ++ ++&dac { ++ status = "disabled"; ++}; ++ ++&dma2 { ++ status = "disabled"; ++}; ++ ++&dmamux1 { ++ dma-masters = <&dma1>; ++ dma-channels = <8>; ++}; ++ ++&m4_adc { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_dac { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_dma2 { ++ status = "okay"; ++}; ++ ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ ++&m4_hash2 { ++ status = "okay"; ++}; ++ ++&m4_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_i2c5_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_rng2 { ++ status = "okay"; ++}; ++ ++&m4_rproc { ++ m4_system_resources { ++ status = "okay"; ++ ++ button { ++ compatible = "rproc-srm-dev"; ++ interrupt-parent = <&gpioa>; ++ interrupts = <14 2>; ++ interrupt-names = "irq"; ++ status = "okay"; ++ }; ++ ++ m4_led: m4_led { ++ compatible = "rproc-srm-dev"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_leds_orange_pins>; ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&m4_spi4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_spi4_pins_a>; ++ status = "okay"; ++}; ++ ++ ++&m4_timers2 { ++ status = "okay"; ++}; ++ ++&m4_timers1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_pwm1_pins_a_ch1>; ++ status = "okay"; ++}; ++ ++&m4_uart7 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_uart7_pins_a>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ m4_leds_orange_pins: m4-leds-orange-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_pwm1_pins_a_ch1: m4-pwm1-0-ch1 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++}; ++ ++&timers1 { ++ status = "disabled"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157f-dk2.dts b/arch/arm/boot/dts/stm32mp157f-dk2.dts +new file mode 100644 +index 000000000000..15a397c4cf5d +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157f-dk2.dts +@@ -0,0 +1,157 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xf.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157F-DK2 Discovery Board"; ++ compatible = "st,stm32mp157f-dk2", "st,stm32mp157"; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; ++ serial3 = &usart2; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ wifi_pwrseq: wifi-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpioh 4 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++&dsi { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ reg = <0>; ++ dsi_in: endpoint { ++ remote-endpoint = <<dc_ep1_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ dsi_out: endpoint { ++ remote-endpoint = <&panel_in>; ++ }; ++ }; ++ }; ++ ++ panel_otm8009a: panel-otm8009a@0 { ++ compatible = "orisetech,otm8009a"; ++ reg = <0>; ++ reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; ++ power-supply = <&v3v3>; ++ status = "okay"; ++ ++ port { ++ panel_in: endpoint { ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ touchscreen@2a { ++ compatible = "focaltech,ft6236"; ++ reg = <0x2a>; ++ interrupts = <2 2>; ++ interrupt-parent = <&gpiof>; ++ interrupt-controller; ++ touchscreen-size-x = <480>; ++ touchscreen-size-y = <800>; ++ panel = <&panel_otm8009a>; ++ vcc-supply = <&v3v3>; ++ status = "okay"; ++ }; ++ touchscreen@38 { ++ compatible = "focaltech,ft6236"; ++ reg = <0x38>; ++ interrupts = <2 2>; ++ interrupt-parent = <&gpiof>; ++ interrupt-controller; ++ touchscreen-size-x = <480>; ++ touchscreen-size-y = <800>; ++ panel = <&panel_otm8009a>; ++ vcc-supply = <&v3v3>; ++ status = "okay"; ++ }; ++}; ++ ++<dc { ++ status = "okay"; ++ ++ port { ++ ltdc_ep1_out: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&dsi_in>; ++ }; ++ }; ++}; ++ ++&rtc { ++ st,lsco = ; ++ pinctrl-0 = <&rtc_out2_rmp_pins_a>; ++ pinctrl-names = "default"; ++}; ++ ++/* Wifi */ ++&sdmmc2 { ++ arm,primecell-periphid = <0x10153180>; ++ pinctrl-names = "default", "opendrain", "sleep"; ++ pinctrl-0 = <&sdmmc2_b4_pins_a>; ++ pinctrl-1 = <&sdmmc2_b4_od_pins_a>; ++ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>; ++ non-removable; ++ st,neg-edge; ++ bus-width = <4>; ++ vmmc-supply = <&v3v3>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ brcmf: bcrmf@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; ++ ++/* Bluetooth */ ++&usart2 { ++ pinctrl-names = "default", "sleep", "idle"; ++ pinctrl-0 = <&usart2_pins_c>; ++ pinctrl-1 = <&usart2_sleep_pins_c>; ++ pinctrl-2 = <&usart2_idle_pins_c>; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ shutdown-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>; ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <3000000>; ++ vbat-supply = <&v3v3>; ++ vddio-supply = <&v3v3>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157f-ed1.dts b/arch/arm/boot/dts/stm32mp157f-ed1.dts +new file mode 100644 +index 000000000000..29c6833e2896 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157f-ed1.dts +@@ -0,0 +1,37 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xf.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157F eval daughter"; ++ compatible = "st,stm32mp157f-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ reserved-memory { ++ gpu_reserved: gpu@f6000000 { ++ reg = <0xf6000000 0x8000000>; ++ no-map; ++ }; ++ }; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++&gpu { ++ contiguous-area = <&gpu_reserved>; ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts +new file mode 100644 +index 000000000000..3d51e48d14fe +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157f-ev1.dts" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157F-EV1 configured to run Linux A7 examples"; ++ compatible = "st,stm32mp157f-ev1-a7-examples", "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; ++ ++ test_keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ autorepeat; ++ status = "okay"; ++ /* gpio needs vdd core in retention for wakeup */ ++ power-domains = <&pd_core_ret>; ++ ++ button@1 { ++ label = "PA13"; ++ linux,code = ; ++ interrupts-extended = <&gpioa 13 IRQ_TYPE_EDGE_FALLING>; ++ status = "okay"; ++ wakeup-source; ++ }; ++ }; ++}; ++ ++&adc { ++ status = "okay"; ++}; ++ ++&dac { ++ status = "okay"; ++}; ++ ++&timers2 { ++ status = "okay"; ++}; ++ ++&timers8 { ++ status = "okay"; ++}; ++ ++&timers12 { ++ status = "okay"; ++}; ++ ++&usart3 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts +new file mode 100644 +index 000000000000..d508be27666a +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts +@@ -0,0 +1,146 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157f-ev1.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157F-EV1 configured to run M4 examples"; ++ compatible = "st,stm32mp157f-ev1-m4-examples", "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "disabled"; ++}; ++ ++&dac { ++ status = "disabled"; ++}; ++ ++&dcmi { ++ status = "disabled"; ++}; ++ ++&dma2 { ++ status = "disabled"; ++}; ++ ++&dmamux1 { ++ dma-masters = <&dma1>; ++ dma-channels = <8>; ++}; ++ ++&fmc { ++ status = "disabled"; ++}; ++ ++&i2c5 { ++ status = "disabled"; ++}; ++ ++&m4_adc { ++ vref-supply = <&vdda>; ++ status = "okay"; ++}; ++ ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ ++&m4_dac { ++ vref-supply = <&vdda>; ++ status = "okay"; ++}; ++ ++&m4_dma2 { ++ status = "okay"; ++}; ++ ++&m4_hash2 { ++ status = "okay"; ++}; ++ ++&m4_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_i2c5_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_qspi { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_qspi_clk_pins_a &m4_qspi_bk1_pins_a ++ &m4_qspi_bk2_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_rproc { ++ m4_system_resources { ++ status = "okay"; ++ ++ /* button { ++ compatible = "rproc-srm-dev"; ++ interrupt-parent = <&gpioa>; ++ interrupts = <14 2>; ++ interrupt-names = "irq"; ++ status = "okay"; ++ };*/ ++ ++ m4_led: m4_led { ++ compatible = "rproc-srm-dev"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_leds_orange_pins>; ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&m4_rng2 { ++ status = "okay"; ++}; ++ ++&m4_spi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_spi1_pins_a>; ++ status = "okay"; ++}; ++ ++ ++&m4_timers2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_pwm2_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_usart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_usart3_pins_a>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ m4_leds_orange_pins: m4-leds-orange-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++}; ++ ++&qspi { ++ status = "disabled"; ++}; ++ ++&sai2b { ++ status = "disabled"; ++}; ++ ++&timers2 { ++ status = "disabled"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157f-ev1.dts b/arch/arm/boot/dts/stm32mp157f-ev1.dts +new file mode 100644 +index 000000000000..6fe600f81388 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157f-ev1.dts +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157f-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157F eval daughter on eval mother"; ++ compatible = "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ }; ++}; ++ ++<dc { ++ status = "okay"; ++ ++ port { ++ ltdc_ep0_out: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&dsi_in>; ++ }; ++ }; ++}; ++ ++&dsi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ dsi_in: endpoint { ++ remote-endpoint = <<dc_ep0_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ dsi_out: endpoint { ++ remote-endpoint = <&dsi_panel_in>; ++ }; ++ }; ++ }; ++ ++ panel_dsi: panel-dsi@0 { ++ compatible = "raydium,rm68200"; ++ reg = <0>; ++ reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; ++ backlight = <&panel_backlight>; ++ power-supply = <&v3v3>; ++ status = "okay"; ++ ++ port { ++ dsi_panel_in: endpoint { ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c2 { ++ gt9147: goodix_ts@5d { ++ compatible = "goodix,gt9147"; ++ reg = <0x5d>; ++ panel = <&panel_dsi>; ++ pinctrl-0 = <&goodix_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ interrupts = <14 IRQ_TYPE_EDGE_RISING>; ++ interrupt-parent = <&stmfx_pinctrl>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp15xa.dtsi b/arch/arm/boot/dts/stm32mp15xa.dtsi +new file mode 100644 +index 000000000000..5ed7e594f4cd +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15xa.dtsi +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++&cpu0_opp_table { ++ opp-650000000 { ++ opp-hz = /bits/ 64 <650000000>; ++ opp-microvolt = <1200000>; ++ opp-supported-hw = <0x1>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp15xc.dtsi b/arch/arm/boot/dts/stm32mp15xc.dtsi +index b06a55a2fa18..adc1568a7285 100644 +--- a/arch/arm/boot/dts/stm32mp15xc.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xc.dtsi +@@ -4,14 +4,16 @@ + * Author: Alexandre Torgue for STMicroelectronics. + */ + ++#include "stm32mp15xa.dtsi" ++ + / { + soc { + cryp1: cryp@54001000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54001000 0x400>; + interrupts = ; +- clocks = <&rcc CRYP1>; +- resets = <&rcc CRYP1_R>; ++ clocks = <&scmi0_clk CK_SCMI0_CRYP1>; ++ resets = <&scmi0_reset RST_SCMI0_CRYP1>; + status = "disabled"; + }; + }; +diff --git a/arch/arm/boot/dts/stm32mp15xd.dtsi b/arch/arm/boot/dts/stm32mp15xd.dtsi +new file mode 100644 +index 000000000000..e2f8b1297c33 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15xd.dtsi +@@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++&cpu0_opp_table { ++ opp-800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1350000>; ++ opp-supported-hw = <0x2>; ++ }; ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <1200000>; ++ opp-supported-hw = <0x2>; ++ opp-suspend; ++ }; ++}; ++ ++&cpu_thermal { ++ trips { ++ cpu-crit { ++ temperature = <105000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ ++ cpu_alert: cpu-alert { ++ temperature = <95000>; ++ hysteresis = <10000>; ++ type = "passive"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_alert>; ++ cooling-device = <&cpu0 1 1>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp15xf.dtsi b/arch/arm/boot/dts/stm32mp15xf.dtsi +new file mode 100644 +index 000000000000..77f50b9bda64 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15xf.dtsi +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp15xd.dtsi" ++ ++/ { ++ soc { ++ cryp1: cryp@54001000 { ++ compatible = "st,stm32mp1-cryp"; ++ reg = <0x54001000 0x400>; ++ interrupts = ; ++ clocks = <&scmi0_clk CK_SCMI0_CRYP1>; ++ resets = <&scmi0_reset RST_SCMI0_CRYP1>; ++ status = "disabled"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +index 93398cfae97e..acff8755d308 100644 +--- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +@@ -4,10 +4,16 @@ + * Author: Alexandre Torgue for STMicroelectronics. + */ + ++#include "stm32mp15-m4-srm.dtsi" ++#include "stm32mp15-m4-srm-pinctrl.dtsi" + #include + #include + + / { ++ aliases { ++ ethernet0 = ðernet0; ++ }; ++ + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; +@@ -72,7 +78,7 @@ + + sound { + compatible = "audio-graph-card"; +- label = "STM32MP1-DK"; ++ label = "STM32MP15-DK"; + routing = + "Playback" , "MCLK", + "Capture" , "MCLK", +@@ -81,6 +87,17 @@ + status = "okay"; + }; + ++ usb_phy_tuning: usb-phy-tuning { ++ st,hs-dc-level = <2>; ++ st,fs-rftime-tuning; ++ st,hs-rftime-reduction; ++ st,hs-current-trim = <15>; ++ st,hs-impedance-trim = <1>; ++ st,squelch-level = <3>; ++ st,hs-rx-offset = <2>; ++ st,no-lsfs-sc; ++ }; ++ + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; +@@ -124,6 +141,26 @@ + status = "okay"; + }; + ++&cpu0{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&cpu1{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&crc1 { ++ status = "okay"; ++}; ++ ++&dma1 { ++ sram = <&dma_pool>; ++}; ++ ++&dma2 { ++ sram = <&dma_pool>; ++}; ++ + &dts { + status = "okay"; + }; +@@ -136,6 +173,8 @@ + phy-mode = "rgmii-id"; + max-speed = <1000>; + phy-handle = <&phy0>; ++ nvmem-cells = <ðernet_mac_address>; ++ nvmem-cell-names = "mac-address"; + + mdio0 { + #address-cells = <1>; +@@ -151,6 +190,10 @@ + contiguous-area = <&gpu_reserved>; + }; + ++&hash1 { ++ status = "okay"; ++}; ++ + &i2c1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c1_pins_a>; +@@ -238,10 +281,34 @@ + /delete-property/dmas; + /delete-property/dma-names; + ++ stusb1600@28 { ++ compatible = "st,stusb1600"; ++ reg = <0x28>; ++ interrupts = <11 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-parent = <&gpioi>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&stusb1600_pins_a>; ++ status = "okay"; ++ vdd-supply = <&vin>; ++ ++ connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ power-role = "dual"; ++ typec-power-opmode = "default"; ++ ++ port { ++ con_usbotg_hs_ep: endpoint { ++ remote-endpoint = <&usbotg_hs_ep>; ++ }; ++ }; ++ }; ++ }; ++ + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; +- interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; ++ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; +@@ -348,23 +415,24 @@ + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; ++ regulator-over-current-protection; + }; + +- bst_out: boost { ++ bst_out: boost { + regulator-name = "bst_out"; + interrupts = ; +- }; ++ }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = ; +- }; ++ }; + +- vbus_sw: pwr_sw2 { ++ vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = ; + regulator-active-discharge = <1>; +- }; ++ }; + }; + + onkey { +@@ -442,6 +510,7 @@ + mbox-names = "vq0", "vq1", "shutdown"; + interrupt-parent = <&exti>; + interrupts = <68 1>; ++ wakeup-source; + status = "okay"; + }; + +@@ -469,8 +538,6 @@ + sai2a: audio-controller@4400b004 { + #clock-cells = <0>; + dma-names = "tx"; +- clocks = <&rcc SAI2_K>; +- clock-names = "sai_ck"; + status = "okay"; + + sai2a_port: port { +@@ -528,6 +595,27 @@ + status = "disabled"; + }; + ++&spi4 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&spi4_pins_b>; ++ pinctrl-1 = <&spi4_sleep_pins_b>; ++ status = "disabled"; ++}; ++ ++&spi5 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&spi5_pins_a>; ++ pinctrl-1 = <&spi5_sleep_pins_a>; ++ status = "disabled"; ++}; ++ ++&sram { ++ dma_pool: dma_pool@0 { ++ reg = <0x50000 0x10000>; ++ pool; ++ }; ++}; ++ + &timers1 { + /* spare dmas for other usage */ + /delete-property/dmas; +@@ -618,6 +706,8 @@ + pinctrl-0 = <&uart4_pins_a>; + pinctrl-1 = <&uart4_sleep_pins_a>; + pinctrl-2 = <&uart4_idle_pins_a>; ++ /delete-property/dmas; ++ /delete-property/dma-names; + status = "okay"; + }; + +@@ -626,6 +716,8 @@ + pinctrl-0 = <&uart7_pins_c>; + pinctrl-1 = <&uart7_sleep_pins_c>; + pinctrl-2 = <&uart7_idle_pins_c>; ++ /delete-property/dmas; ++ /delete-property/dma-names; + status = "disabled"; + }; + +@@ -648,6 +740,12 @@ + phy-names = "usb2-phy"; + usb-role-switch; + status = "okay"; ++ ++ port { ++ usbotg_hs_ep: endpoint { ++ remote-endpoint = <&con_usbotg_hs_ep>; ++ }; ++ }; + }; + + &usbphyc { +@@ -656,14 +754,12 @@ + + &usbphyc_port0 { + phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; ++ st,phy-tuning = <&usb_phy_tuning>; + }; + + &usbphyc_port1 { + phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; ++ st,phy-tuning = <&usb_phy_tuning>; + }; + + &vrefbuf { +diff --git a/arch/arm/boot/dts/stm32mp15xx-edx.dtsi b/arch/arm/boot/dts/stm32mp15xx-edx.dtsi +new file mode 100644 +index 000000000000..3662f449de23 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15xx-edx.dtsi +@@ -0,0 +1,413 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. ++ */ ++ ++#include "stm32mp15-m4-srm.dtsi" ++#include "stm32mp15-m4-srm-pinctrl.dtsi" ++#include ++#include ++ ++/ { ++ memory@c0000000 { ++ device_type = "memory"; ++ reg = <0xC0000000 0x40000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ mcuram2: mcuram2@10000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x10000000 0x40000>; ++ no-map; ++ }; ++ ++ vdev0vring0: vdev0vring0@10040000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x10040000 0x1000>; ++ no-map; ++ }; ++ ++ vdev0vring1: vdev0vring1@10041000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x10041000 0x1000>; ++ no-map; ++ }; ++ ++ vdev0buffer: vdev0buffer@10042000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x10042000 0x4000>; ++ no-map; ++ }; ++ ++ mcuram: mcuram@30000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x30000000 0x40000>; ++ no-map; ++ }; ++ ++ retram: retram@38000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x38000000 0x10000>; ++ no-map; ++ }; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ }; ++ ++ led { ++ compatible = "gpio-leds"; ++ led-blue { ++ label = "heartbeat"; ++ gpios = <&gpiod 9 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "off"; ++ }; ++ }; ++ ++ sd_switch: regulator-sd_switch { ++ compatible = "regulator-gpio"; ++ regulator-name = "sd_switch"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <2900000>; ++ regulator-type = "voltage"; ++ regulator-always-on; ++ ++ gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; ++ gpios-states = <0>; ++ states = <1800000 0x1>, ++ <2900000 0x0>; ++ }; ++ ++ vin: vin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vin"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++}; ++ ++&adc { ++ /* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */ ++ pinctrl-0 = <&adc1_in6_pins_a>; ++ pinctrl-names = "default"; ++ vdd-supply = <&vdd>; ++ vdda-supply = <&vdda>; ++ vref-supply = <&vdda>; ++ status = "disabled"; ++ adc1: adc@0 { ++ st,adc-channels = <0 1 6>; ++ /* 16.5 ck_cycles sampling time */ ++ st,min-sample-time-nsecs = <400>; ++ status = "okay"; ++ }; ++}; ++ ++&cpu0{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&cpu1{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&crc1 { ++ status = "okay"; ++}; ++ ++&dac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; ++ vref-supply = <&vdda>; ++ status = "disabled"; ++ dac1: dac@1 { ++ status = "okay"; ++ }; ++ dac2: dac@2 { ++ status = "okay"; ++ }; ++}; ++ ++&dma1 { ++ sram = <&dma_pool>; ++}; ++ ++&dma2 { ++ sram = <&dma_pool>; ++}; ++ ++&dts { ++ status = "okay"; ++}; ++ ++&hash1 { ++ status = "okay"; ++}; ++ ++&i2c4 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&i2c4_pins_a>; ++ pinctrl-1 = <&i2c4_sleep_pins_a>; ++ i2c-scl-rising-time-ns = <185>; ++ i2c-scl-falling-time-ns = <20>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ /* spare dmas for other usage */ ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ ++ pmic: stpmic@33 { ++ compatible = "st,stpmic1"; ++ reg = <0x33>; ++ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ status = "okay"; ++ regulators { ++ compatible = "st,stpmic1-regulators"; ++ buck1-supply = <&vin>; ++ buck2-supply = <&vin>; ++ buck3-supply = <&vin>; ++ buck4-supply = <&vin>; ++ ldo1-supply = <&v3v3>; ++ ldo2-supply = <&v3v3>; ++ ldo3-supply = <&vdd_ddr>; ++ ldo4-supply = <&vin>; ++ ldo5-supply = <&v3v3>; ++ ldo6-supply = <&v3v3>; ++ vref_ddr-supply = <&vin>; ++ boost-supply = <&vin>; ++ pwr_sw1-supply = <&bst_out>; ++ pwr_sw2-supply = <&bst_out>; ++ ++ vddcore: buck1 { ++ regulator-name = "vddcore"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-always-on; ++ regulator-initial-mode = <0>; ++ regulator-over-current-protection; ++ }; ++ ++ vdd_ddr: buck2 { ++ regulator-name = "vdd_ddr"; ++ regulator-min-microvolt = <1350000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-always-on; ++ regulator-initial-mode = <0>; ++ regulator-over-current-protection; ++ }; ++ ++ vdd: buck3 { ++ regulator-name = "vdd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ st,mask-reset; ++ regulator-initial-mode = <0>; ++ regulator-over-current-protection; ++ }; ++ ++ v3v3: buck4 { ++ regulator-name = "v3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ regulator-initial-mode = <0>; ++ }; ++ ++ vdda: ldo1 { ++ regulator-name = "vdda"; ++ regulator-min-microvolt = <2900000>; ++ regulator-max-microvolt = <2900000>; ++ interrupts = ; ++ }; ++ ++ v2v8: ldo2 { ++ regulator-name = "v2v8"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ interrupts = ; ++ }; ++ ++ vtt_ddr: ldo3 { ++ regulator-name = "vtt_ddr"; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <750000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ vdd_usb: ldo4 { ++ regulator-name = "vdd_usb"; ++ interrupts = ; ++ }; ++ ++ vdd_sd: ldo5 { ++ regulator-name = "vdd_sd"; ++ regulator-min-microvolt = <2900000>; ++ regulator-max-microvolt = <2900000>; ++ interrupts = ; ++ regulator-boot-on; ++ }; ++ ++ v1v8: ldo6 { ++ regulator-name = "v1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ interrupts = ; ++ }; ++ ++ vref_ddr: vref_ddr { ++ regulator-name = "vref_ddr"; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ bst_out: boost { ++ regulator-name = "bst_out"; ++ interrupts = ; ++ }; ++ ++ vbus_otg: pwr_sw1 { ++ regulator-name = "vbus_otg"; ++ interrupts = ; ++ }; ++ ++ vbus_sw: pwr_sw2 { ++ regulator-name = "vbus_sw"; ++ interrupts = ; ++ regulator-active-discharge = <1>; ++ }; ++ }; ++ ++ onkey { ++ compatible = "st,stpmic1-onkey"; ++ interrupts = , ; ++ interrupt-names = "onkey-falling", "onkey-rising"; ++ power-off-time-sec = <10>; ++ status = "okay"; ++ }; ++ ++ watchdog { ++ compatible = "st,stpmic1-wdt"; ++ status = "disabled"; ++ }; ++ }; ++}; ++ ++&ipcc { ++ status = "okay"; ++}; ++ ++&iwdg2 { ++ timeout-sec = <32>; ++ status = "okay"; ++}; ++ ++&m4_rproc { ++ memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, ++ <&vdev0vring1>, <&vdev0buffer>; ++ mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; ++ mbox-names = "vq0", "vq1", "shutdown"; ++ interrupt-parent = <&exti>; ++ interrupts = <68 1>; ++ wakeup-source; ++ status = "okay"; ++}; ++ ++&pwr_regulators { ++ vdd-supply = <&vdd>; ++ vdd_3v3_usbfs-supply = <&vdd_usb>; ++}; ++ ++&rng1 { ++ status = "okay"; ++}; ++ ++&rtc { ++ status = "okay"; ++}; ++ ++&sdmmc1 { ++ pinctrl-names = "default", "opendrain", "sleep"; ++ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; ++ pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; ++ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; ++ cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; ++ disable-wp; ++ st,sig-dir; ++ st,neg-edge; ++ st,use-ckin; ++ bus-width = <4>; ++ vmmc-supply = <&vdd_sd>; ++ vqmmc-supply = <&sd_switch>; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-ddr50; ++ status = "okay"; ++}; ++ ++&sdmmc2 { ++ pinctrl-names = "default", "opendrain", "sleep"; ++ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; ++ pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; ++ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; ++ non-removable; ++ no-sd; ++ no-sdio; ++ st,neg-edge; ++ bus-width = <8>; ++ vmmc-supply = <&v3v3>; ++ vqmmc-supply = <&vdd>; ++ mmc-ddr-3_3v; ++ status = "okay"; ++}; ++ ++&sram { ++ dma_pool: dma_pool@0 { ++ reg = <0x50000 0x10000>; ++ pool; ++ }; ++}; ++ ++&timers6 { ++ status = "okay"; ++ /* spare dmas for other usage */ ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ timer@5 { ++ status = "okay"; ++ }; ++}; ++ ++&uart4 { ++ pinctrl-names = "default", "sleep", "idle"; ++ pinctrl-0 = <&uart4_pins_a>; ++ pinctrl-1 = <&uart4_sleep_pins_a>; ++ pinctrl-2 = <&uart4_idle_pins_a>; ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ status = "okay"; ++}; ++ ++&usbotg_hs { ++ vbus-supply = <&vbus_otg>; ++}; ++ ++&usbphyc_port0 { ++ phy-supply = <&vdd_usb>; ++}; ++ ++&usbphyc_port1 { ++ phy-supply = <&vdd_usb>; ++}; +diff --git a/arch/arm/boot/dts/stm32mp15xx-evx.dtsi b/arch/arm/boot/dts/stm32mp15xx-evx.dtsi +new file mode 100644 +index 000000000000..47a2c8e5ead7 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp15xx-evx.dtsi +@@ -0,0 +1,686 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. ++ */ ++ ++#include ++#include ++ ++/ { ++ aliases { ++ ethernet0 = ðernet0; ++ }; ++ ++ clocks { ++ clk_ext_camera: clk-ext-camera { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ }; ++ }; ++ ++ joystick { ++ compatible = "gpio-keys"; ++ #size-cells = <0>; ++ pinctrl-0 = <&joystick_pins>; ++ pinctrl-names = "default"; ++ button-0 { ++ label = "JoySel"; ++ linux,code = ; ++ interrupt-parent = <&stmfx_pinctrl>; ++ interrupts = <0 IRQ_TYPE_EDGE_RISING>; ++ }; ++ button-1 { ++ label = "JoyDown"; ++ linux,code = ; ++ interrupt-parent = <&stmfx_pinctrl>; ++ interrupts = <1 IRQ_TYPE_EDGE_RISING>; ++ }; ++ button-2 { ++ label = "JoyLeft"; ++ linux,code = ; ++ interrupt-parent = <&stmfx_pinctrl>; ++ interrupts = <2 IRQ_TYPE_EDGE_RISING>; ++ }; ++ button-3 { ++ label = "JoyRight"; ++ linux,code = ; ++ interrupt-parent = <&stmfx_pinctrl>; ++ interrupts = <3 IRQ_TYPE_EDGE_RISING>; ++ }; ++ button-4 { ++ label = "JoyUp"; ++ linux,code = ; ++ interrupt-parent = <&stmfx_pinctrl>; ++ interrupts = <4 IRQ_TYPE_EDGE_RISING>; ++ }; ++ }; ++ ++ panel_backlight: panel-backlight { ++ compatible = "gpio-backlight"; ++ gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; ++ default-on; ++ status = "okay"; ++ }; ++ ++ spdif_out: spdif-out { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ ++ spdif_out_port: port { ++ spdif_out_endpoint: endpoint { ++ remote-endpoint = <&sai4a_endpoint>; ++ }; ++ }; ++ }; ++ ++ spdif_in: spdif-in { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dir"; ++ status = "okay"; ++ ++ spdif_in_port: port { ++ spdif_in_endpoint: endpoint { ++ remote-endpoint = <&spdifrx_endpoint>; ++ }; ++ }; ++ }; ++ ++ sound { ++ compatible = "audio-graph-card"; ++ label = "STM32MP15-EV"; ++ routing = ++ "AIF1CLK" , "MCLK1", ++ "AIF2CLK" , "MCLK1", ++ "IN1LN" , "MICBIAS2", ++ "DMIC2DAT" , "MICBIAS1", ++ "DMIC1DAT" , "MICBIAS1"; ++ dais = <&sai2a_port &sai2b_port &sai4a_port &spdifrx_port ++ &dfsdm0_port &dfsdm1_port &dfsdm2_port &dfsdm3_port>; ++ status = "okay"; ++ }; ++ ++ dmic0: dmic-0 { ++ compatible = "dmic-codec"; ++ #sound-dai-cells = <1>; ++ sound-name-prefix = "dmic0"; ++ status = "okay"; ++ ++ port { ++ dmic0_endpoint: endpoint { ++ remote-endpoint = <&dfsdm_endpoint0>; ++ }; ++ }; ++ }; ++ ++ dmic1: dmic-1 { ++ compatible = "dmic-codec"; ++ #sound-dai-cells = <1>; ++ sound-name-prefix = "dmic1"; ++ status = "okay"; ++ ++ port { ++ dmic1_endpoint: endpoint { ++ remote-endpoint = <&dfsdm_endpoint1>; ++ }; ++ }; ++ }; ++ ++ dmic2: dmic-2 { ++ compatible = "dmic-codec"; ++ #sound-dai-cells = <1>; ++ sound-name-prefix = "dmic2"; ++ status = "okay"; ++ ++ port { ++ dmic2_endpoint: endpoint { ++ remote-endpoint = <&dfsdm_endpoint2>; ++ }; ++ }; ++ }; ++ ++ dmic3: dmic-3 { ++ compatible = "dmic-codec"; ++ #sound-dai-cells = <1>; ++ sound-name-prefix = "dmic3"; ++ status = "okay"; ++ ++ port { ++ dmic3_endpoint: endpoint { ++ remote-endpoint = <&dfsdm_endpoint3>; ++ }; ++ }; ++ }; ++ ++ usb_phy_tuning: usb-phy-tuning { ++ st,hs-dc-level = <2>; ++ st,fs-rftime-tuning; ++ st,hs-rftime-reduction; ++ st,hs-current-trim = <15>; ++ st,hs-impedance-trim = <1>; ++ st,squelch-level = <3>; ++ st,hs-rx-offset = <2>; ++ st,no-lsfs-sc; ++ }; ++}; ++ ++&cec { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cec_pins_a>; ++ status = "okay"; ++}; ++ ++&dcmi { ++ status = "okay"; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&dcmi_pins_a>; ++ pinctrl-1 = <&dcmi_sleep_pins_a>; ++ ++ port { ++ dcmi_0: endpoint { ++ remote-endpoint = <&ov5640_0>; ++ bus-type = <5>; ++ bus-width = <8>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ pclk-sample = <1>; ++ pclk-max-frequency = <77000000>; ++ }; ++ }; ++}; ++ ++&dfsdm { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&dfsdm_clkout_pins_a ++ &dfsdm_data1_pins_a &dfsdm_data3_pins_a>; ++ pinctrl-1 = <&dfsdm_clkout_sleep_pins_a ++ &dfsdm_data1_sleep_pins_a &dfsdm_data3_sleep_pins_a>; ++ spi-max-frequency = <2048000>; ++ ++ clocks = <&rcc DFSDM_K>, <&rcc ADFSDM_K>; ++ clock-names = "dfsdm", "audio"; ++ status = "okay"; ++ ++ dfsdm0: filter@0 { ++ compatible = "st,stm32-dfsdm-dmic"; ++ st,adc-channels = <3>; ++ st,adc-channel-names = "dmic_u1"; ++ st,adc-channel-types = "SPI_R"; ++ st,adc-channel-clk-src = "CLKOUT"; ++ st,filter-order = <3>; ++ status = "okay"; ++ ++ asoc_pdm0: dfsdm-dai { ++ compatible = "st,stm32h7-dfsdm-dai"; ++ #sound-dai-cells = <0>; ++ io-channels = <&dfsdm0 0>; ++ status = "okay"; ++ ++ dfsdm0_port: port { ++ dfsdm_endpoint0: endpoint { ++ remote-endpoint = <&dmic0_endpoint>; ++ }; ++ }; ++ }; ++ }; ++ ++ dfsdm1: filter@1 { ++ compatible = "st,stm32-dfsdm-dmic"; ++ st,adc-channels = <0>; ++ st,adc-channel-names = "dmic_u2"; ++ st,adc-channel-types = "SPI_F"; ++ st,adc-channel-clk-src = "CLKOUT"; ++ st,filter-order = <3>; ++ st,adc-alt-channel = <1>; ++ status = "okay"; ++ ++ asoc_pdm1: dfsdm-dai { ++ compatible = "st,stm32h7-dfsdm-dai"; ++ #sound-dai-cells = <0>; ++ io-channels = <&dfsdm1 0>; ++ status = "okay"; ++ ++ dfsdm1_port: port { ++ dfsdm_endpoint1: endpoint { ++ remote-endpoint = <&dmic1_endpoint>; ++ }; ++ }; ++ }; ++ }; ++ ++ dfsdm2: filter@2 { ++ compatible = "st,stm32-dfsdm-dmic"; ++ st,adc-channels = <2>; ++ st,adc-channel-names = "dmic_u3"; ++ st,adc-channel-types = "SPI_F"; ++ st,adc-channel-clk-src = "CLKOUT"; ++ st,adc-alt-channel = <1>; ++ st,filter-order = <3>; ++ status = "okay"; ++ ++ asoc_pdm2: dfsdm-dai { ++ compatible = "st,stm32h7-dfsdm-dai"; ++ #sound-dai-cells = <0>; ++ io-channels = <&dfsdm2 0>; ++ status = "okay"; ++ ++ dfsdm2_port: port { ++ dfsdm_endpoint2: endpoint { ++ remote-endpoint = <&dmic2_endpoint>; ++ }; ++ }; ++ }; ++ }; ++ ++ dfsdm3: filter@3 { ++ compatible = "st,stm32-dfsdm-dmic"; ++ st,adc-channels = <1>; ++ st,adc-channel-names = "dmic_u4"; ++ st,adc-channel-types = "SPI_R"; ++ st,adc-channel-clk-src = "CLKOUT"; ++ st,filter-order = <3>; ++ status = "okay"; ++ ++ asoc_pdm3: dfsdm-dai { ++ compatible = "st,stm32h7-dfsdm-dai"; ++ #sound-dai-cells = <0>; ++ io-channels = <&dfsdm3 0>; ++ status = "okay"; ++ ++ dfsdm3_port: port { ++ dfsdm_endpoint3: endpoint { ++ remote-endpoint = <&dmic3_endpoint>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++ðernet0 { ++ status = "okay"; ++ pinctrl-0 = <ðernet0_rgmii_pins_a>; ++ pinctrl-1 = <ðernet0_rgmii_sleep_pins_a>; ++ pinctrl-names = "default", "sleep"; ++ phy-mode = "rgmii-id"; ++ max-speed = <1000>; ++ phy-handle = <&phy0>; ++ nvmem-cells = <ðernet_mac_address>; ++ nvmem-cell-names = "mac-address"; ++ ++ mdio0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "snps,dwmac-mdio"; ++ phy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ }; ++}; ++ ++&fmc { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&fmc_pins_a>; ++ pinctrl-1 = <&fmc_sleep_pins_a>; ++ status = "okay"; ++ ++ nand-controller@4,0 { ++ status = "okay"; ++ ++ nand@0 { ++ reg = <0>; ++ nand-on-flash-bbt; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ }; ++}; ++ ++&hdp { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&hdp0_pins_a &hdp6_pins_a &hdp7_pins_a>; ++ pinctrl-1 = <&hdp0_pins_sleep_a &hdp6_pins_sleep_a &hdp7_pins_sleep_a>; ++ status = "disabled"; ++ ++ muxing-hdp = <(STM32_HDP(0, HDP0_GPOVAL_0) | ++ STM32_HDP(6, HDP6_GPOVAL_6) | ++ STM32_HDP(7, HDP7_GPOVAL_7))>; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&i2c2_pins_a>; ++ pinctrl-1 = <&i2c2_sleep_pins_a>; ++ i2c-scl-rising-time-ns = <185>; ++ i2c-scl-falling-time-ns = <20>; ++ status = "okay"; ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ ++ wm8994: wm8994@1b { ++ compatible = "wlf,wm8994"; ++ #sound-dai-cells = <0>; ++ reg = <0x1b>; ++ status = "okay"; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ DBVDD-supply = <&vdd>; ++ SPKVDD1-supply = <&vdd>; ++ SPKVDD2-supply = <&vdd>; ++ AVDD2-supply = <&v1v8>; ++ CPVDD-supply = <&v1v8>; ++ ++ wlf,ldoena-always-driven; ++ ++ clocks = <&sai2a>; ++ clock-names = "MCLK1"; ++ ++ wlf,gpio-cfg = <0x8101 0xa100 0xa100 0xa100 0xa101 0xa101 0xa100 0xa101 0xa101 0xa101 0xa101>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wm8994_tx_port: port@0 { ++ reg = <0>; ++ wm8994_tx_endpoint: endpoint { ++ remote-endpoint = <&sai2a_endpoint>; ++ }; ++ }; ++ ++ wm8994_rx_port: port@1 { ++ reg = <1>; ++ wm8994_rx_endpoint: endpoint { ++ remote-endpoint = <&sai2b_endpoint>; ++ }; ++ }; ++ }; ++ }; ++ ++ ov5640: camera@3c { ++ compatible = "ovti,ov5640"; ++ reg = <0x3c>; ++ clocks = <&clk_ext_camera>; ++ clock-names = "xclk"; ++ DOVDD-supply = <&v2v8>; ++ powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; ++ reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; ++ rotation = <180>; ++ status = "okay"; ++ ++ port { ++ ov5640_0: endpoint { ++ remote-endpoint = <&dcmi_0>; ++ bus-width = <8>; ++ data-shift = <2>; /* lines 9:2 are used */ ++ hsync-active = <0>; ++ vsync-active = <0>; ++ pclk-sample = <1>; ++ pclk-max-frequency = <77000000>; ++ }; ++ }; ++ }; ++ ++ stmfx: stmfx@42 { ++ compatible = "st,stmfx-0300"; ++ reg = <0x42>; ++ interrupts = <8 IRQ_TYPE_EDGE_RISING>; ++ interrupt-parent = <&gpioi>; ++ vdd-supply = <&v3v3>; ++ ++ stmfx_pinctrl: pinctrl { ++ compatible = "st,stmfx-0300-pinctrl"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ gpio-ranges = <&stmfx_pinctrl 0 0 24>; ++ ++ goodix_pins: goodix { ++ pins = "gpio14"; ++ bias-pull-down; ++ }; ++ ++ joystick_pins: joystick-pins { ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; ++ bias-pull-down; ++ }; ++ }; ++ }; ++}; ++ ++&i2c4 { ++ pmic: stpmic@33 { ++ regulators { ++ v1v8: ldo6 { ++ regulator-enable-ramp-delay = <300000>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c5 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&i2c5_pins_a>; ++ pinctrl-1 = <&i2c5_sleep_pins_a>; ++ i2c-scl-rising-time-ns = <185>; ++ i2c-scl-falling-time-ns = <20>; ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ status = "okay"; ++}; ++ ++&m_can1 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&m_can1_pins_a>; ++ pinctrl-1 = <&m_can1_sleep_pins_a>; ++ status = "okay"; ++}; ++ ++&qspi { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; ++ pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; ++ reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ flash0: mx66l51235l@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-rx-bus-width = <4>; ++ spi-max-frequency = <108000000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ ++ flash1: mx66l51235l@1 { ++ compatible = "jedec,spi-nor"; ++ reg = <1>; ++ spi-rx-bus-width = <4>; ++ spi-max-frequency = <108000000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++}; ++ ++&sai2 { ++ clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_a>; ++ pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_a>; ++ clock-names = "pclk", "x8k", "x11k"; ++ status = "okay"; ++ ++ sai2a: audio-controller@4400b004 { ++ #clock-cells = <0>; ++ dma-names = "tx"; ++ status = "okay"; ++ ++ sai2a_port: port { ++ sai2a_endpoint: endpoint { ++ remote-endpoint = <&wm8994_tx_endpoint>; ++ format = "i2s"; ++ mclk-fs = <256>; ++ }; ++ }; ++ }; ++ ++ sai2b: audio-controller@4400b024 { ++ dma-names = "rx"; ++ clocks = <&rcc SAI2_K>, <&sai2a>; ++ clock-names = "sai_ck", "MCLK"; ++ status = "okay"; ++ ++ sai2b_port: port { ++ sai2b_endpoint: endpoint { ++ remote-endpoint = <&wm8994_rx_endpoint>; ++ format = "i2s"; ++ mclk-fs = <256>; ++ }; ++ }; ++ }; ++}; ++ ++&sai4 { ++ clocks = <&rcc SAI4>, <&rcc PLL3_Q>, <&rcc PLL3_R>; ++ clock-names = "pclk", "x8k", "x11k"; ++ status = "okay"; ++ ++ sai4a: audio-controller@50027004 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&sai4a_pins_a>; ++ pinctrl-1 = <&sai4a_sleep_pins_a>; ++ dma-names = "tx"; ++ st,iec60958; ++ status = "okay"; ++ ++ sai4a_port: port { ++ sai4a_endpoint: endpoint { ++ remote-endpoint = <&spdif_out_endpoint>; ++ }; ++ }; ++ }; ++}; ++ ++&sdmmc3 { ++ pinctrl-names = "default", "opendrain", "sleep"; ++ pinctrl-0 = <&sdmmc3_b4_pins_a>; ++ pinctrl-1 = <&sdmmc3_b4_od_pins_a>; ++ pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; ++ broken-cd; ++ st,neg-edge; ++ bus-width = <4>; ++ vmmc-supply = <&v3v3>; ++ status = "disabled"; ++}; ++ ++&spdifrx { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&spdifrx_pins_a>; ++ pinctrl-1 = <&spdifrx_sleep_pins_a>; ++ status = "okay"; ++ ++ spdifrx_port: port { ++ spdifrx_endpoint: endpoint { ++ remote-endpoint = <&spdif_in_endpoint>; ++ }; ++ }; ++}; ++ ++&spi1 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&spi1_pins_a>; ++ pinctrl-1 = <&spi1_sleep_pins_a>; ++ status = "disabled"; ++}; ++ ++&timers2 { ++ /* spare dmas for other usage (un-delete to enable pwm capture) */ ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ status = "disabled"; ++ pwm { ++ pinctrl-0 = <&pwm2_pins_a>; ++ pinctrl-1 = <&pwm2_sleep_pins_a>; ++ pinctrl-names = "default", "sleep"; ++ status = "okay"; ++ }; ++ timer@1 { ++ status = "okay"; ++ }; ++}; ++ ++&timers8 { ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ status = "disabled"; ++ pwm { ++ pinctrl-0 = <&pwm8_pins_a>; ++ pinctrl-1 = <&pwm8_sleep_pins_a>; ++ pinctrl-names = "default", "sleep"; ++ status = "okay"; ++ }; ++ timer@7 { ++ status = "okay"; ++ }; ++}; ++ ++&timers12 { ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ status = "disabled"; ++ pwm { ++ pinctrl-0 = <&pwm12_pins_a>; ++ pinctrl-1 = <&pwm12_sleep_pins_a>; ++ pinctrl-names = "default", "sleep"; ++ status = "okay"; ++ }; ++ timer@11 { ++ status = "okay"; ++ }; ++}; ++ ++&usart3 { ++ pinctrl-names = "default", "sleep", "idle"; ++ pinctrl-0 = <&usart3_pins_b>; ++ pinctrl-1 = <&usart3_sleep_pins_b>; ++ pinctrl-2 = <&usart3_idle_pins_b>; ++ /* ++ * HW flow control USART3_RTS is optional, and isn't default wired to ++ * the connector. SB23 needs to be soldered in order to use it, and R77 ++ * (ETH_CLK) should be removed. ++ */ ++ uart-has-rtscts; ++ status = "disabled"; ++}; ++ ++&usbh_ehci { ++ phys = <&usbphyc_port0>; ++ status = "okay"; ++}; ++ ++&usbotg_hs { ++ pinctrl-0 = <&usbotg_hs_pins_a>; ++ pinctrl-names = "default"; ++ phys = <&usbphyc_port1 0>; ++ phy-names = "usb2-phy"; ++ status = "okay"; ++}; ++ ++&usbphyc { ++ status = "okay"; ++}; ++ ++&usbphyc_port0 { ++ st,phy-tuning = <&usb_phy_tuning>; ++ vbus-supply = <&vbus_sw>; ++}; ++ ++&usbphyc_port1 { ++ st,phy-tuning = <&usb_phy_tuning>; ++}; +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0021-ARM-stm32mp1-r2-CONFIG.patch b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0022-ARM-5.10.10-stm32mp1-r1-CONFIG.patch similarity index 51% rename from recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0021-ARM-stm32mp1-r2-CONFIG.patch rename to recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0022-ARM-5.10.10-stm32mp1-r1-CONFIG.patch index 34dc997..12cf834 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0021-ARM-stm32mp1-r2-CONFIG.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.10/5.10.10/0022-ARM-5.10.10-stm32mp1-r1-CONFIG.patch @@ -1,22 +1,23 @@ -From 850ec78d02a21c585da6ede580eaff5fbe3db61b Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:55 +0200 -Subject: [PATCH 21/22] ARM-stm32mp1-r2-rc8-CONFIG +From 106f488712b412ed24f600c82febf95901c45054 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 16 Mar 2021 09:03:42 +0100 +Subject: [PATCH 22/22] ARM 5.10.10-stm32mp1-r1 CONFIG +Signed-off-by: Romuald JEANNE --- - .../fragment-01-multiv7_cleanup.config | 148 ++++++ - .../configs/fragment-02-multiv7_addons.config | 434 ++++++++++++++++++ - arch/arm/configs/multi_v7_defconfig | 1 + - 3 files changed, 583 insertions(+) + .../fragment-01-multiv7_cleanup.config | 374 ++++++++++++++++ + .../configs/fragment-02-multiv7_addons.config | 398 ++++++++++++++++++ + arch/arm/configs/multi_v7_defconfig | 5 + + 3 files changed, 777 insertions(+) create mode 100644 arch/arm/configs/fragment-01-multiv7_cleanup.config create mode 100644 arch/arm/configs/fragment-02-multiv7_addons.config diff --git a/arch/arm/configs/fragment-01-multiv7_cleanup.config b/arch/arm/configs/fragment-01-multiv7_cleanup.config new file mode 100644 -index 0000000000000..3c43593d5665f +index 000000000000..0c5667237e27 --- /dev/null +++ b/arch/arm/configs/fragment-01-multiv7_cleanup.config -@@ -0,0 +1,148 @@ +@@ -0,0 +1,374 @@ +# +# CPU Core family selection +# @@ -76,7 +77,6 @@ index 0000000000000..3c43593d5665f +# CONFIG_SOC_TI is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set -+# CONFIG_MEMORY is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set @@ -165,12 +165,239 @@ index 0000000000000..3c43593d5665f +# Debug Lockups and Hangs +# +# CONFIG_SCHED_DEBUG is not set ++ ++# SPI NOR device support ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++ ++# ++# Media core support ++# ++# CONFIG_DVB_CORE is not set ++# CONFIG_MEDIA_TUNER is not set ++# CONFIG_MEDIA_CONTROLLER_REQUEST_API is not set ++ ++# Digital TV options ++# ++# CONFIG_DVB_NET is not set ++# CONFIG_DVB_MAX_ADAPTERS is not set ++# CONFIG_DVB_DYNAMIC_MINORS is not set ++# end of Digital TV options ++ ++# ++# Media SPI Adapters ++# ++# CONFIG_CXD2880_SPI_DRV is not set ++# end of Media SPI Adapters ++ ++# ++# Customize TV tuners ++# ++# CONFIG_MEDIA_TUNER_SIMPLE is not set ++# CONFIG_MEDIA_TUNER_TDA18250 is not set ++# CONFIG_MEDIA_TUNER_TDA8290 is not set ++# CONFIG_MEDIA_TUNER_TDA827X is not set ++# CONFIG_MEDIA_TUNER_TDA18271 is not set ++# CONFIG_MEDIA_TUNER_TDA9887 is not set ++# CONFIG_MEDIA_TUNER_TEA5761 is not set ++# CONFIG_MEDIA_TUNER_TEA5767 is not set ++# CONFIG_MEDIA_TUNER_MSI001 is not set ++# CONFIG_MEDIA_TUNER_MT20XX is not set ++# CONFIG_MEDIA_TUNER_MT2060 is not set ++# CONFIG_MEDIA_TUNER_MT2063 is not set ++# CONFIG_MEDIA_TUNER_MT2266 is not set ++# CONFIG_MEDIA_TUNER_MT2131 is not set ++# CONFIG_MEDIA_TUNER_QT1010 is not set ++# CONFIG_MEDIA_TUNER_XC2028 is not set ++# CONFIG_MEDIA_TUNER_XC5000 is not set ++# CONFIG_MEDIA_TUNER_XC4000 is not set ++# CONFIG_MEDIA_TUNER_MXL5005S is not set ++# CONFIG_MEDIA_TUNER_MXL5007T is not set ++# CONFIG_MEDIA_TUNER_MC44S803 is not set ++# CONFIG_MEDIA_TUNER_MAX2165 is not set ++# CONFIG_MEDIA_TUNER_TDA18218 is not set ++# CONFIG_MEDIA_TUNER_FC0011 is not set ++# CONFIG_MEDIA_TUNER_FC0012 is not set ++# CONFIG_MEDIA_TUNER_FC0013 is not set ++# CONFIG_MEDIA_TUNER_TDA18212 is not set ++# CONFIG_MEDIA_TUNER_E4000 is not set ++# CONFIG_MEDIA_TUNER_FC2580 is not set ++# CONFIG_MEDIA_TUNER_M88RS6000T is not set ++# CONFIG_MEDIA_TUNER_TUA9001 is not set ++# CONFIG_MEDIA_TUNER_SI2157 is not set ++# CONFIG_MEDIA_TUNER_IT913X is not set ++# CONFIG_MEDIA_TUNER_R820T is not set ++# CONFIG_MEDIA_TUNER_MXL301RF is not set ++# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set ++# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set ++# end of Customize TV tuners ++# ++# Customise DVB Frontends ++# ++ ++# ++# Multistandard (satellite) frontends ++# ++# CONFIG_DVB_STB0899 is not set ++# CONFIG_DVB_STB6100 is not set ++# CONFIG_DVB_STV090x is not set ++# CONFIG_DVB_STV0910 is not set ++# CONFIG_DVB_STV6110x is not set ++# CONFIG_DVB_STV6111 is not set ++# CONFIG_DVB_MXL5XX is not set ++# CONFIG_DVB_M88DS3103 is not set ++ ++# ++# Multistandard (cable + terrestrial) frontends ++# ++# CONFIG_DVB_DRXK is not set ++# CONFIG_DVB_TDA18271C2DD is not set ++# CONFIG_DVB_SI2165 is not set ++# CONFIG_DVB_MN88472 is not set ++# CONFIG_DVB_MN88473 is not set ++ ++# ++# DVB-S (satellite) frontends ++# ++# CONFIG_DVB_CX24110 is not set ++# CONFIG_DVB_CX24123 is not set ++# CONFIG_DVB_MT312 is not set ++# CONFIG_DVB_ZL10036 is not set ++# CONFIG_DVB_ZL10039 is not set ++# CONFIG_DVB_S5H1420 is not set ++# CONFIG_DVB_STV0288 is not set ++# CONFIG_DVB_STB6000 is not set ++# CONFIG_DVB_STV0299 is not set ++# CONFIG_DVB_STV6110 is not set ++# CONFIG_DVB_STV0900 is not set ++# CONFIG_DVB_TDA8083 is not set ++# CONFIG_DVB_TDA10086 is not set ++# CONFIG_DVB_TDA8261 is not set ++# CONFIG_DVB_VES1X93 is not set ++# CONFIG_DVB_TUNER_ITD1000 is not set ++# CONFIG_DVB_TUNER_CX24113 is not set ++# CONFIG_DVB_TDA826X is not set ++# CONFIG_DVB_TUA6100 is not set ++# CONFIG_DVB_CX24116 is not set ++# CONFIG_DVB_CX24117 is not set ++# CONFIG_DVB_CX24120 is not set ++# CONFIG_DVB_SI21XX is not set ++# CONFIG_DVB_TS2020 is not set ++# CONFIG_DVB_DS3000 is not set ++# CONFIG_DVB_MB86A16 is not set ++# CONFIG_DVB_TDA10071 is not set ++ ++# ++# DVB-T (terrestrial) frontends ++# ++# CONFIG_DVB_SP8870 is not set ++# CONFIG_DVB_SP887X is not set ++# CONFIG_DVB_CX22700 is not set ++# CONFIG_DVB_CX22702 is not set ++# CONFIG_DVB_S5H1432 is not set ++# CONFIG_DVB_DRXD is not set ++# CONFIG_DVB_L64781 is not set ++# CONFIG_DVB_TDA1004X is not set ++# CONFIG_DVB_NXT6000 is not set ++# CONFIG_DVB_MT352 is not set ++# CONFIG_DVB_ZL10353 is not set ++# CONFIG_DVB_DIB3000MB is not set ++# CONFIG_DVB_DIB3000MC is not set ++# CONFIG_DVB_DIB7000M is not set ++# CONFIG_DVB_DIB7000P is not set ++# CONFIG_DVB_DIB9000 is not set ++# CONFIG_DVB_TDA10048 is not set ++# CONFIG_DVB_AF9013 is not set ++# CONFIG_DVB_EC100 is not set ++# CONFIG_DVB_STV0367 is not set ++# CONFIG_DVB_CXD2820R is not set ++# CONFIG_DVB_CXD2841ER is not set ++# CONFIG_DVB_RTL2830 is not set ++# CONFIG_DVB_RTL2832 is not set ++# CONFIG_DVB_RTL2832_SDR is not set ++# CONFIG_DVB_SI2168 is not set ++# CONFIG_DVB_ZD1301_DEMOD is not set ++# CONFIG_DVB_CXD2880 is not set ++ ++# ++# DVB-C (cable) frontends ++# ++# CONFIG_DVB_VES1820 is not set ++# CONFIG_DVB_TDA10021 is not set ++# CONFIG_DVB_TDA10023 is not set ++# CONFIG_DVB_STV0297 is not set ++ ++# ++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends ++# ++# CONFIG_DVB_NXT200X is not set ++# CONFIG_DVB_OR51211 is not set ++# CONFIG_DVB_OR51132 is not set ++# CONFIG_DVB_BCM3510 is not set ++# CONFIG_DVB_LGDT330X is not set ++# CONFIG_DVB_LGDT3305 is not set ++# CONFIG_DVB_LGDT3306A is not set ++# CONFIG_DVB_LG2160 is not set ++# CONFIG_DVB_S5H1409 is not set ++# CONFIG_DVB_AU8522 is not set ++# CONFIG_DVB_AU8522_DTV is not set ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_S5H1411 is not set ++ ++# ++# ISDB-T (terrestrial) frontends ++# ++# CONFIG_DVB_S921 is not set ++# CONFIG_DVB_DIB8000 is not set ++# CONFIG_DVB_MB86A20S is not set ++ ++# ++# ISDB-S (satellite) & ISDB-T (terrestrial) frontends ++# ++# CONFIG_DVB_TC90522 is not set ++# CONFIG_DVB_MN88443X is not set ++ ++# ++# Digital terrestrial only tuners/PLL ++# ++# CONFIG_DVB_PLL is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# SEC control devices for DVB-S ++# ++# CONFIG_DVB_DRX39XYJ is not set ++# CONFIG_DVB_LNBH25 is not set ++# CONFIG_DVB_LNBH29 is not set ++# CONFIG_DVB_LNBP21 is not set ++# CONFIG_DVB_LNBP22 is not set ++# CONFIG_DVB_ISL6405 is not set ++# CONFIG_DVB_ISL6421 is not set ++# CONFIG_DVB_ISL6423 is not set ++# CONFIG_DVB_A8293 is not set ++# CONFIG_DVB_LGS8GL5 is not set ++# CONFIG_DVB_LGS8GXX is not set ++# CONFIG_DVB_ATBM8830 is not set ++# CONFIG_DVB_TDA665x is not set ++# CONFIG_DVB_IX2505V is not set ++# CONFIG_DVB_M88RS2000 is not set ++# CONFIG_DVB_AF9033 is not set ++# CONFIG_DVB_HORUS3A is not set ++# CONFIG_DVB_ASCOT2E is not set ++# CONFIG_DVB_HELENE is not set ++ ++# ++# Common Interface (EN50221) controller drivers ++# ++# CONFIG_DVB_CXD2099 is not set ++# CONFIG_DVB_SP2 is not set ++# end of Customise DVB Frontends diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config new file mode 100644 -index 0000000000000..5fd995006583f +index 000000000000..d6c1a48d5702 --- /dev/null +++ b/arch/arm/configs/fragment-02-multiv7_addons.config -@@ -0,0 +1,434 @@ +@@ -0,0 +1,398 @@ +# +# General setup +# @@ -259,7 +486,6 @@ index 0000000000000..5fd995006583f +# +# Disk-On-Chip Device Drivers +# -+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set + +# +# LPDDR & LPDDR2 PCM memory drivers @@ -311,6 +537,7 @@ index 0000000000000..5fd995006583f +# + +CONFIG_MTD_SPI_NAND=y ++CONFIG_MTD_MCHP23K256=m + +# +# USB GPIO expanders @@ -344,18 +571,13 @@ index 0000000000000..5fd995006583f +CONFIG_PROTECTION_CONSUMER=y + +# -+# Regulator drivers -+# -+CONFIG_REGULATOR_STM32_PWR=y -+ -+# +# Multimedia core support +# + +# +# USB HDMI CEC adapters +# -+CONFIG_VIDEO_STM32_HDMI_CEC=m ++CONFIG_CEC_STM32=m + +# +# Camera sensor devices @@ -402,29 +624,19 @@ index 0000000000000..5fd995006583f +CONFIG_BACKLIGHT_GPIO=y + +# -+# HD-Audio ++# STMicroelectronics STM32 SOC audio support +# -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_SOC=y -+CONFIG_SND_SOC_STM32_SAI=y -+CONFIG_SND_SOC_STM32_I2S=y -+CONFIG_SND_SOC_STM32_SPDIFRX=y -+CONFIG_SND_SOC_STM32_DFSDM=y -+CONFIG_SND_AUDIO_GRAPH_CARD=y ++CONFIG_SND_SOC_STM32_SPDIFRX=m ++CONFIG_SND_SOC_STM32_DFSDM=m + +# +# CODEC drivers +# -+CONFIG_MFD_WM8994=y -+CONFIG_SND_SOC_WM8994=y -+CONFIG_SND_SOC_DMIC=y -+CONFIG_SND_SOC_CS42L42=y -+CONFIG_SND_SOC_CS42L51_I2C=y ++ +# +# USB Device Class drivers +# -+CONFIG_USB_ACM=y ++CONFIG_USB_ACM=m + +# +# also be needed; see USB_STORAGE Help for more info @@ -433,13 +645,10 @@ index 0000000000000..5fd995006583f +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# -+CONFIG_USB_CONFIGFS=y + +# +# USB Physical Layer drivers +# -+CONFIG_TYPEC=y -+CONFIG_TYPEC_STUSB=y + +# +# Platform Support @@ -454,8 +663,23 @@ index 0000000000000..5fd995006583f +# + +# ++# Regulators ++# ++CONFIG_REGULATOR_STM32_VREFBUF=y ++ ++# ++# Remoteproc drivers ++# ++CONFIG_REMOTEPROC=y ++CONFIG_STM32_RPROC=y ++CONFIG_REMOTEPROC_SRM_CORE=y ++CONFIG_REMOTEPROC_SRM_DEV=y ++ ++# +# Rpmsg drivers +# ++CONFIG_RPMSG_VIRTIO=y ++CONFIG_RPMSG_TTY=m + +# +# File systems @@ -497,10 +721,6 @@ index 0000000000000..5fd995006583f +# +CONFIG_KEYS=y + -+CONFIG_CRYPTO_DEV_STM32_CRC=y -+CONFIG_CRYPTO_DEV_STM32_HASH=y -+CONFIG_CRYPTO_DEV_STM32_CRYP=y -+ +# +# Library routines +# @@ -510,12 +730,6 @@ index 0000000000000..5fd995006583f +# STM32 DFSDM +# +CONFIG_SD_ADC_MODULATOR=y -+CONFIG_STM32_DFSDM_ADC=y -+ -+# -+# STM32 BSEC NVMEM -+# -+CONFIG_NVMEM_STM32_ROMEM=y + +# +# STM32 HSEM @@ -529,59 +743,6 @@ index 0000000000000..5fd995006583f +CONFIG_STM32_IPCC=y + +# -+# STM32 RPROC -+# -+CONFIG_REMOTEPROC=y -+CONFIG_STM32_RPROC=y -+CONFIG_RPMSG_VIRTIO=y -+ -+# -+# RPMSG_TTY -+# -+CONFIG_RPMSG_VIRTIO=y -+CONFIG_RPMSG_TTY=y -+ -+# -+# RPMSG client sample -+# -+CONFIG_SAMPLES=y -+CONFIG_SAMPLE_RPMSG_CLIENT=m -+ -+# -+# STM32 TIMER -+# -+CONFIG_MFD_STM32_TIMERS=y -+CONFIG_IIO_STM32_TIMER_TRIGGER=y -+CONFIG_PWM_STM32=y -+CONFIG_COUNTER=y -+CONFIG_STM32_TIMER_CNT=y -+ -+# -+# STM32 LPTIMER -+# -+CONFIG_MFD_STM32_LPTIMER=y -+CONFIG_PWM_STM32_LP=y -+CONFIG_IIO_STM32_LPTIMER_TRIGGER=y -+CONFIG_STM32_LPTIMER_CNT=y -+CONFIG_CLKSRC_STM32_LP=y -+ -+# -+# STM32 ADC -+# -+CONFIG_STM32_ADC_CORE=y -+CONFIG_STM32_ADC=y -+ -+# -+# STM32 DAC -+# -+CONFIG_STM32_DAC=y -+ -+# -+# STM32 VREFBUF -+# -+CONFIG_REGULATOR_STM32_VREFBUF=y -+ -+# +# SCMI +# +CONFIG_ARM_SCMI_PROTOCOL=y @@ -594,10 +755,21 @@ index 0000000000000..5fd995006583f +CONFIG_LEGACY_PTY_COUNT=8 + +# -+# FMC EBI ++# STM32 BSEC NVMEM +# -+CONFIG_MEMORY=y -+CONFIG_STM32_FMC2_EBI=y ++CONFIG_NVMEM_STM32_ROMEM=y ++ ++# ++# RPMSG client sample ++# ++CONFIG_SAMPLES=y ++CONFIG_SAMPLE_RPMSG_CLIENT=m ++ ++# ++# REBOOT ++# ++CONFIG_REBOOT_MODE=y ++CONFIG_SYSCON_REBOOT_MODE=y + +# +# STM32 CPUIDLE @@ -605,18 +777,48 @@ index 0000000000000..5fd995006583f +CONFIG_CPU_IDLE=y +CONFIG_ARM_STM32_CPUIDLE=y +CONFIG_ARM_CPUIDLE=n ++ ++# ++# STM32 TIMER ++# ++CONFIG_COUNTER=m ++CONFIG_STM32_TIMER_CNT=m ++ ++# ++# STM32 LPTIMER ++# ++CONFIG_MFD_STM32_LPTIMER=y ++CONFIG_STM32_LPTIMER_CNT=m ++CONFIG_CLKSRC_STM32_LP=y ++ ++# ++# TEE drivers ++# ++CONFIG_TEE=y ++CONFIG_OPTEE=y diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig -index e4c8def9a0a57..4231ad37ea3bc 100644 +index a611b0c1e540..abf1b17cb03a 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig -@@ -1038,6 +1038,7 @@ CONFIG_TI_PIPE3=y - CONFIG_TWL4030_USB=m - CONFIG_MESON_MX_EFUSE=m - CONFIG_ROCKCHIP_EFUSE=m -+CONFIG_STM32_DDR_PMU=y - CONFIG_NVMEM_IMX_OCOTP=y - CONFIG_NVMEM_SUNXI_SID=y - CONFIG_NVMEM_VF610_OCOTP=y +@@ -829,6 +829,8 @@ CONFIG_USB_CONFIGFS_F_HID=y + CONFIG_USB_CONFIGFS_F_UVC=y + CONFIG_USB_CONFIGFS_F_PRINTER=y + CONFIG_USB_ETH=m ++CONFIG_TYPEC=m ++CONFIG_TYPEC_STUSB160X=m + CONFIG_MMC=y + CONFIG_MMC_BLOCK_MINORS=16 + CONFIG_MMC_ARMMMCI=y +@@ -1133,6 +1135,9 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=m + CONFIG_CRYPTO_DEV_ATMEL_TDES=m + CONFIG_CRYPTO_DEV_ATMEL_SHA=m + CONFIG_CRYPTO_DEV_ROCKCHIP=m ++CONFIG_CRYPTO_DEV_STM32_CRC=m ++CONFIG_CRYPTO_DEV_STM32_HASH=m ++CONFIG_CRYPTO_DEV_STM32_CRYP=m + CONFIG_CMA_SIZE_MBYTES=64 + CONFIG_PRINTK_TIME=y + CONFIG_MAGIC_SYSRQ=y -- 2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/fragment-03-systemd.config b/recipes-kernel/linux/linux-stm32mp/5.10/fragment-03-systemd.config similarity index 100% rename from recipes-kernel/linux/linux-stm32mp/5.4/fragment-03-systemd.config rename to recipes-kernel/linux/linux-stm32mp/5.10/fragment-03-systemd.config diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/fragment-05-modules.config b/recipes-kernel/linux/linux-stm32mp/5.10/fragment-04-modules.config similarity index 93% rename from recipes-kernel/linux/linux-stm32mp/5.4/fragment-05-modules.config rename to recipes-kernel/linux/linux-stm32mp/5.10/fragment-04-modules.config index 94b8df6..2282a60 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.4/fragment-05-modules.config +++ b/recipes-kernel/linux/linux-stm32mp/5.10/fragment-04-modules.config @@ -1,3 +1,5 @@ +# CONFIG_GCC_PLUGINS is not set + # Allow to load kernel modules built with different kernel version CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODVERSIONS=y @@ -18,4 +20,3 @@ CONFIG_INPUT_UINPUT=m CONFIG_USBIP_CORE=m CONFIG_USBIP_HOST=m # CONFIG_USBIP_DEBUG is not set - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/fragment-06-signature.config b/recipes-kernel/linux/linux-stm32mp/5.10/fragment-05-signature.config similarity index 100% rename from recipes-kernel/linux/linux-stm32mp/5.4/fragment-06-signature.config rename to recipes-kernel/linux/linux-stm32mp/5.10/fragment-05-signature.config diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0001-ARM-stm32mp1-r2-MACHINE.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0001-ARM-stm32mp1-r2-MACHINE.patch deleted file mode 100644 index ac148b7..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0001-ARM-stm32mp1-r2-MACHINE.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 4556074b66971918536ed27d52f5f4f6337f0646 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:40 +0200 -Subject: [PATCH 01/22] ARM-stm32mp1-r2-rc8-MACHINE - ---- - arch/arm/kernel/time.c | 2 ++ - arch/arm/mach-stm32/Kconfig | 1 + - arch/arm/mach-stm32/board-dt.c | 2 ++ - 3 files changed, 5 insertions(+) - -diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c -index b996b2cf07038..dddc7ebf4db44 100644 ---- a/arch/arm/kernel/time.c -+++ b/arch/arm/kernel/time.c -@@ -9,6 +9,7 @@ - * reading the RTC at bootup, etc... - */ - #include -+#include - #include - #include - #include -@@ -107,5 +108,6 @@ void __init time_init(void) - of_clk_init(NULL); - #endif - timer_probe(); -+ tick_setup_hrtimer_broadcast(); - } - } -diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig -index 57699bd8f1075..8f9fd1da9ea05 100644 ---- a/arch/arm/mach-stm32/Kconfig -+++ b/arch/arm/mach-stm32/Kconfig -@@ -46,6 +46,7 @@ if ARCH_MULTI_V7 - config MACH_STM32MP157 - bool "STMicroelectronics STM32MP157" - select ARM_ERRATA_814220 -+ select REGULATOR - default y - - endif # ARMv7-A -diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c -index 011d57b488c2e..8e06a94421d9b 100644 ---- a/arch/arm/mach-stm32/board-dt.c -+++ b/arch/arm/mach-stm32/board-dt.c -@@ -17,6 +17,8 @@ static const char *const stm32_compat[] __initconst = { - "st,stm32f746", - "st,stm32f769", - "st,stm32h743", -+ "st,stm32mp151", -+ "st,stm32mp153", - "st,stm32mp157", - NULL - }; --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0004-ARM-stm32mp1-r2-RNG-DEBUG-NVMEM.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0004-ARM-stm32mp1-r2-RNG-DEBUG-NVMEM.patch deleted file mode 100644 index ce1aa9a..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0004-ARM-stm32mp1-r2-RNG-DEBUG-NVMEM.patch +++ /dev/null @@ -1,231 +0,0 @@ -From bfe89db1821d391733d9410f1102f456de687474 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:41 +0200 -Subject: [PATCH 04/22] ARM-stm32mp1-r2-rc8-RNG-DEBUG-NVMEM - ---- - arch/arm/Kconfig.debug | 42 +++++++++++++++++++++++++----- - arch/arm/include/debug/stm32.S | 9 +++---- - drivers/char/hw_random/stm32-rng.c | 5 +++- - drivers/nvmem/core.c | 37 ++++++++++++++++++++++++++ - include/linux/nvmem-consumer.h | 7 +++++ - 5 files changed, 88 insertions(+), 12 deletions(-) - -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 8bcbd0cd739b5..3357e294a7cc0 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -1201,23 +1201,49 @@ choice - - config STM32F4_DEBUG_UART - bool "Use STM32F4 UART for low-level debug" -- depends on ARCH_STM32 -+ depends on MACH_STM32F429 || MACH_STM32F469 - select DEBUG_STM32_UART - help - Say Y here if you want kernel low-level debugging support - on STM32F4 based platforms, which default UART is wired on -- USART1. -+ USART1, but another UART instance can be selected by modifying -+ CONFIG_DEBUG_UART_PHYS. - - If unsure, say N. - - config STM32F7_DEBUG_UART - bool "Use STM32F7 UART for low-level debug" -- depends on ARCH_STM32 -+ depends on MACH_STM32F746 || MACH_STM32F769 - select DEBUG_STM32_UART - help - Say Y here if you want kernel low-level debugging support - on STM32F7 based platforms, which default UART is wired on -- USART1. -+ USART1, but another UART instance can be selected by modifying -+ CONFIG_DEBUG_UART_PHYS. -+ -+ If unsure, say N. -+ -+ config STM32H7_DEBUG_UART -+ bool "Use STM32H7 UART for low-level debug" -+ depends on MACH_STM32H743 -+ select DEBUG_STM32_UART -+ help -+ Say Y here if you want kernel low-level debugging support -+ on STM32H7 based platforms, which default UART is wired on -+ USART1, but another UART instance can be selected by modifying -+ CONFIG_DEBUG_UART_PHYS. -+ -+ If unsure, say N. -+ -+ config STM32MP1_DEBUG_UART -+ bool "Use STM32MP1 UART for low-level debug" -+ depends on MACH_STM32MP157 -+ select DEBUG_STM32_UART -+ help -+ Say Y here if you want kernel low-level debugging support -+ on STM32MP1 based platforms, wich default UART is wired on -+ UART4, but another UART instance can be selected by modifying -+ CONFIG_DEBUG_UART_PHYS and CONFIG_DEBUG_UART_VIRT. - - If unsure, say N. - -@@ -1619,6 +1645,9 @@ config DEBUG_UART_PHYS - default 0x3e000000 if DEBUG_BCM_KONA_UART - default 0x3f201000 if DEBUG_BCM2836 - default 0x4000e400 if DEBUG_LL_UART_EFM32 -+ default 0x40010000 if STM32MP1_DEBUG_UART -+ default 0x40011000 if STM32F4_DEBUG_UART || STM32F7_DEBUG_UART || \ -+ STM32H7_DEBUG_UART - default 0x40028000 if DEBUG_AT91_SAMV7_USART1 - default 0x40081000 if DEBUG_LPC18XX_UART0 - default 0x40090000 if DEBUG_LPC32XX -@@ -1713,7 +1742,7 @@ config DEBUG_UART_PHYS - DEBUG_S3C64XX_UART || \ - DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \ - DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \ -- DEBUG_AT91_UART -+ DEBUG_AT91_UART || DEBUG_STM32_UART - - config DEBUG_UART_VIRT - hex "Virtual base address of debug UART" -@@ -1779,6 +1808,7 @@ config DEBUG_UART_VIRT - default 0xfcfe8600 if DEBUG_BCM63XX_UART - default 0xfd000000 if DEBUG_SPEAR3XX || DEBUG_SPEAR13XX - default 0xfd883000 if DEBUG_ALPINE_UART0 -+ default 0xfe010000 if STM32MP1_DEBUG_UART - default 0xfe017000 if DEBUG_MMP_UART2 - default 0xfe018000 if DEBUG_MMP_UART3 - default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART -@@ -1823,7 +1853,7 @@ config DEBUG_UART_VIRT - DEBUG_S3C64XX_UART || \ - DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \ - DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \ -- DEBUG_AT91_UART -+ DEBUG_AT91_UART || DEBUG_STM32_UART - - config DEBUG_UART_8250_SHIFT - int "Register offset shift for the 8250 debug UART" -diff --git a/arch/arm/include/debug/stm32.S b/arch/arm/include/debug/stm32.S -index 1abb32f685fdb..6446e4692025d 100644 ---- a/arch/arm/include/debug/stm32.S -+++ b/arch/arm/include/debug/stm32.S -@@ -4,14 +4,13 @@ - * Author: Gerald Baeza for STMicroelectronics. - */ - --#define STM32_UART_BASE 0x40011000 /* USART1 */ -- - #ifdef CONFIG_STM32F4_DEBUG_UART - #define STM32_USART_SR_OFF 0x00 - #define STM32_USART_TDR_OFF 0x04 - #endif - --#ifdef CONFIG_STM32F7_DEBUG_UART -+#if defined(CONFIG_STM32F7_DEBUG_UART) || (CONFIG_STM32H7_DEBUG_UART) || \ -+ defined(CONFIG_STM32MP1_DEBUG_UART) - #define STM32_USART_SR_OFF 0x1C - #define STM32_USART_TDR_OFF 0x28 - #endif -@@ -20,8 +19,8 @@ - #define STM32_USART_TXE (1 << 7) /* Tx data reg empty */ - - .macro addruart, rp, rv, tmp -- ldr \rp, =STM32_UART_BASE @ physical base -- ldr \rv, =STM32_UART_BASE @ virt base /* NoMMU */ -+ ldr \rp, =CONFIG_DEBUG_UART_PHYS @ physical base -+ ldr \rv, =CONFIG_DEBUG_UART_VIRT @ virt base - .endm - - .macro senduart,rd,rx -diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c -index 38324c2ddda10..a25c4b5c3d1bc 100644 ---- a/drivers/char/hw_random/stm32-rng.c -+++ b/drivers/char/hw_random/stm32-rng.c -@@ -135,7 +135,10 @@ static int stm32_rng_probe(struct platform_device *ofdev) - return PTR_ERR(priv->clk); - - priv->rst = devm_reset_control_get(&ofdev->dev, NULL); -- if (!IS_ERR(priv->rst)) { -+ if (IS_ERR(priv->rst)) { -+ if (PTR_ERR(priv->rst) != -ENOENT) -+ return PTR_ERR(priv->rst); -+ } else { - reset_control_assert(priv->rst); - udelay(2); - reset_control_deassert(priv->rst); -diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c -index 960542dea5adb..8105fe4230cc5 100644 ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -1080,6 +1080,43 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len) - } - EXPORT_SYMBOL_GPL(nvmem_cell_write); - -+/** -+ * nvmem_cell_read_u8() - Read a cell value as an u8 -+ * -+ * @dev: Device that requests the nvmem cell. -+ * @cell_id: Name of nvmem cell to read. -+ * @val: pointer to output value. -+ * -+ * Return: 0 on success or negative errno. -+ */ -+int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val) -+{ -+ struct nvmem_cell *cell; -+ void *buf; -+ size_t len; -+ -+ cell = nvmem_cell_get(dev, cell_id); -+ if (IS_ERR(cell)) -+ return PTR_ERR(cell); -+ -+ buf = nvmem_cell_read(cell, &len); -+ if (IS_ERR(buf)) { -+ nvmem_cell_put(cell); -+ return PTR_ERR(buf); -+ } -+ if (len != sizeof(*val)) { -+ kfree(buf); -+ nvmem_cell_put(cell); -+ return -EINVAL; -+ } -+ memcpy(val, buf, sizeof(*val)); -+ kfree(buf); -+ nvmem_cell_put(cell); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(nvmem_cell_read_u8); -+ - /** - * nvmem_cell_read_u16() - Read a cell value as an u16 - * -diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h -index 5c17cb7332241..c3c53a63e358a 100644 ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -61,6 +61,7 @@ void nvmem_cell_put(struct nvmem_cell *cell); - void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell); - void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len); - int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len); -+int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val); - int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val); - int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val); - -@@ -123,6 +124,12 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell, - return -EOPNOTSUPP; - } - -+static inline int nvmem_cell_read_u8(struct device *dev, -+ const char *cell_id, u8 *val) -+{ -+ return -EOPNOTSUPP; -+} -+ - static inline int nvmem_cell_read_u16(struct device *dev, - const char *cell_id, u16 *val) - { --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0007-ARM-stm32mp1-r2-DRM.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0007-ARM-stm32mp1-r2-DRM.patch deleted file mode 100644 index d36e404..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0007-ARM-stm32mp1-r2-DRM.patch +++ /dev/null @@ -1,1584 +0,0 @@ -From 8cfec718ba7f8e1e8e004d7033b4f48b901b2779 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:43 +0200 -Subject: [PATCH 07/22] ARM-stm32mp1-r2-rc8-DRM - ---- - .../display/panel/orisetech,otm8009a.txt | 23 -- - .../display/panel/orisetech,otm8009a.yaml | 53 ++++ - .../display/panel/raydium,rm68200.txt | 25 -- - .../display/panel/raydium,rm68200.yaml | 52 ++++ - drivers/gpu/drm/bridge/sii902x.c | 145 +++++++++- - drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 212 ++++++++++---- - drivers/gpu/drm/drm_modes.c | 19 +- - .../gpu/drm/panel/panel-orisetech-otm8009a.c | 20 +- - drivers/gpu/drm/panel/panel-raydium-rm68200.c | 14 +- - drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 9 +- - drivers/gpu/drm/stm/ltdc.c | 270 +++++++++++------- - drivers/gpu/drm/stm/ltdc.h | 1 + - drivers/input/touchscreen/edt-ft5x06.c | 18 +- - drivers/input/touchscreen/goodix.c | 16 ++ - include/uapi/drm/drm_mode.h | 6 + - 15 files changed, 648 insertions(+), 235 deletions(-) - delete mode 100644 Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.txt - create mode 100644 Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml - delete mode 100644 Documentation/devicetree/bindings/display/panel/raydium,rm68200.txt - create mode 100644 Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml - -diff --git a/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.txt b/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.txt -deleted file mode 100644 -index 203b03eefb688..0000000000000 ---- a/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.txt -+++ /dev/null -@@ -1,23 +0,0 @@ --Orise Tech OTM8009A 3.97" 480x800 TFT LCD panel (MIPI-DSI video mode) -- --The Orise Tech OTM8009A is a 3.97" 480x800 TFT LCD panel connected using --a MIPI-DSI video interface. Its backlight is managed through the DSI link. -- --Required properties: -- - compatible: "orisetech,otm8009a" -- - reg: the virtual channel number of a DSI peripheral -- --Optional properties: -- - reset-gpios: a GPIO spec for the reset pin (active low). -- - power-supply: phandle of the regulator that provides the supply voltage. -- --Example: --&dsi { -- ... -- panel@0 { -- compatible = "orisetech,otm8009a"; -- reg = <0>; -- reset-gpios = <&gpioh 7 GPIO_ACTIVE_LOW>; -- power-supply = <&v1v8>; -- }; --}; -diff --git a/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml b/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml -new file mode 100644 -index 0000000000000..6eda24035c9eb ---- /dev/null -+++ b/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml -@@ -0,0 +1,53 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/display/panel/orisetech,otm8009a.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Orise Tech OTM8009A 3.97" 480x800 panel -+ -+maintainers: -+ - Yannick Fertre -+ -+description: -+ The Orise Tech OTM8009A is a 3.97" 480x800 TFT LCD panel connected using -+ a MIPI-DSI video interface. Its backlight is managed through the DSI link. -+ -+properties: -+ compatible: -+ const: orisetech,otm8009a -+ -+ power-supply: true -+ reset-gpios: true -+ backlight: true -+ port: true -+ reg: true -+ -+required: -+ - compatible -+ - reg -+ - port -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ display1: display { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ panel { -+ compatible = "orisetech,otm8009a"; -+ reg = <0>; -+ reset-gpios = <&gpioh 7 GPIO_ACTIVE_LOW>; -+ power-supply = <&v1v8>; -+ -+ port { -+ panel_in_dsi: endpoint { -+ remote-endpoint = <&controller_out_dsi>; -+ }; -+ }; -+ }; -+ }; -+ -+... -diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm68200.txt b/Documentation/devicetree/bindings/display/panel/raydium,rm68200.txt -deleted file mode 100644 -index cbb79ef3bfc98..0000000000000 ---- a/Documentation/devicetree/bindings/display/panel/raydium,rm68200.txt -+++ /dev/null -@@ -1,25 +0,0 @@ --Raydium Semiconductor Corporation RM68200 5.5" 720p MIPI-DSI TFT LCD panel -- --The Raydium Semiconductor Corporation RM68200 is a 5.5" 720x1280 TFT LCD --panel connected using a MIPI-DSI video interface. -- --Required properties: -- - compatible: "raydium,rm68200" -- - reg: the virtual channel number of a DSI peripheral -- --Optional properties: -- - reset-gpios: a GPIO spec for the reset pin (active low). -- - power-supply: phandle of the regulator that provides the supply voltage. -- - backlight: phandle of the backlight device attached to the panel. -- --Example: --&dsi { -- ... -- panel@0 { -- compatible = "raydium,rm68200"; -- reg = <0>; -- reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; -- power-supply = <&v1v8>; -- backlight = <&pwm_backlight>; -- }; --}; -diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml b/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml -new file mode 100644 -index 0000000000000..2bbd4a0cb5da8 ---- /dev/null -+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml -@@ -0,0 +1,52 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/display/panel/raydium,rm68200.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Raydium RM68200 5.5" 720x1280 panel -+ -+maintainers: -+ - Yannick Fertre -+ -+description: -+ The Raydium Semiconductor Corporation RM68200 is a 5.5" 720x1280 TFT LCD -+ panel connected using a MIPI-DSI video interface. -+ -+properties: -+ compatible: -+ const: raydium,rm68200 -+ -+ power-supply: true -+ reset-gpios: true -+ backlight: true -+ port: true -+ reg: true -+ -+required: -+ - compatible -+ - reg -+ - port -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ display0: display { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ panel { -+ compatible = "raydium,rm68200"; -+ reg = <0>; -+ reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; -+ power-supply = <&v1v8>; -+ port { -+ panel_in_dsi: endpoint { -+ remote-endpoint = <&controller_out_dsi>; -+ }; -+ }; -+ }; -+ }; -+ -+... -diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c -index 38f75ac580df4..92299884f6cb9 100644 ---- a/drivers/gpu/drm/bridge/sii902x.c -+++ b/drivers/gpu/drm/bridge/sii902x.c -@@ -16,8 +16,10 @@ - #include - #include - #include -+#include - #include - #include -+#include - - #include - #include -@@ -160,6 +162,11 @@ - - #define SII902X_AUDIO_PORT_INDEX 3 - -+/* CEC device */ -+#define SII902X_CEC_I2C_ADDR 0x30 -+ -+#define SII902X_CEC_SETUP 0x8e -+ - struct sii902x { - struct i2c_client *i2c; - struct regmap *regmap; -@@ -167,6 +174,7 @@ struct sii902x { - struct drm_connector connector; - struct gpio_desc *reset_gpio; - struct i2c_mux_core *i2cmux; -+ struct edid *edid; - /* - * Mutex protects audio and video functions from interfering - * each other, by keeping their i2c command sequences atomic. -@@ -177,6 +185,7 @@ struct sii902x { - struct clk *mclk; - u32 i2s_fifo_sequence[4]; - } audio; -+ struct regulator_bulk_data supplies[2]; - }; - - static int sii902x_read_unlocked(struct i2c_client *i2c, u8 reg, u8 *val) -@@ -277,6 +286,8 @@ static int sii902x_get_modes(struct drm_connector *connector) - - mutex_lock(&sii902x->mutex); - -+ kfree(sii902x->edid); -+ sii902x->edid = NULL; - edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]); - drm_connector_update_edid_property(connector, edid); - if (edid) { -@@ -284,7 +295,7 @@ static int sii902x_get_modes(struct drm_connector *connector) - output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI; - - num = drm_add_edid_modes(connector, edid); -- kfree(edid); -+ sii902x->edid = edid; - } - - ret = drm_display_info_set_bus_formats(&connector->display_info, -@@ -334,6 +345,7 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge) - static void sii902x_bridge_enable(struct drm_bridge *bridge) - { - struct sii902x *sii902x = bridge_to_sii902x(bridge); -+ u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI; - - mutex_lock(&sii902x->mutex); - -@@ -343,6 +355,14 @@ static void sii902x_bridge_enable(struct drm_bridge *bridge) - regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, - SII902X_SYS_CTRL_PWR_DWN, 0); - -+ if (sii902x->edid) { -+ if (drm_detect_hdmi_monitor(sii902x->edid)) -+ output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI; -+ } -+ -+ regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, -+ SII902X_SYS_CTRL_OUTPUT_MODE, output_mode); -+ - mutex_unlock(&sii902x->mutex); - } - -@@ -952,6 +972,13 @@ static int sii902x_probe(struct i2c_client *client, - struct device *dev = &client->dev; - unsigned int status = 0; - struct sii902x *sii902x; -+ unsigned char data[2] = { SII902X_CEC_SETUP, 0}; -+ struct i2c_msg msg = { -+ .addr = SII902X_CEC_I2C_ADDR << 1, -+ .flags = 0, -+ .len = 2, -+ .buf = data, -+ }; - u8 chipid[4]; - int ret; - -@@ -980,40 +1007,66 @@ static int sii902x_probe(struct i2c_client *client, - } - - mutex_init(&sii902x->mutex); -+ sii902x->supplies[0].supply = "iovcc"; -+ sii902x->supplies[1].supply = "cvcc12"; -+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sii902x->supplies), -+ sii902x->supplies); -+ if (ret) { -+ if(ret != -EPROBE_DEFER) -+ dev_err(dev, "regulator_bulk_get failed\n"); -+ return ret; -+ } -+ -+ ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies), -+ sii902x->supplies); -+ if (ret) { -+ dev_err(dev, "regulator_bulk_enable failed\n"); -+ return ret; -+ } - - sii902x_reset(sii902x); - - ret = regmap_write(sii902x->regmap, SII902X_REG_TPI_RQB, 0x0); - if (ret) -- return ret; -+ goto err_disable_regulator; - - ret = regmap_bulk_read(sii902x->regmap, SII902X_REG_CHIPID(0), - &chipid, 4); - if (ret) { - dev_err(dev, "regmap_read failed %d\n", ret); -- return ret; -+ goto err_disable_regulator; - } - - if (chipid[0] != 0xb0) { - dev_err(dev, "Invalid chipid: %02x (expecting 0xb0)\n", - chipid[0]); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_disable_regulator; - } - -+ /* -+ * By default, CEC must be disabled to allow other CEC devives -+ * to bypass the bridge. -+ */ -+ ret = i2c_transfer(client->adapter, &msg, 1); -+ if (ret < 0) -+ dev_warn(&client->dev, "Failed to disable CEC device!\n"); -+ - /* Clear all pending interrupts */ - regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status); - regmap_write(sii902x->regmap, SII902X_INT_STATUS, status); - - if (client->irq > 0) { -- regmap_write(sii902x->regmap, SII902X_INT_ENABLE, -- SII902X_HOTPLUG_EVENT); -+ regmap_update_bits(sii902x->regmap, SII902X_INT_ENABLE, -+ SII902X_HOTPLUG_EVENT, -+ SII902X_HOTPLUG_EVENT); - - ret = devm_request_threaded_irq(dev, client->irq, NULL, - sii902x_interrupt, - IRQF_ONESHOT, dev_name(dev), - sii902x); - if (ret) -- return ret; -+ goto err_disable_regulator; - } - - sii902x->bridge.funcs = &sii902x_bridge_funcs; -@@ -1033,7 +1086,20 @@ static int sii902x_probe(struct i2c_client *client, - return -ENOMEM; - - sii902x->i2cmux->priv = sii902x; -- return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0); -+ -+ ret = i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0); -+ if (ret) { -+ dev_err(dev, "Couldn't add i2c mux adapter\n"); -+ return ret; -+ } -+ -+ return 0; -+ -+err_disable_regulator: -+ regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies), -+ sii902x->supplies); -+ -+ return ret; - } - - static int sii902x_remove(struct i2c_client *client) -@@ -1044,9 +1110,71 @@ static int sii902x_remove(struct i2c_client *client) - i2c_mux_del_adapters(sii902x->i2cmux); - drm_bridge_remove(&sii902x->bridge); - -+ regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies), -+ sii902x->supplies); -+ -+ return 0; -+} -+ -+static int sii902x_pm_suspend(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sii902x *sii902x = i2c_get_clientdata(client); -+ -+ DRM_DEBUG_DRIVER("\n"); -+ -+ if (sii902x->reset_gpio) -+ gpiod_set_value(sii902x->reset_gpio, 1); -+ -+ regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies), -+ sii902x->supplies); -+ -+ return 0; -+} -+ -+static int sii902x_pm_resume(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sii902x *sii902x = i2c_get_clientdata(client); -+ unsigned char data[2] = { SII902X_CEC_SETUP, 0}; -+ struct i2c_msg msg = { -+ .addr = SII902X_CEC_I2C_ADDR << 1, -+ .flags = 0, -+ .len = 2, -+ .buf = data, -+ }; -+ int ret; -+ -+ DRM_DEBUG_DRIVER("\n"); -+ -+ ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies), -+ sii902x->supplies); -+ if (ret) { -+ DRM_ERROR("regulator_bulk_enable failed\n"); -+ return ret; -+ } -+ -+ if (sii902x->reset_gpio) -+ gpiod_set_value(sii902x->reset_gpio, 0); -+ -+ regmap_write(sii902x->regmap, SII902X_REG_TPI_RQB, 0x00); -+ -+ ret = i2c_transfer(client->adapter, &msg, 1); -+ if (ret < 0) -+ DRM_ERROR("Failed to disable CEC device!\n"); -+ -+ if (client->irq > 0) -+ regmap_update_bits(sii902x->regmap, SII902X_INT_ENABLE, -+ SII902X_HOTPLUG_EVENT, -+ SII902X_HOTPLUG_EVENT); -+ - return 0; - } - -+static const struct dev_pm_ops sii902x_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(sii902x_pm_suspend, sii902x_pm_resume) -+}; -+ - static const struct of_device_id sii902x_dt_ids[] = { - { .compatible = "sil,sii9022", }, - { } -@@ -1065,6 +1193,7 @@ static struct i2c_driver sii902x_driver = { - .driver = { - .name = "sii902x", - .of_match_table = sii902x_dt_ids, -+ .pm = &sii902x_pm_ops, - }, - .id_table = sii902x_i2c_ids, - }; -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c -index 675442bfc1bd7..34a9569e28f6d 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c -@@ -90,6 +90,7 @@ - #define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS 0x1 - #define VID_MODE_TYPE_BURST 0x2 - #define VID_MODE_TYPE_MASK 0x3 -+#define ENABLE_LOW_POWER_CMD BIT(15) - #define VID_MODE_VPG_ENABLE BIT(16) - #define VID_MODE_VPG_HORIZONTAL BIT(24) - -@@ -212,6 +213,20 @@ - - #define DSI_INT_ST0 0xbc - #define DSI_INT_ST1 0xc0 -+#define GPRXE BIT(12) -+#define GPRDE BIT(11) -+#define GPTXE BIT(10) -+#define GPWRE BIT(9) -+#define GCWRE BIT(8) -+#define DPIPLDWE BIT(7) -+#define EOTPE BIT(6) -+#define PSE BIT(5) -+#define CRCE BIT(4) -+#define ECCME BIT(3) -+#define ECCSE BIT(2) -+#define TOLPRX BIT(1) -+#define TOHSTX BIT(0) -+ - #define DSI_INT_MSK0 0xc4 - #define DSI_INT_MSK1 0xc8 - -@@ -295,9 +310,7 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, - { - struct dw_mipi_dsi *dsi = host_to_dsi(host); - const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data; -- struct drm_bridge *bridge; -- struct drm_panel *panel; -- int ret; -+ int ret = -ENODEV; - - if (device->lanes > dsi->plat_data->max_data_lanes) { - dev_err(dsi->dev, "the number of data lanes(%u) is too many\n", -@@ -310,21 +323,6 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, - dsi->format = device->format; - dsi->mode_flags = device->mode_flags; - -- ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0, -- &panel, &bridge); -- if (ret) -- return ret; -- -- if (panel) { -- bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI); -- if (IS_ERR(bridge)) -- return PTR_ERR(bridge); -- } -- -- dsi->panel_bridge = bridge; -- -- drm_bridge_add(&dsi->bridge); -- - if (pdata->host_ops && pdata->host_ops->attach) { - ret = pdata->host_ops->attach(pdata->priv_data, device); - if (ret < 0) -@@ -347,10 +345,6 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host, - return ret; - } - -- drm_of_panel_bridge_remove(host->dev->of_node, 1, 0); -- -- drm_bridge_remove(&dsi->bridge); -- - return 0; - } - -@@ -360,13 +354,32 @@ static void dw_mipi_message_config(struct dw_mipi_dsi *dsi, - bool lpm = msg->flags & MIPI_DSI_MSG_USE_LPM; - u32 val = 0; - -+ /* -+ * In lpm mode, we maybe can compute the packet size dependig on -+ * message lenght. -+ */ -+ /* -+ * TODO dw drv improvements -+ * largest packet sizes during hfp or during vsa/vpb/vfp -+ * should be computed according to byte lane, lane number and only -+ * if sending lp cmds in high speed is enable (PHY_TXREQUESTCLKHS) -+ */ -+ dsi_write(dsi, DSI_DPI_LP_CMD_TIM, OUTVACT_LPCMD_TIME(16) -+ | INVACT_LPCMD_TIME(4)); -+ - if (msg->flags & MIPI_DSI_MSG_REQ_ACK) - val |= ACK_RQST_EN; - if (lpm) - val |= CMD_MODE_ALL_LP; - -- dsi_write(dsi, DSI_LPCLK_CTRL, lpm ? 0 : PHY_TXREQUESTCLKHS); - dsi_write(dsi, DSI_CMD_MODE_CFG, val); -+ -+ val = dsi_read(dsi, DSI_VID_MODE_CFG); -+ if (lpm) -+ val |= ENABLE_LOW_POWER_CMD; -+ else -+ val &= ~ENABLE_LOW_POWER_CMD; -+ dsi_write(dsi, DSI_VID_MODE_CFG, val); - } - - static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) -@@ -396,6 +409,42 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) - return 0; - } - -+static int dw_mipi_dsi_read_status(struct dw_mipi_dsi *dsi) -+{ -+ u32 val; -+ -+ val = dsi_read(dsi, DSI_INT_ST1); -+ -+ if (val & GPRXE) -+ DRM_DEBUG_DRIVER("DSI Generic payload receive error\n"); -+ if (val & GPRDE) -+ DRM_DEBUG_DRIVER("DSI Generic payload read error\n"); -+ if (val & GPTXE) -+ DRM_DEBUG_DRIVER("DSI Generic payload transmit error\n"); -+ if (val & GPWRE) -+ DRM_DEBUG_DRIVER("DSI Generic payload write error\n"); -+ if (val & GCWRE) -+ DRM_DEBUG_DRIVER("DSI Generic command write error\n"); -+ if (val & DPIPLDWE) -+ DRM_DEBUG_DRIVER("DSI DPI payload write error\n"); -+ if (val & EOTPE) -+ DRM_DEBUG_DRIVER("DSI EoTp error\n"); -+ if (val & PSE) -+ DRM_DEBUG_DRIVER("DSI Packet size error\n"); -+ if (val & CRCE) -+ DRM_DEBUG_DRIVER("DSI CRC error\n"); -+ if (val & ECCME) -+ DRM_DEBUG_DRIVER("DSI ECC multi-bit error\n"); -+ if (val & ECCSE) -+ DRM_DEBUG_DRIVER("DSI ECC single-bit error\n"); -+ if (val & TOLPRX) -+ DRM_DEBUG_DRIVER("DSI Timeout low-power reception\n"); -+ if (val & TOHSTX) -+ DRM_DEBUG_DRIVER("DSI Timeout high-speed transmission\n"); -+ -+ return val; -+} -+ - static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi, - const struct mipi_dsi_packet *packet) - { -@@ -425,6 +474,12 @@ static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi, - "failed to get available write payload FIFO\n"); - return ret; - } -+ -+ val = dw_mipi_dsi_read_status(dsi); -+ if (val) { -+ dev_err(dsi->dev, "dsi status error 0x%0x\n", val); -+ return -EINVAL; -+ } - } - - word = 0; -@@ -458,6 +513,12 @@ static int dw_mipi_dsi_read(struct dw_mipi_dsi *dsi, - return ret; - } - -+ val = dw_mipi_dsi_read_status(dsi); -+ if (val) { -+ dev_err(dsi->dev, "dsi status error 0x%0x\n", val); -+ return -EINVAL; -+ } -+ - val = dsi_read(dsi, DSI_GEN_PLD_DATA); - for (j = 0; j < 4 && j + i < len; j++) - buf[i + j] = val >> (8 * j); -@@ -472,6 +533,7 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, - struct dw_mipi_dsi *dsi = host_to_dsi(host); - struct mipi_dsi_packet packet; - int ret, nb_bytes; -+ int retry = 3; - - ret = mipi_dsi_create_packet(&packet, msg); - if (ret) { -@@ -483,24 +545,32 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, - if (dsi->slave) - dw_mipi_message_config(dsi->slave, msg); - -- ret = dw_mipi_dsi_write(dsi, &packet); -- if (ret) -- return ret; -- if (dsi->slave) { -- ret = dw_mipi_dsi_write(dsi->slave, &packet); -+ while (retry--) { -+ ret = dw_mipi_dsi_write(dsi, &packet); - if (ret) -- return ret; -- } -+ continue; - -- if (msg->rx_buf && msg->rx_len) { -- ret = dw_mipi_dsi_read(dsi, msg); -- if (ret) -- return ret; -- nb_bytes = msg->rx_len; -- } else { -- nb_bytes = packet.size; -+ if (dsi->slave) { -+ ret = dw_mipi_dsi_write(dsi->slave, &packet); -+ if (ret) -+ continue; -+ } -+ -+ if (msg->rx_buf && msg->rx_len) { -+ ret = dw_mipi_dsi_read(dsi, msg); -+ if (ret) -+ continue; -+ nb_bytes = msg->rx_len; -+ break; -+ } else { -+ nb_bytes = packet.size; -+ break; -+ } - } - -+ if (ret) -+ return ret; -+ - return nb_bytes; - } - -@@ -541,16 +611,22 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) - static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi, - unsigned long mode_flags) - { -+ u32 val; -+ - dsi_write(dsi, DSI_PWR_UP, RESET); - - if (mode_flags & MIPI_DSI_MODE_VIDEO) { - dsi_write(dsi, DSI_MODE_CFG, ENABLE_VIDEO_MODE); - dw_mipi_dsi_video_mode_config(dsi); -- dsi_write(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS); - } else { - dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE); - } - -+ val = PHY_TXREQUESTCLKHS; -+ if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) -+ val |= AUTO_CLKLANE_CTRL; -+ dsi_write(dsi, DSI_LPCLK_CTRL, val); -+ - dsi_write(dsi, DSI_PWR_UP, POWERUP); - } - -@@ -611,14 +687,6 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi, - dsi_write(dsi, DSI_DPI_VCID, DPI_VCID(dsi->channel)); - dsi_write(dsi, DSI_DPI_COLOR_CODING, color); - dsi_write(dsi, DSI_DPI_CFG_POL, val); -- /* -- * TODO dw drv improvements -- * largest packet sizes during hfp or during vsa/vpb/vfp -- * should be computed according to byte lane, lane number and only -- * if sending lp cmds in high speed is enable (PHY_TXREQUESTCLKHS) -- */ -- dsi_write(dsi, DSI_DPI_LP_CMD_TIM, OUTVACT_LPCMD_TIME(4) -- | INVACT_LPCMD_TIME(4)); - } - - static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi) -@@ -814,7 +882,8 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge) - * This needs to be fixed in the drm_bridge framework and the API - * needs to be updated to manage our own call chains... - */ -- dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge); -+ if (dsi->panel_bridge->funcs->post_disable) -+ dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge); - - if (dsi->slave) { - dw_mipi_dsi_disable(dsi->slave); -@@ -982,6 +1051,9 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, - struct reset_control *apb_rst; - struct dw_mipi_dsi *dsi; - struct resource *res; -+ struct drm_bridge *bridge; -+ struct drm_panel *panel; -+ int i, nb_endpoints; - int ret; - - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); -@@ -1052,8 +1124,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, - ret = mipi_dsi_host_register(&dsi->dsi_host); - if (ret) { - dev_err(dev, "Failed to register MIPI host: %d\n", ret); -- dw_mipi_dsi_debugfs_remove(dsi); -- return ERR_PTR(ret); -+ goto err_pmr_enable; - } - - dsi->bridge.driver_private = dsi; -@@ -1062,11 +1133,54 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, - dsi->bridge.of_node = pdev->dev.of_node; - #endif - -+ /* Get number of endpoints */ -+ nb_endpoints = of_graph_get_endpoint_count(pdev->dev.of_node); -+ if (!nb_endpoints) { -+ ret = -ENODEV; -+ goto err_host_reg; -+ } -+ -+ for (i = 1; i < nb_endpoints; i++) { -+ ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, i, 0, -+ &panel, &bridge); -+ if (!ret) -+ break; -+ else if (ret == -EPROBE_DEFER) -+ goto err_host_reg; -+ } -+ -+ /* check if an error is returned >> no panel or bridge detected */ -+ if (ret) -+ goto err_host_reg; -+ -+ if (panel) { -+ bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI); -+ if (IS_ERR(bridge)) { -+ ret = PTR_ERR(bridge); -+ goto err_host_reg; -+ } -+ } -+ -+ dsi->panel_bridge = bridge; -+ -+ drm_bridge_add(&dsi->bridge); -+ - return dsi; -+ -+err_host_reg: -+ mipi_dsi_host_unregister(&dsi->dsi_host); -+ -+err_pmr_enable: -+ pm_runtime_disable(dev); -+ dw_mipi_dsi_debugfs_remove(dsi); -+ -+ return ERR_PTR(ret); - } - - static void __dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi) - { -+ drm_bridge_remove(&dsi->bridge); -+ drm_panel_bridge_remove(dsi->panel_bridge); - mipi_dsi_host_unregister(&dsi->dsi_host); - - pm_runtime_disable(dsi->dev); -diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c -index 3fd35e6b9d535..80de2fb7ed817 100644 ---- a/drivers/gpu/drm/drm_modes.c -+++ b/drivers/gpu/drm/drm_modes.c -@@ -127,7 +127,7 @@ EXPORT_SYMBOL(drm_mode_probed_add); - * according to the hdisplay, vdisplay, vrefresh. - * It is based from the VESA(TM) Coordinated Video Timing Generator by - * Graham Loveridge April 9, 2003 available at -- * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls -+ * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls - * - * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. - * What I have done is to translate it by using integer calculation. -@@ -614,6 +614,15 @@ void drm_display_mode_from_videomode(const struct videomode *vm, - dmode->flags |= DRM_MODE_FLAG_DBLSCAN; - if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) - dmode->flags |= DRM_MODE_FLAG_DBLCLK; -+ if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) -+ dmode->flags |= DRM_MODE_FLAG_PPIXDATA; -+ else if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) -+ dmode->flags |= DRM_MODE_FLAG_NPIXDATA; -+ if (vm->flags & DISPLAY_FLAGS_DE_HIGH) -+ dmode->flags |= DRM_MODE_FLAG_PDE; -+ else if (vm->flags & DISPLAY_FLAGS_DE_LOW) -+ dmode->flags |= DRM_MODE_FLAG_NDE; -+ - drm_mode_set_name(dmode); - } - EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); -@@ -655,6 +664,14 @@ void drm_display_mode_to_videomode(const struct drm_display_mode *dmode, - vm->flags |= DISPLAY_FLAGS_DOUBLESCAN; - if (dmode->flags & DRM_MODE_FLAG_DBLCLK) - vm->flags |= DISPLAY_FLAGS_DOUBLECLK; -+ if (dmode->flags & DRM_MODE_FLAG_PPIXDATA) -+ vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; -+ else if (dmode->flags & DRM_MODE_FLAG_NPIXDATA) -+ vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE; -+ if (dmode->flags & DRM_MODE_FLAG_PDE) -+ vm->flags |= DISPLAY_FLAGS_DE_HIGH; -+ else if (dmode->flags & DRM_MODE_FLAG_NDE) -+ vm->flags |= DISPLAY_FLAGS_DE_LOW; - } - EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); - -diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c -index c7b48df8869a1..2fdf9d183d239 100644 ---- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c -+++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c -@@ -101,20 +101,6 @@ static void otm8009a_dcs_write_buf(struct otm8009a *ctx, const void *data, - DRM_WARN("mipi dsi dcs write buffer failed\n"); - } - --static void otm8009a_dcs_write_buf_hs(struct otm8009a *ctx, const void *data, -- size_t len) --{ -- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); -- -- /* data will be sent in dsi hs mode (ie. no lpm) */ -- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; -- -- otm8009a_dcs_write_buf(ctx, data, len); -- -- /* restore back the dsi lpm mode */ -- dsi->mode_flags |= MIPI_DSI_MODE_LPM; --} -- - #define dcs_write_seq(ctx, seq...) \ - ({ \ - static const u8 d[] = { seq }; \ -@@ -401,7 +387,7 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd) - */ - data[0] = MIPI_DCS_SET_DISPLAY_BRIGHTNESS; - data[1] = bd->props.brightness; -- otm8009a_dcs_write_buf_hs(ctx, data, ARRAY_SIZE(data)); -+ otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data)); - - /* set Brightness Control & Backlight on */ - data[1] = 0x24; -@@ -413,7 +399,7 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd) - - /* Update Brightness Control & Backlight */ - data[0] = MIPI_DCS_WRITE_CONTROL_DISPLAY; -- otm8009a_dcs_write_buf_hs(ctx, data, ARRAY_SIZE(data)); -+ otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data)); - - return 0; - } -@@ -453,7 +439,7 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi) - dsi->lanes = 2; - dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | -- MIPI_DSI_MODE_LPM; -+ MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS; - - drm_panel_init(&ctx->panel); - ctx->panel.dev = dev; -diff --git a/drivers/gpu/drm/panel/panel-raydium-rm68200.c b/drivers/gpu/drm/panel/panel-raydium-rm68200.c -index ba889625ad435..b20e26666c7cb 100644 ---- a/drivers/gpu/drm/panel/panel-raydium-rm68200.c -+++ b/drivers/gpu/drm/panel/panel-raydium-rm68200.c -@@ -84,15 +84,15 @@ struct rm68200 { - }; - - static const struct drm_display_mode default_mode = { -- .clock = 52582, -+ .clock = 54000, - .hdisplay = 720, -- .hsync_start = 720 + 38, -- .hsync_end = 720 + 38 + 8, -- .htotal = 720 + 38 + 8 + 38, -+ .hsync_start = 720 + 48, -+ .hsync_end = 720 + 48 + 9, -+ .htotal = 720 + 48 + 9 + 48, - .vdisplay = 1280, - .vsync_start = 1280 + 12, -- .vsync_end = 1280 + 12 + 4, -- .vtotal = 1280 + 12 + 4 + 12, -+ .vsync_end = 1280 + 12 + 5, -+ .vtotal = 1280 + 12 + 5 + 12, - .vrefresh = 50, - .flags = 0, - .width_mm = 68, -@@ -402,7 +402,7 @@ static int rm68200_probe(struct mipi_dsi_device *dsi) - dsi->lanes = 2; - dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | -- MIPI_DSI_MODE_LPM; -+ MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS; - - drm_panel_init(&ctx->panel); - ctx->panel.dev = dev; -diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c -index a03a642c147cc..d1689758fea0d 100644 ---- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c -+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c -@@ -260,8 +260,11 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, - /* Compute requested pll out */ - bpp = mipi_dsi_pixel_format_to_bpp(format); - pll_out_khz = mode->clock * bpp / lanes; -+ - /* Add 20% to pll out to be higher than pixel bw (burst mode only) */ -- pll_out_khz = (pll_out_khz * 12) / 10; -+ if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST) -+ pll_out_khz = (pll_out_khz * 12) / 10; -+ - if (pll_out_khz > dsi->lane_max_kbps) { - pll_out_khz = dsi->lane_max_kbps; - DRM_WARN("Warning max phy mbps is used\n"); -@@ -361,7 +364,9 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) - dsi->pllref_clk = devm_clk_get(dev, "ref"); - if (IS_ERR(dsi->pllref_clk)) { - ret = PTR_ERR(dsi->pllref_clk); -- DRM_ERROR("Unable to get pll reference clock: %d\n", ret); -+ if (ret != -EPROBE_DEFER) -+ DRM_ERROR("Unable to get pll reference clock: %d\n", -+ ret); - goto err_clk_get; - } - -diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c -index 3ab4fbf8eb0d1..1f7836be2e6a9 100644 ---- a/drivers/gpu/drm/stm/ltdc.c -+++ b/drivers/gpu/drm/stm/ltdc.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -39,10 +40,6 @@ - #define NB_CRTC 1 - #define CRTC_MASK GENMASK(NB_CRTC - 1, 0) - --#define MAX_IRQ 4 -- --#define MAX_ENDPOINTS 2 -- - #define HWVER_10200 0x010200 - #define HWVER_10300 0x010300 - #define HWVER_20101 0x020101 -@@ -436,9 +433,6 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, - /* Commit shadow registers = update planes at next vblank */ - reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR); - -- /* Enable LTDC */ -- reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN); -- - drm_crtc_vblank_on(crtc); - } - -@@ -452,9 +446,6 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc, - - drm_crtc_vblank_off(crtc); - -- /* disable LTDC */ -- reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN); -- - /* disable IRQ */ - reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE); - -@@ -653,9 +644,14 @@ static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = { - static int ltdc_crtc_enable_vblank(struct drm_crtc *crtc) - { - struct ltdc_device *ldev = crtc_to_ltdc(crtc); -+ struct drm_crtc_state *state = crtc->state; - - DRM_DEBUG_DRIVER("\n"); -- reg_set(ldev->regs, LTDC_IER, IER_LIE); -+ -+ if (state->enable) -+ reg_set(ldev->regs, LTDC_IER, IER_LIE); -+ else -+ return -EPERM; - - return 0; - } -@@ -735,22 +731,44 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) - { - struct drm_framebuffer *fb = state->fb; -- u32 src_w, src_h; -+ struct drm_crtc_state *crtc_state; -+ struct drm_rect *src = &state->src; -+ struct drm_rect *dst = &state->dst; - - DRM_DEBUG_DRIVER("\n"); - - if (!fb) - return 0; - -- /* convert src_ from 16:16 format */ -- src_w = state->src_w >> 16; -- src_h = state->src_h >> 16; -+ /* convert src from 16:16 format */ -+ src->x1 = state->src_x >> 16; -+ src->y1 = state->src_y >> 16; -+ src->x2 = (state->src_w >> 16) + src->x1 - 1; -+ src->y2 = (state->src_h >> 16) + src->y1 - 1; - -- /* Reject scaling */ -- if (src_w != state->crtc_w || src_h != state->crtc_h) { -- DRM_ERROR("Scaling is not supported"); -+ dst->x1 = state->crtc_x; -+ dst->y1 = state->crtc_y; -+ dst->x2 = state->crtc_w + dst->x1 - 1; -+ dst->y2 = state->crtc_h + dst->y1 - 1; -+ -+ DRM_DEBUG_DRIVER("plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n", -+ plane->base.id, fb->base.id, -+ src->x2 - src->x1 + 1, src->y2 - src->y1 + 1, -+ src->x1, src->y1, -+ dst->x2 - dst->x1 + 1, dst->y2 - dst->y1 + 1, -+ dst->x1, dst->y1); -+ -+ crtc_state = drm_atomic_get_existing_crtc_state(state->state, -+ state->crtc); -+ /* destination coordinates do not have to exceed display sizes */ -+ if (crtc_state && (crtc_state->mode.hdisplay <= dst->x2 || -+ crtc_state->mode.vdisplay <= dst->y2)) -+ return -EINVAL; -+ -+ /* source sizes do not have to exceed destination sizes */ -+ if (dst->x2 - dst->x1 < src->x2 - src->x1 || -+ dst->y2 - dst->y1 < src->y2 - src->y1) - return -EINVAL; -- } - - return 0; - } -@@ -760,44 +778,36 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, - { - struct ltdc_device *ldev = plane_to_ltdc(plane); - struct drm_plane_state *state = plane->state; -+ struct drm_rect *src = &state->src; -+ struct drm_rect *dst = &state->dst; - struct drm_framebuffer *fb = state->fb; - u32 lofs = plane->index * LAY_OFS; -- u32 x0 = state->crtc_x; -- u32 x1 = state->crtc_x + state->crtc_w - 1; -- u32 y0 = state->crtc_y; -- u32 y1 = state->crtc_y + state->crtc_h - 1; -- u32 src_x, src_y, src_w, src_h; - u32 val, pitch_in_bytes, line_length, paddr, ahbp, avbp, bpcr; - enum ltdc_pix_fmt pf; -+ struct drm_rect dr; - - if (!state->crtc || !fb) { - DRM_DEBUG_DRIVER("fb or crtc NULL"); - return; - } - -- /* convert src_ from 16:16 format */ -- src_x = state->src_x >> 16; -- src_y = state->src_y >> 16; -- src_w = state->src_w >> 16; -- src_h = state->src_h >> 16; -- -- DRM_DEBUG_DRIVER("plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n", -- plane->base.id, fb->base.id, -- src_w, src_h, src_x, src_y, -- state->crtc_w, state->crtc_h, -- state->crtc_x, state->crtc_y); -+ /* compute final coordinates of frame buffer */ -+ dr.x1 = src->x1 + dst->x1; -+ dr.y1 = src->y1 + dst->y1; -+ dr.x2 = src->x2 + dst->x1; -+ dr.y2 = src->y2 + dst->y1; - - bpcr = reg_read(ldev->regs, LTDC_BPCR); - ahbp = (bpcr & BPCR_AHBP) >> 16; - avbp = bpcr & BPCR_AVBP; - - /* Configures the horizontal start and stop position */ -- val = ((x1 + 1 + ahbp) << 16) + (x0 + 1 + ahbp); -+ val = ((dr.x2 + 1 + ahbp) << 16) + (dr.x1 + 1 + ahbp); - reg_update_bits(ldev->regs, LTDC_L1WHPCR + lofs, - LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS, val); - - /* Configures the vertical start and stop position */ -- val = ((y1 + 1 + avbp) << 16) + (y0 + 1 + avbp); -+ val = ((dr.y2 + 1 + avbp) << 16) + (dr.y1 + 1 + avbp); - reg_update_bits(ldev->regs, LTDC_L1WVPCR + lofs, - LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, val); - -@@ -816,8 +826,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, - - /* Configures the color frame buffer pitch in bytes & line length */ - pitch_in_bytes = fb->pitches[0]; -- line_length = fb->format->cpp[0] * -- (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1; -+ line_length = fb->format->cpp[0] * (dr.x2 - dr.x1 + 1) + -+ (ldev->caps.bus_width >> 3) - 1; - val = ((pitch_in_bytes << 16) | line_length); - reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs, - LXCFBLR_CFBLL | LXCFBLR_CFBP, val); -@@ -840,7 +850,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, - LXBFCR_BF2 | LXBFCR_BF1, val); - - /* Configures the frame buffer line number */ -- val = y1 - y0 + 1; -+ val = dr.y2 - dr.y1 + 1; - reg_update_bits(ldev->regs, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, val); - - /* Sets the FB address */ -@@ -1040,6 +1050,54 @@ static const struct drm_encoder_funcs ltdc_encoder_funcs = { - .destroy = drm_encoder_cleanup, - }; - -+static void ltdc_encoder_disable(struct drm_encoder *encoder) -+{ -+ struct drm_device *ddev = encoder->dev; -+ struct ltdc_device *ldev = ddev->dev_private; -+ -+ DRM_DEBUG_DRIVER("\n"); -+ -+ /* Disable LTDC */ -+ reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN); -+ -+ /* Set to sleep state the pinctrl whatever type of encoder */ -+ pinctrl_pm_select_sleep_state(ddev->dev); -+} -+ -+static void ltdc_encoder_enable(struct drm_encoder *encoder) -+{ -+ struct drm_device *ddev = encoder->dev; -+ struct ltdc_device *ldev = ddev->dev_private; -+ -+ DRM_DEBUG_DRIVER("\n"); -+ -+ /* Enable LTDC */ -+ reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN); -+} -+ -+static void ltdc_encoder_mode_set(struct drm_encoder *encoder, -+ struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct drm_device *ddev = encoder->dev; -+ -+ DRM_DEBUG_DRIVER("\n"); -+ -+ /* -+ * Set to default state the pinctrl only with DPI type. -+ * Others types like DSI, don't need pinctrl due to -+ * internal bridge (the signals do not come out of the chipset). -+ */ -+ if (encoder->encoder_type == DRM_MODE_ENCODER_DPI) -+ pinctrl_pm_select_default_state(ddev->dev); -+} -+ -+static const struct drm_encoder_helper_funcs ltdc_encoder_helper_funcs = { -+ .disable = ltdc_encoder_disable, -+ .enable = ltdc_encoder_enable, -+ .mode_set = ltdc_encoder_mode_set, -+}; -+ - static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge) - { - struct drm_encoder *encoder; -@@ -1055,6 +1113,8 @@ static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge) - drm_encoder_init(ddev, encoder, <dc_encoder_funcs, - DRM_MODE_ENCODER_DPI, NULL); - -+ drm_encoder_helper_add(encoder, <dc_encoder_helper_funcs); -+ - ret = drm_bridge_attach(encoder, bridge, NULL); - if (ret) { - drm_encoder_cleanup(encoder); -@@ -1101,12 +1161,14 @@ static int ltdc_get_caps(struct drm_device *ddev) - ldev->caps.pad_max_freq_hz = 90000000; - if (ldev->caps.hw_version == HWVER_10200) - ldev->caps.pad_max_freq_hz = 65000000; -+ ldev->caps.nb_irq = 2; - break; - case HWVER_20101: - ldev->caps.reg_ofs = REG_OFS_4; - ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a1; - ldev->caps.non_alpha_only_l1 = false; - ldev->caps.pad_max_freq_hz = 150000000; -+ ldev->caps.nb_irq = 4; - break; - default: - return -ENODEV; -@@ -1145,36 +1207,20 @@ int ltdc_load(struct drm_device *ddev) - struct ltdc_device *ldev = ddev->dev_private; - struct device *dev = ddev->dev; - struct device_node *np = dev->of_node; -- struct drm_bridge *bridge[MAX_ENDPOINTS] = {NULL}; -- struct drm_panel *panel[MAX_ENDPOINTS] = {NULL}; -+ struct drm_bridge *bridge; -+ struct drm_panel *panel; - struct drm_crtc *crtc; - struct reset_control *rstc; - struct resource *res; -- int irq, ret, i, endpoint_not_ready = -ENODEV; -+ int irq, i, nb_endpoints; -+ int ret = -ENODEV; - - DRM_DEBUG_DRIVER("\n"); - -- /* Get endpoints if any */ -- for (i = 0; i < MAX_ENDPOINTS; i++) { -- ret = drm_of_find_panel_or_bridge(np, 0, i, &panel[i], -- &bridge[i]); -- -- /* -- * If at least one endpoint is -EPROBE_DEFER, defer probing, -- * else if at least one endpoint is ready, continue probing. -- */ -- if (ret == -EPROBE_DEFER) -- return ret; -- else if (!ret) -- endpoint_not_ready = 0; -- } -- -- if (endpoint_not_ready) -- return endpoint_not_ready; -- -- rstc = devm_reset_control_get_exclusive(dev, NULL); -- -- mutex_init(&ldev->err_lock); -+ /* Get number of endpoints */ -+ nb_endpoints = of_graph_get_endpoint_count(np); -+ if (!nb_endpoints) -+ return -ENODEV; - - ldev->pixel_clk = devm_clk_get(dev, "lcd"); - if (IS_ERR(ldev->pixel_clk)) { -@@ -1188,6 +1234,43 @@ int ltdc_load(struct drm_device *ddev) - return -ENODEV; - } - -+ /* Get endpoints if any */ -+ for (i = 0; i < nb_endpoints; i++) { -+ ret = drm_of_find_panel_or_bridge(np, 0, i, &panel, &bridge); -+ -+ /* -+ * If at least one endpoint is -ENODEV, continue probing, -+ * else if at least one endpoint returned an error -+ * (ie -EPROBE_DEFER) then stop probing. -+ */ -+ if (ret == -ENODEV) -+ continue; -+ else if (ret) -+ goto err; -+ -+ if (panel) { -+ bridge = drm_panel_bridge_add(panel, -+ DRM_MODE_CONNECTOR_DPI); -+ if (IS_ERR(bridge)) { -+ DRM_ERROR("panel-bridge endpoint %d\n", i); -+ ret = PTR_ERR(bridge); -+ goto err; -+ } -+ } -+ -+ if (bridge) { -+ ret = ltdc_encoder_init(ddev, bridge); -+ if (ret) { -+ DRM_ERROR("init encoder endpoint %d\n", i); -+ goto err; -+ } -+ } -+ } -+ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ -+ mutex_init(&ldev->err_lock); -+ - if (!IS_ERR(rstc)) { - reset_control_assert(rstc); - usleep_range(10, 20); -@@ -1206,24 +1289,6 @@ int ltdc_load(struct drm_device *ddev) - reg_clear(ldev->regs, LTDC_IER, - IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE); - -- for (i = 0; i < MAX_IRQ; i++) { -- irq = platform_get_irq(pdev, i); -- if (irq == -EPROBE_DEFER) -- goto err; -- -- if (irq < 0) -- continue; -- -- ret = devm_request_threaded_irq(dev, irq, ltdc_irq, -- ltdc_irq_thread, IRQF_ONESHOT, -- dev_name(dev), ddev); -- if (ret) { -- DRM_ERROR("Failed to register LTDC interrupt\n"); -- goto err; -- } -- } -- -- - ret = ltdc_get_caps(ddev); - if (ret) { - DRM_ERROR("hardware identifier (0x%08x) not supported!\n", -@@ -1233,25 +1298,21 @@ int ltdc_load(struct drm_device *ddev) - - DRM_DEBUG_DRIVER("ltdc hw version 0x%08x\n", ldev->caps.hw_version); - -- /* Add endpoints panels or bridges if any */ -- for (i = 0; i < MAX_ENDPOINTS; i++) { -- if (panel[i]) { -- bridge[i] = drm_panel_bridge_add(panel[i], -- DRM_MODE_CONNECTOR_DPI); -- if (IS_ERR(bridge[i])) { -- DRM_ERROR("panel-bridge endpoint %d\n", i); -- ret = PTR_ERR(bridge[i]); -- goto err; -- } -+ for (i = 0; i < ldev->caps.nb_irq; i++) { -+ irq = platform_get_irq(pdev, i); -+ if (irq < 0) { -+ ret = irq; -+ goto err; - } - -- if (bridge[i]) { -- ret = ltdc_encoder_init(ddev, bridge[i]); -- if (ret) { -- DRM_ERROR("init encoder endpoint %d\n", i); -- goto err; -- } -+ ret = devm_request_threaded_irq(dev, irq, ltdc_irq, -+ ltdc_irq_thread, IRQF_ONESHOT, -+ dev_name(dev), ddev); -+ if (ret) { -+ DRM_ERROR("Failed to register LTDC interrupt\n"); -+ goto err; - } -+ - } - - crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); -@@ -1280,12 +1341,14 @@ int ltdc_load(struct drm_device *ddev) - - clk_disable_unprepare(ldev->pixel_clk); - -+ pinctrl_pm_select_sleep_state(ddev->dev); -+ - pm_runtime_enable(ddev->dev); - - return 0; - err: -- for (i = 0; i < MAX_ENDPOINTS; i++) -- drm_panel_bridge_remove(bridge[i]); -+ for (i = 0; i < nb_endpoints; i++) -+ drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i); - - clk_disable_unprepare(ldev->pixel_clk); - -@@ -1294,11 +1357,14 @@ int ltdc_load(struct drm_device *ddev) - - void ltdc_unload(struct drm_device *ddev) - { -- int i; -+ struct device *dev = ddev->dev; -+ int nb_endpoints, i; - - DRM_DEBUG_DRIVER("\n"); - -- for (i = 0; i < MAX_ENDPOINTS; i++) -+ nb_endpoints = of_graph_get_endpoint_count(dev->of_node); -+ -+ for (i = 0; i < nb_endpoints; i++) - drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i); - - pm_runtime_disable(ddev->dev); -diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h -index a1ad0ae3b0068..310e87f0667c2 100644 ---- a/drivers/gpu/drm/stm/ltdc.h -+++ b/drivers/gpu/drm/stm/ltdc.h -@@ -19,6 +19,7 @@ struct ltdc_caps { - const u32 *pix_fmt_hw; /* supported pixel formats */ - bool non_alpha_only_l1; /* non-native no-alpha formats on layer 1 */ - int pad_max_freq_hz; /* max frequency supported by pad */ -+ int nb_irq; /* number of hardware interrupts */ - }; - - #define LTDC_MAX_LAYER 4 -diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c -index b41b97c962edc..fd21d31b64644 100644 ---- a/drivers/input/touchscreen/edt-ft5x06.c -+++ b/drivers/input/touchscreen/edt-ft5x06.c -@@ -28,6 +28,8 @@ - #include - #include - #include -+#include -+#include - - #define WORK_REGISTER_THRESHOLD 0x00 - #define WORK_REGISTER_REPORT_RATE 0x08 -@@ -1048,6 +1050,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, - const struct edt_i2c_chip_data *chip_data; - struct edt_ft5x06_ts_data *tsdata; - u8 buf[2] = { 0xfc, 0x00 }; -+ struct mipi_dsi_device *panel; -+ struct device_node *np; - struct input_dev *input; - unsigned long irq_flags; - int error; -@@ -1113,7 +1117,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, - - error = edt_ft5x06_ts_identify(client, tsdata, fw_version); - if (error) { -- dev_err(&client->dev, "touchscreen probe failed\n"); -+ dev_dbg(&client->dev, "touchscreen probe failed\n"); - return error; - } - -@@ -1182,6 +1186,18 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, - if (error) - return error; - -+ np = of_parse_phandle(client->dev.of_node, "panel", 0); -+ if (np) { -+ panel = of_find_mipi_dsi_device_by_node(np); -+ of_node_put(np); -+ if (!panel) -+ return -EPROBE_DEFER; -+ -+ device_link_add(&client->dev, &panel->dev, DL_FLAG_STATELESS | -+ DL_FLAG_AUTOREMOVE_SUPPLIER); -+ put_device(&panel->dev); -+ } -+ - edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); - device_init_wakeup(&client->dev, 1); - -diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c -index 37b35ab97beb2..ed63c343ba423 100644 ---- a/drivers/input/touchscreen/goodix.c -+++ b/drivers/input/touchscreen/goodix.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -866,6 +867,8 @@ static int goodix_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) - { - struct goodix_ts_data *ts; -+ struct mipi_dsi_device *panel; -+ struct device_node *np; - int error; - - dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr); -@@ -958,6 +961,17 @@ static int goodix_ts_probe(struct i2c_client *client, - return error; - } - -+ np = of_parse_phandle(client->dev.of_node, "panel", 0); -+ if (np) { -+ panel = of_find_mipi_dsi_device_by_node(np); -+ of_node_put(np); -+ if (!panel) -+ return -EPROBE_DEFER; -+ device_link_add(&client->dev, &panel->dev, DL_FLAG_STATELESS | -+ DL_FLAG_AUTOREMOVE_SUPPLIER); -+ put_device(&panel->dev); -+ } -+ - return 0; - } - -@@ -1012,6 +1026,7 @@ static int __maybe_unused goodix_suspend(struct device *dev) - * sooner, delay 58ms here. - */ - msleep(58); -+ - return 0; - } - -@@ -1076,6 +1091,7 @@ static const struct of_device_id goodix_of_match[] = { - { .compatible = "goodix,gt9271" }, - { .compatible = "goodix,gt928" }, - { .compatible = "goodix,gt967" }, -+ { .compatible = "goodix,gt9147",}, - { } - }; - MODULE_DEVICE_TABLE(of, goodix_of_match); -diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h -index 735c8cfdaaa14..28a9ea94ea2ed 100644 ---- a/include/uapi/drm/drm_mode.h -+++ b/include/uapi/drm/drm_mode.h -@@ -97,6 +97,12 @@ extern "C" { - #define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) - #define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) - -+/* flags for polarity clock & data enable polarities */ -+#define DRM_MODE_FLAG_PPIXDATA (1 << 19) -+#define DRM_MODE_FLAG_NPIXDATA (1 << 20) -+#define DRM_MODE_FLAG_PDE (1 << 21) -+#define DRM_MODE_FLAG_NDE (1 << 22) -+ - /* Picture aspect ratio options */ - #define DRM_MODE_PICTURE_ASPECT_NONE 0 - #define DRM_MODE_PICTURE_ASPECT_4_3 1 --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0009-ARM-stm32mp1-r2-I2C-IIO-IRQCHIP.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0009-ARM-stm32mp1-r2-I2C-IIO-IRQCHIP.patch deleted file mode 100644 index 471a787..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0009-ARM-stm32mp1-r2-I2C-IIO-IRQCHIP.patch +++ /dev/null @@ -1,3431 +0,0 @@ -From 7d5ade3a72ec6ff24276380a84c15c2b048a5c16 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:44 +0200 -Subject: [PATCH 09/22] ARM-stm32mp1-r2-rc8-I2C-IIO-IRQCHIP - ---- - drivers/i2c/busses/Kconfig | 1 + - drivers/i2c/busses/i2c-stm32.c | 19 +- - drivers/i2c/busses/i2c-stm32f4.c | 4 +- - drivers/i2c/busses/i2c-stm32f7.c | 623 ++++++++++++++++++---- - drivers/iio/adc/sd_adc_modulator.c | 84 ++- - drivers/iio/adc/stm32-adc-core.c | 97 ++-- - drivers/iio/adc/stm32-adc-core.h | 9 + - drivers/iio/adc/stm32-adc.c | 146 +++-- - drivers/iio/adc/stm32-dfsdm-adc.c | 136 ++++- - drivers/iio/dac/stm32-dac-core.c | 153 ++++-- - drivers/iio/dac/stm32-dac.c | 94 +++- - drivers/iio/trigger/stm32-timer-trigger.c | 164 +++++- - drivers/irqchip/irq-stm32-exti.c | 274 +++++++--- - 13 files changed, 1461 insertions(+), 343 deletions(-) - -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 146ce40d8e0aa..19f05c44f6f91 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -1008,6 +1008,7 @@ config I2C_STM32F7 - tristate "STMicroelectronics STM32F7 I2C support" - depends on ARCH_STM32 || COMPILE_TEST - select I2C_SLAVE -+ select I2C_SMBUS - help - Enable this option to add support for STM32 I2C controller embedded - in STM32F7 SoCs. -diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c -index 1da347e6a3586..448c0df71eab9 100644 ---- a/drivers/i2c/busses/i2c-stm32.c -+++ b/drivers/i2c/busses/i2c-stm32.c -@@ -25,9 +25,11 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, - /* Request and configure I2C TX dma channel */ - dma->chan_tx = dma_request_chan(dev, "tx"); - if (IS_ERR(dma->chan_tx)) { -- dev_dbg(dev, "can't request DMA tx channel\n"); - ret = PTR_ERR(dma->chan_tx); -- goto fail_al; -+ if ((ret != -EPROBE_DEFER) && (ret != -ENODEV)) -+ dev_err(dev, "can't request DMA tx channel: %d\n", ret); -+ -+ goto fail_mem; - } - - memset(&dma_sconfig, 0, sizeof(dma_sconfig)); -@@ -37,15 +39,17 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, - dma_sconfig.direction = DMA_MEM_TO_DEV; - ret = dmaengine_slave_config(dma->chan_tx, &dma_sconfig); - if (ret < 0) { -- dev_err(dev, "can't configure tx channel\n"); -+ dev_err(dev, "can't configure tx channel: %d\n", ret); - goto fail_tx; - } - - /* Request and configure I2C RX dma channel */ - dma->chan_rx = dma_request_chan(dev, "rx"); - if (IS_ERR(dma->chan_rx)) { -- dev_err(dev, "can't request DMA rx channel\n"); - ret = PTR_ERR(dma->chan_rx); -+ if ((ret != -EPROBE_DEFER) && (ret != -ENODEV)) -+ dev_err(dev, "can't request DMA rx channel: %d\n", ret); -+ - goto fail_tx; - } - -@@ -56,7 +60,7 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, - dma_sconfig.direction = DMA_DEV_TO_MEM; - ret = dmaengine_slave_config(dma->chan_rx, &dma_sconfig); - if (ret < 0) { -- dev_err(dev, "can't configure rx channel\n"); -+ dev_err(dev, "can't configure rx channel: %d\n", ret); - goto fail_rx; - } - -@@ -71,9 +75,10 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, - dma_release_channel(dma->chan_rx); - fail_tx: - dma_release_channel(dma->chan_tx); --fail_al: -+fail_mem: - devm_kfree(dev, dma); -- dev_info(dev, "can't use DMA\n"); -+ if (ret == -ENODEV) -+ dev_info(dev, "doesn't use DMA\n"); - - return ERR_PTR(ret); - } -diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c -index ba600d77a3f88..1b8cad506ad75 100644 ---- a/drivers/i2c/busses/i2c-stm32f4.c -+++ b/drivers/i2c/busses/i2c-stm32f4.c -@@ -797,8 +797,10 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) - - rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (IS_ERR(rst)) { -- dev_err(&pdev->dev, "Error: Missing controller reset\n"); - ret = PTR_ERR(rst); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Error: Missing reset ctrl\n"); -+ - goto clk_free; - } - reset_control_assert(rst); -diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c -index b2634afe066d3..f59c45a4f61b2 100644 ---- a/drivers/i2c/busses/i2c-stm32f7.c -+++ b/drivers/i2c/busses/i2c-stm32f7.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -29,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -49,6 +51,9 @@ - - /* STM32F7 I2C control 1 */ - #define STM32F7_I2C_CR1_PECEN BIT(23) -+#define STM32F7_I2C_CR1_ALERTEN BIT(22) -+#define STM32F7_I2C_CR1_SMBHEN BIT(20) -+#define STM32F7_I2C_CR1_WUPEN BIT(18) - #define STM32F7_I2C_CR1_SBC BIT(16) - #define STM32F7_I2C_CR1_RXDMAEN BIT(15) - #define STM32F7_I2C_CR1_TXDMAEN BIT(14) -@@ -119,6 +124,7 @@ - (((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17) - #define STM32F7_I2C_ISR_DIR BIT(16) - #define STM32F7_I2C_ISR_BUSY BIT(15) -+#define STM32F7_I2C_ISR_ALERT BIT(13) - #define STM32F7_I2C_ISR_PECERR BIT(11) - #define STM32F7_I2C_ISR_ARLO BIT(9) - #define STM32F7_I2C_ISR_BERR BIT(8) -@@ -132,6 +138,7 @@ - #define STM32F7_I2C_ISR_TXE BIT(0) - - /* STM32F7 I2C Interrupt Clear */ -+#define STM32F7_I2C_ICR_ALERTCF BIT(13) - #define STM32F7_I2C_ICR_PECCF BIT(11) - #define STM32F7_I2C_ICR_ARLOCF BIT(9) - #define STM32F7_I2C_ICR_BERRCF BIT(8) -@@ -148,7 +155,7 @@ - - #define STM32F7_I2C_MAX_LEN 0xff - #define STM32F7_I2C_DMA_LEN_MIN 0x16 --#define STM32F7_I2C_MAX_SLAVE 0x2 -+#define STM32F7_I2C_MAX_SLAVE 0x3 - - #define STM32F7_I2C_DNF_DEFAULT 0 - #define STM32F7_I2C_DNF_MAX 16 -@@ -168,11 +175,25 @@ - - #define STM32F7_AUTOSUSPEND_DELAY (HZ / 100) - -+/** -+ * struct stm32f7_i2c_regs - i2c f7 registers backup -+ * @cr1: Control register 1 -+ * @cr2: Control register 2 -+ * @oar1: Own address 1 register -+ * @oar2: Own address 2 register -+ * @tmgr: Timing register -+ */ -+struct stm32f7_i2c_regs { -+ u32 cr1; -+ u32 cr2; -+ u32 oar1; -+ u32 oar2; -+ u32 tmgr; -+}; -+ - /** - * struct stm32f7_i2c_spec - private i2c specification timing - * @rate: I2C bus speed (Hz) -- * @rate_min: 80% of I2C bus speed (Hz) -- * @rate_max: 100% of I2C bus speed (Hz) - * @fall_max: Max fall time of both SDA and SCL signals (ns) - * @rise_max: Max rise time of both SDA and SCL signals (ns) - * @hddat_min: Min data hold time (ns) -@@ -183,8 +204,6 @@ - */ - struct stm32f7_i2c_spec { - u32 rate; -- u32 rate_min; -- u32 rate_max; - u32 fall_max; - u32 rise_max; - u32 hddat_min; -@@ -196,22 +215,22 @@ struct stm32f7_i2c_spec { - - /** - * struct stm32f7_i2c_setup - private I2C timing setup parameters -- * @speed: I2C speed mode (standard, Fast Plus) - * @speed_freq: I2C speed frequency (Hz) - * @clock_src: I2C clock source frequency (Hz) - * @rise_time: Rise time (ns) - * @fall_time: Fall time (ns) - * @dnf: Digital filter coefficient (0-16) - * @analog_filter: Analog filter delay (On/Off) -+ * @fmp_clr_offset: Fast Mode Plus clear register offset from set register - */ - struct stm32f7_i2c_setup { -- enum stm32_i2c_speed speed; - u32 speed_freq; - u32 clock_src; - u32 rise_time; - u32 fall_time; - u8 dnf; - bool analog_filter; -+ u32 fmp_clr_offset; - }; - - /** -@@ -260,14 +279,38 @@ struct stm32f7_i2c_msg { - u8 smbus_buf[I2C_SMBUS_BLOCK_MAX + 3] __aligned(4); - }; - -+/** -+ * struct stm32f7_i2c_host - SMBus host specific data -+ * @client: I2C slave device that represents SMBus host -+ * @notify_start: indicate that this is the start of the notify transaction -+ * @addr: device address of SMBus device that initiate SMBus host protocol -+ */ -+struct stm32f7_i2c_host { -+ struct i2c_client *client; -+ bool notify_start; -+ u8 addr; -+}; -+ -+/** -+ * struct stm32f7_i2c_alert - SMBus alert specific data -+ * @setup: platform data for the smbus_alert i2c client -+ * @ara: I2C slave device used to respond to the SMBus Alert with Alert -+ * Response Address -+ */ -+struct stm32f7_i2c_alert { -+ struct i2c_smbus_alert_setup setup; -+ struct i2c_client *ara; -+}; -+ - /** - * struct stm32f7_i2c_dev - private data of the controller - * @adap: I2C adapter for this controller - * @dev: device for this controller -+ * @irq_event: interrupt event line for the controller - * @base: virtual memory area - * @complete: completion of I2C message - * @clk: hw i2c clock -- * @speed: I2C clock frequency of the controller. Standard, Fast or Fast+ -+ * @bus_rate: I2C clock frequency of the controller. - * @msg: Pointer to data to be written - * @msg_num: number of I2C messages to be executed - * @msg_id: message identifiant -@@ -276,20 +319,28 @@ struct stm32f7_i2c_msg { - * @timing: I2C computed timings - * @slave: list of slave devices registered on the I2C bus - * @slave_running: slave device currently used -+ * @regs: registers backup for suspend/resume - * @slave_dir: transfer direction for the current slave device - * @master_mode: boolean to know in which mode the I2C is running (master or - * slave) - * @dma: dma data - * @use_dma: boolean to know if dma is used in the current transfer - * @regmap: holds SYSCFG phandle for Fast Mode Plus bits -+ * @regmap_sreg: register address for setting Fast Mode Plus bits -+ * @regmap_creg: register address for clearing Fast Mode Plus bits -+ * @regmap_mask: mask for Fast Mode Plus bits -+ * @host: SMBus host protocol specific data -+ * @alert: SMBus alert specific data -+ * @wakeup_src: boolean to know if the device is a wakeup source - */ - struct stm32f7_i2c_dev { - struct i2c_adapter adap; - struct device *dev; - void __iomem *base; -+ int irq_event; - struct completion complete; - struct clk *clk; -- int speed; -+ unsigned int bus_rate; - struct i2c_msg *msg; - unsigned int msg_num; - unsigned int msg_id; -@@ -298,11 +349,18 @@ struct stm32f7_i2c_dev { - struct stm32f7_i2c_timings timing; - struct i2c_client *slave[STM32F7_I2C_MAX_SLAVE]; - struct i2c_client *slave_running; -+ struct stm32f7_i2c_regs regs; - u32 slave_dir; - bool master_mode; - struct stm32_i2c_dma *dma; - bool use_dma; - struct regmap *regmap; -+ u32 regmap_sreg; -+ u32 regmap_creg; -+ u32 regmap_mask; -+ struct stm32f7_i2c_host *host; -+ struct stm32f7_i2c_alert *alert; -+ bool wakeup_src; - }; - - /* -@@ -312,11 +370,13 @@ struct stm32f7_i2c_dev { - * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast, - * and Fast-mode Plus I2C-bus devices - */ -+#define I2C_STD_RATE 100000 -+#define I2C_FAST_RATE 400000 -+#define I2C_FASTPLUS_RATE 1000000 - static struct stm32f7_i2c_spec i2c_specs[] = { -- [STM32_I2C_SPEED_STANDARD] = { -- .rate = 100000, -- .rate_min = 80000, -- .rate_max = 100000, -+ /* Standard - 100KHz */ -+ { -+ .rate = I2C_STD_RATE, - .fall_max = 300, - .rise_max = 1000, - .hddat_min = 0, -@@ -325,10 +385,9 @@ static struct stm32f7_i2c_spec i2c_specs[] = { - .l_min = 4700, - .h_min = 4000, - }, -- [STM32_I2C_SPEED_FAST] = { -- .rate = 400000, -- .rate_min = 320000, -- .rate_max = 400000, -+ /* Fast - 400KHz */ -+ { -+ .rate = I2C_FAST_RATE, - .fall_max = 300, - .rise_max = 300, - .hddat_min = 0, -@@ -337,10 +396,9 @@ static struct stm32f7_i2c_spec i2c_specs[] = { - .l_min = 1300, - .h_min = 600, - }, -- [STM32_I2C_SPEED_FAST_PLUS] = { -- .rate = 1000000, -- .rate_min = 800000, -- .rate_max = 1000000, -+ /* FastPlus - 1MHz */ -+ { -+ .rate = I2C_FASTPLUS_RATE, - .fall_max = 100, - .rise_max = 120, - .hddat_min = 0, -@@ -358,6 +416,14 @@ static const struct stm32f7_i2c_setup stm32f7_setup = { - .analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE, - }; - -+static const struct stm32f7_i2c_setup stm32mp15_setup = { -+ .rise_time = STM32F7_I2C_RISE_TIME_DEFAULT, -+ .fall_time = STM32F7_I2C_FALL_TIME_DEFAULT, -+ .dnf = STM32F7_I2C_DNF_DEFAULT, -+ .analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE, -+ .fmp_clr_offset = 0x40, -+}; -+ - static inline void stm32f7_i2c_set_bits(void __iomem *reg, u32 mask) - { - writel_relaxed(readl_relaxed(reg) | mask, reg); -@@ -373,10 +439,24 @@ static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask) - stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask); - } - -+static struct stm32f7_i2c_spec *get_specs(u32 rate) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(i2c_specs); i++) -+ if (rate <= i2c_specs[i].rate) -+ return &i2c_specs[i]; -+ -+ /* NOT REACHED */ -+ return ERR_PTR(-EINVAL); -+} -+ -+#define RATE_MIN(rate) (rate / 100 * 80) - static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - struct stm32f7_i2c_setup *setup, - struct stm32f7_i2c_timings *output) - { -+ struct stm32f7_i2c_spec *specs; - u32 p_prev = STM32F7_PRESC_MAX; - u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC, - setup->clock_src); -@@ -394,18 +474,19 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - u16 p, l, a, h; - int ret = 0; - -- if (setup->speed >= STM32_I2C_SPEED_END) { -- dev_err(i2c_dev->dev, "speed out of bound {%d/%d}\n", -- setup->speed, STM32_I2C_SPEED_END - 1); -+ specs = get_specs(setup->speed_freq); -+ if (specs == ERR_PTR(-EINVAL)) { -+ dev_err(i2c_dev->dev, "speed out of bound {%d}\n", -+ setup->speed_freq); - return -EINVAL; - } - -- if ((setup->rise_time > i2c_specs[setup->speed].rise_max) || -- (setup->fall_time > i2c_specs[setup->speed].fall_max)) { -+ if ((setup->rise_time > specs->rise_max) || -+ (setup->fall_time > specs->fall_max)) { - dev_err(i2c_dev->dev, - "timings out of bound Rise{%d>%d}/Fall{%d>%d}\n", -- setup->rise_time, i2c_specs[setup->speed].rise_max, -- setup->fall_time, i2c_specs[setup->speed].fall_max); -+ setup->rise_time, specs->rise_max, -+ setup->fall_time, specs->fall_max); - return -EINVAL; - } - -@@ -416,12 +497,6 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - return -EINVAL; - } - -- if (setup->speed_freq > i2c_specs[setup->speed].rate) { -- dev_err(i2c_dev->dev, "ERROR: Freq {%d/%d}\n", -- setup->speed_freq, i2c_specs[setup->speed].rate); -- return -EINVAL; -- } -- - /* Analog and Digital Filters */ - af_delay_min = - (setup->analog_filter ? -@@ -431,13 +506,13 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0); - dnf_delay = setup->dnf * i2cclk; - -- sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time - -+ sdadel_min = specs->hddat_min + setup->fall_time - - af_delay_min - (setup->dnf + 3) * i2cclk; - -- sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time - -+ sdadel_max = specs->vddat_max - setup->rise_time - - af_delay_max - (setup->dnf + 4) * i2cclk; - -- scldel_min = setup->rise_time + i2c_specs[setup->speed].sudat_min; -+ scldel_min = setup->rise_time + specs->sudat_min; - - if (sdadel_min < 0) - sdadel_min = 0; -@@ -492,8 +567,8 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - - tsync = af_delay_min + dnf_delay + (2 * i2cclk); - s = NULL; -- clk_max = NSEC_PER_SEC / i2c_specs[setup->speed].rate_min; -- clk_min = NSEC_PER_SEC / i2c_specs[setup->speed].rate_max; -+ clk_max = NSEC_PER_SEC / RATE_MIN(setup->speed_freq); -+ clk_min = NSEC_PER_SEC / setup->speed_freq; - - /* - * Among Prescaler possibilities discovered above figures out SCL Low -@@ -511,7 +586,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - for (l = 0; l < STM32F7_SCLL_MAX; l++) { - u32 tscl_l = (l + 1) * prescaler + tsync; - -- if ((tscl_l < i2c_specs[setup->speed].l_min) || -+ if ((tscl_l < specs->l_min) || - (i2cclk >= - ((tscl_l - af_delay_min - dnf_delay) / 4))) { - continue; -@@ -523,7 +598,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - setup->rise_time + setup->fall_time; - - if ((tscl >= clk_min) && (tscl <= clk_max) && -- (tscl_h >= i2c_specs[setup->speed].h_min) && -+ (tscl_h >= specs->h_min) && - (i2cclk < tscl_h)) { - int clk_error = tscl - i2cbus; - -@@ -569,13 +644,23 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, - return ret; - } - -+static u32 get_lower_rate(u32 rate) -+{ -+ int i; -+ -+ for (i = ARRAY_SIZE(i2c_specs) - 1; i >= 0; i--) -+ if (i2c_specs[i].rate < rate) -+ return i2c_specs[i].rate; -+ -+ return i2c_specs[0].rate; -+} -+ - static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, - struct stm32f7_i2c_setup *setup) - { - int ret = 0; - -- setup->speed = i2c_dev->speed; -- setup->speed_freq = i2c_specs[setup->speed].rate; -+ setup->speed_freq = i2c_dev->bus_rate; - setup->clock_src = clk_get_rate(i2c_dev->clk); - - if (!setup->clock_src) { -@@ -589,14 +674,12 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, - if (ret) { - dev_err(i2c_dev->dev, - "failed to compute I2C timings.\n"); -- if (i2c_dev->speed > STM32_I2C_SPEED_STANDARD) { -- i2c_dev->speed--; -- setup->speed = i2c_dev->speed; -+ if (setup->speed_freq > I2C_STD_RATE) { - setup->speed_freq = -- i2c_specs[setup->speed].rate; -+ get_lower_rate(setup->speed_freq); - dev_warn(i2c_dev->dev, - "downgrade I2C Speed Freq to (%i)\n", -- i2c_specs[setup->speed].rate); -+ setup->speed_freq); - } else { - break; - } -@@ -608,13 +691,15 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, - return ret; - } - -- dev_dbg(i2c_dev->dev, "I2C Speed(%i), Freq(%i), Clk Source(%i)\n", -- setup->speed, setup->speed_freq, setup->clock_src); -+ dev_dbg(i2c_dev->dev, "I2C Freq(%i), Clk Source(%i)\n", -+ setup->speed_freq, setup->clock_src); - dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n", - setup->rise_time, setup->fall_time); - dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n", - (setup->analog_filter ? "On" : "Off"), setup->dnf); - -+ i2c_dev->bus_rate = setup->speed_freq; -+ - return 0; - } - -@@ -1264,11 +1349,21 @@ static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev, - int i; - - /* -- * slave[0] supports 7-bit and 10-bit slave address -- * slave[1] supports 7-bit slave address only -+ * slave[0] support only SMBus Host address (0x8) -+ * slave[1] supports 7-bit and 10-bit slave address -+ * slave[2] supports 7-bit slave address only - */ -- for (i = STM32F7_I2C_MAX_SLAVE - 1; i >= 0; i--) { -- if (i == 1 && (slave->flags & I2C_CLIENT_TEN)) -+ if (i2c_dev->host) { -+ if (slave->addr == 0x08) { -+ if (i2c_dev->slave[0]) -+ goto fail; -+ *id = 0; -+ return 0; -+ } -+ } -+ -+ for (i = STM32F7_I2C_MAX_SLAVE - 1; i > 0; i--) { -+ if (i == 2 && (slave->flags & I2C_CLIENT_TEN)) - continue; - if (!i2c_dev->slave[i]) { - *id = i; -@@ -1276,6 +1371,7 @@ static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev, - } - } - -+fail: - dev_err(dev, "Slave 0x%x could not be registered\n", slave->addr); - - return -EINVAL; -@@ -1407,7 +1503,8 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) - - /* NACK received */ - if (status & STM32F7_I2C_ISR_NACKF) { -- dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__); -+ dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", -+ __func__, f7_msg->addr); - writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); - f7_msg->result = -ENXIO; - } -@@ -1528,6 +1625,13 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) - f7_msg->result = -EINVAL; - } - -+ if (status & STM32F7_I2C_ISR_ALERT) { -+ dev_dbg(dev, "<%s>: SMBus alert received\n", __func__); -+ writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR); -+ i2c_handle_smbus_alert(i2c_dev->alert->ara); -+ return IRQ_HANDLED; -+ } -+ - if (!i2c_dev->slave_running) { - u32 mask; - /* Disable interrupts */ -@@ -1671,6 +1775,9 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - return ret; - } - -+static void stm32f7_i2c_enable_wakeup(struct stm32f7_i2c_dev *i2c_dev, -+ bool enable); -+ - static int stm32f7_i2c_reg_slave(struct i2c_client *slave) - { - struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter); -@@ -1697,7 +1804,16 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) - if (ret < 0) - return ret; - -- if (id == 0) { -+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) -+ stm32f7_i2c_enable_wakeup(i2c_dev, true); -+ -+ switch (id) { -+ case 0: -+ /* Slave SMBus Host */ -+ i2c_dev->slave[id] = slave; -+ break; -+ -+ case 1: - /* Configure Own Address 1 */ - oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1); - oar1 &= ~STM32F7_I2C_OAR1_MASK; -@@ -1710,7 +1826,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) - oar1 |= STM32F7_I2C_OAR1_OA1EN; - i2c_dev->slave[id] = slave; - writel_relaxed(oar1, i2c_dev->base + STM32F7_I2C_OAR1); -- } else if (id == 1) { -+ break; -+ -+ case 2: - /* Configure Own Address 2 */ - oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2); - oar2 &= ~STM32F7_I2C_OAR2_MASK; -@@ -1723,7 +1841,10 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) - oar2 |= STM32F7_I2C_OAR2_OA2EN; - i2c_dev->slave[id] = slave; - writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2); -- } else { -+ break; -+ -+ default: -+ dev_err(dev, "I2C slave id not supported\n"); - ret = -ENODEV; - goto pm_free; - } -@@ -1738,6 +1859,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) - - ret = 0; - pm_free: -+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) -+ stm32f7_i2c_enable_wakeup(i2c_dev, false); -+ - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - -@@ -1761,18 +1885,20 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave) - if (ret < 0) - return ret; - -- if (id == 0) { -+ if (id == 1) { - mask = STM32F7_I2C_OAR1_OA1EN; - stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask); -- } else { -+ } else if (id == 2) { - mask = STM32F7_I2C_OAR2_OA2EN; - stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR2, mask); - } - - i2c_dev->slave[id] = NULL; - -- if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) -+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) { - stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK); -+ stm32f7_i2c_enable_wakeup(i2c_dev, false); -+ } - - pm_runtime_mark_last_busy(i2c_dev->dev); - pm_runtime_put_autosuspend(i2c_dev->dev); -@@ -1780,6 +1906,31 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave) - return 0; - } - -+static int stm32f7_i2c_write_fm_plus_bits(struct stm32f7_i2c_dev *i2c_dev, -+ bool enable) -+{ -+ int ret; -+ -+ if (i2c_dev->bus_rate <= I2C_FAST_RATE || -+ IS_ERR_OR_NULL(i2c_dev->regmap)) { -+ /* Optional */ -+ return 0; -+ } -+ -+ if (i2c_dev->regmap_sreg == i2c_dev->regmap_creg) -+ ret = regmap_update_bits(i2c_dev->regmap, -+ i2c_dev->regmap_sreg, -+ i2c_dev->regmap_mask, -+ enable ? i2c_dev->regmap_mask : 0); -+ else -+ ret = regmap_write(i2c_dev->regmap, -+ enable ? i2c_dev->regmap_sreg : -+ i2c_dev->regmap_creg, -+ i2c_dev->regmap_mask); -+ -+ return ret; -+} -+ - static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev, - struct stm32f7_i2c_dev *i2c_dev) - { -@@ -1801,7 +1952,137 @@ static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev, - if (ret) - return ret; - -- return regmap_update_bits(i2c_dev->regmap, reg, mask, mask); -+ i2c_dev->regmap_sreg = reg; -+ i2c_dev->regmap_creg = reg + i2c_dev->setup.fmp_clr_offset; -+ i2c_dev->regmap_mask = mask; -+ -+ return stm32f7_i2c_write_fm_plus_bits(i2c_dev, 1); -+} -+ -+static int stm32f7_i2c_smbus_host_cb(struct i2c_client *client, -+ enum i2c_slave_event event, -+ u8 *val) -+{ -+ struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(client->adapter); -+ struct stm32f7_i2c_host *host = i2c_dev->host; -+ int ret; -+ -+ switch (event) { -+ case I2C_SLAVE_WRITE_REQUESTED: -+ host->notify_start = true; -+ break; -+ case I2C_SLAVE_WRITE_RECEIVED: -+ /* We only retrieve the first byte received (addr) -+ * From Documentation/i2c/smbus-protocol: -+ * There is currently no way to retrieve the data parameter -+ * from the client. -+ */ -+ if (!host->notify_start) -+ break; -+ host->addr = *val; -+ host->notify_start = false; -+ break; -+ case I2C_SLAVE_STOP: -+ ret = i2c_handle_smbus_host_notify(client->adapter, -+ host->addr); -+ if (ret < 0) { -+ dev_dbg(i2c_dev->dev, "failed to handle host_notify (%d)\n", -+ ret); -+ return ret; -+ } -+ break; -+ default: -+ dev_err(i2c_dev->dev, "slave event not supported\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int stm32f7_i2c_enable_smbus_host(struct stm32f7_i2c_dev *i2c_dev) -+{ -+ struct stm32f7_i2c_host *host; -+ struct i2c_adapter *adap = &i2c_dev->adap; -+ struct device *dev = i2c_dev->dev; -+ void __iomem *base = i2c_dev->base; -+ struct i2c_board_info host_notify_board_info = { -+ I2C_BOARD_INFO("smbus_host_notify", 0x8), -+ .flags = I2C_CLIENT_SLAVE, -+ }; -+ int ret; -+ -+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); -+ if (!host) -+ return -ENOMEM; -+ -+ host->client = i2c_new_client_device(adap, &host_notify_board_info); -+ if (IS_ERR(host->client)) -+ return PTR_ERR(host->client); -+ -+ i2c_dev->host = host; -+ -+ ret = i2c_slave_register(host->client, stm32f7_i2c_smbus_host_cb); -+ if (ret) { -+ i2c_dev->host = NULL; -+ i2c_unregister_device(host->client); -+ return ret; -+ } -+ -+ /* Enable SMBus Host address */ -+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_SMBHEN); -+ -+ return 0; -+} -+ -+static void stm32f7_i2c_disable_smbus_host(struct stm32f7_i2c_dev *i2c_dev) -+{ -+ void __iomem *base = i2c_dev->base; -+ struct stm32f7_i2c_host *host = i2c_dev->host; -+ -+ if (host) { -+ /* Disable SMBus Host address */ -+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, -+ STM32F7_I2C_CR1_SMBHEN); -+ i2c_slave_unregister(host->client); -+ i2c_dev->host = NULL; -+ i2c_unregister_device(host->client); -+ } -+} -+ -+static int stm32f7_i2c_enable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) -+{ -+ struct stm32f7_i2c_alert *alert; -+ struct i2c_adapter *adap = &i2c_dev->adap; -+ struct device *dev = i2c_dev->dev; -+ void __iomem *base = i2c_dev->base; -+ -+ alert = devm_kzalloc(dev, sizeof(*alert), GFP_KERNEL); -+ if (!alert) -+ return -ENOMEM; -+ -+ alert->ara = i2c_setup_smbus_alert(adap, &alert->setup); -+ if (!alert->ara) -+ return -ENOMEM; -+ -+ i2c_dev->alert = alert; -+ -+ /* Enable SMBus Alert */ -+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_ALERTEN); -+ -+ return 0; -+} -+ -+static void stm32f7_i2c_disable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) -+{ -+ struct stm32f7_i2c_alert *alert = i2c_dev->alert; -+ void __iomem *base = i2c_dev->base; -+ -+ if (alert) { -+ /* Disable SMBus Alert */ -+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, -+ STM32F7_I2C_CR1_ALERTEN); -+ i2c_unregister_device(alert->ara); -+ } - } - - static u32 stm32f7_i2c_func(struct i2c_adapter *adap) -@@ -1811,7 +2092,7 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap) - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | - I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC | -- I2C_FUNC_SMBUS_I2C_BLOCK; -+ I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HOST_NOTIFY; - } - - static const struct i2c_algorithm stm32f7_i2c_algo = { -@@ -1827,11 +2108,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - struct stm32f7_i2c_dev *i2c_dev; - const struct stm32f7_i2c_setup *setup; - struct resource *res; -- u32 clk_rate, rise_time, fall_time; -+ u32 rise_time, fall_time; - struct i2c_adapter *adap; - struct reset_control *rst; - dma_addr_t phy_addr; -- int irq_error, irq_event, ret; -+ int irq_error, ret; - - i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); - if (!i2c_dev) -@@ -1843,12 +2124,12 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - return PTR_ERR(i2c_dev->base); - phy_addr = (dma_addr_t)res->start; - -- irq_event = platform_get_irq(pdev, 0); -- if (irq_event <= 0) { -- if (irq_event != -EPROBE_DEFER) -+ i2c_dev->irq_event = platform_get_irq(pdev, 0); -+ if (i2c_dev->irq_event <= 0) { -+ if (i2c_dev->irq_event != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get IRQ event: %d\n", -- irq_event); -- return irq_event ? : -ENOENT; -+ i2c_dev->irq_event); -+ return i2c_dev->irq_event ? : -ENOENT; - } - - irq_error = platform_get_irq(pdev, 1); -@@ -1859,9 +2140,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - return irq_error ? : -ENOENT; - } - -+ i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node, -+ "wakeup-source"); -+ - i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c_dev->clk)) { -- dev_err(&pdev->dev, "Error: Missing controller clock\n"); -+ if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Failed to get controller clock\n"); - return PTR_ERR(i2c_dev->clk); - } - -@@ -1871,24 +2156,23 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - return ret; - } - -- i2c_dev->speed = STM32_I2C_SPEED_STANDARD; - ret = device_property_read_u32(&pdev->dev, "clock-frequency", -- &clk_rate); -- if (!ret && clk_rate >= 1000000) { -- i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS; -- ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev); -- if (ret) -- goto clk_free; -- } else if (!ret && clk_rate >= 400000) { -- i2c_dev->speed = STM32_I2C_SPEED_FAST; -- } else if (!ret && clk_rate >= 100000) { -- i2c_dev->speed = STM32_I2C_SPEED_STANDARD; -+ &i2c_dev->bus_rate); -+ if (ret) -+ i2c_dev->bus_rate = I2C_STD_RATE; -+ -+ if (i2c_dev->bus_rate > I2C_FASTPLUS_RATE) { -+ dev_err(&pdev->dev, "Invalid bus speed (%i>%i)\n", -+ i2c_dev->bus_rate, I2C_FASTPLUS_RATE); -+ return -EINVAL; - } - - rst = devm_reset_control_get(&pdev->dev, NULL); - if (IS_ERR(rst)) { -- dev_err(&pdev->dev, "Error: Missing controller reset\n"); - ret = PTR_ERR(rst); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Error: Missing reset ctrl\n"); -+ - goto clk_free; - } - reset_control_assert(rst); -@@ -1897,14 +2181,14 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - - i2c_dev->dev = &pdev->dev; - -- ret = devm_request_threaded_irq(&pdev->dev, irq_event, -+ ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_event, - stm32f7_i2c_isr_event, - stm32f7_i2c_isr_event_thread, - IRQF_ONESHOT, - pdev->name, i2c_dev); - if (ret) { - dev_err(&pdev->dev, "Failed to request irq event %i\n", -- irq_event); -+ i2c_dev->irq_event); - goto clk_free; - } - -@@ -1938,6 +2222,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - if (ret) - goto clk_free; - -+ /* Setup Fast mode plus if necessary */ -+ if (i2c_dev->bus_rate > I2C_FAST_RATE) { -+ ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev); -+ if (ret) -+ goto clk_free; -+ } -+ - adap = &i2c_dev->adap; - i2c_set_adapdata(adap, i2c_dev); - snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)", -@@ -1959,10 +2250,17 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - i2c_dev->dma = NULL; - else if (IS_ERR(i2c_dev->dma)) { - ret = PTR_ERR(i2c_dev->dma); -- if (ret != -EPROBE_DEFER) -- dev_err(&pdev->dev, -- "Failed to request dma error %i\n", ret); -- goto clk_free; -+ goto fmp_clear; -+ } -+ -+ if (i2c_dev->wakeup_src) { -+ device_set_wakeup_capable(i2c_dev->dev, true); -+ -+ ret = dev_pm_set_wake_irq(i2c_dev->dev, i2c_dev->irq_event); -+ if (ret) { -+ dev_err(i2c_dev->dev, "Failed to set wake up irq\n"); -+ goto clr_wakeup_capable; -+ } - } - - platform_set_drvdata(pdev, i2c_dev); -@@ -1981,6 +2279,26 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - if (ret) - goto pm_disable; - -+ if (device_property_read_bool(&pdev->dev, "st,smbus-host-notify")) { -+ ret = stm32f7_i2c_enable_smbus_host(i2c_dev); -+ if (ret) { -+ dev_err(i2c_dev->dev, -+ "failed to enable SMBus host notify (%d)\n", -+ ret); -+ goto i2c_adapter_remove; -+ } -+ } -+ -+ if (device_property_read_bool(&pdev->dev, "st,smbus-alert")) { -+ ret = stm32f7_i2c_enable_smbus_alert(i2c_dev); -+ if (ret) { -+ dev_err(i2c_dev->dev, -+ "failed to enable SMBus alert protocol (%d)\n", -+ ret); -+ goto host_notify_disable; -+ } -+ } -+ - dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr); - - pm_runtime_mark_last_busy(i2c_dev->dev); -@@ -1988,17 +2306,33 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) - - return 0; - -+host_notify_disable: -+ stm32f7_i2c_disable_smbus_host(i2c_dev); -+ -+i2c_adapter_remove: -+ i2c_del_adapter(adap); -+ - pm_disable: - pm_runtime_put_noidle(i2c_dev->dev); - pm_runtime_disable(i2c_dev->dev); - pm_runtime_set_suspended(i2c_dev->dev); - pm_runtime_dont_use_autosuspend(i2c_dev->dev); - -+ if (i2c_dev->wakeup_src) -+ dev_pm_clear_wake_irq(i2c_dev->dev); -+ -+clr_wakeup_capable: -+ if (i2c_dev->wakeup_src) -+ device_set_wakeup_capable(i2c_dev->dev, false); -+ - if (i2c_dev->dma) { - stm32_i2c_dma_free(i2c_dev->dma); - i2c_dev->dma = NULL; - } - -+fmp_clear: -+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 0); -+ - clk_free: - clk_disable_unprepare(i2c_dev->clk); - -@@ -2009,9 +2343,22 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) - { - struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - -+ stm32f7_i2c_disable_smbus_alert(i2c_dev); -+ -+ stm32f7_i2c_disable_smbus_host(i2c_dev); -+ - i2c_del_adapter(&i2c_dev->adap); - pm_runtime_get_sync(i2c_dev->dev); - -+ if (i2c_dev->wakeup_src) { -+ dev_pm_clear_wake_irq(i2c_dev->dev); -+ /* -+ * enforce that wakeup is disabled and that the device -+ * is marked as non wakeup capable -+ */ -+ device_init_wakeup(i2c_dev->dev, false); -+ } -+ - pm_runtime_put_noidle(i2c_dev->dev); - pm_runtime_disable(i2c_dev->dev); - pm_runtime_set_suspended(i2c_dev->dev); -@@ -2022,23 +2369,60 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) - i2c_dev->dma = NULL; - } - -+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 0); -+ - clk_disable_unprepare(i2c_dev->clk); - - return 0; - } - --#ifdef CONFIG_PM --static int stm32f7_i2c_runtime_suspend(struct device *dev) -+static void __maybe_unused -+stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) -+{ -+ i2c_dev->regs.cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1); -+ i2c_dev->regs.cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2); -+ i2c_dev->regs.oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1); -+ i2c_dev->regs.oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2); -+ i2c_dev->regs.tmgr = readl_relaxed(i2c_dev->base + STM32F7_I2C_TIMINGR); -+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 0); -+} -+ -+static void __maybe_unused -+stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) -+{ -+ u32 cr1; -+ -+ cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1); -+ if (cr1 & STM32F7_I2C_CR1_PE) -+ stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, -+ STM32F7_I2C_CR1_PE); -+ -+ writel_relaxed(i2c_dev->regs.tmgr, i2c_dev->base + STM32F7_I2C_TIMINGR); -+ writel_relaxed(i2c_dev->regs.cr1 & ~STM32F7_I2C_CR1_PE, -+ i2c_dev->base + STM32F7_I2C_CR1); -+ if (i2c_dev->regs.cr1 & STM32F7_I2C_CR1_PE) -+ stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, -+ STM32F7_I2C_CR1_PE); -+ writel_relaxed(i2c_dev->regs.cr2, i2c_dev->base + STM32F7_I2C_CR2); -+ writel_relaxed(i2c_dev->regs.oar1, i2c_dev->base + STM32F7_I2C_OAR1); -+ writel_relaxed(i2c_dev->regs.oar2, i2c_dev->base + STM32F7_I2C_OAR2); -+ stm32f7_i2c_write_fm_plus_bits(i2c_dev, 1); -+} -+ -+ -+static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev) - { - struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); - -+ stm32f7_i2c_regs_backup(i2c_dev); -+ - if (!stm32f7_i2c_is_slave_registered(i2c_dev)) - clk_disable_unprepare(i2c_dev->clk); - - return 0; - } - --static int stm32f7_i2c_runtime_resume(struct device *dev) -+static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev) - { - struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); - int ret; -@@ -2051,17 +2435,70 @@ static int stm32f7_i2c_runtime_resume(struct device *dev) - } - } - -+ stm32f7_i2c_regs_restore(i2c_dev); -+ -+ return 0; -+} -+ -+static void stm32f7_i2c_enable_wakeup(struct stm32f7_i2c_dev *i2c_dev, -+ bool enable) -+{ -+ void __iomem *base = i2c_dev->base; -+ u32 mask = STM32F7_I2C_CR1_WUPEN; -+ -+ if (!i2c_dev->wakeup_src) -+ return; -+ -+ if (enable) { -+ device_set_wakeup_enable(i2c_dev->dev, true); -+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask); -+ readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1); -+ } else { -+ device_set_wakeup_enable(i2c_dev->dev, false); -+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask); -+ } -+} -+ -+static int __maybe_unused stm32f7_i2c_suspend(struct device *dev) -+{ -+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); -+ -+ i2c_mark_adapter_suspended(&i2c_dev->adap); -+ -+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) -+ pinctrl_pm_select_sleep_state(dev); -+ -+ pm_runtime_force_suspend(dev); -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32f7_i2c_resume(struct device *dev) -+{ -+ struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = pm_runtime_force_resume(dev); -+ if (ret < 0) -+ return ret; -+ -+ if (!stm32f7_i2c_is_slave_registered(i2c_dev)) -+ pinctrl_pm_select_default_state(dev); -+ -+ i2c_mark_adapter_resumed(&i2c_dev->adap); -+ - return 0; - } --#endif - - static const struct dev_pm_ops stm32f7_i2c_pm_ops = { - SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend, - stm32f7_i2c_runtime_resume, NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(stm32f7_i2c_suspend, stm32f7_i2c_resume) - }; - - static const struct of_device_id stm32f7_i2c_match[] = { - { .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup}, -+ { .compatible = "st,stm32mp15-i2c", .data = &stm32mp15_setup}, - {}, - }; - MODULE_DEVICE_TABLE(of, stm32f7_i2c_match); -diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c -index 560d8c7d9d862..c0a6e89cd77a3 100644 ---- a/drivers/iio/adc/sd_adc_modulator.c -+++ b/drivers/iio/adc/sd_adc_modulator.c -@@ -10,8 +10,7 @@ - #include - #include - #include -- --static const struct iio_info iio_sd_mod_iio_info; -+#include - - static const struct iio_chan_spec iio_sd_mod_ch = { - .type = IIO_VOLTAGE, -@@ -21,36 +20,99 @@ static const struct iio_chan_spec iio_sd_mod_ch = { - .realbits = 1, - .shift = 0, - }, -+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), -+}; -+ -+static const struct iio_chan_spec iio_sd_mod_ch_ads = { -+ .type = IIO_VOLTAGE, -+ .indexed = 1, -+ .scan_type = { -+ .sign = 'u', -+ .realbits = 1, -+ .shift = 0, -+ }, -+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), -+ .differential = 1, -+}; -+ -+struct iio_sd_mod_priv { -+ int vref_mv; -+}; -+ -+static const struct of_device_id sd_adc_of_match[] = { -+ { .compatible = "sd-modulator", .data = &iio_sd_mod_ch }, -+ { .compatible = "ads1201", .data = &iio_sd_mod_ch_ads }, -+ { } -+}; -+ -+static int iio_sd_mod_read_raw(struct iio_dev *indio_dev, -+ struct iio_chan_spec const *chan, int *val, -+ int *val2, long mask) -+{ -+ struct iio_sd_mod_priv *priv = iio_priv(indio_dev); -+ -+ switch (mask) { -+ case IIO_CHAN_INFO_SCALE: -+ *val = priv->vref_mv; -+ *val2 = chan->scan_type.realbits; -+ return IIO_VAL_INT; -+ } -+ -+ return -EINVAL; -+} -+ -+static const struct iio_info iio_sd_mod_iio_info = { -+ .read_raw = iio_sd_mod_read_raw, - }; - - static int iio_sd_mod_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -+ struct iio_sd_mod_priv *priv; -+ struct regulator *vref; - struct iio_dev *iio; -+ int ret; - -- iio = devm_iio_device_alloc(dev, 0); -+ iio = devm_iio_device_alloc(dev, sizeof(*priv)); - if (!iio) - return -ENOMEM; - -+ iio->channels = (const struct iio_chan_spec *) -+ of_match_device(sd_adc_of_match, &pdev->dev)->data; -+ -+ priv = iio_priv(iio); -+ - iio->dev.parent = dev; - iio->dev.of_node = dev->of_node; - iio->name = dev_name(dev); - iio->info = &iio_sd_mod_iio_info; - iio->modes = INDIO_BUFFER_HARDWARE; -- - iio->num_channels = 1; -- iio->channels = &iio_sd_mod_ch; - -- platform_set_drvdata(pdev, iio); -+ vref = devm_regulator_get_optional(dev, "vref"); -+ if (IS_ERR(vref)) { -+ ret = PTR_ERR(vref); -+ if (ret != -ENODEV) { -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "vref get failed, %d\n", ret); -+ return ret; -+ } -+ } -+ -+ if (!IS_ERR(vref)) { -+ ret = regulator_get_voltage(vref); -+ if (ret < 0) { -+ dev_err(dev, "vref get failed, %d\n", ret); -+ return ret; -+ } -+ -+ priv->vref_mv = ret / 1000; -+ dev_dbg(dev, "vref+=%dmV\n", priv->vref_mv); -+ } - - return devm_iio_device_register(&pdev->dev, iio); - } - --static const struct of_device_id sd_adc_of_match[] = { -- { .compatible = "sd-modulator" }, -- { .compatible = "ads1201" }, -- { } --}; - MODULE_DEVICE_TABLE(of, sd_adc_of_match); - - static struct platform_driver iio_sd_mod_adc = { -diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c -index 74f3a2be17a64..614d774438b98 100644 ---- a/drivers/iio/adc/stm32-adc-core.c -+++ b/drivers/iio/adc/stm32-adc-core.c -@@ -38,21 +38,19 @@ - #define HAS_ANASWVDD BIT(1) - - /** -- * stm32_adc_common_regs - stm32 common registers, compatible dependent data -+ * struct stm32_adc_common_regs - stm32 common registers - * @csr: common status register offset - * @ccr: common control register offset -- * @eoc1: adc1 end of conversion flag in @csr -- * @eoc2: adc2 end of conversion flag in @csr -- * @eoc3: adc3 end of conversion flag in @csr -+ * @eoc_msk: array of eoc (end of conversion flag) masks in csr for adc1..n -+ * @ovr_msk: array of ovr (overrun flag) masks in csr for adc1..n - * @ier: interrupt enable register offset for each adc - * @eocie_msk: end of conversion interrupt enable mask in @ier - */ - struct stm32_adc_common_regs { - u32 csr; - u32 ccr; -- u32 eoc1_msk; -- u32 eoc2_msk; -- u32 eoc3_msk; -+ u32 eoc_msk[STM32_ADC_MAX_ADCS]; -+ u32 ovr_msk[STM32_ADC_MAX_ADCS]; - u32 ier; - u32 eocie_msk; - }; -@@ -60,7 +58,7 @@ struct stm32_adc_common_regs { - struct stm32_adc_priv; - - /** -- * stm32_adc_priv_cfg - stm32 core compatible configuration data -+ * struct stm32_adc_priv_cfg - stm32 core compatible configuration data - * @regs: common registers for all instances - * @clk_sel: clock selection routine - * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) -@@ -81,6 +79,7 @@ struct stm32_adc_priv_cfg { - * @domain: irq domain reference - * @aclk: clock reference for the analog circuitry - * @bclk: bus clock common for all ADCs, depends on part used -+ * @max_clk_rate: desired maximum clock rate - * @booster: booster supply reference - * @vdd: vdd supply reference - * @vdda: vdda analog supply reference -@@ -97,6 +96,7 @@ struct stm32_adc_priv { - struct irq_domain *domain; - struct clk *aclk; - struct clk *bclk; -+ u32 max_clk_rate; - struct regulator *booster; - struct regulator *vdd; - struct regulator *vdda; -@@ -119,6 +119,7 @@ static int stm32f4_pclk_div[] = {2, 4, 6, 8}; - - /** - * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler -+ * @pdev: platform device - * @priv: stm32 ADC core private data - * Select clock prescaler used for analog conversions, before using ADC. - */ -@@ -142,7 +143,7 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev, - } - - for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) { -- if ((rate / stm32f4_pclk_div[i]) <= priv->cfg->max_clk_rate_hz) -+ if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate) - break; - } - if (i >= ARRAY_SIZE(stm32f4_pclk_div)) { -@@ -199,7 +200,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, - { - u32 ckmode, presc, val; - unsigned long rate; -- int i, div; -+ int i, div, duty; - - /* stm32h7 bus clock is common for all ADC instances (mandatory) */ - if (!priv->bclk) { -@@ -223,6 +224,11 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, - return -EINVAL; - } - -+ /* If duty is an error, kindly use at least /2 divider */ -+ duty = clk_get_scaled_duty_cycle(priv->aclk, 100); -+ if (duty < 0) -+ dev_warn(&pdev->dev, "adc clock duty: %d\n", duty); -+ - for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { - ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; - presc = stm32h7_adc_ckmodes_spec[i].presc; -@@ -231,7 +237,14 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, - if (ckmode) - continue; - -- if ((rate / div) <= priv->cfg->max_clk_rate_hz) -+ /* -+ * For proper operation, clock duty cycle range is 49% -+ * to 51%. Apply at least /2 prescaler otherwise. -+ */ -+ if (div == 1 && (duty < 49 || duty > 51)) -+ continue; -+ -+ if ((rate / div) <= priv->max_clk_rate) - goto out; - } - } -@@ -243,6 +256,10 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, - return -EINVAL; - } - -+ duty = clk_get_scaled_duty_cycle(priv->bclk, 100); -+ if (duty < 0) -+ dev_warn(&pdev->dev, "bus clock duty: %d\n", duty); -+ - for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { - ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; - presc = stm32h7_adc_ckmodes_spec[i].presc; -@@ -251,7 +268,10 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, - if (!ckmode) - continue; - -- if ((rate / div) <= priv->cfg->max_clk_rate_hz) -+ if (div == 1 && (duty < 49 || duty > 51)) -+ continue; -+ -+ if ((rate / div) <= priv->max_clk_rate) - goto out; - } - -@@ -279,9 +299,8 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, - static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { - .csr = STM32F4_ADC_CSR, - .ccr = STM32F4_ADC_CCR, -- .eoc1_msk = STM32F4_EOC1, -- .eoc2_msk = STM32F4_EOC2, -- .eoc3_msk = STM32F4_EOC3, -+ .eoc_msk = { STM32F4_EOC1, STM32F4_EOC2, STM32F4_EOC3}, -+ .ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3}, - .ier = STM32F4_ADC_CR1, - .eocie_msk = STM32F4_EOCIE, - }; -@@ -290,8 +309,8 @@ static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { - static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { - .csr = STM32H7_ADC_CSR, - .ccr = STM32H7_ADC_CCR, -- .eoc1_msk = STM32H7_EOC_MST, -- .eoc2_msk = STM32H7_EOC_SLV, -+ .eoc_msk = { STM32H7_EOC_MST, STM32H7_EOC_SLV}, -+ .ovr_msk = { STM32H7_OVR_MST, STM32H7_OVR_SLV}, - .ier = STM32H7_ADC_IER, - .eocie_msk = STM32H7_EOCIE, - }; -@@ -315,6 +334,7 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) - { - struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); -+ int i; - u32 status; - - chained_irq_enter(chip, desc); -@@ -332,17 +352,12 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) - * before invoking the interrupt handler (e.g. call ISR only for - * IRQ-enabled ADCs). - */ -- if (status & priv->cfg->regs->eoc1_msk && -- stm32_adc_eoc_enabled(priv, 0)) -- generic_handle_irq(irq_find_mapping(priv->domain, 0)); -- -- if (status & priv->cfg->regs->eoc2_msk && -- stm32_adc_eoc_enabled(priv, 1)) -- generic_handle_irq(irq_find_mapping(priv->domain, 1)); -- -- if (status & priv->cfg->regs->eoc3_msk && -- stm32_adc_eoc_enabled(priv, 2)) -- generic_handle_irq(irq_find_mapping(priv->domain, 2)); -+ for (i = 0; i < priv->cfg->num_irqs; i++) { -+ if ((status & priv->cfg->regs->eoc_msk[i] && -+ stm32_adc_eoc_enabled(priv, i)) || -+ (status & priv->cfg->regs->ovr_msk[i])) -+ generic_handle_irq(irq_find_mapping(priv->domain, i)); -+ } - - chained_irq_exit(chip, desc); - }; -@@ -645,6 +660,7 @@ static int stm32_adc_probe(struct platform_device *pdev) - struct device *dev = &pdev->dev; - struct device_node *np = pdev->dev.of_node; - struct resource *res; -+ u32 max_rate; - int ret; - - if (!pdev->dev.of_node) -@@ -675,7 +691,8 @@ static int stm32_adc_probe(struct platform_device *pdev) - priv->vref = devm_regulator_get(&pdev->dev, "vref"); - if (IS_ERR(priv->vref)) { - ret = PTR_ERR(priv->vref); -- dev_err(&pdev->dev, "vref get failed, %d\n", ret); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "vref get failed, %d\n", ret); - return ret; - } - -@@ -683,7 +700,8 @@ static int stm32_adc_probe(struct platform_device *pdev) - if (IS_ERR(priv->aclk)) { - ret = PTR_ERR(priv->aclk); - if (ret != -ENOENT) { -- dev_err(&pdev->dev, "Can't get 'adc' clock\n"); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Can't get 'adc' clock\n"); - return ret; - } - priv->aclk = NULL; -@@ -693,7 +711,8 @@ static int stm32_adc_probe(struct platform_device *pdev) - if (IS_ERR(priv->bclk)) { - ret = PTR_ERR(priv->bclk); - if (ret != -ENOENT) { -- dev_err(&pdev->dev, "Can't get 'bus' clock\n"); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Can't get 'bus' clock\n"); - return ret; - } - priv->bclk = NULL; -@@ -721,6 +740,13 @@ static int stm32_adc_probe(struct platform_device *pdev) - priv->common.vref_mv = ret / 1000; - dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv); - -+ ret = of_property_read_u32(pdev->dev.of_node, "st,max-clk-rate-hz", -+ &max_rate); -+ if (!ret) -+ priv->max_clk_rate = min(max_rate, priv->cfg->max_clk_rate_hz); -+ else -+ priv->max_clk_rate = priv->cfg->max_clk_rate_hz; -+ - ret = priv->cfg->clk_sel(pdev, priv); - if (ret < 0) - goto err_hw_stop; -@@ -780,6 +806,13 @@ static int stm32_adc_core_runtime_resume(struct device *dev) - { - return stm32_adc_core_hw_start(dev); - } -+ -+static int stm32_adc_core_runtime_idle(struct device *dev) -+{ -+ pm_runtime_mark_last_busy(dev); -+ -+ return 0; -+} - #endif - - static const struct dev_pm_ops stm32_adc_core_pm_ops = { -@@ -787,7 +820,7 @@ static const struct dev_pm_ops stm32_adc_core_pm_ops = { - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend, - stm32_adc_core_runtime_resume, -- NULL) -+ stm32_adc_core_runtime_idle) - }; - - static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = { -diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h -index 2579d514c2a34..2322809bfd2f7 100644 ---- a/drivers/iio/adc/stm32-adc-core.h -+++ b/drivers/iio/adc/stm32-adc-core.h -@@ -51,10 +51,12 @@ - #define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04) - - /* STM32F4_ADC_SR - bit fields */ -+#define STM32F4_OVR BIT(5) - #define STM32F4_STRT BIT(4) - #define STM32F4_EOC BIT(1) - - /* STM32F4_ADC_CR1 - bit fields */ -+#define STM32F4_OVRIE BIT(26) - #define STM32F4_RES_SHIFT 24 - #define STM32F4_RES_MASK GENMASK(25, 24) - #define STM32F4_SCAN BIT(8) -@@ -72,8 +74,11 @@ - #define STM32F4_ADON BIT(0) - - /* STM32F4_ADC_CSR - bit fields */ -+#define STM32F4_OVR3 BIT(21) - #define STM32F4_EOC3 BIT(17) -+#define STM32F4_OVR2 BIT(13) - #define STM32F4_EOC2 BIT(9) -+#define STM32F4_OVR1 BIT(5) - #define STM32F4_EOC1 BIT(1) - - /* STM32F4_ADC_CCR - bit fields */ -@@ -103,10 +108,12 @@ - - /* STM32H7_ADC_ISR - bit fields */ - #define STM32MP1_VREGREADY BIT(12) -+#define STM32H7_OVR BIT(4) - #define STM32H7_EOC BIT(2) - #define STM32H7_ADRDY BIT(0) - - /* STM32H7_ADC_IER - bit fields */ -+#define STM32H7_OVRIE STM32H7_OVR - #define STM32H7_EOCIE STM32H7_EOC - - /* STM32H7_ADC_CR - bit fields */ -@@ -155,7 +162,9 @@ enum stm32h7_adc_dmngt { - #define STM32H7_LINCALFACT_MASK GENMASK(29, 0) - - /* STM32H7_ADC_CSR - bit fields */ -+#define STM32H7_OVR_SLV BIT(20) - #define STM32H7_EOC_SLV BIT(18) -+#define STM32H7_OVR_MST BIT(4) - #define STM32H7_EOC_MST BIT(2) - - /* STM32H7_ADC_CCR - bit fields */ -diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c -index 94fde39d9ff7a..cd1bbecd54921 100644 ---- a/drivers/iio/adc/stm32-adc.c -+++ b/drivers/iio/adc/stm32-adc.c -@@ -102,7 +102,7 @@ struct stm32_adc_calib { - }; - - /** -- * stm32_adc_regs - stm32 ADC misc registers & bitfield desc -+ * struct stm32_adc_regs - stm32 ADC misc registers & bitfield desc - * @reg: register offset - * @mask: bitfield mask - * @shift: left shift -@@ -114,10 +114,12 @@ struct stm32_adc_regs { - }; - - /** -- * stm32_adc_regspec - stm32 registers definition, compatible dependent data -+ * struct stm32_adc_regspec - stm32 registers definition - * @dr: data register offset - * @ier_eoc: interrupt enable register & eocie bitfield -+ * @ier_ovr: interrupt enable register & overrun bitfield - * @isr_eoc: interrupt status register & eoc bitfield -+ * @isr_ovr: interrupt status register & overrun bitfield - * @sqr: reference to sequence registers array - * @exten: trigger control register & bitfield - * @extsel: trigger selection register & bitfield -@@ -128,7 +130,9 @@ struct stm32_adc_regs { - struct stm32_adc_regspec { - const u32 dr; - const struct stm32_adc_regs ier_eoc; -+ const struct stm32_adc_regs ier_ovr; - const struct stm32_adc_regs isr_eoc; -+ const struct stm32_adc_regs isr_ovr; - const struct stm32_adc_regs *sqr; - const struct stm32_adc_regs exten; - const struct stm32_adc_regs extsel; -@@ -140,7 +144,7 @@ struct stm32_adc_regspec { - struct stm32_adc; - - /** -- * stm32_adc_cfg - stm32 compatible configuration data -+ * struct stm32_adc_cfg - stm32 compatible configuration data - * @regs: registers descriptions - * @adc_info: per instance input channels definitions - * @trigs: external trigger sources -@@ -150,6 +154,7 @@ struct stm32_adc; - * @start_conv: routine to start conversions - * @stop_conv: routine to stop conversions - * @unprepare: optional unprepare routine (disable, power-down) -+ * @irq_clear: routine to clear irqs - * @smp_cycles: programmable sampling time (ADC clock cycles) - */ - struct stm32_adc_cfg { -@@ -162,6 +167,7 @@ struct stm32_adc_cfg { - void (*start_conv)(struct stm32_adc *, bool dma); - void (*stop_conv)(struct stm32_adc *); - void (*unprepare)(struct stm32_adc *); -+ void (*irq_clear)(struct stm32_adc *adc, u32 msk); - const unsigned int *smp_cycles; - }; - -@@ -183,8 +189,8 @@ struct stm32_adc_cfg { - * @rx_buf: dma rx buffer cpu address - * @rx_dma_buf: dma rx buffer bus address - * @rx_buf_sz: dma rx buffer size -- * @difsel bitmask to set single-ended/differential channel -- * @pcsel bitmask to preselect channels on some devices -+ * @difsel: bitmask to set single-ended/differential channel -+ * @pcsel: bitmask to preselect channels on some devices - * @smpr_val: sampling time settings (e.g. smpr1 / smpr2) - * @cal: optional calibration data on some devices - * @chan_name: channel name array -@@ -254,7 +260,7 @@ static const struct stm32_adc_info stm32h7_adc_info = { - .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), - }; - --/** -+/* - * stm32f4_sq - describe regular sequence registers - * - L: sequence len (register & bit field) - * - SQ1..SQ16: sequence entries (register & bit field) -@@ -301,7 +307,7 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = { - {}, /* sentinel */ - }; - --/** -+/* - * stm32f4_smp_bits[] - describe sampling time register index & bit fields - * Sorted so it can be indexed by channel number. - */ -@@ -337,7 +343,9 @@ static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { - static const struct stm32_adc_regspec stm32f4_adc_regspec = { - .dr = STM32F4_ADC_DR, - .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE }, -+ .ier_ovr = { STM32F4_ADC_CR1, STM32F4_OVRIE }, - .isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC }, -+ .isr_ovr = { STM32F4_ADC_SR, STM32F4_OVR }, - .sqr = stm32f4_sq, - .exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT }, - .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK, -@@ -392,7 +400,7 @@ static struct stm32_adc_trig_info stm32h7_adc_trigs[] = { - {}, - }; - --/** -+/* - * stm32h7_smp_bits - describe sampling time register index & bit fields - * Sorted so it can be indexed by channel number. - */ -@@ -429,7 +437,9 @@ static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { - static const struct stm32_adc_regspec stm32h7_adc_regspec = { - .dr = STM32H7_ADC_DR, - .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, -+ .ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE }, - .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC }, -+ .isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR }, - .sqr = stm32h7_sq, - .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT }, - .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, -@@ -506,6 +516,18 @@ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc) - adc->cfg->regs->ier_eoc.mask); - } - -+static void stm32_adc_ovr_irq_enable(struct stm32_adc *adc) -+{ -+ stm32_adc_set_bits(adc, adc->cfg->regs->ier_ovr.reg, -+ adc->cfg->regs->ier_ovr.mask); -+} -+ -+static void stm32_adc_ovr_irq_disable(struct stm32_adc *adc) -+{ -+ stm32_adc_clr_bits(adc, adc->cfg->regs->ier_ovr.reg, -+ adc->cfg->regs->ier_ovr.mask); -+} -+ - static void stm32_adc_set_res(struct stm32_adc *adc) - { - const struct stm32_adc_regs *res = &adc->cfg->regs->res; -@@ -595,6 +617,11 @@ static void stm32f4_adc_stop_conv(struct stm32_adc *adc) - STM32F4_ADON | STM32F4_DMA | STM32F4_DDS); - } - -+static void stm32f4_adc_irq_clear(struct stm32_adc *adc, u32 msk) -+{ -+ stm32_adc_clr_bits(adc, adc->cfg->regs->isr_eoc.reg, msk); -+} -+ - static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma) - { - enum stm32h7_adc_dmngt dmngt; -@@ -632,6 +659,12 @@ static void stm32h7_adc_stop_conv(struct stm32_adc *adc) - stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK); - } - -+static void stm32h7_adc_irq_clear(struct stm32_adc *adc, u32 msk) -+{ -+ /* On STM32H7 IRQs are cleared by writing 1 into ISR register */ -+ stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk); -+} -+ - static int stm32h7_adc_exit_pwr_down(struct stm32_adc *adc) - { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); -@@ -994,6 +1027,7 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, - - /** - * stm32_adc_get_trig_extsel() - Get external trigger selection -+ * @indio_dev: IIO device structure - * @trig: trigger - * - * Returns trigger extsel value, if trig matches, -EINVAL otherwise. -@@ -1204,12 +1238,63 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, - } - } - -+static void stm32_adc_irq_clear(struct stm32_adc *adc, u32 msk) -+{ -+ adc->cfg->irq_clear(adc, msk); -+} -+ -+static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) -+{ -+ struct stm32_adc *adc = data; -+ struct iio_dev *indio_dev = iio_priv_to_dev(adc); -+ const struct stm32_adc_regspec *regs = adc->cfg->regs; -+ u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); -+ u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg); -+ -+ /* Check ovr status right now, as ovr mask should be already disabled */ -+ if (status & regs->isr_ovr.mask) { -+ /* -+ * Clear ovr bit to avoid subsequent calls to IRQ handler. -+ * This requires to stop ADC first. OVR bit state in ISR, -+ * is propaged to CSR register by hardware. -+ */ -+ adc->cfg->stop_conv(adc); -+ stm32_adc_irq_clear(adc, regs->isr_ovr.mask); -+ dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n"); -+ return IRQ_HANDLED; -+ } -+ -+ if (!(status & mask)) -+ dev_err_ratelimited(&indio_dev->dev, -+ "Unexpected IRQ: IER=0x%08x, ISR=0x%08x\n", -+ mask, status); -+ -+ return IRQ_NONE; -+} -+ - static irqreturn_t stm32_adc_isr(int irq, void *data) - { - struct stm32_adc *adc = data; - struct iio_dev *indio_dev = iio_priv_to_dev(adc); - const struct stm32_adc_regspec *regs = adc->cfg->regs; - u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); -+ u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg); -+ -+ if (!(status & mask)) -+ return IRQ_WAKE_THREAD; -+ -+ if (status & regs->isr_ovr.mask) { -+ /* -+ * Overrun occurred on regular conversions: data for wrong -+ * channel may be read. Unconditionally disable interrupts -+ * to stop processing data and print error message. -+ * Restarting the capture can be done by disabling, then -+ * re-enabling it (e.g. write 0, then 1 to buffer/enable). -+ */ -+ stm32_adc_ovr_irq_disable(adc); -+ stm32_adc_conv_irq_disable(adc); -+ return IRQ_WAKE_THREAD; -+ } - - if (status & regs->isr_eoc.mask) { - /* Reading DR also clears EOC status flag */ -@@ -1253,7 +1338,7 @@ static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) - * dma cyclic transfers are used, buffer is split into two periods. - * There should be : - * - always one buffer (period) dma is working on -- * - one buffer (period) driver can push with iio_trigger_poll(). -+ * - one buffer (period) driver can push data. - */ - watermark = min(watermark, val * (unsigned)(sizeof(u16))); - adc->rx_buf_sz = min(rx_buf_sz, watermark * 2 * adc->num_conv); -@@ -1297,6 +1382,10 @@ static int stm32_adc_of_xlate(struct iio_dev *indio_dev, - - /** - * stm32_adc_debugfs_reg_access - read or write register value -+ * @indio_dev: IIO device structure -+ * @reg: register offset -+ * @writeval: value to write -+ * @readval: value to read - * - * To read a value from an ADC register: - * echo [ADC reg offset] > direct_reg_access -@@ -1458,6 +1547,8 @@ static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev) - /* Reset adc buffer index */ - adc->bufi = 0; - -+ stm32_adc_ovr_irq_enable(adc); -+ - if (!adc->dma_chan) - stm32_adc_conv_irq_enable(adc); - -@@ -1498,6 +1589,8 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev) - if (!adc->dma_chan) - stm32_adc_conv_irq_disable(adc); - -+ stm32_adc_ovr_irq_disable(adc); -+ - if (adc->dma_chan) - dmaengine_terminate_sync(adc->dma_chan); - -@@ -1534,31 +1627,14 @@ static irqreturn_t stm32_adc_trigger_handler(int irq, void *p) - - dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi); - -- if (!adc->dma_chan) { -- /* reset buffer index */ -- adc->bufi = 0; -- iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer, -- pf->timestamp); -- } else { -- int residue = stm32_adc_dma_residue(adc); -- -- while (residue >= indio_dev->scan_bytes) { -- u16 *buffer = (u16 *)&adc->rx_buf[adc->bufi]; -- -- iio_push_to_buffers_with_timestamp(indio_dev, buffer, -- pf->timestamp); -- residue -= indio_dev->scan_bytes; -- adc->bufi += indio_dev->scan_bytes; -- if (adc->bufi >= adc->rx_buf_sz) -- adc->bufi = 0; -- } -- } -- -+ /* reset buffer index */ -+ adc->bufi = 0; -+ iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer, -+ pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); - - /* re-enable eoc irq */ -- if (!adc->dma_chan) -- stm32_adc_conv_irq_enable(adc); -+ stm32_adc_conv_irq_enable(adc); - - return IRQ_HANDLED; - } -@@ -1848,8 +1924,9 @@ static int stm32_adc_probe(struct platform_device *pdev) - if (adc->irq < 0) - return adc->irq; - -- ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, -- 0, pdev->name, adc); -+ ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr, -+ stm32_adc_threaded_isr, -+ 0, pdev->name, adc); - if (ret) { - dev_err(&pdev->dev, "failed to request IRQ\n"); - return ret; -@@ -2013,6 +2090,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = { - .start_conv = stm32f4_adc_start_conv, - .stop_conv = stm32f4_adc_stop_conv, - .smp_cycles = stm32f4_adc_smp_cycles, -+ .irq_clear = stm32f4_adc_irq_clear, - }; - - static const struct stm32_adc_cfg stm32h7_adc_cfg = { -@@ -2024,6 +2102,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { - .prepare = stm32h7_adc_prepare, - .unprepare = stm32h7_adc_unprepare, - .smp_cycles = stm32h7_adc_smp_cycles, -+ .irq_clear = stm32h7_adc_irq_clear, - }; - - static const struct stm32_adc_cfg stm32mp1_adc_cfg = { -@@ -2036,6 +2115,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { - .prepare = stm32h7_adc_prepare, - .unprepare = stm32h7_adc_unprepare, - .smp_cycles = stm32h7_adc_smp_cycles, -+ .irq_clear = stm32h7_adc_irq_clear, - }; - - static const struct of_device_id stm32_adc_of_match[] = { -diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c -index c2948defa7853..b9a536a6c24f2 100644 ---- a/drivers/iio/adc/stm32-dfsdm-adc.c -+++ b/drivers/iio/adc/stm32-dfsdm-adc.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -67,6 +68,13 @@ struct stm32_dfsdm_dev_data { - const struct regmap_config *regmap_cfg; - }; - -+struct stm32_dfsdm_sd_chan_info { -+ int scale_val; -+ int scale_val2; -+ int offset; -+ unsigned int differential; -+}; -+ - struct stm32_dfsdm_adc { - struct stm32_dfsdm *dfsdm; - const struct stm32_dfsdm_dev_data *dev_data; -@@ -79,6 +87,7 @@ struct stm32_dfsdm_adc { - struct iio_hw_consumer *hwc; - struct completion completion; - u32 *buffer; -+ struct stm32_dfsdm_sd_chan_info *sd_chan; - - /* Audio specific */ - unsigned int spi_freq; /* SPI bus clock frequency */ -@@ -1199,14 +1208,32 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, - unsigned int spi_freq; - int ret = -EINVAL; - -+ switch (ch->src) { -+ case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: -+ spi_freq = adc->dfsdm->spi_master_freq; -+ break; -+ case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: -+ case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: -+ spi_freq = adc->dfsdm->spi_master_freq / 2; -+ break; -+ default: -+ spi_freq = adc->spi_freq; -+ } -+ - switch (mask) { - case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; -+ - ret = stm32_dfsdm_compute_all_osrs(indio_dev, val); -- if (!ret) -+ if (!ret) { -+ dev_dbg(&indio_dev->dev, -+ "Sampling rate changed from (%u) to (%u)\n", -+ adc->sample_freq, spi_freq / val); - adc->oversamp = val; -+ adc->sample_freq = spi_freq / val; -+ } - iio_device_release_direct_mode(indio_dev); - return ret; - -@@ -1218,18 +1245,6 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, - if (ret) - return ret; - -- switch (ch->src) { -- case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: -- spi_freq = adc->dfsdm->spi_master_freq; -- break; -- case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: -- case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: -- spi_freq = adc->dfsdm->spi_master_freq / 2; -- break; -- default: -- spi_freq = adc->spi_freq; -- } -- - ret = dfsdm_adc_set_samp_freq(indio_dev, val, spi_freq); - iio_device_release_direct_mode(indio_dev); - return ret; -@@ -1243,7 +1258,10 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, - int *val2, long mask) - { - struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); -- int ret; -+ struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; -+ struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast]; -+ u32 max = flo->max << (flo->lshift - chan->scan_type.shift); -+ int ret, idx = chan->scan_index; - - switch (mask) { - case IIO_CHAN_INFO_RAW: -@@ -1279,6 +1297,39 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, - *val = adc->sample_freq; - - return IIO_VAL_INT; -+ -+ case IIO_CHAN_INFO_SCALE: -+ /* -+ * Scale is expressed in mV. -+ * When fast mode is disabled, actual resolution may be lower -+ * than 2^n, where n=realbits-1. -+ * This leads to underestimating input voltage. To -+ * compensate this deviation, the voltage reference can be -+ * corrected with a factor = realbits resolution / actual max -+ */ -+ *val = div_u64((u64)adc->sd_chan[idx].scale_val * -+ (u64)BIT(DFSDM_DATA_RES - 1), max); -+ *val2 = chan->scan_type.realbits; -+ if (adc->sd_chan[idx].differential) -+ *val *= 2; -+ return IIO_VAL_FRACTIONAL_LOG2; -+ -+ case IIO_CHAN_INFO_OFFSET: -+ /* -+ * DFSDM output data are in the range [-2^n,2^n-1], -+ * with n=realbits-1. -+ * - Differential modulator: -+ * Offset correspond to SD modulator offset. -+ * - Single ended modulator: -+ * Input is in [0V,Vref] range, where 0V corresponds to -2^n. -+ * Add 2^n to offset. (i.e. middle of input range) -+ * offset = offset(sd) * vref / res(sd) * max / vref. -+ */ -+ *val = div_u64((u64)max * adc->sd_chan[idx].offset, -+ BIT(adc->sd_chan[idx].scale_val2 - 1)); -+ if (!adc->sd_chan[idx].differential) -+ *val += max; -+ return IIO_VAL_INT; - } - - return -EINVAL; -@@ -1403,7 +1454,9 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, - * IIO_CHAN_INFO_RAW: used to compute regular conversion - * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling - */ -- ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); -+ ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | -+ BIT(IIO_CHAN_INFO_SCALE) | -+ BIT(IIO_CHAN_INFO_OFFSET); - ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | - BIT(IIO_CHAN_INFO_SAMP_FREQ); - -@@ -1413,7 +1466,7 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, - ch->scan_type.shift = 8; - } - ch->scan_type.sign = 's'; -- ch->scan_type.realbits = 24; -+ ch->scan_type.realbits = DFSDM_DATA_RES; - ch->scan_type.storagebits = 32; - - return stm32_dfsdm_chan_configure(adc->dfsdm, -@@ -1454,8 +1507,10 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) - { - struct iio_chan_spec *ch; - struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); -+ struct iio_channel *channels, *chan; -+ struct stm32_dfsdm_sd_chan_info *sd_chan; - int num_ch; -- int ret, chan_idx; -+ int ret, chan_idx, val2; - - adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING; - ret = stm32_dfsdm_compute_all_osrs(indio_dev, adc->oversamp); -@@ -1479,6 +1534,21 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) - if (!ch) - return -ENOMEM; - -+ /* Get SD modulator channels */ -+ channels = iio_channel_get_all(&indio_dev->dev); -+ if (IS_ERR(channels)) { -+ dev_err(&indio_dev->dev, "Failed to get channel %ld\n", -+ PTR_ERR(channels)); -+ return PTR_ERR(channels); -+ } -+ chan = &channels[0]; -+ -+ adc->sd_chan = devm_kzalloc(&indio_dev->dev, -+ sizeof(*adc->sd_chan) * num_ch, GFP_KERNEL); -+ if (!adc->sd_chan) -+ return -ENOMEM; -+ sd_chan = adc->sd_chan; -+ - for (chan_idx = 0; chan_idx < num_ch; chan_idx++) { - ch[chan_idx].scan_index = chan_idx; - ret = stm32_dfsdm_adc_chan_init_one(indio_dev, &ch[chan_idx]); -@@ -1486,6 +1556,38 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) - dev_err(&indio_dev->dev, "Channels init failed\n"); - return ret; - } -+ -+ if (!chan->indio_dev) -+ return -EINVAL; -+ -+ ret = iio_read_channel_scale(chan, &sd_chan->scale_val, -+ &sd_chan->scale_val2); -+ if (ret < 0) { -+ dev_err(&indio_dev->dev, -+ "Failed to get channel %d scale\n", chan_idx); -+ return ret; -+ } -+ -+ if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_OFFSET)) { -+ ret = iio_read_channel_offset(chan, &sd_chan->offset, -+ &val2); -+ if (ret < 0) { -+ dev_err(&indio_dev->dev, -+ "Failed to get channel %d offset\n", -+ chan_idx); -+ return ret; -+ } -+ } -+ -+ sd_chan->differential = chan->channel->differential; -+ -+ dev_dbg(&indio_dev->dev, "Channel %d %s scale ref=%d offset=%d", -+ chan_idx, chan->channel->differential ? -+ "differential" : "single-ended", -+ sd_chan->scale_val, sd_chan->offset); -+ -+ chan++; -+ sd_chan++; - } - - indio_dev->num_channels = num_ch; -diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c -index d0fb3124de076..7e5809ba0dee1 100644 ---- a/drivers/iio/dac/stm32-dac-core.c -+++ b/drivers/iio/dac/stm32-dac-core.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -19,13 +20,11 @@ - /** - * struct stm32_dac_priv - stm32 DAC core private data - * @pclk: peripheral clock common for all DACs -- * @rst: peripheral reset control - * @vref: regulator reference - * @common: Common data for all DAC instances - */ - struct stm32_dac_priv { - struct clk *pclk; -- struct reset_control *rst; - struct regulator *vref; - struct stm32_dac_common common; - }; -@@ -50,6 +49,41 @@ static const struct regmap_config stm32_dac_regmap_cfg = { - .max_register = 0x3fc, - }; - -+static int stm32_dac_core_hw_start(struct device *dev) -+{ -+ struct stm32_dac_common *common = dev_get_drvdata(dev); -+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common); -+ int ret; -+ -+ ret = regulator_enable(priv->vref); -+ if (ret < 0) { -+ dev_err(dev, "vref enable failed: %d\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(priv->pclk); -+ if (ret < 0) { -+ dev_err(dev, "pclk enable failed: %d\n", ret); -+ goto err_regulator_disable; -+ } -+ -+ return 0; -+ -+err_regulator_disable: -+ regulator_disable(priv->vref); -+ -+ return ret; -+} -+ -+static void stm32_dac_core_hw_stop(struct device *dev) -+{ -+ struct stm32_dac_common *common = dev_get_drvdata(dev); -+ struct stm32_dac_priv *priv = to_stm32_dac_priv(common); -+ -+ clk_disable_unprepare(priv->pclk); -+ regulator_disable(priv->vref); -+} -+ - static int stm32_dac_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -58,6 +92,7 @@ static int stm32_dac_probe(struct platform_device *pdev) - struct regmap *regmap; - struct resource *res; - void __iomem *mmio; -+ struct reset_control *rst; - int ret; - - if (!dev->of_node) -@@ -66,6 +101,8 @@ static int stm32_dac_probe(struct platform_device *pdev) - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; -+ platform_set_drvdata(pdev, &priv->common); -+ - cfg = (const struct stm32_dac_cfg *) - of_match_device(dev->driver->of_match_table, dev)->data; - -@@ -74,11 +111,19 @@ static int stm32_dac_probe(struct platform_device *pdev) - if (IS_ERR(mmio)) - return PTR_ERR(mmio); - -- regmap = devm_regmap_init_mmio(dev, mmio, &stm32_dac_regmap_cfg); -+ regmap = devm_regmap_init_mmio_clk(dev, "pclk", mmio, -+ &stm32_dac_regmap_cfg); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - priv->common.regmap = regmap; - -+ priv->pclk = devm_clk_get(dev, "pclk"); -+ if (IS_ERR(priv->pclk)) { -+ ret = PTR_ERR(priv->pclk); -+ dev_err(dev, "pclk get failed\n"); -+ return ret; -+ } -+ - priv->vref = devm_regulator_get(dev, "vref"); - if (IS_ERR(priv->vref)) { - ret = PTR_ERR(priv->vref); -@@ -86,38 +131,35 @@ static int stm32_dac_probe(struct platform_device *pdev) - return ret; - } - -- ret = regulator_enable(priv->vref); -- if (ret < 0) { -- dev_err(dev, "vref enable failed\n"); -- return ret; -- } -+ pm_runtime_get_noresume(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ -+ ret = stm32_dac_core_hw_start(dev); -+ if (ret) -+ goto err_pm_stop; - - ret = regulator_get_voltage(priv->vref); - if (ret < 0) { - dev_err(dev, "vref get voltage failed, %d\n", ret); -- goto err_vref; -+ goto err_hw_stop; - } - priv->common.vref_mv = ret / 1000; - dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv); - -- priv->pclk = devm_clk_get(dev, "pclk"); -- if (IS_ERR(priv->pclk)) { -- ret = PTR_ERR(priv->pclk); -- dev_err(dev, "pclk get failed\n"); -- goto err_vref; -- } -+ rst = devm_reset_control_get_optional_exclusive(dev, NULL); -+ if (rst) { -+ if (IS_ERR(rst)) { -+ ret = PTR_ERR(rst); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "reset get failed, %d\n", ret); - -- ret = clk_prepare_enable(priv->pclk); -- if (ret < 0) { -- dev_err(dev, "pclk enable failed\n"); -- goto err_vref; -- } -+ goto err_hw_stop; -+ } - -- priv->rst = devm_reset_control_get_exclusive(dev, NULL); -- if (!IS_ERR(priv->rst)) { -- reset_control_assert(priv->rst); -+ reset_control_assert(rst); - udelay(2); -- reset_control_deassert(priv->rst); -+ reset_control_deassert(rst); - } - - if (cfg && cfg->has_hfsel) { -@@ -128,39 +170,79 @@ static int stm32_dac_probe(struct platform_device *pdev) - priv->common.hfsel ? - STM32H7_DAC_CR_HFSEL : 0); - if (ret) -- goto err_pclk; -+ goto err_hw_stop; - } - -- platform_set_drvdata(pdev, &priv->common); - - ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, dev); - if (ret < 0) { - dev_err(dev, "failed to populate DT children\n"); -- goto err_pclk; -+ goto err_hw_stop; - } - -+ pm_runtime_put(dev); -+ - return 0; - --err_pclk: -- clk_disable_unprepare(priv->pclk); --err_vref: -- regulator_disable(priv->vref); -+err_hw_stop: -+ stm32_dac_core_hw_stop(dev); -+err_pm_stop: -+ pm_runtime_disable(dev); -+ pm_runtime_set_suspended(dev); -+ pm_runtime_put_noidle(dev); - - return ret; - } - - static int stm32_dac_remove(struct platform_device *pdev) - { -- struct stm32_dac_common *common = platform_get_drvdata(pdev); -+ pm_runtime_get_sync(&pdev->dev); -+ of_platform_depopulate(&pdev->dev); -+ stm32_dac_core_hw_stop(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ pm_runtime_set_suspended(&pdev->dev); -+ pm_runtime_put_noidle(&pdev->dev); -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32_dac_core_resume(struct device *dev) -+{ -+ struct stm32_dac_common *common = dev_get_drvdata(dev); - struct stm32_dac_priv *priv = to_stm32_dac_priv(common); -+ int ret; - -- of_platform_depopulate(&pdev->dev); -- clk_disable_unprepare(priv->pclk); -- regulator_disable(priv->vref); -+ if (priv->common.hfsel) { -+ /* restore hfsel (maybe lost under low power state) */ -+ ret = regmap_update_bits(priv->common.regmap, STM32_DAC_CR, -+ STM32H7_DAC_CR_HFSEL, -+ STM32H7_DAC_CR_HFSEL); -+ if (ret) -+ return ret; -+ } -+ -+ return pm_runtime_force_resume(dev); -+} -+ -+static int __maybe_unused stm32_dac_core_runtime_suspend(struct device *dev) -+{ -+ stm32_dac_core_hw_stop(dev); - - return 0; - } - -+static int __maybe_unused stm32_dac_core_runtime_resume(struct device *dev) -+{ -+ return stm32_dac_core_hw_start(dev); -+} -+ -+static const struct dev_pm_ops stm32_dac_core_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, stm32_dac_core_resume) -+ SET_RUNTIME_PM_OPS(stm32_dac_core_runtime_suspend, -+ stm32_dac_core_runtime_resume, -+ NULL) -+}; -+ - static const struct stm32_dac_cfg stm32h7_dac_cfg = { - .has_hfsel = true, - }; -@@ -182,6 +264,7 @@ static struct platform_driver stm32_dac_driver = { - .driver = { - .name = "stm32-dac-core", - .of_match_table = stm32_dac_of_match, -+ .pm = &stm32_dac_core_pm_ops, - }, - }; - module_platform_driver(stm32_dac_driver); -diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c -index cce26a3a6627c..f22c1d9129b28 100644 ---- a/drivers/iio/dac/stm32-dac.c -+++ b/drivers/iio/dac/stm32-dac.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include "stm32-dac-core.h" - -@@ -20,6 +21,8 @@ - #define STM32_DAC_CHANNEL_2 2 - #define STM32_DAC_IS_CHAN_1(ch) ((ch) & STM32_DAC_CHANNEL_1) - -+#define STM32_DAC_AUTO_SUSPEND_DELAY_MS 2000 -+ - /** - * struct stm32_dac - private data of DAC driver - * @common: reference to DAC common data -@@ -49,15 +52,34 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch, - bool enable) - { - struct stm32_dac *dac = iio_priv(indio_dev); -+ struct device *dev = indio_dev->dev.parent; - u32 msk = STM32_DAC_IS_CHAN_1(ch) ? STM32_DAC_CR_EN1 : STM32_DAC_CR_EN2; - u32 en = enable ? msk : 0; - int ret; - -+ /* already enabled / disabled ? */ -+ mutex_lock(&indio_dev->mlock); -+ ret = stm32_dac_is_enabled(indio_dev, ch); -+ if (ret < 0 || enable == !!ret) { -+ mutex_unlock(&indio_dev->mlock); -+ return ret < 0 ? ret : 0; -+ } -+ -+ if (enable) { -+ ret = pm_runtime_get_sync(dev); -+ if (ret < 0) { -+ pm_runtime_put_noidle(dev); -+ mutex_unlock(&indio_dev->mlock); -+ return ret; -+ } -+ } -+ - ret = regmap_update_bits(dac->common->regmap, STM32_DAC_CR, msk, en); -+ mutex_unlock(&indio_dev->mlock); - if (ret < 0) { - dev_err(&indio_dev->dev, "%s failed\n", en ? - "Enable" : "Disable"); -- return ret; -+ goto err_put_pm; - } - - /* -@@ -68,7 +90,20 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch, - if (en && dac->common->hfsel) - udelay(1); - -+ if (!enable) { -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ } -+ - return 0; -+ -+err_put_pm: -+ if (enable) { -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ } -+ -+ return ret; - } - - static int stm32_dac_get_value(struct stm32_dac *dac, int channel, int *val) -@@ -272,6 +307,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev) - static int stm32_dac_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; -+ struct device *dev = &pdev->dev; - struct iio_dev *indio_dev; - struct stm32_dac *dac; - int ret; -@@ -296,9 +332,61 @@ static int stm32_dac_probe(struct platform_device *pdev) - if (ret < 0) - return ret; - -- return devm_iio_device_register(&pdev->dev, indio_dev); -+ /* Get stm32-dac-core PM online */ -+ pm_runtime_get_noresume(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_set_autosuspend_delay(dev, STM32_DAC_AUTO_SUSPEND_DELAY_MS); -+ pm_runtime_use_autosuspend(dev); -+ pm_runtime_enable(dev); -+ -+ ret = iio_device_register(indio_dev); -+ if (ret) -+ goto err_pm_put; -+ -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ -+ return 0; -+ -+err_pm_put: -+ pm_runtime_disable(dev); -+ pm_runtime_set_suspended(dev); -+ pm_runtime_put_noidle(dev); -+ -+ return ret; - } - -+static int stm32_dac_remove(struct platform_device *pdev) -+{ -+ struct iio_dev *indio_dev = platform_get_drvdata(pdev); -+ -+ pm_runtime_get_sync(&pdev->dev); -+ iio_device_unregister(indio_dev); -+ pm_runtime_disable(&pdev->dev); -+ pm_runtime_set_suspended(&pdev->dev); -+ pm_runtime_put_noidle(&pdev->dev); -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32_dac_suspend(struct device *dev) -+{ -+ struct iio_dev *indio_dev = dev_get_drvdata(dev); -+ int channel = indio_dev->channels[0].channel; -+ int ret; -+ -+ /* Ensure DAC is disabled before suspend */ -+ ret = stm32_dac_is_enabled(indio_dev, channel); -+ if (ret) -+ return ret < 0 ? ret : -EBUSY; -+ -+ return pm_runtime_force_suspend(dev); -+} -+ -+static const struct dev_pm_ops stm32_dac_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(stm32_dac_suspend, pm_runtime_force_resume) -+}; -+ - static const struct of_device_id stm32_dac_of_match[] = { - { .compatible = "st,stm32-dac", }, - {}, -@@ -307,9 +395,11 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match); - - static struct platform_driver stm32_dac_driver = { - .probe = stm32_dac_probe, -+ .remove = stm32_dac_remove, - .driver = { - .name = "stm32-dac", - .of_match_table = stm32_dac_of_match, -+ .pm = &stm32_dac_pm_ops, - }, - }; - module_platform_driver(stm32_dac_driver); -diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c -index f98510c714b57..7d8962d6566a1 100644 ---- a/drivers/iio/trigger/stm32-timer-trigger.c -+++ b/drivers/iio/trigger/stm32-timer-trigger.c -@@ -75,14 +75,27 @@ static const void *stm32h7_valids_table[][MAX_VALIDS] = { - { }, /* timer 17 */ - }; - -+struct stm32_timer_trigger_regs { -+ u32 cr1; -+ u32 cr2; -+ u32 psc; -+ u32 arr; -+ u32 cnt; -+ u32 smcr; -+}; -+ - struct stm32_timer_trigger { - struct device *dev; - struct regmap *regmap; - struct clk *clk; -+ bool enabled; - u32 max_arr; - const void *triggers; - const void *valids; - bool has_trgo2; -+ struct mutex lock; /* concurrent sysfs configuration */ -+ struct list_head tr_list; -+ struct stm32_timer_trigger_regs bak; - }; - - struct stm32_timer_trigger_cfg { -@@ -106,7 +119,7 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, - { - unsigned long long prd, div; - int prescaler = 0; -- u32 ccer, cr1; -+ u32 ccer; - - /* Period and prescaler values depends of clock rate */ - div = (unsigned long long)clk_get_rate(priv->clk); -@@ -136,9 +149,11 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, - if (ccer & TIM_CCER_CCXE) - return -EBUSY; - -- regmap_read(priv->regmap, TIM_CR1, &cr1); -- if (!(cr1 & TIM_CR1_CEN)) -+ mutex_lock(&priv->lock); -+ if (!priv->enabled) { -+ priv->enabled = true; - clk_enable(priv->clk); -+ } - - regmap_write(priv->regmap, TIM_PSC, prescaler); - regmap_write(priv->regmap, TIM_ARR, prd - 1); -@@ -157,6 +172,7 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, - - /* Enable controller */ - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN); -+ mutex_unlock(&priv->lock); - - return 0; - } -@@ -164,16 +180,13 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, - static void stm32_timer_stop(struct stm32_timer_trigger *priv, - struct iio_trigger *trig) - { -- u32 ccer, cr1; -+ u32 ccer; - - regmap_read(priv->regmap, TIM_CCER, &ccer); - if (ccer & TIM_CCER_CCXE) - return; - -- regmap_read(priv->regmap, TIM_CR1, &cr1); -- if (cr1 & TIM_CR1_CEN) -- clk_disable(priv->clk); -- -+ mutex_lock(&priv->lock); - /* Stop timer */ - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); -@@ -188,6 +201,12 @@ static void stm32_timer_stop(struct stm32_timer_trigger *priv, - - /* Make sure that registers are updated */ - regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); -+ -+ if (priv->enabled) { -+ priv->enabled = false; -+ clk_disable(priv->clk); -+ } -+ mutex_unlock(&priv->lock); - } - - static ssize_t stm32_tt_store_frequency(struct device *dev, -@@ -302,11 +321,15 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, - for (i = 0; i <= master_mode_max; i++) { - if (!strncmp(master_mode_table[i], buf, - strlen(master_mode_table[i]))) { -+ mutex_lock(&priv->lock); -+ if (!priv->enabled) { -+ /* Clock should be enabled first */ -+ priv->enabled = true; -+ clk_enable(priv->clk); -+ } - regmap_update_bits(priv->regmap, TIM_CR2, mask, - i << shift); -- /* Make sure that registers are updated */ -- regmap_update_bits(priv->regmap, TIM_EGR, -- TIM_EGR_UG, TIM_EGR_UG); -+ mutex_unlock(&priv->lock); - return len; - } - } -@@ -364,11 +387,21 @@ static const struct attribute_group *stm32_trigger_attr_groups[] = { - static const struct iio_trigger_ops timer_trigger_ops = { - }; - --static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) -+static void stm32_unregister_iio_triggers(struct stm32_timer_trigger *priv) -+{ -+ struct iio_trigger *tr; -+ -+ list_for_each_entry(tr, &priv->tr_list, alloc_list) -+ iio_trigger_unregister(tr); -+} -+ -+static int stm32_register_iio_triggers(struct stm32_timer_trigger *priv) - { - int ret; - const char * const *cur = priv->triggers; - -+ INIT_LIST_HEAD(&priv->tr_list); -+ - while (cur && *cur) { - struct iio_trigger *trig; - bool cur_is_trgo = stm32_timer_is_trgo_name(*cur); -@@ -395,9 +428,13 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) - - iio_trigger_set_drvdata(trig, priv); - -- ret = devm_iio_trigger_register(priv->dev, trig); -- if (ret) -+ ret = iio_trigger_register(trig); -+ if (ret) { -+ stm32_unregister_iio_triggers(priv); - return ret; -+ } -+ -+ list_add_tail(&trig->alloc_list, &priv->tr_list); - cur++; - } - -@@ -444,7 +481,6 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, - int val, int val2, long mask) - { - struct stm32_timer_trigger *priv = iio_priv(indio_dev); -- u32 dat; - - switch (mask) { - case IIO_CHAN_INFO_RAW: -@@ -455,19 +491,23 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, - return -EINVAL; - - case IIO_CHAN_INFO_ENABLE: -+ mutex_lock(&priv->lock); - if (val) { -- regmap_read(priv->regmap, TIM_CR1, &dat); -- if (!(dat & TIM_CR1_CEN)) -+ if (!priv->enabled) { -+ priv->enabled = true; - clk_enable(priv->clk); -+ } - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, - TIM_CR1_CEN); - } else { -- regmap_read(priv->regmap, TIM_CR1, &dat); - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, - 0); -- if (dat & TIM_CR1_CEN) -+ if (priv->enabled) { -+ priv->enabled = false; - clk_disable(priv->clk); -+ } - } -+ mutex_unlock(&priv->lock); - return 0; - } - -@@ -563,7 +603,6 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev, - { - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - int sms = stm32_enable_mode2sms(mode); -- u32 val; - - if (sms < 0) - return sms; -@@ -571,11 +610,12 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev, - * Triggered mode sets CEN bit automatically by hardware. So, first - * enable counter clock, so it can use it. Keeps it in sync with CEN. - */ -- if (sms == 6) { -- regmap_read(priv->regmap, TIM_CR1, &val); -- if (!(val & TIM_CR1_CEN)) -- clk_enable(priv->clk); -+ mutex_lock(&priv->lock); -+ if (sms == 6 && !priv->enabled) { -+ clk_enable(priv->clk); -+ priv->enabled = true; - } -+ mutex_unlock(&priv->lock); - - regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms); - -@@ -759,8 +799,9 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) - priv->triggers = triggers_table[index]; - priv->valids = cfg->valids_table[index]; - stm32_timer_detect_trgo2(priv); -+ mutex_init(&priv->lock); - -- ret = stm32_setup_iio_triggers(priv); -+ ret = stm32_register_iio_triggers(priv); - if (ret) - return ret; - -@@ -769,6 +810,77 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) - return 0; - } - -+static int stm32_timer_trigger_remove(struct platform_device *pdev) -+{ -+ struct stm32_timer_trigger *priv = platform_get_drvdata(pdev); -+ u32 val; -+ -+ /* Unregister triggers before everything can be safely turned off */ -+ stm32_unregister_iio_triggers(priv); -+ -+ /* Check if nobody else use the timer, then disable it */ -+ regmap_read(priv->regmap, TIM_CCER, &val); -+ if (!(val & TIM_CCER_CCXE)) -+ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); -+ -+ if (priv->enabled) -+ clk_disable(priv->clk); -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32_timer_trigger_suspend(struct device *dev) -+{ -+ struct stm32_timer_trigger *priv = dev_get_drvdata(dev); -+ -+ /* Only take care of enabled timer: don't disturb other MFD child */ -+ if (priv->enabled) { -+ /* Backup registers that may get lost in low power mode */ -+ regmap_read(priv->regmap, TIM_CR1, &priv->bak.cr1); -+ regmap_read(priv->regmap, TIM_CR2, &priv->bak.cr2); -+ regmap_read(priv->regmap, TIM_PSC, &priv->bak.psc); -+ regmap_read(priv->regmap, TIM_ARR, &priv->bak.arr); -+ regmap_read(priv->regmap, TIM_CNT, &priv->bak.cnt); -+ regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr); -+ -+ /* Disable the timer */ -+ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); -+ clk_disable(priv->clk); -+ } -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32_timer_trigger_resume(struct device *dev) -+{ -+ struct stm32_timer_trigger *priv = dev_get_drvdata(dev); -+ int ret; -+ -+ if (priv->enabled) { -+ ret = clk_enable(priv->clk); -+ if (ret) -+ return ret; -+ -+ /* restore master/slave modes */ -+ regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr); -+ regmap_write(priv->regmap, TIM_CR2, priv->bak.cr2); -+ -+ /* restore sampling_frequency (trgo / trgo2 triggers) */ -+ regmap_write(priv->regmap, TIM_PSC, priv->bak.psc); -+ regmap_write(priv->regmap, TIM_ARR, priv->bak.arr); -+ regmap_write(priv->regmap, TIM_CNT, priv->bak.cnt); -+ -+ /* Also re-enables the timer */ -+ regmap_write(priv->regmap, TIM_CR1, priv->bak.cr1); -+ } -+ -+ return 0; -+} -+ -+static SIMPLE_DEV_PM_OPS(stm32_timer_trigger_pm_ops, -+ stm32_timer_trigger_suspend, -+ stm32_timer_trigger_resume); -+ - static const struct stm32_timer_trigger_cfg stm32_timer_trg_cfg = { - .valids_table = valids_table, - .num_valids_table = ARRAY_SIZE(valids_table), -@@ -793,9 +905,11 @@ MODULE_DEVICE_TABLE(of, stm32_trig_of_match); - - static struct platform_driver stm32_timer_trigger_driver = { - .probe = stm32_timer_trigger_probe, -+ .remove = stm32_timer_trigger_remove, - .driver = { - .name = "stm32-timer-trigger", - .of_match_table = stm32_trig_of_match, -+ .pm = &stm32_timer_trigger_pm_ops, - }, - }; - module_platform_driver(stm32_timer_trigger_driver); -diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c -index e00f2fa27f00e..0337c71d7b625 100644 ---- a/drivers/irqchip/irq-stm32-exti.c -+++ b/drivers/irqchip/irq-stm32-exti.c -@@ -25,7 +25,6 @@ - #define IRQS_PER_BANK 32 - - #define HWSPNLCK_TIMEOUT 1000 /* usec */ --#define HWSPNLCK_RETRY_DELAY 100 /* usec */ - - struct stm32_exti_bank { - u32 imr_ofst; -@@ -42,6 +41,7 @@ struct stm32_exti_bank { - struct stm32_desc_irq { - u32 exti; - u32 irq_parent; -+ struct irq_chip *chip; - }; - - struct stm32_exti_drv_data { -@@ -166,27 +166,54 @@ static const struct stm32_exti_bank *stm32mp1_exti_banks[] = { - &stm32mp1_exti_b3, - }; - -+static struct irq_chip stm32_exti_h_chip; -+static struct irq_chip stm32_exti_h_chip_direct; -+ - static const struct stm32_desc_irq stm32mp1_desc_irq[] = { -- { .exti = 0, .irq_parent = 6 }, -- { .exti = 1, .irq_parent = 7 }, -- { .exti = 2, .irq_parent = 8 }, -- { .exti = 3, .irq_parent = 9 }, -- { .exti = 4, .irq_parent = 10 }, -- { .exti = 5, .irq_parent = 23 }, -- { .exti = 6, .irq_parent = 64 }, -- { .exti = 7, .irq_parent = 65 }, -- { .exti = 8, .irq_parent = 66 }, -- { .exti = 9, .irq_parent = 67 }, -- { .exti = 10, .irq_parent = 40 }, -- { .exti = 11, .irq_parent = 42 }, -- { .exti = 12, .irq_parent = 76 }, -- { .exti = 13, .irq_parent = 77 }, -- { .exti = 14, .irq_parent = 121 }, -- { .exti = 15, .irq_parent = 127 }, -- { .exti = 16, .irq_parent = 1 }, -- { .exti = 65, .irq_parent = 144 }, -- { .exti = 68, .irq_parent = 143 }, -- { .exti = 73, .irq_parent = 129 }, -+ { .exti = 0, .irq_parent = 6, .chip = &stm32_exti_h_chip }, -+ { .exti = 1, .irq_parent = 7, .chip = &stm32_exti_h_chip }, -+ { .exti = 2, .irq_parent = 8, .chip = &stm32_exti_h_chip }, -+ { .exti = 3, .irq_parent = 9, .chip = &stm32_exti_h_chip }, -+ { .exti = 4, .irq_parent = 10, .chip = &stm32_exti_h_chip }, -+ { .exti = 5, .irq_parent = 23, .chip = &stm32_exti_h_chip }, -+ { .exti = 6, .irq_parent = 64, .chip = &stm32_exti_h_chip }, -+ { .exti = 7, .irq_parent = 65, .chip = &stm32_exti_h_chip }, -+ { .exti = 8, .irq_parent = 66, .chip = &stm32_exti_h_chip }, -+ { .exti = 9, .irq_parent = 67, .chip = &stm32_exti_h_chip }, -+ { .exti = 10, .irq_parent = 40, .chip = &stm32_exti_h_chip }, -+ { .exti = 11, .irq_parent = 42, .chip = &stm32_exti_h_chip }, -+ { .exti = 12, .irq_parent = 76, .chip = &stm32_exti_h_chip }, -+ { .exti = 13, .irq_parent = 77, .chip = &stm32_exti_h_chip }, -+ { .exti = 14, .irq_parent = 121, .chip = &stm32_exti_h_chip }, -+ { .exti = 15, .irq_parent = 127, .chip = &stm32_exti_h_chip }, -+ { .exti = 16, .irq_parent = 1, .chip = &stm32_exti_h_chip }, -+ { .exti = 19, .irq_parent = 3, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 21, .irq_parent = 31, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 22, .irq_parent = 33, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 23, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 24, .irq_parent = 95, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 25, .irq_parent = 107, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 26, .irq_parent = 37, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 27, .irq_parent = 38, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 28, .irq_parent = 39, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 29, .irq_parent = 71, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 30, .irq_parent = 52, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 31, .irq_parent = 53, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 32, .irq_parent = 82, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 33, .irq_parent = 83, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 43, .irq_parent = 75, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 44, .irq_parent = 98, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 48, .irq_parent = 138, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 50, .irq_parent = 139, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 52, .irq_parent = 140, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 53, .irq_parent = 141, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 54, .irq_parent = 135, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 61, .irq_parent = 100, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 65, .irq_parent = 144, .chip = &stm32_exti_h_chip }, -+ { .exti = 68, .irq_parent = 143, .chip = &stm32_exti_h_chip }, -+ { .exti = 70, .irq_parent = 62, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 73, .irq_parent = 129, .chip = &stm32_exti_h_chip }, - }; - - static const struct stm32_exti_drv_data stm32mp1_drv_data = { -@@ -196,22 +223,23 @@ static const struct stm32_exti_drv_data stm32mp1_drv_data = { - .irq_nr = ARRAY_SIZE(stm32mp1_desc_irq), - }; - --static int stm32_exti_to_irq(const struct stm32_exti_drv_data *drv_data, -- irq_hw_number_t hwirq) -+static const struct -+stm32_desc_irq *stm32_exti_get_desc(const struct stm32_exti_drv_data *drv_data, -+ irq_hw_number_t hwirq) - { -- const struct stm32_desc_irq *desc_irq; -+ const struct stm32_desc_irq *desc = NULL; - int i; - - if (!drv_data->desc_irqs) -- return -EINVAL; -+ return NULL; - - for (i = 0; i < drv_data->irq_nr; i++) { -- desc_irq = &drv_data->desc_irqs[i]; -- if (desc_irq->exti == hwirq) -- return desc_irq->irq_parent; -+ desc = &drv_data->desc_irqs[i]; -+ if (desc->exti == hwirq) -+ break; - } - -- return -EINVAL; -+ return desc; - } - - static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) -@@ -277,55 +305,24 @@ static int stm32_exti_set_type(struct irq_data *d, - return 0; - } - --static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data) --{ -- int ret, timeout = 0; -- -- if (!chip_data->host_data->hwlock) -- return 0; -- -- /* -- * Use the x_raw API since we are under spin_lock protection. -- * Do not use the x_timeout API because we are under irq_disable -- * mode (see __setup_irq()) -- */ -- do { -- ret = hwspin_trylock_raw(chip_data->host_data->hwlock); -- if (!ret) -- return 0; -- -- udelay(HWSPNLCK_RETRY_DELAY); -- timeout += HWSPNLCK_RETRY_DELAY; -- } while (timeout < HWSPNLCK_TIMEOUT); -- -- if (ret == -EBUSY) -- ret = -ETIMEDOUT; -- -- if (ret) -- pr_err("%s can't get hwspinlock (%d)\n", __func__, ret); -- -- return ret; --} -- --static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data) --{ -- if (chip_data->host_data->hwlock) -- hwspin_unlock_raw(chip_data->host_data->hwlock); --} -- - static int stm32_irq_set_type(struct irq_data *d, unsigned int type) - { - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct stm32_exti_chip_data *chip_data = gc->private; - const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; -+ struct hwspinlock *hwlock = chip_data->host_data->hwlock; - u32 rtsr, ftsr; - int err; - - irq_gc_lock(gc); - -- err = stm32_exti_hwspin_lock(chip_data); -- if (err) -- goto unlock; -+ if (hwlock) { -+ err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); -+ if (err) { -+ pr_err("%s can't get hwspinlock (%d)\n", __func__, err); -+ goto unlock; -+ } -+ } - - rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst); - ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst); -@@ -338,7 +335,8 @@ static int stm32_irq_set_type(struct irq_data *d, unsigned int type) - irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst); - - unspinlock: -- stm32_exti_hwspin_unlock(chip_data); -+ if (hwlock) -+ hwspin_unlock_in_atomic(hwlock); - unlock: - irq_gc_unlock(gc); - -@@ -431,6 +429,16 @@ static void stm32_irq_ack(struct irq_data *d) - irq_gc_unlock(gc); - } - -+/* directly set the target bit without reading first. */ -+static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg) -+{ -+ struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); -+ void __iomem *base = chip_data->host_data->base; -+ u32 val = BIT(d->hwirq % IRQS_PER_BANK); -+ -+ writel_relaxed(val, base + reg); -+} -+ - static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg) - { - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); -@@ -464,9 +472,9 @@ static void stm32_exti_h_eoi(struct irq_data *d) - - raw_spin_lock(&chip_data->rlock); - -- stm32_exti_set_bit(d, stm32_bank->rpr_ofst); -+ stm32_exti_write_bit(d, stm32_bank->rpr_ofst); - if (stm32_bank->fpr_ofst != UNDEF_REG) -- stm32_exti_set_bit(d, stm32_bank->fpr_ofst); -+ stm32_exti_write_bit(d, stm32_bank->fpr_ofst); - - raw_spin_unlock(&chip_data->rlock); - -@@ -504,15 +512,20 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) - { - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); - const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; -+ struct hwspinlock *hwlock = chip_data->host_data->hwlock; - void __iomem *base = chip_data->host_data->base; - u32 rtsr, ftsr; - int err; - - raw_spin_lock(&chip_data->rlock); - -- err = stm32_exti_hwspin_lock(chip_data); -- if (err) -- goto unlock; -+ if (hwlock) { -+ err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); -+ if (err) { -+ pr_err("%s can't get hwspinlock (%d)\n", __func__, err); -+ goto unlock; -+ } -+ } - - rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst); - ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst); -@@ -525,10 +538,14 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) - writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst); - - unspinlock: -- stm32_exti_hwspin_unlock(chip_data); -+ if (hwlock) -+ hwspin_unlock_in_atomic(hwlock); - unlock: - raw_spin_unlock(&chip_data->rlock); - -+ if (d->parent_data->chip) -+ irq_chip_set_type_parent(d, type); -+ - return err; - } - -@@ -546,6 +563,9 @@ static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on) - - raw_spin_unlock(&chip_data->rlock); - -+ if (d->parent_data->chip) -+ irq_chip_set_wake_parent(d, on); -+ - return 0; - } - -@@ -555,7 +575,13 @@ static int stm32_exti_h_set_affinity(struct irq_data *d, - if (d->parent_data->chip) - return irq_chip_set_affinity_parent(d, dest, force); - -- return -EINVAL; -+ return IRQ_SET_MASK_OK_DONE; -+} -+ -+static void stm32_exti_h_ack(struct irq_data *d) -+{ -+ if (d->parent_data->chip) -+ irq_chip_ack_parent(d); - } - - static int __maybe_unused stm32_exti_h_suspend(void) -@@ -604,45 +630,90 @@ static void stm32_exti_h_syscore_deinit(void) - unregister_syscore_ops(&stm32_exti_h_syscore_ops); - } - -+static int stm32_exti_h_retrigger(struct irq_data *d) -+{ -+ struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); -+ const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; -+ void __iomem *base = chip_data->host_data->base; -+ u32 mask = BIT(d->hwirq % IRQS_PER_BANK); -+ -+ writel_relaxed(mask, base + stm32_bank->swier_ofst); -+ -+ return 0; -+} -+ - static struct irq_chip stm32_exti_h_chip = { - .name = "stm32-exti-h", - .irq_eoi = stm32_exti_h_eoi, -+ .irq_ack = stm32_exti_h_ack, - .irq_mask = stm32_exti_h_mask, - .irq_unmask = stm32_exti_h_unmask, -- .irq_retrigger = irq_chip_retrigger_hierarchy, -+ .irq_retrigger = stm32_exti_h_retrigger, - .irq_set_type = stm32_exti_h_set_type, - .irq_set_wake = stm32_exti_h_set_wake, - .flags = IRQCHIP_MASK_ON_SUSPEND, - .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : NULL, - }; - -+static struct irq_chip stm32_exti_h_chip_direct = { -+ .name = "stm32-exti-h-direct", -+ .irq_eoi = irq_chip_eoi_parent, -+ .irq_ack = irq_chip_ack_parent, -+ .irq_mask = stm32_exti_h_mask, -+ .irq_unmask = stm32_exti_h_unmask, -+ .irq_retrigger = irq_chip_retrigger_hierarchy, -+ .irq_set_type = irq_chip_set_type_parent, -+ .irq_set_wake = stm32_exti_h_set_wake, -+ .flags = IRQCHIP_MASK_ON_SUSPEND, -+ .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL, -+}; -+ - static int stm32_exti_h_domain_alloc(struct irq_domain *dm, - unsigned int virq, - unsigned int nr_irqs, void *data) - { - struct stm32_exti_host_data *host_data = dm->host_data; - struct stm32_exti_chip_data *chip_data; -+ const struct stm32_desc_irq *desc; - struct irq_fwspec *fwspec = data; - struct irq_fwspec p_fwspec; - irq_hw_number_t hwirq; -- int p_irq, bank; -+ int bank; - - hwirq = fwspec->param[0]; - bank = hwirq / IRQS_PER_BANK; - chip_data = &host_data->chips_data[bank]; - -- irq_domain_set_hwirq_and_chip(dm, virq, hwirq, -- &stm32_exti_h_chip, chip_data); - -- p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq); -- if (p_irq >= 0) { -+ desc = stm32_exti_get_desc(host_data->drv_data, hwirq); -+ if (!desc) -+ return -EINVAL; -+ -+ irq_domain_set_hwirq_and_chip(dm, virq, hwirq, desc->chip, -+ chip_data); -+ -+ /* -+ * EXTI 55 to 60 are mapped to PWR interrupt controller. -+ * The hwirq translation is done diferently than for GIC. -+ */ -+ if (hwirq >= 55 && hwirq <= 60) { - p_fwspec.fwnode = dm->parent->fwnode; -- p_fwspec.param_count = 3; -- p_fwspec.param[0] = GIC_SPI; -- p_fwspec.param[1] = p_irq; -- p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; -+ p_fwspec.param_count = 2; -+ p_fwspec.param[0] = hwirq - 55; -+ p_fwspec.param[1] = fwspec->param[1]; - - return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); -+ } else { -+ if (desc->irq_parent) { -+ p_fwspec.fwnode = dm->parent->fwnode; -+ p_fwspec.param_count = 3; -+ p_fwspec.param[0] = GIC_SPI; -+ p_fwspec.param[1] = desc->irq_parent; -+ p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; -+ -+ return irq_domain_alloc_irqs_parent(dm, virq, 1, -+ &p_fwspec); -+ } - } - - return 0; -@@ -807,11 +878,12 @@ static int stm32_exti_probe(struct platform_device *pdev) - { - int ret, i; - struct device *dev = &pdev->dev; -- struct device_node *np = dev->of_node; -+ struct device_node *child, *np = dev->of_node; - struct irq_domain *parent_domain, *domain; - struct stm32_exti_host_data *host_data; - const struct stm32_exti_drv_data *drv_data; - struct resource *res; -+ u32 nirqs; - - host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); - if (!host_data) -@@ -879,6 +951,34 @@ static int stm32_exti_probe(struct platform_device *pdev) - if (ret) - return ret; - -+ for_each_child_of_node(np, child) { -+ parent_domain = irq_find_host(of_irq_find_parent(child)); -+ if (!parent_domain) { -+ dev_err(dev, "child interrupt-parent not found\n"); -+ return -EINVAL; -+ } -+ -+ ret = of_property_read_u32(child, "st,irq-number", &nirqs); -+ if (ret || !nirqs) { -+ dev_err(dev, "Missing or bad irq-number property\n"); -+ return -EINVAL; -+ } -+ -+ domain = irq_domain_add_hierarchy(parent_domain, 0, nirqs, -+ child, -+ &stm32_exti_h_domain_ops, -+ host_data); -+ if (!domain) { -+ dev_err(dev, "Could not register exti domain\n"); -+ return -ENOMEM; -+ } -+ -+ ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, -+ domain); -+ if (ret) -+ return ret; -+ } -+ - stm32_exti_h_syscore_init(host_data); - - return 0; --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0013-ARM-stm32mp1-r2-MFD.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0013-ARM-stm32mp1-r2-MFD.patch deleted file mode 100644 index 0002c9f..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0013-ARM-stm32mp1-r2-MFD.patch +++ /dev/null @@ -1,929 +0,0 @@ -From c37d67ecd03c14eabef9d8cde67913bdfe497ae8 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:47 +0200 -Subject: [PATCH 13/22] ARM-stm32mp1-r2-rc8-MFD - ---- - .../bindings/mfd/st,stm32mp1-pwr.txt | 57 +++ - .../devicetree/bindings/mfd/stm32-lptimer.txt | 10 + - .../bindings/mtd/st,stm32-fmc2-nand.yaml | 129 ++++++ - drivers/mfd/Kconfig | 10 + - drivers/mfd/Makefile | 1 + - drivers/mfd/stm32-lptimer.c | 1 + - drivers/mfd/stm32-pwr.c | 400 ++++++++++++++++++ - drivers/mfd/stm32-timers.c | 36 +- - drivers/mfd/stpmic1.c | 6 + - drivers/mfd/wm8994-core.c | 21 + - include/dt-bindings/mfd/stm32f4-rcc.h | 1 - - include/linux/mfd/stm32-lptimer.h | 5 + - include/linux/mfd/stm32-timers.h | 12 +- - include/linux/mfd/wm8994/pdata.h | 6 + - 14 files changed, 675 insertions(+), 20 deletions(-) - create mode 100644 Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt - create mode 100644 Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml - create mode 100644 drivers/mfd/stm32-pwr.c - -diff --git a/Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt b/Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt -new file mode 100644 -index 0000000000000..eb622387bb651 ---- /dev/null -+++ b/Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt -@@ -0,0 +1,57 @@ -+STMicroelectronics STM32MP1 Power Management Controller -+======================================================= -+ -+The PWR IP is responsible for handling the power related resources such as -+clocks, power supplies and resets. It provides 6 wake-up pins that are handled -+by an interrupt-controller. Wake-up pin can be used to wake-up from STANDBY SoC state. -+ -+Required properties: -+- compatible should be: "st,stm32mp1-pwr" -+- reg: should be register base and length as documented in the -+ datasheet -+- interrupts: contains the reference to the gic wake-up pin interrupt -+- interrupt-controller; Enable interrupt controller for wake-up pins. -+- #interrupt-cells = <3> -+- wakeup-gpios: contains a list of GPIO spec describing each wake-up pin. -+ -+Optional Properties: -+- pwr-supply: main soc power supply -+ -+Interrupt consumers have to specify 3 cells: -+ - cell 1: wake-up pin id from 0 to 5 -+ - cell 2: IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_RISING -+ - cell 3: Pull config: 0 = No Pull, 1=Pull Up, 2=Pull Down -+ -+ -+Example: -+ -+ pwr: pwr@50001000 { -+ compatible = "st,stm32mp1-pwr", "simple-mfd"; -+ reg = <0x50001000 0x400>; -+ interrupts = ; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ -+ wakeup-gpios = <&gpioa 0 0>, <&gpioa 2 0>, -+ <&gpioc 13 0>, <&gpioi 8 0>, -+ <&gpioi 11 0>, <&gpioc 1 0>; -+ -+ pwr-supply = <&vdd>; -+ }; -+ -+ -+Example of interrupt user: -+gpio_keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ button@4 { -+ label = "WakeUp4"; -+ linux,code = ; -+ interrupt-parent = <&pwr>; -+ interrupts = <3 IRQ_TYPE_EDGE_FALLING 1>; -+ wakeup-source; -+ }; -+}; -+ -diff --git a/Documentation/devicetree/bindings/mfd/stm32-lptimer.txt b/Documentation/devicetree/bindings/mfd/stm32-lptimer.txt -index fb54e4dad5b3e..ef3b795b5d9f0 100644 ---- a/Documentation/devicetree/bindings/mfd/stm32-lptimer.txt -+++ b/Documentation/devicetree/bindings/mfd/stm32-lptimer.txt -@@ -14,10 +14,15 @@ Required properties: - - #address-cells: Should be '<1>'. - - #size-cells: Should be '<0>'. - -+Optional properties: -+- interrupts: Interrupt line for the LP timer. -+ - Optional subnodes: - - pwm: See ../pwm/pwm-stm32-lp.txt - - counter: See ../counter/stm32-lptimer-cnt.txt - - trigger: See ../iio/timer/stm32-lptimer-trigger.txt -+- timer: Must contain "st,stm32-lptimer-timer" compatible -+ property. - - Example: - -@@ -26,6 +31,7 @@ Example: - reg = <0x40002400 0x400>; - clocks = <&timer_clk>; - clock-names = "mux"; -+ interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - -@@ -45,4 +51,8 @@ Example: - pinctrl-names = "default"; - pinctrl-0 = <&lptim1_in_pins>; - }; -+ -+ timer { -+ compatible = "st,stm32-lptimer-timer"; -+ }; - }; -diff --git a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml -new file mode 100644 -index 0000000000000..6ae7de15d172f ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml -@@ -0,0 +1,129 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/st,stm32-fmc2-nand.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: STMicroelectronics Flexible Memory Controller 2 (FMC2) Bindings -+ -+maintainers: -+ - Christophe Kerello -+ -+properties: -+ compatible: -+ enum: -+ - st,stm32mp15-fmc2 -+ - st,stm32mp1-fmc2-nfc -+ -+ reg: -+ minItems: 6 -+ maxItems: 7 -+ -+ interrupts: -+ maxItems: 1 -+ -+ dmas: -+ items: -+ - description: tx DMA channel -+ - description: rx DMA channel -+ - description: ecc DMA channel -+ -+ dma-names: -+ items: -+ - const: tx -+ - const: rx -+ - const: ecc -+ -+patternProperties: -+ "^nand@[a-f0-9]$": -+ type: object -+ properties: -+ nand-ecc-step-size: -+ const: 512 -+ -+ nand-ecc-strength: -+ enum: [1, 4 ,8 ] -+ -+allOf: -+ - $ref: "nand-controller.yaml#" -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: st,stm32mp15-fmc2 -+ then: -+ properties: -+ reg: -+ items: -+ - description: Registers -+ - description: Chip select 0 data -+ - description: Chip select 0 command -+ - description: Chip select 0 address space -+ - description: Chip select 1 data -+ - description: Chip select 1 command -+ - description: Chip select 1 address space -+ -+ clocks: -+ maxItems: 1 -+ -+ resets: -+ maxItems: 1 -+ -+ required: -+ - clocks -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: st,stm32mp1-fmc2-nfc -+ then: -+ properties: -+ reg: -+ items: -+ - description: Chip select 0 data -+ - description: Chip select 0 command -+ - description: Chip select 0 address space -+ - description: Chip select 1 data -+ - description: Chip select 1 command -+ - description: Chip select 1 address space -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ nand-controller@58002000 { -+ compatible = "st,stm32mp15-fmc2"; -+ reg = <0x58002000 0x1000>, -+ <0x80000000 0x1000>, -+ <0x88010000 0x1000>, -+ <0x88020000 0x1000>, -+ <0x81000000 0x1000>, -+ <0x89010000 0x1000>, -+ <0x89020000 0x1000>; -+ interrupts = ; -+ dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>, -+ <&mdma1 20 0x2 0x12000a08 0x0 0x0>, -+ <&mdma1 21 0x2 0x12000a0a 0x0 0x0>; -+ dma-names = "tx", "rx", "ecc"; -+ clocks = <&rcc FMC_K>; -+ resets = <&rcc FMC_R>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ nand@0 { -+ reg = <0>; -+ nand-on-flash-bbt; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+ }; -+ -+... -diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 43169f25da1fd..48ef1822ab1ce 100644 ---- a/drivers/mfd/Kconfig -+++ b/drivers/mfd/Kconfig -@@ -1955,6 +1955,16 @@ config MFD_STPMIC1 - To compile this driver as a module, choose M here: the - module will be called stpmic1. - -+config MFD_STM32MP1_PWR -+ bool "STM32MP1 wake-up pins" -+ depends on MACH_STM32MP157 -+ default y -+ help -+ Select this option to enable STM32 PWR Wake-up pins driver. -+ -+ This driver provides interruptions that can be used to wake-up from -+ suspend. -+ - config MFD_STMFX - tristate "Support for STMicroelectronics Multi-Function eXpander (STMFX)" - depends on I2C -diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index c1067ea462046..11acfa1bf8160 100644 ---- a/drivers/mfd/Makefile -+++ b/drivers/mfd/Makefile -@@ -249,6 +249,7 @@ obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o - - obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o - obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o -+obj-$(CONFIG_MFD_STM32MP1_PWR) += stm32-pwr.o - obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o - obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o - obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o -diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c -index a00f99f365595..746e51a17cc8e 100644 ---- a/drivers/mfd/stm32-lptimer.c -+++ b/drivers/mfd/stm32-lptimer.c -@@ -17,6 +17,7 @@ static const struct regmap_config stm32_lptimer_regmap_cfg = { - .val_bits = 32, - .reg_stride = sizeof(u32), - .max_register = STM32_LPTIM_MAX_REGISTER, -+ .fast_io = true, - }; - - static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata) -diff --git a/drivers/mfd/stm32-pwr.c b/drivers/mfd/stm32-pwr.c -new file mode 100644 -index 0000000000000..48ca8b4745d34 ---- /dev/null -+++ b/drivers/mfd/stm32-pwr.c -@@ -0,0 +1,400 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Pascal Paillet for STMicroelectronics. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define NB_WAKEUPPINS 6 -+ -+#define STM32_SVC_PWR 0x82001001 -+#define STM32_WRITE 0x1 -+#define STM32_SET_BITS 0x2 -+#define STM32_CLEAR_BITS 0x3 -+ -+#define PWR_WKUP_OFFSET 0x20 -+// PWR Registers -+#define WKUPCR 0x0 -+#define WKUPFR 0x4 -+#define MPUWKUPENR 0x8 -+ -+#define WKUP_FLAGS_MASK GENMASK(5, 0) -+ -+// WKUPCR bits definition -+#define WKUP_EDGE_SHIFT 8 -+#define WKUP_PULL_SHIFT 16 -+#define WKUP_PULL_MASK GENMASK(1, 0) -+ -+enum wkup_pull_setting { -+ WKUP_NO_PULL = 0, -+ WKUP_PULL_UP, -+ WKUP_PULL_DOWN, -+ WKUP_PULL_RESERVED -+}; -+ -+#define SMC(class, op, offset, val) do { \ -+ struct arm_smccc_res res; \ -+ arm_smccc_smc(class, op, PWR_WKUP_OFFSET + (offset), val, \ -+ 0, 0, 0, 0, &res); \ -+} while (0) \ -+ -+struct stm32_pwr_data { -+ struct device *dev; -+ void __iomem *base; /* IO Memory base address */ -+ struct irq_domain *domain; /* Domain for this controller */ -+ int irq; /* Parent interrupt */ -+ u32 masked; /* IRQ is masked */ -+ u32 wake; /* IRQ is wake on */ -+ u32 pending; /* IRQ has been received while wake on*/ -+ struct gpio_desc *gpio[NB_WAKEUPPINS]; -+}; -+ -+static void stm32_pwr_irq_ack(struct irq_data *d) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ -+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); -+ SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, BIT(d->hwirq)); -+} -+ -+static void stm32_pwr_irq_set_enable(struct irq_data *d) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ -+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); -+ if (!(priv->masked & BIT(d->hwirq)) || (priv->wake & BIT(d->hwirq))) -+ SMC(STM32_SVC_PWR, STM32_SET_BITS, MPUWKUPENR, BIT(d->hwirq)); -+ else -+ SMC(STM32_SVC_PWR, STM32_CLEAR_BITS, MPUWKUPENR, BIT(d->hwirq)); -+} -+ -+static void stm32_pwr_irq_mask(struct irq_data *d) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ -+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); -+ priv->masked |= BIT(d->hwirq); -+ stm32_pwr_irq_set_enable(d); -+} -+ -+static void stm32_pwr_irq_unmask(struct irq_data *d) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ -+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); -+ priv->masked &= ~BIT(d->hwirq); -+ stm32_pwr_irq_set_enable(d); -+} -+ -+static int stm32_pwr_irq_set_wake(struct irq_data *d, unsigned int on) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ struct irq_data *parent = irq_get_irq_data(priv->irq); -+ -+ dev_dbg(priv->dev, "irq:%lu on:%d\n", d->hwirq, on); -+ if (on) { -+ priv->wake |= BIT(d->hwirq); -+ } else { -+ priv->wake &= ~BIT(d->hwirq); -+ priv->pending &= ~BIT(d->hwirq); -+ } -+ stm32_pwr_irq_set_enable(d); -+ -+ if (parent->chip && parent->chip->irq_set_wake) -+ return parent->chip->irq_set_wake(parent, on); -+ -+ return 0; -+} -+ -+static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ int pin_id = d->hwirq; -+ u32 wkupcr; -+ int en; -+ -+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); -+ -+ en = readl_relaxed(priv->base + MPUWKUPENR) & BIT(pin_id); -+ /* reference manual request to disable the wakeup pin while -+ * changing the edge detection setting -+ */ -+ if (en) -+ stm32_pwr_irq_mask(d); -+ -+ wkupcr = readl_relaxed(priv->base + WKUPCR); -+ switch (flow_type & IRQ_TYPE_SENSE_MASK) { -+ case IRQF_TRIGGER_FALLING: -+ wkupcr |= (1 << (WKUP_EDGE_SHIFT + pin_id)); -+ break; -+ case IRQF_TRIGGER_RISING: -+ wkupcr &= ~(1 << (WKUP_EDGE_SHIFT + pin_id)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr); -+ -+ if (en) -+ stm32_pwr_irq_unmask(d); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_SMP -+static int stm32_pwr_set_affinity_parent(struct irq_data *data, -+ const struct cpumask *dest, bool force) -+{ -+ struct stm32_pwr_data *priv = data->domain->host_data; -+ struct irq_data *parent = irq_get_irq_data(priv->irq); -+ -+ if (parent->chip && parent->chip->irq_set_affinity) -+ return parent->chip->irq_set_affinity(parent, dest, force); -+ -+ return IRQ_SET_MASK_OK_DONE; -+} -+#endif -+ -+static int stm32_pwr_irq_request_resources(struct irq_data *d) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ struct gpio_desc *gpio; -+ int ret; -+ -+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); -+ gpio = gpiod_get_index(priv->dev, "wakeup", d->hwirq, GPIOD_IN); -+ if (IS_ERR(gpio)) { -+ ret = PTR_ERR(gpio); -+ dev_err(priv->dev, "Failed to get wakeup gpio: %d", ret); -+ return ret; -+ } -+ priv->gpio[d->hwirq] = gpio; -+ return 0; -+} -+ -+static void stm32_pwr_irq_release_resources(struct irq_data *d) -+{ -+ struct stm32_pwr_data *priv = d->domain->host_data; -+ -+ dev_dbg(priv->dev, "irq:%lu\n", d->hwirq); -+ gpiod_put(priv->gpio[d->hwirq]); -+} -+ -+static struct irq_chip stm32_pwr_irq_chip = { -+ .name = "stm32-pwr-irq", -+ .irq_ack = stm32_pwr_irq_ack, -+ .irq_mask = stm32_pwr_irq_mask, -+ .irq_unmask = stm32_pwr_irq_unmask, -+ .irq_set_type = stm32_pwr_irq_set_type, -+ .irq_set_wake = stm32_pwr_irq_set_wake, -+ .irq_request_resources = stm32_pwr_irq_request_resources, -+ .irq_release_resources = stm32_pwr_irq_release_resources, -+#ifdef CONFIG_SMP -+ .irq_set_affinity = stm32_pwr_set_affinity_parent, -+#endif -+}; -+ -+static int stm32_pwr_irq_set_pull_config(struct irq_domain *d, int pin_id, -+ enum wkup_pull_setting config) -+{ -+ struct stm32_pwr_data *priv = d->host_data; -+ u32 wkupcr; -+ -+ dev_dbg(priv->dev, "irq:%d pull config:0x%x\n", pin_id, config); -+ -+ if (config >= WKUP_PULL_RESERVED) { -+ pr_err("%s: bad irq pull config\n", __func__); -+ return -EINVAL; -+ } -+ -+ wkupcr = readl_relaxed(priv->base + WKUPCR); -+ wkupcr &= ~((WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2)); -+ wkupcr |= (config & WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2); -+ -+ SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr); -+ -+ return 0; -+} -+ -+static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr, -+ const u32 *intspec, unsigned int intsize, -+ irq_hw_number_t *out_hwirq, unsigned int *out_type) -+{ -+ if (WARN_ON(intsize < 3)) { -+ pr_err("%s: bad irq config parameters\n", __func__); -+ return -EINVAL; -+ } -+ -+ *out_hwirq = intspec[0]; -+ *out_type = intspec[1] & (IRQ_TYPE_SENSE_MASK); -+ -+ return stm32_pwr_irq_set_pull_config(d, intspec[0], intspec[2]); -+} -+ -+static int stm32_pwr_alloc(struct irq_domain *d, unsigned int virq, -+ unsigned int nr_irqs, void *data) -+{ -+ struct irq_fwspec *fwspec = data; -+ irq_hw_number_t hwirq; -+ -+ hwirq = fwspec->param[0]; -+ irq_domain_set_info(d, virq, hwirq, &stm32_pwr_irq_chip, d->host_data, -+ handle_edge_irq, NULL, NULL); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops stm32_pwr_irq_domain_ops = { -+ .alloc = stm32_pwr_alloc, -+ .xlate = stm32_pwr_xlate, -+ .free = irq_domain_free_irqs_common, -+}; -+ -+/* -+ * Handler for the cascaded IRQ. -+ */ -+static void stm32_pwr_handle_irq(struct irq_desc *desc) -+{ -+ struct stm32_pwr_data *priv = irq_desc_get_handler_data(desc); -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ u32 wkupfr, wkupenr, i; -+ -+ chained_irq_enter(chip, desc); -+ -+ wkupfr = readl_relaxed(priv->base + WKUPFR); -+ wkupenr = readl_relaxed(priv->base + MPUWKUPENR); -+ -+ for (i = 0; i < NB_WAKEUPPINS; i++) { -+ if ((wkupfr & BIT(i)) && (wkupenr & BIT(i))) { -+ struct irq_desc *d; -+ -+ d = irq_to_desc(irq_find_mapping(priv->domain, i)); -+ -+ if (priv->wake & BIT(i)) { -+ dev_dbg(priv->dev, -+ "irq %d while wake enabled\n", i); -+ priv->pending |= BIT(i); -+ } -+ -+ dev_dbg(priv->dev, "handle wkup irq:%d\n", i); -+ handle_edge_irq(d); -+ } -+ } -+ chained_irq_exit(chip, desc); -+} -+ -+static int __maybe_unused stm32_pwr_suspend(struct device *dev) -+{ -+ struct stm32_pwr_data *priv = dev_get_drvdata(dev); -+ -+ pr_debug("suspend"); -+ if (priv->pending != 0) -+ return -EBUSY; -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops stm32_pwr_pm = { -+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_pwr_suspend, NULL) -+}; -+ -+static int stm32_pwr_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct stm32_pwr_data *priv; -+ struct device_node *np = dev->of_node; -+ struct resource *res; -+ int ret; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ priv->dev = dev; -+ dev_set_drvdata(dev, priv); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ priv->base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(priv->base)) { -+ dev_err(dev, "Unable to map registers\n"); -+ return PTR_ERR(priv->base); -+ } -+ -+ /* Disable all wake-up pins */ -+ SMC(STM32_SVC_PWR, STM32_WRITE, MPUWKUPENR, 0); -+ /* Clear all interrupts flags */ -+ SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, WKUP_FLAGS_MASK); -+ -+ priv->domain = irq_domain_add_linear(np, NB_WAKEUPPINS, -+ &stm32_pwr_irq_domain_ops, priv); -+ if (!priv->domain) { -+ dev_err(dev, "%s: Unable to add irq domain!\n", __func__); -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = irq_of_parse_and_map(np, 0); -+ if (ret < 0) { -+ dev_err(dev, "failed to get PWR IRQ\n"); -+ ret = priv->irq; -+ goto out_domain; -+ } -+ -+ priv->irq = ret; -+ irq_set_chained_handler_and_data(priv->irq, stm32_pwr_handle_irq, priv); -+ -+ of_node_clear_flag(np, OF_POPULATED); -+ -+ return 0; -+ -+out_domain: -+ irq_domain_remove(priv->domain); -+out: -+ return ret; -+} -+ -+static int stm32_pwr_remove(struct platform_device *pdev) -+{ -+ struct stm32_pwr_data *priv = dev_get_drvdata(&pdev->dev); -+ -+ irq_domain_remove(priv->domain); -+ return 0; -+} -+ -+static const struct of_device_id stm32_pwr_ids[] = { -+ { .compatible = "st,stm32mp1-pwr", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, stm32_pwr_ids); -+ -+static struct platform_driver stm32_pwr_driver = { -+ .probe = stm32_pwr_probe, -+ .remove = stm32_pwr_remove, -+ .driver = { -+ .name = "stm32_pwr", -+ .of_match_table = stm32_pwr_ids, -+ .pm = &stm32_pwr_pm, -+ }, -+}; -+ -+static int __init stm32_pwr_init(void) -+{ -+ return platform_driver_register(&stm32_pwr_driver); -+} -+ -+static void __exit stm32_pwr_exit(void) -+{ -+ return platform_driver_unregister(&stm32_pwr_driver); -+} -+ -+arch_initcall(stm32_pwr_init); -+module_exit(stm32_pwr_exit); -diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c -index efcd4b980c94c..65a160a264555 100644 ---- a/drivers/mfd/stm32-timers.c -+++ b/drivers/mfd/stm32-timers.c -@@ -167,26 +167,36 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata) - regmap_write(ddata->regmap, TIM_ARR, 0x0); - } - --static void stm32_timers_dma_probe(struct device *dev, -- struct stm32_timers *ddata) -+static int stm32_timers_dma_probe(struct device *dev, -+ struct stm32_timers *ddata) - { - int i; -+ int ret = 0; - char name[4]; - - init_completion(&ddata->dma.completion); - mutex_init(&ddata->dma.lock); - -- /* Optional DMA support: get valid DMA channel(s) or NULL */ -+ /* Optional DMA support but report if an existing one fails */ - for (i = STM32_TIMERS_DMA_CH1; i <= STM32_TIMERS_DMA_CH4; i++) { - snprintf(name, ARRAY_SIZE(name), "ch%1d", i + 1); -- ddata->dma.chans[i] = dma_request_slave_channel(dev, name); -+ ddata->dma.chans[i] = dma_request_chan(dev, name); - } -- ddata->dma.chans[STM32_TIMERS_DMA_UP] = -- dma_request_slave_channel(dev, "up"); -- ddata->dma.chans[STM32_TIMERS_DMA_TRIG] = -- dma_request_slave_channel(dev, "trig"); -- ddata->dma.chans[STM32_TIMERS_DMA_COM] = -- dma_request_slave_channel(dev, "com"); -+ ddata->dma.chans[STM32_TIMERS_DMA_UP] = dma_request_chan(dev, "up"); -+ ddata->dma.chans[STM32_TIMERS_DMA_TRIG] = dma_request_chan(dev, "trig"); -+ ddata->dma.chans[STM32_TIMERS_DMA_COM] = dma_request_chan(dev, "com"); -+ -+ for (i = STM32_TIMERS_DMA_CH1; i < STM32_TIMERS_MAX_DMAS; i++) { -+ if (IS_ERR(ddata->dma.chans[i])) { -+ /* Save the first error code to return */ -+ if (PTR_ERR(ddata->dma.chans[i]) != -ENODEV && !ret) -+ ret = PTR_ERR(ddata->dma.chans[i]); -+ -+ ddata->dma.chans[i] = NULL; -+ } -+ } -+ -+ return ret; - } - - static void stm32_timers_dma_remove(struct device *dev, -@@ -230,7 +240,11 @@ static int stm32_timers_probe(struct platform_device *pdev) - - stm32_timers_get_arr_size(ddata); - -- stm32_timers_dma_probe(dev, ddata); -+ ret = stm32_timers_dma_probe(dev, ddata); -+ if (ret) { -+ stm32_timers_dma_remove(dev, ddata); -+ return ret; -+ } - - platform_set_drvdata(pdev, ddata); - -diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c -index 7dfbe8906cb86..766c3217f30ed 100644 ---- a/drivers/mfd/stpmic1.c -+++ b/drivers/mfd/stpmic1.c -@@ -170,6 +170,9 @@ static int stpmic1_suspend(struct device *dev) - - disable_irq(pmic_dev->irq); - -+ if (device_may_wakeup(dev)) -+ enable_irq_wake(pmic_dev->irq); -+ - return 0; - } - -@@ -183,6 +186,9 @@ static int stpmic1_resume(struct device *dev) - if (ret) - return ret; - -+ if (device_may_wakeup(dev)) -+ disable_irq_wake(pmic_dev->irq); -+ - enable_irq(pmic_dev->irq); - - return 0; -diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c -index 737dede4a95c3..8161ee16c2f86 100644 ---- a/drivers/mfd/wm8994-core.c -+++ b/drivers/mfd/wm8994-core.c -@@ -7,6 +7,7 @@ - * Author: Mark Brown - */ - -+#include - #include - #include - #include -@@ -185,6 +186,12 @@ static int wm8994_resume(struct device *dev) - if (!wm8994->suspended) - return 0; - -+ /* -+ * LDO1/2 minimum cycle time is 36ms according to codec specification -+ * Wait before enabling regulator to make sure we fit this requirement -+ */ -+ msleep(40); -+ - ret = regulator_bulk_enable(wm8994->num_supplies, - wm8994->supplies); - if (ret != 0) { -@@ -300,6 +307,20 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994) - - pdata->csnaddr_pd = of_property_read_bool(np, "wlf,csnaddr-pd"); - -+ -+ pdata->mclk1 = devm_clk_get(wm8994->dev, "MCLK1"); -+ if (IS_ERR(pdata->mclk1)) { -+ if (PTR_ERR(pdata->mclk1) != -ENOENT) -+ return PTR_ERR(pdata->mclk1); -+ pdata->mclk1 = NULL; -+ } -+ -+ pdata->mclk2 = devm_clk_get(wm8994->dev, "MCLK2"); -+ if (IS_ERR(pdata->mclk2)) { -+ if (PTR_ERR(pdata->mclk2) != -ENOENT) -+ return PTR_ERR(pdata->mclk2); -+ pdata->mclk2 = NULL; -+ } - return 0; - } - #else -diff --git a/include/dt-bindings/mfd/stm32f4-rcc.h b/include/dt-bindings/mfd/stm32f4-rcc.h -index 309e8c79f27b1..36448a5619a12 100644 ---- a/include/dt-bindings/mfd/stm32f4-rcc.h -+++ b/include/dt-bindings/mfd/stm32f4-rcc.h -@@ -34,7 +34,6 @@ - #define STM32F4_AHB1_RESET(bit) (STM32F4_RCC_AHB1_##bit + (0x10 * 8)) - #define STM32F4_AHB1_CLOCK(bit) (STM32F4_RCC_AHB1_##bit) - -- - /* AHB2 */ - #define STM32F4_RCC_AHB2_DCMI 0 - #define STM32F4_RCC_AHB2_CRYP 4 -diff --git a/include/linux/mfd/stm32-lptimer.h b/include/linux/mfd/stm32-lptimer.h -index 605f622648258..90b20550c1c8b 100644 ---- a/include/linux/mfd/stm32-lptimer.h -+++ b/include/linux/mfd/stm32-lptimer.h -@@ -27,10 +27,15 @@ - #define STM32_LPTIM_CMPOK BIT(3) - - /* STM32_LPTIM_ICR - bit fields */ -+#define STM32_LPTIM_ARRMCF BIT(1) - #define STM32_LPTIM_CMPOKCF_ARROKCF GENMASK(4, 3) - -+/* STM32_LPTIM_IER - bit flieds */ -+#define STM32_LPTIM_ARRMIE BIT(1) -+ - /* STM32_LPTIM_CR - bit fields */ - #define STM32_LPTIM_CNTSTRT BIT(2) -+#define STM32_LPTIM_SNGSTRT BIT(1) - #define STM32_LPTIM_ENABLE BIT(0) - - /* STM32_LPTIM_CFGR - bit fields */ -diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h -index 067d14655c28b..f8db83aedb2b5 100644 ---- a/include/linux/mfd/stm32-timers.h -+++ b/include/linux/mfd/stm32-timers.h -@@ -70,14 +70,11 @@ - #define TIM_CCER_CC4E BIT(12) /* Capt/Comp 4 out Ena */ - #define TIM_CCER_CC4P BIT(13) /* Capt/Comp 4 Polarity */ - #define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12)) --#define TIM_BDTR_BKE BIT(12) /* Break input enable */ --#define TIM_BDTR_BKP BIT(13) /* Break input polarity */ -+#define TIM_BDTR_BKE(x) BIT(12 + (x) * 12) /* Break input enable */ -+#define TIM_BDTR_BKP(x) BIT(13 + (x) * 12) /* Break input polarity */ - #define TIM_BDTR_AOE BIT(14) /* Automatic Output Enable */ - #define TIM_BDTR_MOE BIT(15) /* Main Output Enable */ --#define TIM_BDTR_BKF (BIT(16) | BIT(17) | BIT(18) | BIT(19)) --#define TIM_BDTR_BK2F (BIT(20) | BIT(21) | BIT(22) | BIT(23)) --#define TIM_BDTR_BK2E BIT(24) /* Break 2 input enable */ --#define TIM_BDTR_BK2P BIT(25) /* Break 2 input polarity */ -+#define TIM_BDTR_BKF(x) (0xf << (16 + (x) * 4)) - #define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */ - #define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */ - -@@ -87,8 +84,7 @@ - #define TIM_CR2_MMS2_SHIFT 20 - #define TIM_SMCR_TS_SHIFT 4 - #define TIM_BDTR_BKF_MASK 0xF --#define TIM_BDTR_BKF_SHIFT 16 --#define TIM_BDTR_BK2F_SHIFT 20 -+#define TIM_BDTR_BKF_SHIFT(x) (16 + (x) * 4) - - enum stm32_timers_dmas { - STM32_TIMERS_DMA_CH1, -diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h -index 81e7dcbd94dfb..addb2fede83d8 100644 ---- a/include/linux/mfd/wm8994/pdata.h -+++ b/include/linux/mfd/wm8994/pdata.h -@@ -231,6 +231,12 @@ struct wm8994_pdata { - * GPIO for the IRQ pin if host only supports edge triggering - */ - int irq_gpio; -+ -+ /* MCLK1 clock provider */ -+ struct clk *mclk1; -+ -+ /* MCLK2 clock provider */ -+ struct clk *mclk2; - }; - - #endif --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0014-ARM-stm32mp1-r2-MMC-NAND.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0014-ARM-stm32mp1-r2-MMC-NAND.patch deleted file mode 100644 index 07a9623..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0014-ARM-stm32mp1-r2-MMC-NAND.patch +++ /dev/null @@ -1,3318 +0,0 @@ -From 207470b1f44164f76939b25ebb0d50fb81375777 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:48 +0200 -Subject: [PATCH 14/22] ARM-stm32mp1-r2-rc8-MMC-NAND - ---- - .../devicetree/bindings/mmc/mmci.txt | 2 + - .../bindings/mtd/stm32-fmc2-nand.txt | 61 - - drivers/mmc/core/block.c | 11 + - drivers/mmc/core/core.c | 31 +- - drivers/mmc/host/mmci.c | 285 ++-- - drivers/mmc/host/mmci.h | 17 +- - drivers/mmc/host/mmci_stm32_sdmmc.c | 256 +++- - drivers/mtd/nand/raw/Kconfig | 1 + - drivers/mtd/nand/raw/stm32_fmc2_nand.c | 1185 ++++++++--------- - include/linux/mmc/core.h | 1 + - include/linux/mmc/host.h | 6 + - 11 files changed, 1089 insertions(+), 767 deletions(-) - delete mode 100644 Documentation/devicetree/bindings/mtd/stm32-fmc2-nand.txt - -diff --git a/Documentation/devicetree/bindings/mmc/mmci.txt b/Documentation/devicetree/bindings/mmc/mmci.txt -index 6d3c626e017d2..4ec921e4bf344 100644 ---- a/Documentation/devicetree/bindings/mmc/mmci.txt -+++ b/Documentation/devicetree/bindings/mmc/mmci.txt -@@ -28,6 +28,8 @@ specific for ux500 variant: - - st,sig-pin-fbclk : feedback clock signal pin used. - - specific for sdmmc variant: -+- reg : a second base register may be defined if a delay -+ block is present and used for tuning. - - st,sig-dir : signal direction polarity used for cmd, dat0 dat123. - - st,neg-edge : data & command phase relation, generated on - sd clock falling edge. -diff --git a/Documentation/devicetree/bindings/mtd/stm32-fmc2-nand.txt b/Documentation/devicetree/bindings/mtd/stm32-fmc2-nand.txt -deleted file mode 100644 -index e55895e8dae44..0000000000000 ---- a/Documentation/devicetree/bindings/mtd/stm32-fmc2-nand.txt -+++ /dev/null -@@ -1,61 +0,0 @@ --STMicroelectronics Flexible Memory Controller 2 (FMC2) --NAND Interface -- --Required properties: --- compatible: Should be one of: -- * st,stm32mp15-fmc2 --- reg: NAND flash controller memory areas. -- First region contains the register location. -- Regions 2 to 4 respectively contain the data, command, -- and address space for CS0. -- Regions 5 to 7 contain the same areas for CS1. --- interrupts: The interrupt number --- pinctrl-0: Standard Pinctrl phandle (see: pinctrl/pinctrl-bindings.txt) --- clocks: The clock needed by the NAND flash controller -- --Optional properties: --- resets: Reference to a reset controller asserting the FMC controller --- dmas: DMA specifiers (see: dma/stm32-mdma.txt) --- dma-names: Must be "tx", "rx" and "ecc" -- --* NAND device bindings: -- --Required properties: --- reg: describes the CS lines assigned to the NAND device. -- --Optional properties: --- nand-on-flash-bbt: see nand-controller.yaml --- nand-ecc-strength: see nand-controller.yaml --- nand-ecc-step-size: see nand-controller.yaml -- --The following ECC strength and step size are currently supported: -- - nand-ecc-strength = <1>, nand-ecc-step-size = <512> (Hamming) -- - nand-ecc-strength = <4>, nand-ecc-step-size = <512> (BCH4) -- - nand-ecc-strength = <8>, nand-ecc-step-size = <512> (BCH8) (default) -- --Example: -- -- fmc: nand-controller@58002000 { -- compatible = "st,stm32mp15-fmc2"; -- reg = <0x58002000 0x1000>, -- <0x80000000 0x1000>, -- <0x88010000 0x1000>, -- <0x88020000 0x1000>, -- <0x81000000 0x1000>, -- <0x89010000 0x1000>, -- <0x89020000 0x1000>; -- interrupts = ; -- clocks = <&rcc FMC_K>; -- resets = <&rcc FMC_R>; -- pinctrl-names = "default"; -- pinctrl-0 = <&fmc_pins_a>; -- #address-cells = <1>; -- #size-cells = <0>; -- -- nand@0 { -- reg = <0>; -- nand-on-flash-bbt; -- #address-cells = <1>; -- #size-cells = <1>; -- }; -- }; -diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c -index 7f480c6b19810..4ac7a07d87cc6 100644 ---- a/drivers/mmc/core/block.c -+++ b/drivers/mmc/core/block.c -@@ -1763,6 +1763,17 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) - u32 blocks; - int err; - -+ /* -+ * the host is in a bad state, and can't sent a new command -+ * without be unstuck -+ */ -+ if (brq->sbc.error == -EDEADLK || brq->cmd.error == -EDEADLK || -+ brq->stop.error == -EDEADLK || brq->data.error == -EDEADLK) { -+ pr_err("%s: host is in bad state, must be unstuck\n", -+ req->rq_disk->disk_name); -+ mmc_hw_unstuck(card->host); -+ } -+ - /* - * Some errors the host driver might not have seen. Set the number of - * bytes transferred to zero in that case. -diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index 26644b7ec13e3..6d00eed17738e 100644 ---- a/drivers/mmc/core/core.c -+++ b/drivers/mmc/core/core.c -@@ -397,6 +397,7 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) - void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) - { - struct mmc_command *cmd; -+ int sbc_err, stop_err, data_err; - - while (1) { - wait_for_completion(&mrq->completion); -@@ -420,8 +421,20 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) - mmc_hostname(host), __func__); - } - } -- if (!cmd->error || !cmd->retries || -- mmc_card_removed(host->card)) -+ -+ sbc_err = mrq->sbc ? mrq->sbc->error : 0; -+ stop_err = mrq->stop ? mrq->stop->error : 0; -+ data_err = mrq->data ? mrq->data->error : 0; -+ -+ if (cmd->error == -EDEADLK || sbc_err == -EDEADLK || -+ stop_err == -EDEADLK || data_err == -EDEADLK) { -+ pr_debug("%s: host is in bad state, must be unstuck\n", -+ mmc_hostname(host)); -+ mmc_hw_unstuck(host); -+ } -+ -+ if ((!cmd->error && !sbc_err && !stop_err && !data_err) || -+ !cmd->retries || mmc_card_removed(host->card)) - break; - - mmc_retune_recheck(host); -@@ -430,6 +443,12 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) - mmc_hostname(host), cmd->opcode, cmd->error); - cmd->retries--; - cmd->error = 0; -+ if (mrq->sbc) -+ mrq->sbc->error = 0; -+ if (mrq->stop) -+ mrq->stop->error = 0; -+ if (mrq->data) -+ mrq->data->error = 0; - __mmc_start_request(host, mrq); - } - -@@ -2163,6 +2182,14 @@ int mmc_sw_reset(struct mmc_host *host) - } - EXPORT_SYMBOL(mmc_sw_reset); - -+void mmc_hw_unstuck(struct mmc_host *host) -+{ -+ if (!host->ops->hw_unstuck) -+ return; -+ host->ops->hw_unstuck(host); -+} -+EXPORT_SYMBOL(mmc_hw_unstuck); -+ - static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) - { - host->f_init = freq; -diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c -index 7e4bc9124efde..f2e74aa3d7274 100644 ---- a/drivers/mmc/host/mmci.c -+++ b/drivers/mmc/host/mmci.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -44,6 +45,7 @@ - #define DRIVER_NAME "mmci-pl18x" - - static void mmci_variant_init(struct mmci_host *host); -+static void ux500_variant_init(struct mmci_host *host); - static void ux500v2_variant_init(struct mmci_host *host); - - static unsigned int fmax = 515633; -@@ -177,7 +179,6 @@ static struct variant_data variant_ux500 = { - .f_max = 100000000, - .signal_direction = true, - .pwrreg_clkgate = true, -- .busy_detect = true, - .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE, - .busy_detect_flag = MCI_ST_CARDBUSY, - .busy_detect_mask = MCI_ST_BUSYENDMASK, -@@ -186,7 +187,7 @@ static struct variant_data variant_ux500 = { - .irq_pio_mask = MCI_IRQ_PIO_MASK, - .start_err = MCI_STARTBITERR, - .opendrain = MCI_OD, -- .init = mmci_variant_init, -+ .init = ux500_variant_init, - }; - - static struct variant_data variant_ux500v2 = { -@@ -212,7 +213,6 @@ static struct variant_data variant_ux500v2 = { - .f_max = 100000000, - .signal_direction = true, - .pwrreg_clkgate = true, -- .busy_detect = true, - .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE, - .busy_detect_flag = MCI_ST_CARDBUSY, - .busy_detect_mask = MCI_ST_BUSYENDMASK, -@@ -264,8 +264,38 @@ static struct variant_data variant_stm32_sdmmc = { - .datacnt_useless = true, - .datalength_bits = 25, - .datactrl_blocksz = 14, -- .datactrl_any_blocksz = true, -+ .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN, -+ .pwrreg_nopower = true, - .stm32_idmabsize_mask = GENMASK(12, 5), -+ .busy_timeout = true, -+ .busy_detect_flag = MCI_STM32_BUSYD0, -+ .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK, -+ .init = sdmmc_variant_init, -+}; -+ -+static struct variant_data variant_stm32_sdmmcv2 = { -+ .fifosize = 16 * 4, -+ .fifohalfsize = 8 * 4, -+ .f_max = 208000000, -+ .stm32_clkdiv = true, -+ .cmdreg_cpsm_enable = MCI_CPSM_STM32_ENABLE, -+ .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC, -+ .cmdreg_srsp_crc = MCI_CPSM_STM32_SRSP_CRC, -+ .cmdreg_srsp = MCI_CPSM_STM32_SRSP, -+ .cmdreg_stop = MCI_CPSM_STM32_CMDSTOP, -+ .data_cmd_enable = MCI_CPSM_STM32_CMDTRANS, -+ .irq_pio_mask = MCI_IRQ_PIO_STM32_MASK, -+ .datactrl_first = true, -+ .datacnt_useless = true, -+ .datalength_bits = 25, -+ .datactrl_blocksz = 14, -+ .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN, -+ .pwrreg_nopower = true, -+ .stm32_idmabsize_mask = GENMASK(16, 5), -+ .dma_lli = true, -+ .busy_timeout = true, -+ .busy_detect_flag = MCI_STM32_BUSYD0, -+ .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK, - .init = sdmmc_variant_init, - }; - -@@ -363,6 +393,24 @@ static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl) - } - } - -+static void mmci_restore(struct mmci_host *host) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (host->variant->pwrreg_nopower) { -+ writel(host->clk_reg, host->base + MMCICLOCK); -+ writel(host->datactrl_reg, host->base + MMCIDATACTRL); -+ writel(host->pwr_reg, host->base + MMCIPOWER); -+ } -+ writel(MCI_IRQENABLE | host->variant->start_err, -+ host->base + MMCIMASK0); -+ mmci_reg_delay(host); -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ - /* - * This must be called with host->lock held - */ -@@ -453,11 +501,11 @@ void mmci_dma_setup(struct mmci_host *host) - static int mmci_validate_data(struct mmci_host *host, - struct mmc_data *data) - { -- struct variant_data *variant = host->variant; -- - if (!data) - return 0; -- if (!is_power_of_2(data->blksz) && !variant->datactrl_any_blocksz) { -+ -+ if ((host->mmc->card && !mmc_card_sdio(host->mmc->card)) && -+ !is_power_of_2(data->blksz)) { - dev_err(mmc_dev(host->mmc), - "unsupported block size (%d bytes)\n", data->blksz); - return -EINVAL; -@@ -619,6 +667,67 @@ static u32 ux500v2_get_dctrl_cfg(struct mmci_host *host) - return MCI_DPSM_ENABLE | (host->data->blksz << 16); - } - -+static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) -+{ -+ void __iomem *base = host->base; -+ -+ /* -+ * Before unmasking for the busy end IRQ, confirm that the -+ * command was sent successfully. To keep track of having a -+ * command in-progress, waiting for busy signaling to end, -+ * store the status in host->busy_status. -+ * -+ * Note that, the card may need a couple of clock cycles before -+ * it starts signaling busy on DAT0, hence re-read the -+ * MMCISTATUS register here, to allow the busy bit to be set. -+ * Potentially we may even need to poll the register for a -+ * while, to allow it to be set, but tests indicates that it -+ * isn't needed. -+ */ -+ if (!host->busy_status && !(status & err_msk) && -+ (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) { -+ writel(readl(base + MMCIMASK0) | -+ host->variant->busy_detect_mask, -+ base + MMCIMASK0); -+ -+ host->busy_status = status & (MCI_CMDSENT | MCI_CMDRESPEND); -+ return false; -+ } -+ -+ /* -+ * If there is a command in-progress that has been successfully -+ * sent, then bail out if busy status is set and wait for the -+ * busy end IRQ. -+ * -+ * Note that, the HW triggers an IRQ on both edges while -+ * monitoring DAT0 for busy completion, but there is only one -+ * status bit in MMCISTATUS for the busy state. Therefore -+ * both the start and the end interrupts needs to be cleared, -+ * one after the other. So, clear the busy start IRQ here. -+ */ -+ if (host->busy_status && -+ (status & host->variant->busy_detect_flag)) { -+ writel(host->variant->busy_detect_mask, base + MMCICLEAR); -+ return false; -+ } -+ -+ /* -+ * If there is a command in-progress that has been successfully -+ * sent and the busy bit isn't set, it means we have received -+ * the busy end IRQ. Clear and mask the IRQ, then continue to -+ * process the command. -+ */ -+ if (host->busy_status) { -+ writel(host->variant->busy_detect_mask, base + MMCICLEAR); -+ -+ writel(readl(base + MMCIMASK0) & -+ ~host->variant->busy_detect_mask, base + MMCIMASK0); -+ host->busy_status = 0; -+ } -+ -+ return true; -+} -+ - /* - * All the DMA operation mode stuff goes inside this ifdef. - * This assumes that you have a generic DMA device interface, -@@ -979,9 +1088,16 @@ void mmci_variant_init(struct mmci_host *host) - host->ops = &mmci_variant_ops; - } - -+void ux500_variant_init(struct mmci_host *host) -+{ -+ host->ops = &mmci_variant_ops; -+ host->ops->busy_complete = ux500_busy_complete; -+} -+ - void ux500v2_variant_init(struct mmci_host *host) - { - host->ops = &mmci_variant_ops; -+ host->ops->busy_complete = ux500_busy_complete; - host->ops->get_datactrl_cfg = ux500v2_get_dctrl_cfg; - } - -@@ -1101,6 +1217,7 @@ static void - mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) - { - void __iomem *base = host->base; -+ unsigned long long clks; - - dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n", - cmd->opcode, cmd->arg, cmd->flags); -@@ -1123,6 +1240,19 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) - else - c |= host->variant->cmdreg_srsp; - } -+ -+ if (host->variant->busy_timeout && cmd->flags & MMC_RSP_BUSY) { -+ if (!cmd->busy_timeout) -+ cmd->busy_timeout = 1000; -+ -+ clks = (unsigned long long)cmd->busy_timeout * host->cclk; -+ do_div(clks, MSEC_PER_SEC); -+ writel_relaxed(clks, host->base + MMCIDATATIMER); -+ } -+ -+ if (host->ops->prep_volt_switch && cmd->opcode == SD_SWITCH_VOLTAGE) -+ host->ops->prep_volt_switch(host); -+ - if (/*interrupt*/0) - c |= MCI_CPSM_INTERRUPT; - -@@ -1227,6 +1357,7 @@ static void - mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, - unsigned int status) - { -+ u32 err_msk = MCI_CMDCRCFAIL | MCI_CMDTIMEOUT; - void __iomem *base = host->base; - bool sbc, busy_resp; - -@@ -1241,74 +1372,17 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, - * handling. Note that we tag on any latent IRQs postponed - * due to waiting for busy status. - */ -- if (!((status|host->busy_status) & -- (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND))) -+ if (host->variant->busy_timeout && busy_resp) -+ err_msk |= MCI_DATATIMEOUT; -+ -+ if (!((status | host->busy_status) & -+ (err_msk | MCI_CMDSENT | MCI_CMDRESPEND))) - return; - - /* Handle busy detection on DAT0 if the variant supports it. */ -- if (busy_resp && host->variant->busy_detect) { -- -- /* -- * Before unmasking for the busy end IRQ, confirm that the -- * command was sent successfully. To keep track of having a -- * command in-progress, waiting for busy signaling to end, -- * store the status in host->busy_status. -- * -- * Note that, the card may need a couple of clock cycles before -- * it starts signaling busy on DAT0, hence re-read the -- * MMCISTATUS register here, to allow the busy bit to be set. -- * Potentially we may even need to poll the register for a -- * while, to allow it to be set, but tests indicates that it -- * isn't needed. -- */ -- if (!host->busy_status && -- !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) && -- (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) { -- -- writel(readl(base + MMCIMASK0) | -- host->variant->busy_detect_mask, -- base + MMCIMASK0); -- -- host->busy_status = -- status & (MCI_CMDSENT|MCI_CMDRESPEND); -- return; -- } -- -- /* -- * If there is a command in-progress that has been successfully -- * sent, then bail out if busy status is set and wait for the -- * busy end IRQ. -- * -- * Note that, the HW triggers an IRQ on both edges while -- * monitoring DAT0 for busy completion, but there is only one -- * status bit in MMCISTATUS for the busy state. Therefore -- * both the start and the end interrupts needs to be cleared, -- * one after the other. So, clear the busy start IRQ here. -- */ -- if (host->busy_status && -- (status & host->variant->busy_detect_flag)) { -- writel(host->variant->busy_detect_mask, -- host->base + MMCICLEAR); -+ if (busy_resp && host->ops->busy_complete) -+ if (!host->ops->busy_complete(host, status, err_msk)) - return; -- } -- -- /* -- * If there is a command in-progress that has been successfully -- * sent and the busy bit isn't set, it means we have received -- * the busy end IRQ. Clear and mask the IRQ, then continue to -- * process the command. -- */ -- if (host->busy_status) { -- -- writel(host->variant->busy_detect_mask, -- host->base + MMCICLEAR); -- -- writel(readl(base + MMCIMASK0) & -- ~host->variant->busy_detect_mask, -- base + MMCIMASK0); -- host->busy_status = 0; -- } -- } - - host->cmd = NULL; - -@@ -1316,6 +1390,9 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, - cmd->error = -ETIMEDOUT; - } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { - cmd->error = -EILSEQ; -+ } else if (host->variant->busy_timeout && busy_resp && -+ status & MCI_DATATIMEOUT) { -+ cmd->error = -EDEADLK; - } else { - cmd->resp[0] = readl(base + MMCIRESPONSE0); - cmd->resp[1] = readl(base + MMCIRESPONSE1); -@@ -1327,7 +1404,6 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, - if (host->data) { - /* Terminate the DMA transfer */ - mmci_dma_error(host); -- - mmci_stop_data(host); - if (host->variant->cmdreg_stop && cmd->error) { - mmci_stop_command(host); -@@ -1546,7 +1622,7 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) - * clear the corresponding IRQ. - */ - status &= readl(host->base + MMCIMASK0); -- if (host->variant->busy_detect) -+ if (host->ops->busy_complete) - writel(status & ~host->variant->busy_detect_mask, - host->base + MMCICLEAR); - else -@@ -1609,6 +1685,20 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) - spin_unlock_irqrestore(&host->lock, flags); - } - -+static void mmci_set_max_busy_timeout(struct mmc_host *mmc) -+{ -+ struct mmci_host *host = mmc_priv(mmc); -+ u32 max_busy_timeout = 0; -+ -+ if (!host->ops->busy_complete) -+ return; -+ -+ if (host->variant->busy_timeout && mmc->actual_clock) -+ max_busy_timeout = ~0UL / (mmc->actual_clock / MSEC_PER_SEC); -+ -+ mmc->max_busy_timeout = max_busy_timeout; -+} -+ - static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) - { - struct mmci_host *host = mmc_priv(mmc); -@@ -1713,6 +1803,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) - else - mmci_set_clkreg(host, ios->clock); - -+ mmci_set_max_busy_timeout(mmc); -+ - if (host->ops && host->ops->set_pwrreg) - host->ops->set_pwrreg(host, pwr); - else -@@ -1740,6 +1832,7 @@ static int mmci_get_cd(struct mmc_host *mmc) - - static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) - { -+ struct mmci_host *host = mmc_priv(mmc); - int ret = 0; - - if (!IS_ERR(mmc->supply.vqmmc)) { -@@ -1759,6 +1852,9 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) - break; - } - -+ if (!ret && host->ops && host->ops->volt_switch) -+ ret = host->ops->volt_switch(host, ios); -+ - if (ret) - dev_warn(mmc_dev(mmc), "Voltage switch failed\n"); - } -@@ -1766,6 +1862,19 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) - return ret; - } - -+static void mmci_hw_unstuck(struct mmc_host *mmc) -+{ -+ struct mmci_host *host = mmc_priv(mmc); -+ -+ if (host->rst) { -+ reset_control_assert(host->rst); -+ udelay(2); -+ reset_control_deassert(host->rst); -+ } -+ -+ mmci_restore(host); -+} -+ - static struct mmc_host_ops mmci_ops = { - .request = mmci_request, - .pre_req = mmci_pre_request, -@@ -1774,6 +1883,7 @@ static struct mmc_host_ops mmci_ops = { - .get_ro = mmc_gpio_get_ro, - .get_cd = mmci_get_cd, - .start_signal_voltage_switch = mmci_sig_volt_switch, -+ .hw_unstuck = mmci_hw_unstuck, - }; - - static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc) -@@ -1843,6 +1953,7 @@ static int mmci_probe(struct amba_device *dev, - - host = mmc_priv(mmc); - host->mmc = mmc; -+ host->mmc_ops = &mmci_ops; - - /* - * Some variant (STM32) doesn't have opendrain bit, nevertheless -@@ -1967,13 +2078,15 @@ static int mmci_probe(struct amba_device *dev, - else if (plat->ocr_mask) - dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); - -+ host->pwr_reg = readl_relaxed(host->base + MMCIPOWER); -+ - /* We support these capabilities. */ - mmc->caps |= MMC_CAP_CMD23; - - /* - * Enable busy detection. - */ -- if (variant->busy_detect) { -+ if (host->ops->busy_complete) { - mmci_ops.card_busy = mmci_card_busy; - /* - * Not all variants have a flag to enable busy detection -@@ -1983,7 +2096,6 @@ static int mmci_probe(struct amba_device *dev, - mmci_write_datactrlreg(host, - host->variant->busy_dpsm_flag); - mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; -- mmc->max_busy_timeout = 0; - } - - /* Prepare a CMD12 - needed to clear the DPSM on some variants. */ -@@ -2141,24 +2253,6 @@ static void mmci_save(struct mmci_host *host) - spin_unlock_irqrestore(&host->lock, flags); - } - --static void mmci_restore(struct mmci_host *host) --{ -- unsigned long flags; -- -- spin_lock_irqsave(&host->lock, flags); -- -- if (host->variant->pwrreg_nopower) { -- writel(host->clk_reg, host->base + MMCICLOCK); -- writel(host->datactrl_reg, host->base + MMCIDATACTRL); -- writel(host->pwr_reg, host->base + MMCIPOWER); -- } -- writel(MCI_IRQENABLE | host->variant->start_err, -- host->base + MMCIMASK0); -- mmci_reg_delay(host); -- -- spin_unlock_irqrestore(&host->lock, flags); --} -- - static int mmci_runtime_suspend(struct device *dev) - { - struct amba_device *adev = to_amba_device(dev); -@@ -2253,6 +2347,11 @@ static const struct amba_id mmci_ids[] = { - .mask = 0xf0ffffff, - .data = &variant_stm32_sdmmc, - }, -+ { -+ .id = 0x00253180, -+ .mask = 0xf0ffffff, -+ .data = &variant_stm32_sdmmcv2, -+ }, - /* Qualcomm variants */ - { - .id = 0x00051180, -diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h -index 89ab73343cf30..a94f384bb1ff5 100644 ---- a/drivers/mmc/host/mmci.h -+++ b/drivers/mmc/host/mmci.h -@@ -133,6 +133,8 @@ - #define MCI_DPSM_STM32_MODE_SDIO (1 << 2) - #define MCI_DPSM_STM32_MODE_STREAM (2 << 2) - #define MCI_DPSM_STM32_MODE_BLOCK_STOP (3 << 2) -+#define MCI_DPSM_STM32_SDIOEN BIT(11) -+ - - #define MMCIDATACNT 0x030 - #define MMCISTATUS 0x034 -@@ -164,6 +166,8 @@ - #define MCI_ST_CARDBUSY (1 << 24) - /* Extended status bits for the STM32 variants */ - #define MCI_STM32_BUSYD0 BIT(20) -+#define MCI_STM32_BUSYD0END BIT(21) -+#define MCI_STM32_VSWEND BIT(25) - - #define MMCICLEAR 0x038 - #define MCI_CMDCRCFAILCLR (1 << 0) -@@ -181,6 +185,9 @@ - #define MCI_ST_SDIOITC (1 << 22) - #define MCI_ST_CEATAENDC (1 << 23) - #define MCI_ST_BUSYENDC (1 << 24) -+/* Extended clear bits for the STM32 variants */ -+#define MCI_STM32_VSWENDC (1 << 25) -+#define MCI_STM32_CKSTOPC (1 << 26) - - #define MMCIMASK0 0x03c - #define MCI_CMDCRCFAILMASK (1 << 0) -@@ -290,7 +297,8 @@ struct mmci_host; - * @f_max: maximum clk frequency supported by the controller. - * @signal_direction: input/out direction of bus signals can be indicated - * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock -- * @busy_detect: true if the variant supports busy detection on DAT0. -+ * @busy_timeout: true if the variant starts data timer when the DPSM -+ * enter in Wait_R or Busy state. - * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM - * @busy_detect_flag: bitmask identifying the bit in the MMCISTATUS register - * indicating that the card is busy -@@ -338,7 +346,7 @@ struct variant_data { - u32 f_max; - u8 signal_direction:1; - u8 pwrreg_clkgate:1; -- u8 busy_detect:1; -+ u8 busy_timeout:1; - u32 busy_dpsm_flag; - u32 busy_detect_flag; - u32 busy_detect_mask; -@@ -372,6 +380,9 @@ struct mmci_host_ops { - void (*dma_error)(struct mmci_host *host); - void (*set_clkreg)(struct mmci_host *host, unsigned int desired); - void (*set_pwrreg)(struct mmci_host *host, unsigned int pwr); -+ bool (*busy_complete)(struct mmci_host *host, u32 status, u32 err_msk); -+ void (*prep_volt_switch)(struct mmci_host *host); -+ int (*volt_switch)(struct mmci_host *host, struct mmc_ios *ios); - }; - - struct mmci_host { -@@ -402,8 +413,10 @@ struct mmci_host { - u32 mask1_reg; - u8 vqmmc_enabled:1; - struct mmci_platform_data *plat; -+ struct mmc_host_ops *mmc_ops; - struct mmci_host_ops *ops; - struct variant_data *variant; -+ void *variant_priv; - struct pinctrl *pinctrl; - struct pinctrl_state *pins_default; - struct pinctrl_state *pins_opendrain; -diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c -index 0953bd8a4f79d..7c6ba518bc08e 100644 ---- a/drivers/mmc/host/mmci_stm32_sdmmc.c -+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c -@@ -3,10 +3,13 @@ - * Copyright (C) STMicroelectronics 2018 - All Rights Reserved - * Author: Ludovic.barre@st.com for STMicroelectronics. - */ -+#include - #include - #include -+#include - #include - #include -+#include - #include - #include - #include "mmci.h" -@@ -14,17 +17,36 @@ - #define SDMMC_LLI_BUF_LEN PAGE_SIZE - #define SDMMC_IDMA_BURST BIT(MMCI_STM32_IDMABNDT_SHIFT) - -+#define DLYB_CR 0x0 -+#define DLYB_CR_DEN BIT(0) -+#define DLYB_CR_SEN BIT(1) -+ -+#define DLYB_CFGR 0x4 -+#define DLYB_CFGR_SEL_MASK GENMASK(3, 0) -+#define DLYB_CFGR_UNIT_MASK GENMASK(14, 8) -+#define DLYB_CFGR_LNG_MASK GENMASK(27, 16) -+#define DLYB_CFGR_LNGF BIT(31) -+ -+#define DLYB_CFGR_SEL_MAX 12 -+#define DLYB_CFGR_UNIT_MAX 127 -+ - struct sdmmc_lli_desc { - u32 idmalar; - u32 idmabase; - u32 idmasize; - }; - --struct sdmmc_priv { -+struct sdmmc_idma { - dma_addr_t sg_dma; - void *sg_cpu; - }; - -+struct sdmmc_dlyb { -+ void __iomem *base; -+ u32 unit; -+ u32 max; -+}; -+ - int sdmmc_idma_validate_data(struct mmci_host *host, - struct mmc_data *data) - { -@@ -36,8 +58,8 @@ int sdmmc_idma_validate_data(struct mmci_host *host, - * excepted the last element which has no constraint on idmasize - */ - for_each_sg(data->sg, sg, data->sg_len - 1, i) { -- if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32)) || -- !IS_ALIGNED(sg_dma_len(data->sg), SDMMC_IDMA_BURST)) { -+ if (!IS_ALIGNED(data->sg->offset, sizeof(u32)) || -+ !IS_ALIGNED(data->sg->length, SDMMC_IDMA_BURST)) { - dev_err(mmc_dev(host->mmc), - "unaligned scatterlist: ofst:%x length:%d\n", - data->sg->offset, data->sg->length); -@@ -45,7 +67,7 @@ int sdmmc_idma_validate_data(struct mmci_host *host, - } - } - -- if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32))) { -+ if (!IS_ALIGNED(data->sg->offset, sizeof(u32))) { - dev_err(mmc_dev(host->mmc), - "unaligned last scatterlist: ofst:%x length:%d\n", - data->sg->offset, data->sg->length); -@@ -92,21 +114,21 @@ static void sdmmc_idma_unprep_data(struct mmci_host *host, - - static int sdmmc_idma_setup(struct mmci_host *host) - { -- struct sdmmc_priv *idma; -+ struct sdmmc_idma *idma; -+ struct device *dev = mmc_dev(host->mmc); - -- idma = devm_kzalloc(mmc_dev(host->mmc), sizeof(*idma), GFP_KERNEL); -- if (!idma) -+ idma = devm_kzalloc(dev, sizeof(*idma), GFP_KERNEL); -+ dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL); -+ if (!idma || !dev->dma_parms) - return -ENOMEM; - - host->dma_priv = idma; - - if (host->variant->dma_lli) { -- idma->sg_cpu = dmam_alloc_coherent(mmc_dev(host->mmc), -- SDMMC_LLI_BUF_LEN, -+ idma->sg_cpu = dmam_alloc_coherent(dev, SDMMC_LLI_BUF_LEN, - &idma->sg_dma, GFP_KERNEL); - if (!idma->sg_cpu) { -- dev_err(mmc_dev(host->mmc), -- "Failed to alloc IDMA descriptor\n"); -+ dev_err(dev, "Failed to alloc IDMA descriptor\n"); - return -ENOMEM; - } - host->mmc->max_segs = SDMMC_LLI_BUF_LEN / -@@ -117,13 +139,15 @@ static int sdmmc_idma_setup(struct mmci_host *host) - host->mmc->max_seg_size = host->mmc->max_req_size; - } - -+ dma_set_max_seg_size(dev, host->mmc->max_seg_size); -+ - return 0; - } - - static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl) - - { -- struct sdmmc_priv *idma = host->dma_priv; -+ struct sdmmc_idma *idma = host->dma_priv; - struct sdmmc_lli_desc *desc = (struct sdmmc_lli_desc *)idma->sg_cpu; - struct mmc_data *data = host->data; - struct scatterlist *sg; -@@ -229,12 +253,25 @@ static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired) - mmci_write_clkreg(host, clk); - } - -+static void sdmmc_dlyb_input_ck(struct sdmmc_dlyb *dlyb) -+{ -+ if (!dlyb || !dlyb->base) -+ return; -+ -+ /* Output clock = Input clock */ -+ writel_relaxed(0, dlyb->base + DLYB_CR); -+} -+ - static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr) - { - struct mmc_ios ios = host->mmc->ios; -+ struct sdmmc_dlyb *dlyb = host->variant_priv; - -+ /* adds OF options */ - pwr = host->pwr_reg_add; - -+ sdmmc_dlyb_input_ck(dlyb); -+ - if (ios.power_mode == MMC_POWER_OFF) { - /* Only a reset could power-off sdmmc */ - reset_control_assert(host->rst); -@@ -257,6 +294,10 @@ static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr) - writel(MCI_IRQENABLE | host->variant->start_err, - host->base + MMCIMASK0); - -+ /* preserves voltage switch bits */ -+ pwr |= host->pwr_reg & (MCI_STM32_VSWITCHEN | -+ MCI_STM32_VSWITCH); -+ - /* - * After a power-cycle state, we must set the SDMMC in - * Power-off. The SDMMC_D[7:0], SDMMC_CMD and SDMMC_CK are -@@ -285,6 +326,178 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host) - return datactrl; - } - -+bool sdmmc_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) -+{ -+ void __iomem *base = host->base; -+ u32 busy_d0, busy_d0end, mask; -+ -+ mask = readl_relaxed(base + MMCIMASK0); -+ busy_d0end = readl_relaxed(base + MMCISTATUS) & MCI_STM32_BUSYD0END; -+ busy_d0 = readl_relaxed(base + MMCISTATUS) & MCI_STM32_BUSYD0; -+ -+ /* complete if there is an error or busy_d0end */ -+ if ((status & err_msk) || busy_d0end) -+ goto complete; -+ -+ /* -+ * On response the busy signaling is reflected in the BUSYD0 flag. -+ * if busy_d0 is in-progress we must activate busyd0end interrupt -+ * to wait this completion. Else this request has no busy step. -+ */ -+ if (busy_d0) { -+ if (!host->busy_status) { -+ writel_relaxed(mask | host->variant->busy_detect_mask, -+ base + MMCIMASK0); -+ host->busy_status = status & -+ (MCI_CMDSENT | MCI_CMDRESPEND); -+ } -+ return false; -+ } -+ -+complete: -+ writel_relaxed(mask & ~host->variant->busy_detect_mask, -+ base + MMCIMASK0); -+ writel_relaxed(host->variant->busy_detect_mask, base + MMCICLEAR); -+ host->busy_status = 0; -+ -+ return true; -+} -+ -+static void sdmmc_dlyb_set_cfgr(struct sdmmc_dlyb *dlyb, -+ int unit, int phase, bool sampler) -+{ -+ u32 cfgr; -+ -+ writel_relaxed(DLYB_CR_SEN | DLYB_CR_DEN, dlyb->base + DLYB_CR); -+ -+ cfgr = FIELD_PREP(DLYB_CFGR_UNIT_MASK, unit) | -+ FIELD_PREP(DLYB_CFGR_SEL_MASK, phase); -+ writel_relaxed(cfgr, dlyb->base + DLYB_CFGR); -+ -+ if (!sampler) -+ writel_relaxed(DLYB_CR_DEN, dlyb->base + DLYB_CR); -+} -+ -+static int sdmmc_dlyb_lng_tuning(struct mmci_host *host) -+{ -+ struct sdmmc_dlyb *dlyb = host->variant_priv; -+ u32 cfgr; -+ int i, lng, ret; -+ -+ for (i = 0; i <= DLYB_CFGR_UNIT_MAX; i++) { -+ sdmmc_dlyb_set_cfgr(dlyb, i, DLYB_CFGR_SEL_MAX, true); -+ -+ ret = readl_relaxed_poll_timeout(dlyb->base + DLYB_CFGR, cfgr, -+ (cfgr & DLYB_CFGR_LNGF), -+ 1, 1000); -+ if (ret) { -+ dev_warn(mmc_dev(host->mmc), -+ "delay line cfg timeout unit:%d cfgr:%d\n", -+ i, cfgr); -+ continue; -+ } -+ -+ lng = FIELD_GET(DLYB_CFGR_LNG_MASK, cfgr); -+ if (lng < (BIT(11) | BIT(10)) && (lng & ~BIT(11)) > 0) -+ break; -+ } -+ -+ if (i > DLYB_CFGR_UNIT_MAX) -+ return -EINVAL; -+ -+ dlyb->unit = i; -+ dlyb->max = __fls(lng & ~BIT(11)); -+ -+ return 0; -+} -+ -+static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode) -+{ -+ struct sdmmc_dlyb *dlyb = host->variant_priv; -+ int cur_len = 0, max_len = 0, end_of_len = 0; -+ int phase; -+ -+ for (phase = 0; phase <= dlyb->max; phase++) { -+ sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false); -+ -+ if (mmc_send_tuning(host->mmc, opcode, NULL)) { -+ cur_len = 0; -+ } else { -+ cur_len++; -+ if (cur_len > max_len) { -+ max_len = cur_len; -+ end_of_len = phase; -+ } -+ } -+ } -+ -+ if (!max_len) { -+ dev_err(mmc_dev(host->mmc), "no tuning point found\n"); -+ return -EINVAL; -+ } -+ -+ writel_relaxed(0, dlyb->base + DLYB_CR); -+ -+ phase = end_of_len - max_len / 2; -+ sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false); -+ -+ dev_dbg(mmc_dev(host->mmc), "unit:%d max_dly:%d phase:%d\n", -+ dlyb->unit, dlyb->max, phase); -+ -+ return 0; -+} -+ -+static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) -+{ -+ struct mmci_host *host = mmc_priv(mmc); -+ struct sdmmc_dlyb *dlyb = host->variant_priv; -+ -+ if (!dlyb || !dlyb->base) -+ return -EINVAL; -+ -+ if (sdmmc_dlyb_lng_tuning(host)) -+ return -EINVAL; -+ -+ return sdmmc_dlyb_phase_tuning(host, opcode); -+} -+ -+static void sdmmc_prep_vswitch(struct mmci_host *host) -+{ -+ /* clear the voltage switch completion flag */ -+ writel_relaxed(MCI_STM32_VSWENDC, host->base + MMCICLEAR); -+ /* enable Voltage switch procedure */ -+ mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCHEN); -+} -+ -+static int sdmmc_vswitch(struct mmci_host *host, struct mmc_ios *ios) -+{ -+ unsigned long flags; -+ u32 status; -+ int ret = 0; -+ -+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { -+ spin_lock_irqsave(&host->lock, flags); -+ mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCH); -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ /* wait voltage switch completion while 10ms */ -+ ret = readl_relaxed_poll_timeout(host->base + MMCISTATUS, -+ status, -+ (status & MCI_STM32_VSWEND), -+ 10, 10000); -+ -+ writel_relaxed(MCI_STM32_VSWENDC | MCI_STM32_CKSTOPC, -+ host->base + MMCICLEAR); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ mmci_write_pwrreg(host, host->pwr_reg & -+ ~(MCI_STM32_VSWITCHEN | MCI_STM32_VSWITCH)); -+ spin_unlock_irqrestore(&host->lock, flags); -+ } -+ -+ return ret; -+} -+ - static struct mmci_host_ops sdmmc_variant_ops = { - .validate_data = sdmmc_idma_validate_data, - .prep_data = sdmmc_idma_prep_data, -@@ -295,9 +508,28 @@ static struct mmci_host_ops sdmmc_variant_ops = { - .dma_finalize = sdmmc_idma_finalize, - .set_clkreg = mmci_sdmmc_set_clkreg, - .set_pwrreg = mmci_sdmmc_set_pwrreg, -+ .busy_complete = sdmmc_busy_complete, -+ .prep_volt_switch = sdmmc_prep_vswitch, -+ .volt_switch = sdmmc_vswitch, - }; - - void sdmmc_variant_init(struct mmci_host *host) - { -+ struct device_node *np = host->mmc->parent->of_node; -+ void __iomem *base_dlyb; -+ struct sdmmc_dlyb *dlyb; -+ - host->ops = &sdmmc_variant_ops; -+ -+ base_dlyb = devm_of_iomap(mmc_dev(host->mmc), np, 1, NULL); -+ if (IS_ERR(base_dlyb)) -+ return; -+ -+ dlyb = devm_kzalloc(mmc_dev(host->mmc), sizeof(*dlyb), GFP_KERNEL); -+ if (!dlyb) -+ return; -+ -+ dlyb->base = base_dlyb; -+ host->variant_priv = dlyb; -+ host->mmc_ops->execute_tuning = sdmmc_execute_tuning; - } -diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig -index e59de3f60cf6b..1b549d58787c2 100644 ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -419,6 +419,7 @@ config MTD_NAND_TEGRA - config MTD_NAND_STM32_FMC2 - tristate "Support for NAND controller on STM32MP SoCs" - depends on MACH_STM32MP157 || COMPILE_TEST -+ select MFD_SYSCON - help - Enables support for NAND Flash chips on SoCs containing the FMC2 - NAND controller. This controller is found on STM32MP SoCs. -diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c -index 5c06e0b4d4ef3..9553702d7a46d 100644 ---- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c -+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c -@@ -4,16 +4,20 @@ - * Author: Christophe Kerello - */ - -+#include - #include - #include - #include - #include - #include - #include -+#include - #include - #include -+#include - #include - #include -+#include - #include - - /* Bad block marker length */ -@@ -37,8 +41,7 @@ - /* Max ECC buffer length */ - #define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG) - --#define FMC2_TIMEOUT_US 1000 --#define FMC2_TIMEOUT_MS 1000 -+#define FMC2_TIMEOUT_MS 5000 - - /* Timings */ - #define FMC2_THIZ 1 -@@ -85,20 +88,16 @@ - /* Register: FMC2_PCR */ - #define FMC2_PCR_PWAITEN BIT(1) - #define FMC2_PCR_PBKEN BIT(2) --#define FMC2_PCR_PWID_MASK GENMASK(5, 4) --#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4) -+#define FMC2_PCR_PWID GENMASK(5, 4) - #define FMC2_PCR_PWID_BUSWIDTH_8 0 - #define FMC2_PCR_PWID_BUSWIDTH_16 1 - #define FMC2_PCR_ECCEN BIT(6) - #define FMC2_PCR_ECCALG BIT(8) --#define FMC2_PCR_TCLR_MASK GENMASK(12, 9) --#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9) -+#define FMC2_PCR_TCLR GENMASK(12, 9) - #define FMC2_PCR_TCLR_DEFAULT 0xf --#define FMC2_PCR_TAR_MASK GENMASK(16, 13) --#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13) -+#define FMC2_PCR_TAR GENMASK(16, 13) - #define FMC2_PCR_TAR_DEFAULT 0xf --#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17) --#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17) -+#define FMC2_PCR_ECCSS GENMASK(19, 17) - #define FMC2_PCR_ECCSS_512 1 - #define FMC2_PCR_ECCSS_2048 3 - #define FMC2_PCR_BCHECC BIT(24) -@@ -108,17 +107,17 @@ - #define FMC2_SR_NWRF BIT(6) - - /* Register: FMC2_PMEM */ --#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0) --#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8) --#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16) --#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24) -+#define FMC2_PMEM_MEMSET GENMASK(7, 0) -+#define FMC2_PMEM_MEMWAIT GENMASK(15, 8) -+#define FMC2_PMEM_MEMHOLD GENMASK(23, 16) -+#define FMC2_PMEM_MEMHIZ GENMASK(31, 24) - #define FMC2_PMEM_DEFAULT 0x0a0a0a0a - - /* Register: FMC2_PATT */ --#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0) --#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8) --#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16) --#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24) -+#define FMC2_PATT_ATTSET GENMASK(7, 0) -+#define FMC2_PATT_ATTWAIT GENMASK(15, 8) -+#define FMC2_PATT_ATTHOLD GENMASK(23, 16) -+#define FMC2_PATT_ATTHIZ GENMASK(31, 24) - #define FMC2_PATT_DEFAULT 0x0a0a0a0a - - /* Register: FMC2_ISR */ -@@ -133,9 +132,9 @@ - /* Register: FMC2_CSQCFGR1 */ - #define FMC2_CSQCFGR1_CMD2EN BIT(1) - #define FMC2_CSQCFGR1_DMADEN BIT(2) --#define FMC2_CSQCFGR1_ACYNBR(x) (((x) & 0x7) << 4) --#define FMC2_CSQCFGR1_CMD1(x) (((x) & 0xff) << 8) --#define FMC2_CSQCFGR1_CMD2(x) (((x) & 0xff) << 16) -+#define FMC2_CSQCFGR1_ACYNBR GENMASK(6, 4) -+#define FMC2_CSQCFGR1_CMD1 GENMASK(15, 8) -+#define FMC2_CSQCFGR1_CMD2 GENMASK(23, 16) - #define FMC2_CSQCFGR1_CMD1T BIT(24) - #define FMC2_CSQCFGR1_CMD2T BIT(25) - -@@ -143,13 +142,13 @@ - #define FMC2_CSQCFGR2_SQSDTEN BIT(0) - #define FMC2_CSQCFGR2_RCMD2EN BIT(1) - #define FMC2_CSQCFGR2_DMASEN BIT(2) --#define FMC2_CSQCFGR2_RCMD1(x) (((x) & 0xff) << 8) --#define FMC2_CSQCFGR2_RCMD2(x) (((x) & 0xff) << 16) -+#define FMC2_CSQCFGR2_RCMD1 GENMASK(15, 8) -+#define FMC2_CSQCFGR2_RCMD2 GENMASK(23, 16) - #define FMC2_CSQCFGR2_RCMD1T BIT(24) - #define FMC2_CSQCFGR2_RCMD2T BIT(25) - - /* Register: FMC2_CSQCFGR3 */ --#define FMC2_CSQCFGR3_SNBR(x) (((x) & 0x1f) << 8) -+#define FMC2_CSQCFGR3_SNBR GENMASK(13, 8) - #define FMC2_CSQCFGR3_AC1T BIT(16) - #define FMC2_CSQCFGR3_AC2T BIT(17) - #define FMC2_CSQCFGR3_AC3T BIT(18) -@@ -160,15 +159,15 @@ - #define FMC2_CSQCFGR3_RAC2T BIT(23) - - /* Register: FMC2_CSQCAR1 */ --#define FMC2_CSQCAR1_ADDC1(x) (((x) & 0xff) << 0) --#define FMC2_CSQCAR1_ADDC2(x) (((x) & 0xff) << 8) --#define FMC2_CSQCAR1_ADDC3(x) (((x) & 0xff) << 16) --#define FMC2_CSQCAR1_ADDC4(x) (((x) & 0xff) << 24) -+#define FMC2_CSQCAR1_ADDC1 GENMASK(7, 0) -+#define FMC2_CSQCAR1_ADDC2 GENMASK(15, 8) -+#define FMC2_CSQCAR1_ADDC3 GENMASK(23, 16) -+#define FMC2_CSQCAR1_ADDC4 GENMASK(31, 24) - - /* Register: FMC2_CSQCAR2 */ --#define FMC2_CSQCAR2_ADDC5(x) (((x) & 0xff) << 0) --#define FMC2_CSQCAR2_NANDCEN(x) (((x) & 0x3) << 10) --#define FMC2_CSQCAR2_SAO(x) (((x) & 0xffff) << 16) -+#define FMC2_CSQCAR2_ADDC5 GENMASK(7, 0) -+#define FMC2_CSQCAR2_NANDCEN GENMASK(11, 10) -+#define FMC2_CSQCAR2_SAO GENMASK(31, 16) - - /* Register: FMC2_CSQIER */ - #define FMC2_CSQIER_TCIE BIT(0) -@@ -189,28 +188,23 @@ - /* Register: FMC2_BCHDSR0 */ - #define FMC2_BCHDSR0_DUE BIT(0) - #define FMC2_BCHDSR0_DEF BIT(1) --#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4) --#define FMC2_BCHDSR0_DEN_SHIFT 4 -+#define FMC2_BCHDSR0_DEN GENMASK(7, 4) - - /* Register: FMC2_BCHDSR1 */ --#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0) --#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16) --#define FMC2_BCHDSR1_EBP2_SHIFT 16 -+#define FMC2_BCHDSR1_EBP1 GENMASK(12, 0) -+#define FMC2_BCHDSR1_EBP2 GENMASK(28, 16) - - /* Register: FMC2_BCHDSR2 */ --#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0) --#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16) --#define FMC2_BCHDSR2_EBP4_SHIFT 16 -+#define FMC2_BCHDSR2_EBP3 GENMASK(12, 0) -+#define FMC2_BCHDSR2_EBP4 GENMASK(28, 16) - - /* Register: FMC2_BCHDSR3 */ --#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0) --#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16) --#define FMC2_BCHDSR3_EBP6_SHIFT 16 -+#define FMC2_BCHDSR3_EBP5 GENMASK(12, 0) -+#define FMC2_BCHDSR3_EBP6 GENMASK(28, 16) - - /* Register: FMC2_BCHDSR4 */ --#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0) --#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16) --#define FMC2_BCHDSR4_EBP8_SHIFT 16 -+#define FMC2_BCHDSR4_EBP7 GENMASK(12, 0) -+#define FMC2_BCHDSR4_EBP8 GENMASK(28, 16) - - enum stm32_fmc2_ecc { - FMC2_ECC_HAM = 1, -@@ -251,7 +245,8 @@ struct stm32_fmc2_nfc { - struct nand_controller base; - struct stm32_fmc2_nand nand; - struct device *dev; -- void __iomem *io_base; -+ struct device *cdev; -+ struct regmap *regmap; - void __iomem *data_base[FMC2_MAX_CE]; - void __iomem *cmd_base[FMC2_MAX_CE]; - void __iomem *addr_base[FMC2_MAX_CE]; -@@ -281,47 +276,42 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_controller *base) - return container_of(base, struct stm32_fmc2_nfc, base); - } - --/* Timings configuration */ --static void stm32_fmc2_timings_init(struct nand_chip *chip) -+static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); - struct stm32_fmc2_timings *timings = &nand->timings; -- u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); - u32 pmem, patt; - - /* Set tclr/tar timings */ -- pcr &= ~FMC2_PCR_TCLR_MASK; -- pcr |= FMC2_PCR_TCLR(timings->tclr); -- pcr &= ~FMC2_PCR_TAR_MASK; -- pcr |= FMC2_PCR_TAR(timings->tar); -+ regmap_update_bits(nfc->regmap, FMC2_PCR, -+ FMC2_PCR_TCLR | FMC2_PCR_TAR, -+ FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) | -+ FIELD_PREP(FMC2_PCR_TAR, timings->tar)); - - /* Set tset/twait/thold/thiz timings in common bank */ -- pmem = FMC2_PMEM_MEMSET(timings->tset_mem); -- pmem |= FMC2_PMEM_MEMWAIT(timings->twait); -- pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem); -- pmem |= FMC2_PMEM_MEMHIZ(timings->thiz); -+ pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem); -+ pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait); -+ pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem); -+ pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz); -+ regmap_write(nfc->regmap, FMC2_PMEM, pmem); - - /* Set tset/twait/thold/thiz timings in attribut bank */ -- patt = FMC2_PATT_ATTSET(timings->tset_att); -- patt |= FMC2_PATT_ATTWAIT(timings->twait); -- patt |= FMC2_PATT_ATTHOLD(timings->thold_att); -- patt |= FMC2_PATT_ATTHIZ(timings->thiz); -- -- writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); -- writel_relaxed(pmem, fmc2->io_base + FMC2_PMEM); -- writel_relaxed(patt, fmc2->io_base + FMC2_PATT); -+ patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att); -+ patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait); -+ patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att); -+ patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz); -+ regmap_write(nfc->regmap, FMC2_PATT, patt); - } - --/* Controller configuration */ --static void stm32_fmc2_setup(struct nand_chip *chip) -+static void stm32_fmc2_nfc_setup(struct nand_chip *chip) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -- u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); -+ u32 pcr = 0, pcr_mask; - - /* Configure ECC algorithm (default configuration is Hamming) */ -- pcr &= ~FMC2_PCR_ECCALG; -- pcr &= ~FMC2_PCR_BCHECC; -+ pcr_mask = FMC2_PCR_ECCALG; -+ pcr_mask |= FMC2_PCR_BCHECC; - if (chip->ecc.strength == FMC2_ECC_BCH8) { - pcr |= FMC2_PCR_ECCALG; - pcr |= FMC2_PCR_BCHECC; -@@ -330,195 +320,159 @@ static void stm32_fmc2_setup(struct nand_chip *chip) - } - - /* Set buswidth */ -- pcr &= ~FMC2_PCR_PWID_MASK; -+ pcr_mask |= FMC2_PCR_PWID; - if (chip->options & NAND_BUSWIDTH_16) -- pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16); -+ pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16); - - /* Set ECC sector size */ -- pcr &= ~FMC2_PCR_ECCSS_MASK; -- pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); -+ pcr_mask |= FMC2_PCR_ECCSS; -+ pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512); - -- writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); -+ regmap_update_bits(nfc->regmap, FMC2_PCR, pcr_mask, pcr); - } - --/* Select target */ --static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr) -+static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); - struct dma_slave_config dma_cfg; - int ret; - -- if (nand->cs_used[chipnr] == fmc2->cs_sel) -+ if (nand->cs_used[chipnr] == nfc->cs_sel) - return 0; - -- fmc2->cs_sel = nand->cs_used[chipnr]; -- -- /* FMC2 setup routine */ -- stm32_fmc2_setup(chip); -+ nfc->cs_sel = nand->cs_used[chipnr]; -+ stm32_fmc2_nfc_setup(chip); -+ stm32_fmc2_nfc_timings_init(chip); - -- /* Apply timings */ -- stm32_fmc2_timings_init(chip); -- -- if (fmc2->dma_tx_ch && fmc2->dma_rx_ch) { -+ if (nfc->dma_tx_ch && nfc->dma_rx_ch) { - memset(&dma_cfg, 0, sizeof(dma_cfg)); -- dma_cfg.src_addr = fmc2->data_phys_addr[fmc2->cs_sel]; -- dma_cfg.dst_addr = fmc2->data_phys_addr[fmc2->cs_sel]; -+ dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel]; -+ dma_cfg.dst_addr = nfc->data_phys_addr[nfc->cs_sel]; - dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_cfg.src_maxburst = 32; - dma_cfg.dst_maxburst = 32; - -- ret = dmaengine_slave_config(fmc2->dma_tx_ch, &dma_cfg); -+ ret = dmaengine_slave_config(nfc->dma_tx_ch, &dma_cfg); - if (ret) { -- dev_err(fmc2->dev, "tx DMA engine slave config failed\n"); -+ dev_err(nfc->dev, "tx DMA engine slave config failed\n"); - return ret; - } - -- ret = dmaengine_slave_config(fmc2->dma_rx_ch, &dma_cfg); -+ ret = dmaengine_slave_config(nfc->dma_rx_ch, &dma_cfg); - if (ret) { -- dev_err(fmc2->dev, "rx DMA engine slave config failed\n"); -+ dev_err(nfc->dev, "rx DMA engine slave config failed\n"); - return ret; - } - } - -- if (fmc2->dma_ecc_ch) { -+ if (nfc->dma_ecc_ch) { - /* - * Hamming: we read HECCR register - * BCH4/BCH8: we read BCHDSRSx registers - */ - memset(&dma_cfg, 0, sizeof(dma_cfg)); -- dma_cfg.src_addr = fmc2->io_phys_addr; -+ dma_cfg.src_addr = nfc->io_phys_addr; - dma_cfg.src_addr += chip->ecc.strength == FMC2_ECC_HAM ? - FMC2_HECCR : FMC2_BCHDSR0; - dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - -- ret = dmaengine_slave_config(fmc2->dma_ecc_ch, &dma_cfg); -+ ret = dmaengine_slave_config(nfc->dma_ecc_ch, &dma_cfg); - if (ret) { -- dev_err(fmc2->dev, "ECC DMA engine slave config failed\n"); -+ dev_err(nfc->dev, "ECC DMA engine slave config failed\n"); - return ret; - } - - /* Calculate ECC length needed for one sector */ -- fmc2->dma_ecc_len = chip->ecc.strength == FMC2_ECC_HAM ? -- FMC2_HECCR_LEN : FMC2_BCHDSRS_LEN; -+ nfc->dma_ecc_len = chip->ecc.strength == FMC2_ECC_HAM ? -+ FMC2_HECCR_LEN : FMC2_BCHDSRS_LEN; - } - - return 0; - } - --/* Set bus width to 16-bit or 8-bit */ --static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set) -+static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc, bool set) - { -- u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); -+ u32 pcr; -+ -+ pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) : -+ FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8); - -- pcr &= ~FMC2_PCR_PWID_MASK; -- if (set) -- pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16); -- writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); -+ regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_PWID, pcr); - } - --/* Enable/disable ECC */ --static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable) -+static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable) - { -- u32 pcr = readl(fmc2->io_base + FMC2_PCR); -- -- pcr &= ~FMC2_PCR_ECCEN; -- if (enable) -- pcr |= FMC2_PCR_ECCEN; -- writel(pcr, fmc2->io_base + FMC2_PCR); -+ regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_ECCEN, -+ enable ? FMC2_PCR_ECCEN : 0); - } - --/* Enable irq sources in case of the sequencer is used */ --static inline void stm32_fmc2_enable_seq_irq(struct stm32_fmc2_nfc *fmc2) -+static void stm32_fmc2_nfc_enable_seq_irq(struct stm32_fmc2_nfc *nfc) - { -- u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER); -- -- csqier |= FMC2_CSQIER_TCIE; -- -- fmc2->irq_state = FMC2_IRQ_SEQ; -+ nfc->irq_state = FMC2_IRQ_SEQ; - -- writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER); -+ regmap_update_bits(nfc->regmap, FMC2_CSQIER, -+ FMC2_CSQIER_TCIE, FMC2_CSQIER_TCIE); - } - --/* Disable irq sources in case of the sequencer is used */ --static inline void stm32_fmc2_disable_seq_irq(struct stm32_fmc2_nfc *fmc2) -+static void stm32_fmc2_nfc_disable_seq_irq(struct stm32_fmc2_nfc *nfc) - { -- u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER); -+ regmap_update_bits(nfc->regmap, FMC2_CSQIER, FMC2_CSQIER_TCIE, 0); - -- csqier &= ~FMC2_CSQIER_TCIE; -- -- writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER); -- -- fmc2->irq_state = FMC2_IRQ_UNKNOWN; -+ nfc->irq_state = FMC2_IRQ_UNKNOWN; - } - --/* Clear irq sources in case of the sequencer is used */ --static inline void stm32_fmc2_clear_seq_irq(struct stm32_fmc2_nfc *fmc2) -+static void stm32_fmc2_nfc_clear_seq_irq(struct stm32_fmc2_nfc *nfc) - { -- writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, fmc2->io_base + FMC2_CSQICR); -+ regmap_write(nfc->regmap, FMC2_CSQICR, FMC2_CSQICR_CLEAR_IRQ); - } - --/* Enable irq sources in case of bch is used */ --static inline void stm32_fmc2_enable_bch_irq(struct stm32_fmc2_nfc *fmc2, -- int mode) -+static void stm32_fmc2_nfc_enable_bch_irq(struct stm32_fmc2_nfc *nfc, int mode) - { -- u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER); -+ nfc->irq_state = FMC2_IRQ_BCH; - - if (mode == NAND_ECC_WRITE) -- bchier |= FMC2_BCHIER_EPBRIE; -+ regmap_update_bits(nfc->regmap, FMC2_BCHIER, -+ FMC2_BCHIER_EPBRIE, FMC2_BCHIER_EPBRIE); - else -- bchier |= FMC2_BCHIER_DERIE; -- -- fmc2->irq_state = FMC2_IRQ_BCH; -- -- writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER); -+ regmap_update_bits(nfc->regmap, FMC2_BCHIER, -+ FMC2_BCHIER_DERIE, FMC2_BCHIER_DERIE); - } - --/* Disable irq sources in case of bch is used */ --static inline void stm32_fmc2_disable_bch_irq(struct stm32_fmc2_nfc *fmc2) -+static void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc) - { -- u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER); -+ regmap_update_bits(nfc->regmap, FMC2_BCHIER, -+ FMC2_BCHIER_DERIE | FMC2_BCHIER_EPBRIE, 0); - -- bchier &= ~FMC2_BCHIER_DERIE; -- bchier &= ~FMC2_BCHIER_EPBRIE; -- -- writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER); -- -- fmc2->irq_state = FMC2_IRQ_UNKNOWN; -+ nfc->irq_state = FMC2_IRQ_UNKNOWN; - } - --/* Clear irq sources in case of bch is used */ --static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2) -+static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc) - { -- writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR); -+ regmap_write(nfc->regmap, FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ); - } - - /* - * Enable ECC logic and reset syndrome/parity bits previously calculated - * Syndrome/parity bits is cleared by setting the ECCEN bit to 0 - */ --static void stm32_fmc2_hwctl(struct nand_chip *chip, int mode) -+static void stm32_fmc2_nfc_hwctl(struct nand_chip *chip, int mode) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - -- stm32_fmc2_set_ecc(fmc2, false); -+ stm32_fmc2_nfc_set_ecc(nfc, false); - - if (chip->ecc.strength != FMC2_ECC_HAM) { -- u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); -- -- if (mode == NAND_ECC_WRITE) -- pcr |= FMC2_PCR_WEN; -- else -- pcr &= ~FMC2_PCR_WEN; -- writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); -+ regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN, -+ mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0); - -- reinit_completion(&fmc2->complete); -- stm32_fmc2_clear_bch_irq(fmc2); -- stm32_fmc2_enable_bch_irq(fmc2, mode); -+ reinit_completion(&nfc->complete); -+ stm32_fmc2_nfc_clear_bch_irq(nfc); -+ stm32_fmc2_nfc_enable_bch_irq(nfc, mode); - } - -- stm32_fmc2_set_ecc(fmc2, true); -+ stm32_fmc2_nfc_set_ecc(nfc, true); - } - - /* -@@ -526,40 +480,37 @@ static void stm32_fmc2_hwctl(struct nand_chip *chip, int mode) - * ECC is 3 bytes for 512 bytes of data (supports error correction up to - * max of 1-bit) - */ --static inline void stm32_fmc2_ham_set_ecc(const u32 ecc_sta, u8 *ecc) -+static void stm32_fmc2_nfc_ham_set_ecc(const u32 ecc_sta, u8 *ecc) - { - ecc[0] = ecc_sta; - ecc[1] = ecc_sta >> 8; - ecc[2] = ecc_sta >> 16; - } - --static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data, -- u8 *ecc) -+static int stm32_fmc2_nfc_ham_calculate(struct nand_chip *chip, const u8 *data, -+ u8 *ecc) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - u32 sr, heccr; - int ret; - -- ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR, -- sr, sr & FMC2_SR_NWRF, 10, -- FMC2_TIMEOUT_MS); -+ ret = regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr, -+ sr & FMC2_SR_NWRF, 1, -+ 1000 * FMC2_TIMEOUT_MS); - if (ret) { -- dev_err(fmc2->dev, "ham timeout\n"); -+ dev_err(nfc->dev, "ham timeout\n"); - return ret; - } - -- heccr = readl_relaxed(fmc2->io_base + FMC2_HECCR); -- -- stm32_fmc2_ham_set_ecc(heccr, ecc); -- -- /* Disable ECC */ -- stm32_fmc2_set_ecc(fmc2, false); -+ regmap_read(nfc->regmap, FMC2_HECCR, &heccr); -+ stm32_fmc2_nfc_ham_set_ecc(heccr, ecc); -+ stm32_fmc2_nfc_set_ecc(nfc, false); - - return 0; - } - --static int stm32_fmc2_ham_correct(struct nand_chip *chip, u8 *dat, -- u8 *read_ecc, u8 *calc_ecc) -+static int stm32_fmc2_nfc_ham_correct(struct nand_chip *chip, u8 *dat, -+ u8 *read_ecc, u8 *calc_ecc) - { - u8 bit_position = 0, b0, b1, b2; - u32 byte_addr = 0, b; -@@ -615,28 +566,28 @@ static int stm32_fmc2_ham_correct(struct nand_chip *chip, u8 *dat, - * ECC is 7/13 bytes for 512 bytes of data (supports error correction up to - * max of 4-bit/8-bit) - */ --static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data, -- u8 *ecc) -+static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data, -+ u8 *ecc) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - u32 bchpbr; - - /* Wait until the BCH code is ready */ -- if (!wait_for_completion_timeout(&fmc2->complete, -+ if (!wait_for_completion_timeout(&nfc->complete, - msecs_to_jiffies(FMC2_TIMEOUT_MS))) { -- dev_err(fmc2->dev, "bch timeout\n"); -- stm32_fmc2_disable_bch_irq(fmc2); -+ dev_err(nfc->dev, "bch timeout\n"); -+ stm32_fmc2_nfc_disable_bch_irq(nfc); - return -ETIMEDOUT; - } - - /* Read parity bits */ -- bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR1); -+ regmap_read(nfc->regmap, FMC2_BCHPBR1, &bchpbr); - ecc[0] = bchpbr; - ecc[1] = bchpbr >> 8; - ecc[2] = bchpbr >> 16; - ecc[3] = bchpbr >> 24; - -- bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR2); -+ regmap_read(nfc->regmap, FMC2_BCHPBR2, &bchpbr); - ecc[4] = bchpbr; - ecc[5] = bchpbr >> 8; - ecc[6] = bchpbr >> 16; -@@ -644,24 +595,22 @@ static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data, - if (chip->ecc.strength == FMC2_ECC_BCH8) { - ecc[7] = bchpbr >> 24; - -- bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR3); -+ regmap_read(nfc->regmap, FMC2_BCHPBR3, &bchpbr); - ecc[8] = bchpbr; - ecc[9] = bchpbr >> 8; - ecc[10] = bchpbr >> 16; - ecc[11] = bchpbr >> 24; - -- bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR4); -+ regmap_read(nfc->regmap, FMC2_BCHPBR4, &bchpbr); - ecc[12] = bchpbr; - } - -- /* Disable ECC */ -- stm32_fmc2_set_ecc(fmc2, false); -+ stm32_fmc2_nfc_set_ecc(nfc, false); - - return 0; - } - --/* BCH algorithm correction */ --static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta) -+static int stm32_fmc2_nfc_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta) - { - u32 bchdsr0 = ecc_sta[0]; - u32 bchdsr1 = ecc_sta[1]; -@@ -680,16 +629,16 @@ static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta) - if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE)) - return -EBADMSG; - -- pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; -- pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; -- pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; -- pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; -- pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; -- pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; -- pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; -- pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; -+ pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1); -+ pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1); -+ pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2); -+ pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2); -+ pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3); -+ pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3); -+ pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4); -+ pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4); - -- den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; -+ den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0); - for (i = 0; i < den; i++) { - if (pos[i] < eccsize * 8) { - change_bit(pos[i], (unsigned long *)dat); -@@ -700,34 +649,29 @@ static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta) - return nb_errs; - } - --static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat, -- u8 *read_ecc, u8 *calc_ecc) -+static int stm32_fmc2_nfc_bch_correct(struct nand_chip *chip, u8 *dat, -+ u8 *read_ecc, u8 *calc_ecc) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - u32 ecc_sta[5]; - - /* Wait until the decoding error is ready */ -- if (!wait_for_completion_timeout(&fmc2->complete, -+ if (!wait_for_completion_timeout(&nfc->complete, - msecs_to_jiffies(FMC2_TIMEOUT_MS))) { -- dev_err(fmc2->dev, "bch timeout\n"); -- stm32_fmc2_disable_bch_irq(fmc2); -+ dev_err(nfc->dev, "bch timeout\n"); -+ stm32_fmc2_nfc_disable_bch_irq(nfc); - return -ETIMEDOUT; - } - -- ecc_sta[0] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR0); -- ecc_sta[1] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR1); -- ecc_sta[2] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR2); -- ecc_sta[3] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR3); -- ecc_sta[4] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR4); -+ regmap_bulk_read(nfc->regmap, FMC2_BCHDSR0, ecc_sta, 5); - -- /* Disable ECC */ -- stm32_fmc2_set_ecc(fmc2, false); -+ stm32_fmc2_nfc_set_ecc(nfc, false); - -- return stm32_fmc2_bch_decode(chip->ecc.size, dat, ecc_sta); -+ return stm32_fmc2_nfc_bch_decode(chip->ecc.size, dat, ecc_sta); - } - --static int stm32_fmc2_read_page(struct nand_chip *chip, u8 *buf, -- int oob_required, int page) -+static int stm32_fmc2_nfc_read_page(struct nand_chip *chip, u8 *buf, -+ int oob_required, int page) - { - struct mtd_info *mtd = nand_to_mtd(chip); - int ret, i, s, stat, eccsize = chip->ecc.size; -@@ -789,35 +733,34 @@ static int stm32_fmc2_read_page(struct nand_chip *chip, u8 *buf, - } - - /* Sequencer read/write configuration */ --static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page, -- int raw, bool write_data) -+static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page, -+ int raw, bool write_data) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - struct mtd_info *mtd = nand_to_mtd(chip); -- u32 csqcfgr1, csqcfgr2, csqcfgr3; -- u32 csqar1, csqar2; - u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN; -- u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); -+ /* -+ * cfg[0] => csqcfgr1, cfg[1] => csqcfgr2, cfg[2] => csqcfgr3 -+ * cfg[3] => csqar1, cfg[4] => csqar2 -+ */ -+ u32 cfg[5]; - -- if (write_data) -- pcr |= FMC2_PCR_WEN; -- else -- pcr &= ~FMC2_PCR_WEN; -- writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); -+ regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN, -+ write_data ? FMC2_PCR_WEN : 0); - - /* - * - Set Program Page/Page Read command - * - Enable DMA request data - * - Set timings - */ -- csqcfgr1 = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T; -+ cfg[0] = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T; - if (write_data) -- csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_SEQIN); -+ cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_SEQIN); - else -- csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_READ0) | -- FMC2_CSQCFGR1_CMD2EN | -- FMC2_CSQCFGR1_CMD2(NAND_CMD_READSTART) | -- FMC2_CSQCFGR1_CMD2T; -+ cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_READ0) | -+ FMC2_CSQCFGR1_CMD2EN | -+ FIELD_PREP(FMC2_CSQCFGR1_CMD2, NAND_CMD_READSTART) | -+ FMC2_CSQCFGR1_CMD2T; - - /* - * - Set Random Data Input/Random Data Read command -@@ -826,29 +769,29 @@ static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page, - * - Set timings - */ - if (write_data) -- csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDIN); -+ cfg[1] = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDIN); - else -- csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDOUT) | -- FMC2_CSQCFGR2_RCMD2EN | -- FMC2_CSQCFGR2_RCMD2(NAND_CMD_RNDOUTSTART) | -- FMC2_CSQCFGR2_RCMD1T | -- FMC2_CSQCFGR2_RCMD2T; -+ cfg[1] = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDOUT) | -+ FMC2_CSQCFGR2_RCMD2EN | -+ FIELD_PREP(FMC2_CSQCFGR2_RCMD2, NAND_CMD_RNDOUTSTART) | -+ FMC2_CSQCFGR2_RCMD1T | -+ FMC2_CSQCFGR2_RCMD2T; - if (!raw) { -- csqcfgr2 |= write_data ? 0 : FMC2_CSQCFGR2_DMASEN; -- csqcfgr2 |= FMC2_CSQCFGR2_SQSDTEN; -+ cfg[1] |= write_data ? 0 : FMC2_CSQCFGR2_DMASEN; -+ cfg[1] |= FMC2_CSQCFGR2_SQSDTEN; - } - - /* - * - Set the number of sectors to be written - * - Set timings - */ -- csqcfgr3 = FMC2_CSQCFGR3_SNBR(chip->ecc.steps - 1); -+ cfg[2] = FIELD_PREP(FMC2_CSQCFGR3_SNBR, chip->ecc.steps - 1); - if (write_data) { -- csqcfgr3 |= FMC2_CSQCFGR3_RAC2T; -+ cfg[2] |= FMC2_CSQCFGR3_RAC2T; - if (chip->options & NAND_ROW_ADDR_3) -- csqcfgr3 |= FMC2_CSQCFGR3_AC5T; -+ cfg[2] |= FMC2_CSQCFGR3_AC5T; - else -- csqcfgr3 |= FMC2_CSQCFGR3_AC4T; -+ cfg[2] |= FMC2_CSQCFGR3_AC4T; - } - - /* -@@ -856,8 +799,8 @@ static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page, - * Byte 1 and byte 2 => column, we start at 0x0 - * Byte 3 and byte 4 => page - */ -- csqar1 = FMC2_CSQCAR1_ADDC3(page); -- csqar1 |= FMC2_CSQCAR1_ADDC4(page >> 8); -+ cfg[3] = FIELD_PREP(FMC2_CSQCAR1_ADDC3, page); -+ cfg[3] |= FIELD_PREP(FMC2_CSQCAR1_ADDC4, page >> 8); - - /* - * - Set chip enable number -@@ -865,43 +808,39 @@ static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page, - * - Calculate the number of address cycles to be issued - * - Set byte 5 of address cycle if needed - */ -- csqar2 = FMC2_CSQCAR2_NANDCEN(fmc2->cs_sel); -+ cfg[4] = FIELD_PREP(FMC2_CSQCAR2_NANDCEN, nfc->cs_sel); - if (chip->options & NAND_BUSWIDTH_16) -- csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset >> 1); -+ cfg[4] |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset >> 1); - else -- csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset); -+ cfg[4] |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset); - if (chip->options & NAND_ROW_ADDR_3) { -- csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(5); -- csqar2 |= FMC2_CSQCAR2_ADDC5(page >> 16); -+ cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 5); -+ cfg[4] |= FIELD_PREP(FMC2_CSQCAR2_ADDC5, page >> 16); - } else { -- csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(4); -+ cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 4); - } - -- writel_relaxed(csqcfgr1, fmc2->io_base + FMC2_CSQCFGR1); -- writel_relaxed(csqcfgr2, fmc2->io_base + FMC2_CSQCFGR2); -- writel_relaxed(csqcfgr3, fmc2->io_base + FMC2_CSQCFGR3); -- writel_relaxed(csqar1, fmc2->io_base + FMC2_CSQAR1); -- writel_relaxed(csqar2, fmc2->io_base + FMC2_CSQAR2); -+ regmap_bulk_write(nfc->regmap, FMC2_CSQCFGR1, cfg, 5); - } - --static void stm32_fmc2_dma_callback(void *arg) -+static void stm32_fmc2_nfc_dma_callback(void *arg) - { - complete((struct completion *)arg); - } - - /* Read/write data from/to a page */ --static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, -- int raw, bool write_data) -+static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, -+ int raw, bool write_data) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - struct dma_async_tx_descriptor *desc_data, *desc_ecc; - struct scatterlist *sg; -- struct dma_chan *dma_ch = fmc2->dma_rx_ch; -+ struct dma_chan *dma_ch = nfc->dma_rx_ch; - enum dma_data_direction dma_data_dir = DMA_FROM_DEVICE; - enum dma_transfer_direction dma_transfer_dir = DMA_DEV_TO_MEM; -- u32 csqcr = readl_relaxed(fmc2->io_base + FMC2_CSQCR); - int eccsteps = chip->ecc.steps; - int eccsize = chip->ecc.size; -+ unsigned long timeout = msecs_to_jiffies(FMC2_TIMEOUT_MS); - const u8 *p = buf; - int s, ret; - -@@ -909,20 +848,20 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, - if (write_data) { - dma_data_dir = DMA_TO_DEVICE; - dma_transfer_dir = DMA_MEM_TO_DEV; -- dma_ch = fmc2->dma_tx_ch; -+ dma_ch = nfc->dma_tx_ch; - } - -- for_each_sg(fmc2->dma_data_sg.sgl, sg, eccsteps, s) { -+ for_each_sg(nfc->dma_data_sg.sgl, sg, eccsteps, s) { - sg_set_buf(sg, p, eccsize); - p += eccsize; - } - -- ret = dma_map_sg(fmc2->dev, fmc2->dma_data_sg.sgl, -+ ret = dma_map_sg(nfc->dev, nfc->dma_data_sg.sgl, - eccsteps, dma_data_dir); - if (ret < 0) - return ret; - -- desc_data = dmaengine_prep_slave_sg(dma_ch, fmc2->dma_data_sg.sgl, -+ desc_data = dmaengine_prep_slave_sg(dma_ch, nfc->dma_data_sg.sgl, - eccsteps, dma_transfer_dir, - DMA_PREP_INTERRUPT); - if (!desc_data) { -@@ -930,10 +869,10 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, - goto err_unmap_data; - } - -- reinit_completion(&fmc2->dma_data_complete); -- reinit_completion(&fmc2->complete); -- desc_data->callback = stm32_fmc2_dma_callback; -- desc_data->callback_param = &fmc2->dma_data_complete; -+ reinit_completion(&nfc->dma_data_complete); -+ reinit_completion(&nfc->complete); -+ desc_data->callback = stm32_fmc2_nfc_dma_callback; -+ desc_data->callback_param = &nfc->dma_data_complete; - ret = dma_submit_error(dmaengine_submit(desc_data)); - if (ret) - goto err_unmap_data; -@@ -942,19 +881,19 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, - - if (!write_data && !raw) { - /* Configure DMA ECC status */ -- p = fmc2->ecc_buf; -- for_each_sg(fmc2->dma_ecc_sg.sgl, sg, eccsteps, s) { -- sg_set_buf(sg, p, fmc2->dma_ecc_len); -- p += fmc2->dma_ecc_len; -+ p = nfc->ecc_buf; -+ for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) { -+ sg_set_buf(sg, p, nfc->dma_ecc_len); -+ p += nfc->dma_ecc_len; - } - -- ret = dma_map_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl, -+ ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl, - eccsteps, dma_data_dir); - if (ret < 0) - goto err_unmap_data; - -- desc_ecc = dmaengine_prep_slave_sg(fmc2->dma_ecc_ch, -- fmc2->dma_ecc_sg.sgl, -+ desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch, -+ nfc->dma_ecc_sg.sgl, - eccsteps, dma_transfer_dir, - DMA_PREP_INTERRUPT); - if (!desc_ecc) { -@@ -962,76 +901,73 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, - goto err_unmap_ecc; - } - -- reinit_completion(&fmc2->dma_ecc_complete); -- desc_ecc->callback = stm32_fmc2_dma_callback; -- desc_ecc->callback_param = &fmc2->dma_ecc_complete; -+ reinit_completion(&nfc->dma_ecc_complete); -+ desc_ecc->callback = stm32_fmc2_nfc_dma_callback; -+ desc_ecc->callback_param = &nfc->dma_ecc_complete; - ret = dma_submit_error(dmaengine_submit(desc_ecc)); - if (ret) - goto err_unmap_ecc; - -- dma_async_issue_pending(fmc2->dma_ecc_ch); -+ dma_async_issue_pending(nfc->dma_ecc_ch); - } - -- stm32_fmc2_clear_seq_irq(fmc2); -- stm32_fmc2_enable_seq_irq(fmc2); -+ stm32_fmc2_nfc_clear_seq_irq(nfc); -+ stm32_fmc2_nfc_enable_seq_irq(nfc); - - /* Start the transfer */ -- csqcr |= FMC2_CSQCR_CSQSTART; -- writel_relaxed(csqcr, fmc2->io_base + FMC2_CSQCR); -+ regmap_update_bits(nfc->regmap, FMC2_CSQCR, -+ FMC2_CSQCR_CSQSTART, FMC2_CSQCR_CSQSTART); - - /* Wait end of sequencer transfer */ -- if (!wait_for_completion_timeout(&fmc2->complete, -- msecs_to_jiffies(FMC2_TIMEOUT_MS))) { -- dev_err(fmc2->dev, "seq timeout\n"); -- stm32_fmc2_disable_seq_irq(fmc2); -+ if (!wait_for_completion_timeout(&nfc->complete, timeout)) { -+ dev_err(nfc->dev, "seq timeout\n"); -+ stm32_fmc2_nfc_disable_seq_irq(nfc); - dmaengine_terminate_all(dma_ch); - if (!write_data && !raw) -- dmaengine_terminate_all(fmc2->dma_ecc_ch); -+ dmaengine_terminate_all(nfc->dma_ecc_ch); - ret = -ETIMEDOUT; - goto err_unmap_ecc; - } - - /* Wait DMA data transfer completion */ -- if (!wait_for_completion_timeout(&fmc2->dma_data_complete, -- msecs_to_jiffies(FMC2_TIMEOUT_MS))) { -- dev_err(fmc2->dev, "data DMA timeout\n"); -+ if (!wait_for_completion_timeout(&nfc->dma_data_complete, timeout)) { -+ dev_err(nfc->dev, "data DMA timeout\n"); - dmaengine_terminate_all(dma_ch); - ret = -ETIMEDOUT; - } - - /* Wait DMA ECC transfer completion */ - if (!write_data && !raw) { -- if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete, -- msecs_to_jiffies(FMC2_TIMEOUT_MS))) { -- dev_err(fmc2->dev, "ECC DMA timeout\n"); -- dmaengine_terminate_all(fmc2->dma_ecc_ch); -+ if (!wait_for_completion_timeout(&nfc->dma_ecc_complete, -+ timeout)) { -+ dev_err(nfc->dev, "ECC DMA timeout\n"); -+ dmaengine_terminate_all(nfc->dma_ecc_ch); - ret = -ETIMEDOUT; - } - } - - err_unmap_ecc: - if (!write_data && !raw) -- dma_unmap_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl, -+ dma_unmap_sg(nfc->dev, nfc->dma_ecc_sg.sgl, - eccsteps, dma_data_dir); - - err_unmap_data: -- dma_unmap_sg(fmc2->dev, fmc2->dma_data_sg.sgl, eccsteps, dma_data_dir); -+ dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir); - - return ret; - } - --static int stm32_fmc2_sequencer_write(struct nand_chip *chip, -- const u8 *buf, int oob_required, -- int page, int raw) -+static int stm32_fmc2_nfc_seq_write(struct nand_chip *chip, const u8 *buf, -+ int oob_required, int page, int raw) - { - struct mtd_info *mtd = nand_to_mtd(chip); - int ret; - - /* Configure the sequencer */ -- stm32_fmc2_rw_page_init(chip, page, raw, true); -+ stm32_fmc2_nfc_rw_page_init(chip, page, raw, true); - - /* Write the page */ -- ret = stm32_fmc2_xfer(chip, buf, raw, true); -+ ret = stm32_fmc2_nfc_xfer(chip, buf, raw, true); - if (ret) - return ret; - -@@ -1047,55 +983,52 @@ static int stm32_fmc2_sequencer_write(struct nand_chip *chip, - return nand_prog_page_end_op(chip); - } - --static int stm32_fmc2_sequencer_write_page(struct nand_chip *chip, -- const u8 *buf, -- int oob_required, -- int page) -+static int stm32_fmc2_nfc_seq_write_page(struct nand_chip *chip, const u8 *buf, -+ int oob_required, int page) - { - int ret; - -- /* Select the target */ -- ret = stm32_fmc2_select_chip(chip, chip->cur_cs); -+ ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs); - if (ret) - return ret; - -- return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, false); -+ return stm32_fmc2_nfc_seq_write(chip, buf, oob_required, page, false); - } - --static int stm32_fmc2_sequencer_write_page_raw(struct nand_chip *chip, -- const u8 *buf, -- int oob_required, -- int page) -+static int stm32_fmc2_nfc_seq_write_page_raw(struct nand_chip *chip, -+ const u8 *buf, int oob_required, -+ int page) - { - int ret; - -- /* Select the target */ -- ret = stm32_fmc2_select_chip(chip, chip->cur_cs); -+ ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs); - if (ret) - return ret; - -- return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, true); -+ return stm32_fmc2_nfc_seq_write(chip, buf, oob_required, page, true); - } - - /* Get a status indicating which sectors have errors */ --static inline u16 stm32_fmc2_get_mapping_status(struct stm32_fmc2_nfc *fmc2) -+static u16 stm32_fmc2_nfc_get_mapping_status(struct stm32_fmc2_nfc *nfc) - { -- u32 csqemsr = readl_relaxed(fmc2->io_base + FMC2_CSQEMSR); -+ u32 csqemsr; - -- return csqemsr & FMC2_CSQEMSR_SEM; -+ regmap_read(nfc->regmap, FMC2_CSQEMSR, &csqemsr); -+ -+ return FIELD_GET(FMC2_CSQEMSR_SEM, csqemsr); - } - --static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat, -- u8 *read_ecc, u8 *calc_ecc) -+static int stm32_fmc2_nfc_seq_correct(struct nand_chip *chip, u8 *dat, -+ u8 *read_ecc, u8 *calc_ecc) - { - struct mtd_info *mtd = nand_to_mtd(chip); -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - int eccbytes = chip->ecc.bytes; - int eccsteps = chip->ecc.steps; - int eccstrength = chip->ecc.strength; - int i, s, eccsize = chip->ecc.size; -- u32 *ecc_sta = (u32 *)fmc2->ecc_buf; -- u16 sta_map = stm32_fmc2_get_mapping_status(fmc2); -+ u32 *ecc_sta = (u32 *)nfc->ecc_buf; -+ u16 sta_map = stm32_fmc2_nfc_get_mapping_status(nfc); - unsigned int max_bitflips = 0; - - for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, dat += eccsize) { -@@ -1104,10 +1037,11 @@ static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat, - if (eccstrength == FMC2_ECC_HAM) { - /* Ecc_sta = FMC2_HECCR */ - if (sta_map & BIT(s)) { -- stm32_fmc2_ham_set_ecc(*ecc_sta, &calc_ecc[i]); -- stat = stm32_fmc2_ham_correct(chip, dat, -- &read_ecc[i], -- &calc_ecc[i]); -+ stm32_fmc2_nfc_ham_set_ecc(*ecc_sta, -+ &calc_ecc[i]); -+ stat = stm32_fmc2_nfc_ham_correct(chip, dat, -+ &read_ecc[i], -+ &calc_ecc[i]); - } - ecc_sta++; - } else { -@@ -1119,8 +1053,8 @@ static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat, - * Ecc_sta[4] = FMC2_BCHDSR4 - */ - if (sta_map & BIT(s)) -- stat = stm32_fmc2_bch_decode(eccsize, dat, -- ecc_sta); -+ stat = stm32_fmc2_nfc_bch_decode(eccsize, dat, -+ ecc_sta); - ecc_sta += 5; - } - -@@ -1143,30 +1077,29 @@ static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat, - return max_bitflips; - } - --static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf, -- int oob_required, int page) -+static int stm32_fmc2_nfc_seq_read_page(struct nand_chip *chip, u8 *buf, -+ int oob_required, int page) - { - struct mtd_info *mtd = nand_to_mtd(chip); -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - u8 *ecc_calc = chip->ecc.calc_buf; - u8 *ecc_code = chip->ecc.code_buf; - u16 sta_map; - int ret; - -- /* Select the target */ -- ret = stm32_fmc2_select_chip(chip, chip->cur_cs); -+ ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs); - if (ret) - return ret; - - /* Configure the sequencer */ -- stm32_fmc2_rw_page_init(chip, page, 0, false); -+ stm32_fmc2_nfc_rw_page_init(chip, page, 0, false); - - /* Read the page */ -- ret = stm32_fmc2_xfer(chip, buf, 0, false); -+ ret = stm32_fmc2_nfc_xfer(chip, buf, 0, false); - if (ret) - return ret; - -- sta_map = stm32_fmc2_get_mapping_status(fmc2); -+ sta_map = stm32_fmc2_nfc_get_mapping_status(nfc); - - /* Check if errors happen */ - if (likely(!sta_map)) { -@@ -1193,22 +1126,21 @@ static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf, - return chip->ecc.correct(chip, buf, ecc_code, ecc_calc); - } - --static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf, -- int oob_required, int page) -+static int stm32_fmc2_nfc_seq_read_page_raw(struct nand_chip *chip, u8 *buf, -+ int oob_required, int page) - { - struct mtd_info *mtd = nand_to_mtd(chip); - int ret; - -- /* Select the target */ -- ret = stm32_fmc2_select_chip(chip, chip->cur_cs); -+ ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs); - if (ret) - return ret; - - /* Configure the sequencer */ -- stm32_fmc2_rw_page_init(chip, page, 1, false); -+ stm32_fmc2_nfc_rw_page_init(chip, page, 1, false); - - /* Read the page */ -- ret = stm32_fmc2_xfer(chip, buf, 1, false); -+ ret = stm32_fmc2_nfc_xfer(chip, buf, 1, false); - if (ret) - return ret; - -@@ -1221,31 +1153,31 @@ static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf, - return 0; - } - --static irqreturn_t stm32_fmc2_irq(int irq, void *dev_id) -+static irqreturn_t stm32_fmc2_nfc_irq(int irq, void *dev_id) - { -- struct stm32_fmc2_nfc *fmc2 = (struct stm32_fmc2_nfc *)dev_id; -+ struct stm32_fmc2_nfc *nfc = (struct stm32_fmc2_nfc *)dev_id; - -- if (fmc2->irq_state == FMC2_IRQ_SEQ) -+ if (nfc->irq_state == FMC2_IRQ_SEQ) - /* Sequencer is used */ -- stm32_fmc2_disable_seq_irq(fmc2); -- else if (fmc2->irq_state == FMC2_IRQ_BCH) -+ stm32_fmc2_nfc_disable_seq_irq(nfc); -+ else if (nfc->irq_state == FMC2_IRQ_BCH) - /* BCH is used */ -- stm32_fmc2_disable_bch_irq(fmc2); -+ stm32_fmc2_nfc_disable_bch_irq(nfc); - -- complete(&fmc2->complete); -+ complete(&nfc->complete); - - return IRQ_HANDLED; - } - --static void stm32_fmc2_read_data(struct nand_chip *chip, void *buf, -- unsigned int len, bool force_8bit) -+static void stm32_fmc2_nfc_read_data(struct nand_chip *chip, void *buf, -+ unsigned int len, bool force_8bit) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -- void __iomem *io_addr_r = fmc2->data_base[fmc2->cs_sel]; -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); -+ void __iomem *io_addr_r = nfc->data_base[nfc->cs_sel]; - - if (force_8bit && chip->options & NAND_BUSWIDTH_16) - /* Reconfigure bus width to 8-bit */ -- stm32_fmc2_set_buswidth_16(fmc2, false); -+ stm32_fmc2_nfc_set_buswidth_16(nfc, false); - - if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) { - if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) { -@@ -1281,18 +1213,18 @@ static void stm32_fmc2_read_data(struct nand_chip *chip, void *buf, - - if (force_8bit && chip->options & NAND_BUSWIDTH_16) - /* Reconfigure bus width to 16-bit */ -- stm32_fmc2_set_buswidth_16(fmc2, true); -+ stm32_fmc2_nfc_set_buswidth_16(nfc, true); - } - --static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf, -- unsigned int len, bool force_8bit) -+static void stm32_fmc2_nfc_write_data(struct nand_chip *chip, const void *buf, -+ unsigned int len, bool force_8bit) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -- void __iomem *io_addr_w = fmc2->data_base[fmc2->cs_sel]; -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); -+ void __iomem *io_addr_w = nfc->data_base[nfc->cs_sel]; - - if (force_8bit && chip->options & NAND_BUSWIDTH_16) - /* Reconfigure bus width to 8-bit */ -- stm32_fmc2_set_buswidth_16(fmc2, false); -+ stm32_fmc2_nfc_set_buswidth_16(nfc, false); - - if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) { - if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) { -@@ -1328,44 +1260,45 @@ static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf, - - if (force_8bit && chip->options & NAND_BUSWIDTH_16) - /* Reconfigure bus width to 16-bit */ -- stm32_fmc2_set_buswidth_16(fmc2, true); -+ stm32_fmc2_nfc_set_buswidth_16(nfc, true); - } - --static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) -+static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip, -+ unsigned long timeout_ms) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - const struct nand_sdr_timings *timings; - u32 isr, sr; - - /* Check if there is no pending requests to the NAND flash */ -- if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr, -- sr & FMC2_SR_NWRF, 1, -- FMC2_TIMEOUT_US)) -- dev_warn(fmc2->dev, "Waitrdy timeout\n"); -+ if (regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr, -+ sr & FMC2_SR_NWRF, 1, -+ 1000 * FMC2_TIMEOUT_MS)) -+ dev_warn(nfc->dev, "Waitrdy timeout\n"); - - /* Wait tWB before R/B# signal is low */ - timings = nand_get_sdr_timings(&chip->data_interface); - ndelay(PSEC_TO_NSEC(timings->tWB_max)); - - /* R/B# signal is low, clear high level flag */ -- writel_relaxed(FMC2_ICR_CIHLF, fmc2->io_base + FMC2_ICR); -+ regmap_write(nfc->regmap, FMC2_ICR, FMC2_ICR_CIHLF); - - /* Wait R/B# signal is high */ -- return readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_ISR, -- isr, isr & FMC2_ISR_IHLF, -- 5, 1000 * timeout_ms); -+ return regmap_read_poll_timeout(nfc->regmap, FMC2_ISR, isr, -+ isr & FMC2_ISR_IHLF, 5, -+ 1000 * FMC2_TIMEOUT_MS); - } - --static int stm32_fmc2_exec_op(struct nand_chip *chip, -- const struct nand_operation *op, -- bool check_only) -+static int stm32_fmc2_nfc_exec_op(struct nand_chip *chip, -+ const struct nand_operation *op, -+ bool check_only) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - const struct nand_op_instr *instr = NULL; -- unsigned int op_id, i; -+ unsigned int op_id, i, timeout; - int ret; - -- ret = stm32_fmc2_select_chip(chip, op->cs); -+ ret = stm32_fmc2_nfc_select_chip(chip, op->cs); - if (ret) - return ret; - -@@ -1378,30 +1311,30 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip, - switch (instr->type) { - case NAND_OP_CMD_INSTR: - writeb_relaxed(instr->ctx.cmd.opcode, -- fmc2->cmd_base[fmc2->cs_sel]); -+ nfc->cmd_base[nfc->cs_sel]); - break; - - case NAND_OP_ADDR_INSTR: - for (i = 0; i < instr->ctx.addr.naddrs; i++) - writeb_relaxed(instr->ctx.addr.addrs[i], -- fmc2->addr_base[fmc2->cs_sel]); -+ nfc->addr_base[nfc->cs_sel]); - break; - - case NAND_OP_DATA_IN_INSTR: -- stm32_fmc2_read_data(chip, instr->ctx.data.buf.in, -- instr->ctx.data.len, -- instr->ctx.data.force_8bit); -+ stm32_fmc2_nfc_read_data(chip, instr->ctx.data.buf.in, -+ instr->ctx.data.len, -+ instr->ctx.data.force_8bit); - break; - - case NAND_OP_DATA_OUT_INSTR: -- stm32_fmc2_write_data(chip, instr->ctx.data.buf.out, -- instr->ctx.data.len, -- instr->ctx.data.force_8bit); -+ stm32_fmc2_nfc_write_data(chip, instr->ctx.data.buf.out, -+ instr->ctx.data.len, -+ instr->ctx.data.force_8bit); - break; - - case NAND_OP_WAITRDY_INSTR: -- ret = stm32_fmc2_waitrdy(chip, -- instr->ctx.waitrdy.timeout_ms); -+ timeout = instr->ctx.waitrdy.timeout_ms; -+ ret = stm32_fmc2_nfc_waitrdy(chip, timeout); - break; - } - } -@@ -1409,21 +1342,21 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip, - return ret; - } - --/* Controller initialization */ --static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2) -+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc) - { -- u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR); -- u32 bcr1 = readl_relaxed(fmc2->io_base + FMC2_BCR1); -+ u32 pcr; -+ -+ regmap_read(nfc->regmap, FMC2_PCR, &pcr); - - /* Set CS used to undefined */ -- fmc2->cs_sel = -1; -+ nfc->cs_sel = -1; - - /* Enable wait feature and nand flash memory bank */ - pcr |= FMC2_PCR_PWAITEN; - pcr |= FMC2_PCR_PBKEN; - - /* Set buswidth to 8 bits mode for identification */ -- pcr &= ~FMC2_PCR_PWID_MASK; -+ pcr &= ~FMC2_PCR_PWID; - - /* ECC logic is disabled */ - pcr &= ~FMC2_PCR_ECCEN; -@@ -1434,32 +1367,32 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2) - pcr &= ~FMC2_PCR_WEN; - - /* Set default ECC sector size */ -- pcr &= ~FMC2_PCR_ECCSS_MASK; -- pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); -+ pcr &= ~FMC2_PCR_ECCSS; -+ pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048); - - /* Set default tclr/tar timings */ -- pcr &= ~FMC2_PCR_TCLR_MASK; -- pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); -- pcr &= ~FMC2_PCR_TAR_MASK; -- pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); -+ pcr &= ~FMC2_PCR_TCLR; -+ pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT); -+ pcr &= ~FMC2_PCR_TAR; -+ pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT); - - /* Enable FMC2 controller */ -- bcr1 |= FMC2_BCR1_FMC2EN; -+ if (nfc->dev == nfc->cdev) -+ regmap_update_bits(nfc->regmap, FMC2_BCR1, -+ FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN); - -- writel_relaxed(bcr1, fmc2->io_base + FMC2_BCR1); -- writel_relaxed(pcr, fmc2->io_base + FMC2_PCR); -- writel_relaxed(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM); -- writel_relaxed(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT); -+ regmap_write(nfc->regmap, FMC2_PCR, pcr); -+ regmap_write(nfc->regmap, FMC2_PMEM, FMC2_PMEM_DEFAULT); -+ regmap_write(nfc->regmap, FMC2_PATT, FMC2_PATT_DEFAULT); - } - --/* Controller timings */ --static void stm32_fmc2_calc_timings(struct nand_chip *chip, -- const struct nand_sdr_timings *sdrt) -+static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip, -+ const struct nand_sdr_timings *sdrt) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); - struct stm32_fmc2_timings *tims = &nand->timings; -- unsigned long hclk = clk_get_rate(fmc2->clk); -+ unsigned long hclk = clk_get_rate(nfc->clk); - unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000); - unsigned long timing, tar, tclr, thiz, twait; - unsigned long tset_mem, tset_att, thold_mem, thold_att; -@@ -1583,8 +1516,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, - tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK); - } - --static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr, -- const struct nand_data_interface *conf) -+static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr, -+ const struct nand_data_interface *conf) - { - const struct nand_sdr_timings *sdrt; - -@@ -1595,77 +1528,102 @@ static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr, - if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) - return 0; - -- stm32_fmc2_calc_timings(chip, sdrt); -- -- /* Apply timings */ -- stm32_fmc2_timings_init(chip); -+ stm32_fmc2_nfc_calc_timings(chip, sdrt); -+ stm32_fmc2_nfc_timings_init(chip); - - return 0; - } - --/* DMA configuration */ --static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2) -+static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) - { -- int ret; -+ int ret = 0; - -- fmc2->dma_tx_ch = dma_request_slave_channel(fmc2->dev, "tx"); -- fmc2->dma_rx_ch = dma_request_slave_channel(fmc2->dev, "rx"); -- fmc2->dma_ecc_ch = dma_request_slave_channel(fmc2->dev, "ecc"); -+ nfc->dma_tx_ch = dma_request_chan(nfc->dev, "tx"); -+ if (IS_ERR(nfc->dma_tx_ch)) { -+ ret = PTR_ERR(nfc->dma_tx_ch); -+ if (ret != -ENODEV && ret != -EPROBE_DEFER) -+ dev_err(nfc->dev, -+ "failed to request tx DMA channel: %d\n", ret); -+ nfc->dma_tx_ch = NULL; -+ goto err_dma; -+ } - -- if (!fmc2->dma_tx_ch || !fmc2->dma_rx_ch || !fmc2->dma_ecc_ch) { -- dev_warn(fmc2->dev, "DMAs not defined in the device tree, polling mode is used\n"); -- return 0; -+ nfc->dma_rx_ch = dma_request_chan(nfc->dev, "rx"); -+ if (IS_ERR(nfc->dma_rx_ch)) { -+ ret = PTR_ERR(nfc->dma_rx_ch); -+ if (ret != -ENODEV && ret != -EPROBE_DEFER) -+ dev_err(nfc->dev, -+ "failed to request rx DMA channel: %d\n", ret); -+ nfc->dma_rx_ch = NULL; -+ goto err_dma; - } - -- ret = sg_alloc_table(&fmc2->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL); -+ nfc->dma_ecc_ch = dma_request_chan(nfc->dev, "ecc"); -+ if (IS_ERR(nfc->dma_ecc_ch)) { -+ ret = PTR_ERR(nfc->dma_ecc_ch); -+ if (ret != -ENODEV && ret != -EPROBE_DEFER) -+ dev_err(nfc->dev, -+ "failed to request ecc DMA channel: %d\n", ret); -+ nfc->dma_ecc_ch = NULL; -+ goto err_dma; -+ } -+ -+ ret = sg_alloc_table(&nfc->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL); - if (ret) - return ret; - - /* Allocate a buffer to store ECC status registers */ -- fmc2->ecc_buf = devm_kzalloc(fmc2->dev, FMC2_MAX_ECC_BUF_LEN, -- GFP_KERNEL); -- if (!fmc2->ecc_buf) -+ nfc->ecc_buf = devm_kzalloc(nfc->dev, FMC2_MAX_ECC_BUF_LEN, GFP_KERNEL); -+ if (!nfc->ecc_buf) - return -ENOMEM; - -- ret = sg_alloc_table(&fmc2->dma_data_sg, FMC2_MAX_SG, GFP_KERNEL); -+ ret = sg_alloc_table(&nfc->dma_data_sg, FMC2_MAX_SG, GFP_KERNEL); - if (ret) - return ret; - -- init_completion(&fmc2->dma_data_complete); -- init_completion(&fmc2->dma_ecc_complete); -+ init_completion(&nfc->dma_data_complete); -+ init_completion(&nfc->dma_ecc_complete); - - return 0; -+ -+err_dma: -+ if (ret == -ENODEV) { -+ dev_warn(nfc->dev, -+ "DMAs not defined in the DT, polling mode is used\n"); -+ ret = 0; -+ } -+ -+ return ret; - } - --/* NAND callbacks setup */ --static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip) -+static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - - /* - * Specific callbacks to read/write a page depending on - * the mode (polling/sequencer) and the algo used (Hamming, BCH). - */ -- if (fmc2->dma_tx_ch && fmc2->dma_rx_ch && fmc2->dma_ecc_ch) { -+ if (nfc->dma_tx_ch && nfc->dma_rx_ch && nfc->dma_ecc_ch) { - /* DMA => use sequencer mode callbacks */ -- chip->ecc.correct = stm32_fmc2_sequencer_correct; -- chip->ecc.write_page = stm32_fmc2_sequencer_write_page; -- chip->ecc.read_page = stm32_fmc2_sequencer_read_page; -- chip->ecc.write_page_raw = stm32_fmc2_sequencer_write_page_raw; -- chip->ecc.read_page_raw = stm32_fmc2_sequencer_read_page_raw; -+ chip->ecc.correct = stm32_fmc2_nfc_seq_correct; -+ chip->ecc.write_page = stm32_fmc2_nfc_seq_write_page; -+ chip->ecc.read_page = stm32_fmc2_nfc_seq_read_page; -+ chip->ecc.write_page_raw = stm32_fmc2_nfc_seq_write_page_raw; -+ chip->ecc.read_page_raw = stm32_fmc2_nfc_seq_read_page_raw; - } else { - /* No DMA => use polling mode callbacks */ -- chip->ecc.hwctl = stm32_fmc2_hwctl; -+ chip->ecc.hwctl = stm32_fmc2_nfc_hwctl; - if (chip->ecc.strength == FMC2_ECC_HAM) { - /* Hamming is used */ -- chip->ecc.calculate = stm32_fmc2_ham_calculate; -- chip->ecc.correct = stm32_fmc2_ham_correct; -+ chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate; -+ chip->ecc.correct = stm32_fmc2_nfc_ham_correct; - chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK; - } else { - /* BCH is used */ -- chip->ecc.calculate = stm32_fmc2_bch_calculate; -- chip->ecc.correct = stm32_fmc2_bch_correct; -- chip->ecc.read_page = stm32_fmc2_read_page; -+ chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate; -+ chip->ecc.correct = stm32_fmc2_nfc_bch_correct; -+ chip->ecc.read_page = stm32_fmc2_nfc_read_page; - } - } - -@@ -1678,9 +1636,8 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip) - chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7; - } - --/* FMC2 layout */ --static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section, -- struct mtd_oob_region *oobregion) -+static int stm32_fmc2_nfc_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobregion) - { - struct nand_chip *chip = mtd_to_nand(mtd); - struct nand_ecc_ctrl *ecc = &chip->ecc; -@@ -1694,8 +1651,8 @@ static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section, - return 0; - } - --static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section, -- struct mtd_oob_region *oobregion) -+static int stm32_fmc2_nfc_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobregion) - { - struct nand_chip *chip = mtd_to_nand(mtd); - struct nand_ecc_ctrl *ecc = &chip->ecc; -@@ -1709,13 +1666,12 @@ static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section, - return 0; - } - --static const struct mtd_ooblayout_ops stm32_fmc2_nand_ooblayout_ops = { -- .ecc = stm32_fmc2_nand_ooblayout_ecc, -- .free = stm32_fmc2_nand_ooblayout_free, -+static const struct mtd_ooblayout_ops stm32_fmc2_nfc_ooblayout_ops = { -+ .ecc = stm32_fmc2_nfc_ooblayout_ecc, -+ .free = stm32_fmc2_nfc_ooblayout_free, - }; - --/* FMC2 caps */ --static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength) -+static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength) - { - /* Hamming */ - if (strength == FMC2_ECC_HAM) -@@ -1729,14 +1685,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength) - return 8; - } - --NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes, -+NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes, - FMC2_ECC_STEP_SIZE, - FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8); - --/* FMC2 controller ops */ --static int stm32_fmc2_attach_chip(struct nand_chip *chip) -+static int stm32_fmc2_nfc_attach_chip(struct nand_chip *chip) - { -- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); -+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller); - struct mtd_info *mtd = nand_to_mtd(chip); - int ret; - -@@ -1748,49 +1703,45 @@ static int stm32_fmc2_attach_chip(struct nand_chip *chip) - * ECC sector size = 512 - */ - if (chip->ecc.mode != NAND_ECC_HW) { -- dev_err(fmc2->dev, "nand_ecc_mode is not well defined in the DT\n"); -+ dev_err(nfc->dev, "nand_ecc_mode is not well defined in the DT\n"); - return -EINVAL; - } - -- ret = nand_ecc_choose_conf(chip, &stm32_fmc2_ecc_caps, -+ ret = nand_ecc_choose_conf(chip, &stm32_fmc2_nfc_ecc_caps, - mtd->oobsize - FMC2_BBM_LEN); - if (ret) { -- dev_err(fmc2->dev, "no valid ECC settings set\n"); -+ dev_err(nfc->dev, "no valid ECC settings set\n"); - return ret; - } - - if (mtd->writesize / chip->ecc.size > FMC2_MAX_SG) { -- dev_err(fmc2->dev, "nand page size is not supported\n"); -+ dev_err(nfc->dev, "nand page size is not supported\n"); - return -EINVAL; - } - - if (chip->bbt_options & NAND_BBT_USE_FLASH) - chip->bbt_options |= NAND_BBT_NO_OOB; - -- /* NAND callbacks setup */ -- stm32_fmc2_nand_callbacks_setup(chip); -+ stm32_fmc2_nfc_nand_callbacks_setup(chip); - -- /* Define ECC layout */ -- mtd_set_ooblayout(mtd, &stm32_fmc2_nand_ooblayout_ops); -+ mtd_set_ooblayout(mtd, &stm32_fmc2_nfc_ooblayout_ops); - -- /* Configure bus width to 16-bit */ - if (chip->options & NAND_BUSWIDTH_16) -- stm32_fmc2_set_buswidth_16(fmc2, true); -+ stm32_fmc2_nfc_set_buswidth_16(nfc, true); - - return 0; - } - --static const struct nand_controller_ops stm32_fmc2_nand_controller_ops = { -- .attach_chip = stm32_fmc2_attach_chip, -- .exec_op = stm32_fmc2_exec_op, -- .setup_data_interface = stm32_fmc2_setup_interface, -+static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = { -+ .attach_chip = stm32_fmc2_nfc_attach_chip, -+ .exec_op = stm32_fmc2_nfc_exec_op, -+ .setup_data_interface = stm32_fmc2_nfc_setup_interface, - }; - --/* FMC2 probe */ --static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2, -- struct device_node *dn) -+static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, -+ struct device_node *dn) - { -- struct stm32_fmc2_nand *nand = &fmc2->nand; -+ struct stm32_fmc2_nand *nand = &nfc->nand; - u32 cs; - int ret, i; - -@@ -1799,29 +1750,29 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2, - - nand->ncs /= sizeof(u32); - if (!nand->ncs) { -- dev_err(fmc2->dev, "invalid reg property size\n"); -+ dev_err(nfc->dev, "invalid reg property size\n"); - return -EINVAL; - } - - for (i = 0; i < nand->ncs; i++) { - ret = of_property_read_u32_index(dn, "reg", i, &cs); - if (ret) { -- dev_err(fmc2->dev, "could not retrieve reg property: %d\n", -+ dev_err(nfc->dev, "could not retrieve reg property: %d\n", - ret); - return ret; - } - - if (cs > FMC2_MAX_CE) { -- dev_err(fmc2->dev, "invalid reg value: %d\n", cs); -+ dev_err(nfc->dev, "invalid reg value: %d\n", cs); - return -EINVAL; - } - -- if (fmc2->cs_assigned & BIT(cs)) { -- dev_err(fmc2->dev, "cs already assigned: %d\n", cs); -+ if (nfc->cs_assigned & BIT(cs)) { -+ dev_err(nfc->dev, "cs already assigned: %d\n", cs); - return -EINVAL; - } - -- fmc2->cs_assigned |= BIT(cs); -+ nfc->cs_assigned |= BIT(cs); - nand->cs_used[i] = cs; - } - -@@ -1830,25 +1781,25 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2, - return 0; - } - --static int stm32_fmc2_parse_dt(struct stm32_fmc2_nfc *fmc2) -+static int stm32_fmc2_nfc_parse_dt(struct stm32_fmc2_nfc *nfc) - { -- struct device_node *dn = fmc2->dev->of_node; -+ struct device_node *dn = nfc->dev->of_node; - struct device_node *child; - int nchips = of_get_child_count(dn); - int ret = 0; - - if (!nchips) { -- dev_err(fmc2->dev, "NAND chip not defined\n"); -+ dev_err(nfc->dev, "NAND chip not defined\n"); - return -EINVAL; - } - - if (nchips > 1) { -- dev_err(fmc2->dev, "too many NAND chips defined\n"); -+ dev_err(nfc->dev, "too many NAND chips defined\n"); - return -EINVAL; - } - - for_each_child_of_node(dn, child) { -- ret = stm32_fmc2_parse_child(fmc2, child); -+ ret = stm32_fmc2_nfc_parse_child(nfc, child); - if (ret < 0) { - of_node_put(child); - return ret; -@@ -1858,107 +1809,145 @@ static int stm32_fmc2_parse_dt(struct stm32_fmc2_nfc *fmc2) - return ret; - } - --static int stm32_fmc2_probe(struct platform_device *pdev) -+static int stm32_fmc2_nfc_set_cdev(struct stm32_fmc2_nfc *nfc) -+{ -+ struct device *dev = nfc->dev; -+ bool ebi_found = false; -+ -+ if (dev->parent && of_device_is_compatible(dev->parent->of_node, -+ "st,stm32mp1-fmc2-ebi")) -+ ebi_found = true; -+ -+ if (of_device_is_compatible(dev->of_node, "st,stm32mp1-fmc2-nfc")) { -+ if (ebi_found) { -+ nfc->cdev = dev->parent; -+ -+ return 0; -+ } -+ -+ return -EINVAL; -+ } -+ -+ if (ebi_found) -+ return -EINVAL; -+ -+ nfc->cdev = dev; -+ -+ return 0; -+} -+ -+static int stm32_fmc2_nfc_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - struct reset_control *rstc; -- struct stm32_fmc2_nfc *fmc2; -+ struct stm32_fmc2_nfc *nfc; - struct stm32_fmc2_nand *nand; - struct resource *res; - struct mtd_info *mtd; - struct nand_chip *chip; -+ struct resource cres; - int chip_cs, mem_region, ret, irq; -+ int start_region = 0; - -- fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL); -- if (!fmc2) -+ nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); -+ if (!nfc) - return -ENOMEM; - -- fmc2->dev = dev; -- nand_controller_init(&fmc2->base); -- fmc2->base.ops = &stm32_fmc2_nand_controller_ops; -+ nfc->dev = dev; -+ nand_controller_init(&nfc->base); -+ nfc->base.ops = &stm32_fmc2_nfc_controller_ops; -+ -+ ret = stm32_fmc2_nfc_set_cdev(nfc); -+ if (ret) -+ return ret; -+ -+ ret = stm32_fmc2_nfc_parse_dt(nfc); -+ if (ret) -+ return ret; - -- ret = stm32_fmc2_parse_dt(fmc2); -+ ret = of_address_to_resource(nfc->cdev->of_node, 0, &cres); - if (ret) - return ret; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- fmc2->io_base = devm_ioremap_resource(dev, res); -- if (IS_ERR(fmc2->io_base)) -- return PTR_ERR(fmc2->io_base); -+ nfc->io_phys_addr = cres.start; - -- fmc2->io_phys_addr = res->start; -+ nfc->regmap = device_node_to_regmap(nfc->cdev->of_node); -+ if (IS_ERR(nfc->regmap)) -+ return PTR_ERR(nfc->regmap); - -- for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE; -+ if (nfc->dev == nfc->cdev) -+ start_region = 1; -+ -+ for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE; - chip_cs++, mem_region += 3) { -- if (!(fmc2->cs_assigned & BIT(chip_cs))) -+ if (!(nfc->cs_assigned & BIT(chip_cs))) - continue; - - res = platform_get_resource(pdev, IORESOURCE_MEM, mem_region); -- fmc2->data_base[chip_cs] = devm_ioremap_resource(dev, res); -- if (IS_ERR(fmc2->data_base[chip_cs])) -- return PTR_ERR(fmc2->data_base[chip_cs]); -+ nfc->data_base[chip_cs] = devm_ioremap_resource(dev, res); -+ if (IS_ERR(nfc->data_base[chip_cs])) -+ return PTR_ERR(nfc->data_base[chip_cs]); - -- fmc2->data_phys_addr[chip_cs] = res->start; -+ nfc->data_phys_addr[chip_cs] = res->start; - - res = platform_get_resource(pdev, IORESOURCE_MEM, - mem_region + 1); -- fmc2->cmd_base[chip_cs] = devm_ioremap_resource(dev, res); -- if (IS_ERR(fmc2->cmd_base[chip_cs])) -- return PTR_ERR(fmc2->cmd_base[chip_cs]); -+ nfc->cmd_base[chip_cs] = devm_ioremap_resource(dev, res); -+ if (IS_ERR(nfc->cmd_base[chip_cs])) -+ return PTR_ERR(nfc->cmd_base[chip_cs]); - - res = platform_get_resource(pdev, IORESOURCE_MEM, - mem_region + 2); -- fmc2->addr_base[chip_cs] = devm_ioremap_resource(dev, res); -- if (IS_ERR(fmc2->addr_base[chip_cs])) -- return PTR_ERR(fmc2->addr_base[chip_cs]); -+ nfc->addr_base[chip_cs] = devm_ioremap_resource(dev, res); -+ if (IS_ERR(nfc->addr_base[chip_cs])) -+ return PTR_ERR(nfc->addr_base[chip_cs]); - } - - irq = platform_get_irq(pdev, 0); -- if (irq < 0) { -- if (irq != -EPROBE_DEFER) -- dev_err(dev, "IRQ error missing or invalid\n"); -+ if (irq < 0) - return irq; -- } - -- ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0, -- dev_name(dev), fmc2); -+ ret = devm_request_irq(dev, irq, stm32_fmc2_nfc_irq, 0, -+ dev_name(dev), nfc); - if (ret) { - dev_err(dev, "failed to request irq\n"); - return ret; - } - -- init_completion(&fmc2->complete); -+ init_completion(&nfc->complete); - -- fmc2->clk = devm_clk_get(dev, NULL); -- if (IS_ERR(fmc2->clk)) -- return PTR_ERR(fmc2->clk); -+ nfc->clk = devm_clk_get(nfc->cdev, NULL); -+ if (IS_ERR(nfc->clk)) -+ return PTR_ERR(nfc->clk); - -- ret = clk_prepare_enable(fmc2->clk); -+ ret = clk_prepare_enable(nfc->clk); - if (ret) { - dev_err(dev, "can not enable the clock\n"); - return ret; - } - - rstc = devm_reset_control_get(dev, NULL); -- if (!IS_ERR(rstc)) { -+ if (IS_ERR(rstc)) { -+ ret = PTR_ERR(rstc); -+ if (ret == -EPROBE_DEFER) -+ goto err_clk_disable; -+ } else { - reset_control_assert(rstc); - reset_control_deassert(rstc); - } - -- /* DMA setup */ -- ret = stm32_fmc2_dma_setup(fmc2); -+ ret = stm32_fmc2_nfc_dma_setup(nfc); - if (ret) -- return ret; -+ goto err_release_dma; - -- /* FMC2 init routine */ -- stm32_fmc2_init(fmc2); -+ stm32_fmc2_nfc_init(nfc); - -- nand = &fmc2->nand; -+ nand = &nfc->nand; - chip = &nand->chip; - mtd = nand_to_mtd(chip); - mtd->dev.parent = dev; - -- chip->controller = &fmc2->base; -+ chip->controller = &nfc->base; - chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE | - NAND_USE_BOUNCE_BUFFER; - -@@ -1970,86 +1959,87 @@ static int stm32_fmc2_probe(struct platform_device *pdev) - /* Scan to find existence of the device */ - ret = nand_scan(chip, nand->ncs); - if (ret) -- goto err_scan; -+ goto err_release_dma; - - ret = mtd_device_register(mtd, NULL, 0); - if (ret) -- goto err_device_register; -+ goto err_nand_cleanup; - -- platform_set_drvdata(pdev, fmc2); -+ platform_set_drvdata(pdev, nfc); - - return 0; - --err_device_register: -+err_nand_cleanup: - nand_cleanup(chip); - --err_scan: -- if (fmc2->dma_ecc_ch) -- dma_release_channel(fmc2->dma_ecc_ch); -- if (fmc2->dma_tx_ch) -- dma_release_channel(fmc2->dma_tx_ch); -- if (fmc2->dma_rx_ch) -- dma_release_channel(fmc2->dma_rx_ch); -+err_release_dma: -+ if (nfc->dma_ecc_ch) -+ dma_release_channel(nfc->dma_ecc_ch); -+ if (nfc->dma_tx_ch) -+ dma_release_channel(nfc->dma_tx_ch); -+ if (nfc->dma_rx_ch) -+ dma_release_channel(nfc->dma_rx_ch); - -- sg_free_table(&fmc2->dma_data_sg); -- sg_free_table(&fmc2->dma_ecc_sg); -+ sg_free_table(&nfc->dma_data_sg); -+ sg_free_table(&nfc->dma_ecc_sg); - -- clk_disable_unprepare(fmc2->clk); -+err_clk_disable: -+ clk_disable_unprepare(nfc->clk); - - return ret; - } - --static int stm32_fmc2_remove(struct platform_device *pdev) -+static int stm32_fmc2_nfc_remove(struct platform_device *pdev) - { -- struct stm32_fmc2_nfc *fmc2 = platform_get_drvdata(pdev); -- struct stm32_fmc2_nand *nand = &fmc2->nand; -+ struct stm32_fmc2_nfc *nfc = platform_get_drvdata(pdev); -+ struct stm32_fmc2_nand *nand = &nfc->nand; - - nand_release(&nand->chip); - -- if (fmc2->dma_ecc_ch) -- dma_release_channel(fmc2->dma_ecc_ch); -- if (fmc2->dma_tx_ch) -- dma_release_channel(fmc2->dma_tx_ch); -- if (fmc2->dma_rx_ch) -- dma_release_channel(fmc2->dma_rx_ch); -+ if (nfc->dma_ecc_ch) -+ dma_release_channel(nfc->dma_ecc_ch); -+ if (nfc->dma_tx_ch) -+ dma_release_channel(nfc->dma_tx_ch); -+ if (nfc->dma_rx_ch) -+ dma_release_channel(nfc->dma_rx_ch); - -- sg_free_table(&fmc2->dma_data_sg); -- sg_free_table(&fmc2->dma_ecc_sg); -+ sg_free_table(&nfc->dma_data_sg); -+ sg_free_table(&nfc->dma_ecc_sg); - -- clk_disable_unprepare(fmc2->clk); -+ clk_disable_unprepare(nfc->clk); - - return 0; - } - --static int __maybe_unused stm32_fmc2_suspend(struct device *dev) -+static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev) - { -- struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev); -+ struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev); - -- clk_disable_unprepare(fmc2->clk); -+ clk_disable_unprepare(nfc->clk); - - pinctrl_pm_select_sleep_state(dev); - - return 0; - } - --static int __maybe_unused stm32_fmc2_resume(struct device *dev) -+static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev) - { -- struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev); -- struct stm32_fmc2_nand *nand = &fmc2->nand; -+ struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev); -+ struct stm32_fmc2_nand *nand = &nfc->nand; - int chip_cs, ret; - - pinctrl_pm_select_default_state(dev); - -- ret = clk_prepare_enable(fmc2->clk); -+ ret = clk_prepare_enable(nfc->clk); - if (ret) { - dev_err(dev, "can not enable the clock\n"); - return ret; - } - -- stm32_fmc2_init(fmc2); -+ stm32_fmc2_nfc_init(nfc); - - for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) { -- if (!(fmc2->cs_assigned & BIT(chip_cs))) -+ if (!(nfc->cs_assigned & BIT(chip_cs))) - continue; - - nand_reset(&nand->chip, chip_cs); -@@ -2058,27 +2048,28 @@ static int __maybe_unused stm32_fmc2_resume(struct device *dev) - return 0; - } - --static SIMPLE_DEV_PM_OPS(stm32_fmc2_pm_ops, stm32_fmc2_suspend, -- stm32_fmc2_resume); -+static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend, -+ stm32_fmc2_nfc_resume); - --static const struct of_device_id stm32_fmc2_match[] = { -+static const struct of_device_id stm32_fmc2_nfc_match[] = { - {.compatible = "st,stm32mp15-fmc2"}, -+ {.compatible = "st,stm32mp1-fmc2-nfc"}, - {} - }; --MODULE_DEVICE_TABLE(of, stm32_fmc2_match); -+MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match); - --static struct platform_driver stm32_fmc2_driver = { -- .probe = stm32_fmc2_probe, -- .remove = stm32_fmc2_remove, -+static struct platform_driver stm32_fmc2_nfc_driver = { -+ .probe = stm32_fmc2_nfc_probe, -+ .remove = stm32_fmc2_nfc_remove, - .driver = { -- .name = "stm32_fmc2_nand", -- .of_match_table = stm32_fmc2_match, -- .pm = &stm32_fmc2_pm_ops, -+ .name = "stm32_fmc2_nfc", -+ .of_match_table = stm32_fmc2_nfc_match, -+ .pm = &stm32_fmc2_nfc_pm_ops, - }, - }; --module_platform_driver(stm32_fmc2_driver); -+module_platform_driver(stm32_fmc2_nfc_driver); - --MODULE_ALIAS("platform:stm32_fmc2_nand"); -+MODULE_ALIAS("platform:stm32_fmc2_nfc"); - MODULE_AUTHOR("Christophe Kerello "); --MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nand driver"); -+MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 NFC driver"); - MODULE_LICENSE("GPL v2"); -diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h -index b7ba8810a3b53..eb10b8194073e 100644 ---- a/include/linux/mmc/core.h -+++ b/include/linux/mmc/core.h -@@ -173,6 +173,7 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq); - int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, - int retries); - -+void mmc_hw_unstuck(struct mmc_host *host); - int mmc_hw_reset(struct mmc_host *host); - int mmc_sw_reset(struct mmc_host *host); - void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card); -diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index 4c5eb3aa8e723..feac3431be49a 100644 ---- a/include/linux/mmc/host.h -+++ b/include/linux/mmc/host.h -@@ -163,6 +163,12 @@ struct mmc_host_ops { - void (*hw_reset)(struct mmc_host *host); - void (*card_event)(struct mmc_host *host); - -+ /* -+ * Optional callback, if your host is in deadlock after a command and -+ * must done specific action before sent new command. -+ */ -+ void (*hw_unstuck)(struct mmc_host *host); -+ - /* - * Optional callback to support controllers with HW issues for multiple - * I/O. Returns the number of supported blocks for the request. --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0016-ARM-stm32mp1-r2-PHY-USB.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0016-ARM-stm32mp1-r2-PHY-USB.patch deleted file mode 100644 index 3a148c3..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0016-ARM-stm32mp1-r2-PHY-USB.patch +++ /dev/null @@ -1,3174 +0,0 @@ -From 95aafdb42d1f3aa59f114a7f076949abac53c38d Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:50 +0200 -Subject: [PATCH 16/22] ARM-stm32mp1-r2-rc8-PHY-USB - ---- - .../bindings/connector/usb-connector.txt | 2 + - .../bindings/phy/phy-stm32-usbphyc.txt | 60 +- - .../devicetree/bindings/usb/dwc2.txt | 8 + - .../devicetree/bindings/usb/generic-ehci.yaml | 5 + - .../bindings/usb/st,typec-stusb.txt | 48 + - drivers/phy/phy-core.c | 48 +- - drivers/phy/st/phy-stm32-usbphyc.c | 497 ++++++++-- - drivers/usb/dwc2/Kconfig | 1 + - drivers/usb/dwc2/Makefile | 2 +- - drivers/usb/dwc2/core.c | 123 ++- - drivers/usb/dwc2/core.h | 21 + - drivers/usb/dwc2/drd.c | 196 ++++ - drivers/usb/dwc2/gadget.c | 7 +- - drivers/usb/dwc2/hcd.c | 6 +- - drivers/usb/dwc2/hw.h | 8 + - drivers/usb/dwc2/params.c | 43 + - drivers/usb/dwc2/platform.c | 131 ++- - drivers/usb/gadget/function/f_acm.c | 16 + - drivers/usb/gadget/function/f_serial.c | 16 + - drivers/usb/gadget/function/u_serial.c | 53 +- - drivers/usb/gadget/function/u_serial.h | 2 + - drivers/usb/host/ehci-platform.c | 7 + - drivers/usb/renesas_usbhs/rcar2.c | 2 +- - drivers/usb/renesas_usbhs/rza2.c | 2 +- - drivers/usb/typec/Kconfig | 9 + - drivers/usb/typec/Makefile | 1 + - drivers/usb/typec/class.c | 15 + - drivers/usb/typec/typec_stusb.c | 910 ++++++++++++++++++ - include/linux/phy/phy.h | 9 +- - include/linux/usb/typec.h | 1 + - 30 files changed, 2102 insertions(+), 147 deletions(-) - create mode 100644 Documentation/devicetree/bindings/usb/st,typec-stusb.txt - create mode 100644 drivers/usb/dwc2/drd.c - create mode 100644 drivers/usb/typec/typec_stusb.c - -diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt -index d357987181ee0..5c0bb0395bc92 100644 ---- a/Documentation/devicetree/bindings/connector/usb-connector.txt -+++ b/Documentation/devicetree/bindings/connector/usb-connector.txt -@@ -34,6 +34,8 @@ Optional properties for usb-b-connector: - Optional properties for usb-c-connector: - - power-role: should be one of "source", "sink" or "dual"(DRP) if typec - connector has power support. -+- power-opmode: should be one of "default", "1.5A", "3.0A" or -+ "usb_power_delivery" if typec connector has power support. - - try-power-role: preferred power role if "dual"(DRP) can support Try.SNK - or Try.SRC, should be "sink" for Try.SNK or "source" for Try.SRC. - - data-role: should be one of "host", "device", "dual"(DRD) if typec -diff --git a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt -index 725ae71ae6535..3953489e3a6bb 100644 ---- a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt -+++ b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.txt -@@ -23,8 +23,11 @@ Required properties: - - compatible: must be "st,stm32mp1-usbphyc" - - reg: address and length of the usb phy control register set - - clocks: phandle + clock specifier for the PLL phy clock -+- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY -+- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY - - #address-cells: number of address cells for phys sub-nodes, must be <1> - - #size-cells: number of size cells for phys sub-nodes, must be <0> -+- #clock-cells: number of clock cells for ck_usbo_48m consumer, must be <0> - - Optional properties: - - assigned-clocks: phandle + clock specifier for the PLL phy clock -@@ -34,40 +37,83 @@ Optional properties: - Required nodes: one sub-node per port the controller provides. - - Phy sub-nodes --============== -+============= - - Required properties: - - reg: phy port index - - phy-supply: phandle to the regulator providing 3V3 power to the PHY, - see phy-bindings.txt in the same directory. --- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY --- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY - - #phy-cells: see phy-bindings.txt in the same directory, must be <0> for PHY - port#1 and must be <1> for PHY port#2, to select USB controller - -+Optional properties: -+- st,phy-tuning : phandle to the usb phy tuning node, see Phy tuning node below -+- vbus-supply: phandle to the regulator providing 5V vbus to the USB connector -+ -+Phy tuning node -+=============== -+ -+It may be necessary to adjust the phy settings to compensate parasitics, which -+can be due to USB connector/receptacle, routing, ESD protection component, ... -+ -+Here is the list of all optional parameters to tune the interface of the phy -+(HS for High-Speed, FS for Full-Speed, LS for Low-Speed) -+ -+Optional properties: -+- st,current-boost: <1> current boosting of 1mA -+ <2> current boosting of 2mA -+- st,no-lsfs-fb-cap: disables the LS/FS feedback capacitor -+- st,hs-slew-ctrl: slows the HS driver slew rate by 10% -+- st,hs-dc-level: <0> decreases the HS driver DC level by 5 to 7mV -+ <1> increases the HS driver DC level by 5 to 7mV -+ <2> increases the HS driver DC level by 10 to 14mV -+- st,fs-rftime-tuning: enables the FS rise/fall tuning option -+- st,hs-rftime-reduction: enables the HS rise/fall reduction feature -+- st,hs-current-trim: controls HS driver current trimming for choke -+- st,hs-impedance-trim: controls HS driver impedance tuning for choke -+- st,squelch-level: adjusts the squelch DC threshold value -+- st,hs-rx-gain-eq: enables the HS Rx gain equalizer -+- st,hs-rx-offset: adjusts the HS Rx offset -+- st,no-hs-ftime-ctrl: disables the HS fall time control of single -+ ended signals during pre-emphasis -+- st,no-lsfs-sc: disables the short circuit protection in LS/FS driver -+- st,hs-tx-staggering: enables the basic staggering in HS Tx mode -+ - - Example: -+ usb_phy_tuning: usb-phy-tuning { -+ st,current-boost = <2>; -+ st,no-lfs-fb-cap; -+ st,hs-dc-level = <2>; -+ st,hs-rftime-reduction; -+ st,hs-current-trim = <5>; -+ st,hs-impedance-trim = <0>; -+ st,squelch-level = <1>; -+ st,no-hs-ftime-ctrl; -+ st,hs-tx-staggering; -+ }; -+ - usbphyc: usb-phy@5a006000 { - compatible = "st,stm32mp1-usbphyc"; - reg = <0x5a006000 0x1000>; - clocks = <&rcc_clk USBPHY_K>; - resets = <&rcc_rst USBPHY_R>; -+ vdda1v1-supply = <®11>; -+ vdda1v8-supply = <®18>; - #address-cells = <1>; - #size-cells = <0>; -+ #clock-cells = <0>; - - usbphyc_port0: usb-phy@0 { - reg = <0>; - phy-supply = <&vdd_usb>; -- vdda1v1-supply = <®11>; -- vdda1v8-supply = <®18> - #phy-cells = <0>; - }; - - usbphyc_port1: usb-phy@1 { - reg = <1>; - phy-supply = <&vdd_usb>; -- vdda1v1-supply = <®11>; -- vdda1v8-supply = <®18> - #phy-cells = <1>; -+ st,phy-tuning = <&usb_phy_tuning>; - }; - }; -diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt -index aafff3a6904d0..1a65303d0ca5c 100644 ---- a/Documentation/devicetree/bindings/usb/dwc2.txt -+++ b/Documentation/devicetree/bindings/usb/dwc2.txt -@@ -23,6 +23,9 @@ Required properties: - configured in HS mode; - - "st,stm32f7-hsotg": The DWC2 USB HS controller instance in STM32F7 SoCs - configured in HS mode; -+ - "st,stm32mp1-fsotg": The DWC2 USB controller instance in STM32MP1 SoCs, -+ configured in FS mode (using dedicated FS transceiver). -+ - "st,stm32mp1-hsotg": The DWC2 USB controller instance in STM32MP1 SoCs; - - reg : Should contain 1 register range (address and length) - - interrupts : Should contain 1 interrupt - - clocks: clock provider specifier -@@ -46,6 +49,11 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties - on for remote wakeup during suspend. - - snps,reset-phy-on-wake: If present indicates that we need to reset the PHY when - we detect a wakeup. This is due to a hardware errata. -+- usb33d-supply: external VBUS and ID sensing comparators supply, in order to -+ perform OTG operation, used on STM32MP1 SoCs. -+- usb-role-switch: use USB Role Switch to support dynamic dual role switch. -+ Refer to usb/generic.txt -+- wakeup-source: bool flag to indicate this device has wakeup capabilities - - Deprecated properties: - - g-use-dma: gadget DMA mode is automatically detected -diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml -index 1ca64c85191aa..b71c15dc8c11f 100644 ---- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml -+++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml -@@ -69,6 +69,11 @@ properties: - phy-names: - const: usb - -+ wakeup-source: -+ $ref: /schemas/types.yaml#/definitions/flag -+ description: -+ Indicate this device has wakeup capabilities. -+ - required: - - compatible - - reg -diff --git a/Documentation/devicetree/bindings/usb/st,typec-stusb.txt b/Documentation/devicetree/bindings/usb/st,typec-stusb.txt -new file mode 100644 -index 0000000000000..415e14e1409ea ---- /dev/null -+++ b/Documentation/devicetree/bindings/usb/st,typec-stusb.txt -@@ -0,0 +1,48 @@ -+STMicroelectronics STUSB Type-C Controller family -+ -+Required properties: -+ - compatible: should be "st,stusb1600". -+ - reg: I2C slave address of the device. -+ -+Optional properties: -+ - vdd-supply: main power supply [4.1V;22V]. -+ - vsys-supply: low power supply [3.0V;5.5V]. -+ - vconn-supply: power supply [2.7;5.5V] used to supply VConn on CC pin in -+ source or dual power role. -+ - interrupts: interrupt specifier triggered by ALERT# signal. -+ Please refer to ../interrupt-controller/interrupt.txt -+ - pinctrl state named "default" may be defined to configure pin for #ALERT -+ signal -+ -+USB-C connector attached to STUSB Type-C port controller can be described in -+an optional connector sub-node. Refer to ../connector/usb-connector.txt. -+In case role switch can be used, an optional port sub-node can be added. Refer -+to ../graph.txt. -+ -+Example : -+ -+ typec: stusb1600@28 { -+ compatible = "st,stusb1600"; -+ reg = <0x28>; -+ vdd-supply = <&vbus_drd>; -+ vsys-supply = <&vdd_usb>; -+ interrupts = <11 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-parent = <&gpioi>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&stusb1600_pins_a>; -+ -+ usb_con: connector { -+ compatible = "usb-c-connector"; -+ label = "USB-C"; -+ power-role = "dual"; -+ power-opmode = "1.5A"; -+ data-role = "dual"; -+ -+ port { -+ con_usbotg_hs_ep: endpoint { -+ remote-endpoint = <&usbotg_hs_ep>; -+ }; -+ }; -+ }; -+ }; -+ -diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c -index b04f4fe85ac2d..8dfb4868c8c3d 100644 ---- a/drivers/phy/phy-core.c -+++ b/drivers/phy/phy-core.c -@@ -29,7 +29,7 @@ static void devm_phy_release(struct device *dev, void *res) - { - struct phy *phy = *(struct phy **)res; - -- phy_put(phy); -+ phy_put(dev, phy); - } - - static void devm_phy_provider_release(struct device *dev, void *res) -@@ -566,12 +566,12 @@ struct phy *of_phy_get(struct device_node *np, const char *con_id) - EXPORT_SYMBOL_GPL(of_phy_get); - - /** -- * phy_put() - release the PHY -- * @phy: the phy returned by phy_get() -+ * of_phy_put() - release the PHY -+ * @phy: the phy returned by of_phy_get() - * -- * Releases a refcount the caller received from phy_get(). -+ * Releases a refcount the caller received from of_phy_get(). - */ --void phy_put(struct phy *phy) -+void of_phy_put(struct phy *phy) - { - if (!phy || IS_ERR(phy)) - return; -@@ -584,6 +584,20 @@ void phy_put(struct phy *phy) - module_put(phy->ops->owner); - put_device(&phy->dev); - } -+EXPORT_SYMBOL_GPL(of_phy_put); -+ -+/** -+ * phy_put() - release the PHY -+ * @dev: device that wants to release this phy -+ * @phy: the phy returned by phy_get() -+ * -+ * Releases a refcount the caller received from phy_get(). -+ */ -+void phy_put(struct device *dev, struct phy *phy) -+{ -+ device_link_remove(dev, &phy->dev); -+ of_phy_put(phy); -+} - EXPORT_SYMBOL_GPL(phy_put); - - /** -@@ -651,6 +665,7 @@ struct phy *phy_get(struct device *dev, const char *string) - { - int index = 0; - struct phy *phy; -+ struct device_link *link; - - if (string == NULL) { - dev_WARN(dev, "missing string\n"); -@@ -672,6 +687,13 @@ struct phy *phy_get(struct device *dev, const char *string) - - get_device(&phy->dev); - -+ link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS); -+ if (!link) { -+ dev_err(dev, "failed to create device link to %s\n", -+ dev_name(phy->dev.parent)); -+ return ERR_PTR(-EINVAL); -+ } -+ - return phy; - } - EXPORT_SYMBOL_GPL(phy_get); -@@ -765,6 +787,7 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, - const char *con_id) - { - struct phy **ptr, *phy; -+ struct device_link *link; - - ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) -@@ -778,6 +801,13 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, - devres_free(ptr); - } - -+ link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS); -+ if (!link) { -+ dev_err(dev, "failed to create device link to %s\n", -+ dev_name(phy->dev.parent)); -+ return ERR_PTR(-EINVAL); -+ } -+ - return phy; - } - EXPORT_SYMBOL_GPL(devm_of_phy_get); -@@ -798,6 +828,7 @@ struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, - int index) - { - struct phy **ptr, *phy; -+ struct device_link *link; - - ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) -@@ -819,6 +850,13 @@ struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, - *ptr = phy; - devres_add(dev, ptr); - -+ link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS); -+ if (!link) { -+ dev_err(dev, "failed to create device link to %s\n", -+ dev_name(phy->dev.parent)); -+ return ERR_PTR(-EINVAL); -+ } -+ - return phy; - } - EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index); -diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c -index 56bdea4b0bd90..0eb699344c071 100644 ---- a/drivers/phy/st/phy-stm32-usbphyc.c -+++ b/drivers/phy/st/phy-stm32-usbphyc.c -@@ -7,8 +7,9 @@ - */ - #include - #include -+#include - #include --#include -+#include - #include - #include - #include -@@ -17,6 +18,8 @@ - - #define STM32_USBPHYC_PLL 0x0 - #define STM32_USBPHYC_MISC 0x8 -+#define STM32_USBPHYC_MONITOR(X) (0x108 + (X * 0x100)) -+#define STM32_USBPHYC_TUNE(X) (0x10C + (X * 0x100)) - #define STM32_USBPHYC_VERSION 0x3F4 - - /* STM32_USBPHYC_PLL bit fields */ -@@ -32,19 +35,93 @@ - /* STM32_USBPHYC_MISC bit fields */ - #define SWITHOST BIT(0) - --/* STM32_USBPHYC_VERSION bit fields */ --#define MINREV GENMASK(3, 0) --#define MAJREV GENMASK(7, 4) -+/* STM32_USBPHYC_MONITOR bit fields */ -+#define STM32_USBPHYC_MON_OUT GENMASK(3, 0) -+#define STM32_USBPHYC_MON_SEL GENMASK(8, 4) -+#define STM32_USBPHYC_MON_SEL_LOCKP 0x1F -+#define STM32_USBPHYC_MON_OUT_LOCKP BIT(3) -+ -+/* STM32_USBPHYC_TUNE bit fields */ -+#define INCURREN BIT(0) -+#define INCURRINT BIT(1) -+#define LFSCAPEN BIT(2) -+#define HSDRVSLEW BIT(3) -+#define HSDRVDCCUR BIT(4) -+#define HSDRVDCLEV BIT(5) -+#define HSDRVCURINCR BIT(6) -+#define FSDRVRFADJ BIT(7) -+#define HSDRVRFRED BIT(8) -+#define HSDRVCHKITRM GENMASK(12, 9) -+#define HSDRVCHKZTRM GENMASK(14, 13) -+#define OTPCOMP GENMASK(19, 15) -+#define SQLCHCTL GENMASK(21, 20) -+#define HDRXGNEQEN BIT(22) -+#define HSRXOFF GENMASK(24, 23) -+#define HSFALLPREEM BIT(25) -+#define SHTCCTCTLPROT BIT(26) -+#define STAGSEL BIT(27) -+ -+enum boosting_vals { -+ BOOST_1_MA = 1, -+ BOOST_2_MA, -+ BOOST_MAX, -+}; -+ -+enum dc_level_vals { -+ DC_MINUS_5_TO_7_MV, -+ DC_PLUS_5_TO_7_MV, -+ DC_PLUS_10_TO_14_MV, -+ DC_MAX, -+}; -+ -+enum current_trim { -+ CUR_NOMINAL, -+ CUR_PLUS_1_56_PCT, -+ CUR_PLUS_3_12_PCT, -+ CUR_PLUS_4_68_PCT, -+ CUR_PLUS_6_24_PCT, -+ CUR_PLUS_7_8_PCT, -+ CUR_PLUS_9_36_PCT, -+ CUR_PLUS_10_92_PCT, -+ CUR_PLUS_12_48_PCT, -+ CUR_PLUS_14_04_PCT, -+ CUR_PLUS_15_6_PCT, -+ CUR_PLUS_17_16_PCT, -+ CUR_PLUS_19_01_PCT, -+ CUR_PLUS_20_58_PCT, -+ CUR_PLUS_22_16_PCT, -+ CUR_PLUS_23_73_PCT, -+ CUR_MAX, -+}; -+ -+enum impedance_trim { -+ IMP_NOMINAL, -+ IMP_MINUS_2_OHMS, -+ IMP_MINUS_4_OMHS, -+ IMP_MINUS_6_OHMS, -+ IMP_MAX, -+}; -+ -+enum squelch_level { -+ SQLCH_NOMINAL, -+ SQLCH_PLUS_7_MV, -+ SQLCH_MINUS_5_MV, -+ SQLCH_PLUS_14_MV, -+ SQLCH_MAX, -+}; - --static const char * const supplies_names[] = { -- "vdda1v1", /* 1V1 */ -- "vdda1v8", /* 1V8 */ -+enum rx_offset { -+ NO_RX_OFFSET, -+ RX_OFFSET_PLUS_5_MV, -+ RX_OFFSET_PLUS_10_MV, -+ RX_OFFSET_MINUS_5_MV, -+ RX_OFFSET_MAX, - }; - --#define NUM_SUPPLIES ARRAY_SIZE(supplies_names) -+/* STM32_USBPHYC_VERSION bit fields */ -+#define MINREV GENMASK(3, 0) -+#define MAJREV GENMASK(7, 4) - --#define PLL_LOCK_TIME_US 100 --#define PLL_PWR_DOWN_TIME_US 5 - #define PLL_FVCO_MHZ 2880 - #define PLL_INFF_MIN_RATE_HZ 19200000 - #define PLL_INFF_MAX_RATE_HZ 38400000 -@@ -58,7 +135,7 @@ struct pll_params { - struct stm32_usbphyc_phy { - struct phy *phy; - struct stm32_usbphyc *usbphyc; -- struct regulator_bulk_data supplies[NUM_SUPPLIES]; -+ struct regulator *vbus; - u32 index; - bool active; - }; -@@ -70,6 +147,10 @@ struct stm32_usbphyc { - struct reset_control *rst; - struct stm32_usbphyc_phy **phys; - int nphys; -+ struct regulator *vdda1v1; -+ struct regulator *vdda1v8; -+ atomic_t n_pll_cons; -+ struct clk_hw clk48_hw; - int switch_setup; - }; - -@@ -83,6 +164,41 @@ static inline void stm32_usbphyc_clr_bits(void __iomem *reg, u32 bits) - writel_relaxed(readl_relaxed(reg) & ~bits, reg); - } - -+static int stm32_usbphyc_regulators_enable(struct stm32_usbphyc *usbphyc) -+{ -+ int ret; -+ -+ ret = regulator_enable(usbphyc->vdda1v1); -+ if (ret) -+ return ret; -+ -+ ret = regulator_enable(usbphyc->vdda1v8); -+ if (ret) -+ goto vdda1v1_disable; -+ -+ return 0; -+ -+vdda1v1_disable: -+ regulator_disable(usbphyc->vdda1v1); -+ -+ return ret; -+} -+ -+static int stm32_usbphyc_regulators_disable(struct stm32_usbphyc *usbphyc) -+{ -+ int ret; -+ -+ ret = regulator_disable(usbphyc->vdda1v8); -+ if (ret) -+ return ret; -+ -+ ret = regulator_disable(usbphyc->vdda1v1); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ - static void stm32_usbphyc_get_pll_params(u32 clk_rate, - struct pll_params *pll_params) - { -@@ -142,83 +258,106 @@ static int stm32_usbphyc_pll_init(struct stm32_usbphyc *usbphyc) - return 0; - } - --static bool stm32_usbphyc_has_one_phy_active(struct stm32_usbphyc *usbphyc) -+static int __stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc) - { -- int i; -+ void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; -+ u32 pllen; - -- for (i = 0; i < usbphyc->nphys; i++) -- if (usbphyc->phys[i]->active) -- return true; -+ stm32_usbphyc_clr_bits(pll_reg, PLLEN); - -- return false; -+ /* Wait for minimum width of powerdown pulse (ENABLE = Low) */ -+ if (readl_relaxed_poll_timeout(pll_reg, pllen, !(pllen & PLLEN), 5, 50)) -+ dev_err(usbphyc->dev, "PLL not reset\n"); -+ -+ return stm32_usbphyc_regulators_disable(usbphyc); -+} -+ -+static int stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc) -+{ -+ /* Check if a phy port is still active or clk48 in use */ -+ if (atomic_dec_return(&usbphyc->n_pll_cons) > 0) -+ return 0; -+ -+ return __stm32_usbphyc_pll_disable(usbphyc); - } - - static int stm32_usbphyc_pll_enable(struct stm32_usbphyc *usbphyc) - { - void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; -- bool pllen = (readl_relaxed(pll_reg) & PLLEN); -+ bool pllen = readl_relaxed(pll_reg) & PLLEN; - int ret; - -- /* Check if one phy port has already configured the pll */ -- if (pllen && stm32_usbphyc_has_one_phy_active(usbphyc)) -+ /* -+ * Check if a phy port or clk48 prepare has configured the pll -+ * and ensure the PLL is enabled -+ */ -+ if(atomic_inc_return(&usbphyc->n_pll_cons) > 1 && pllen) - return 0; - - if (pllen) { -- stm32_usbphyc_clr_bits(pll_reg, PLLEN); -- /* Wait for minimum width of powerdown pulse (ENABLE = Low) */ -- udelay(PLL_PWR_DOWN_TIME_US); -+ /* -+ * PLL shouldn't be enabled without known consumer, -+ * disable it and reinit n_pll_cons -+ */ -+ dev_warn(usbphyc->dev, "PLL enabled without known consumers\n"); -+ -+ ret = __stm32_usbphyc_pll_disable(usbphyc); -+ if (ret) -+ return ret; - } - -+ ret = stm32_usbphyc_regulators_enable(usbphyc); -+ if (ret) -+ goto dec_n_pll_cons; -+ - ret = stm32_usbphyc_pll_init(usbphyc); - if (ret) -- return ret; -+ goto reg_disable; - - stm32_usbphyc_set_bits(pll_reg, PLLEN); - -- /* Wait for maximum lock time */ -- udelay(PLL_LOCK_TIME_US); -- -- if (!(readl_relaxed(pll_reg) & PLLEN)) { -- dev_err(usbphyc->dev, "PLLEN not set\n"); -- return -EIO; -- } -- - return 0; --} -- --static int stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc) --{ -- void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; - -- /* Check if other phy port active */ -- if (stm32_usbphyc_has_one_phy_active(usbphyc)) -- return 0; -- -- stm32_usbphyc_clr_bits(pll_reg, PLLEN); -- /* Wait for minimum width of powerdown pulse (ENABLE = Low) */ -- udelay(PLL_PWR_DOWN_TIME_US); -+reg_disable: -+ stm32_usbphyc_regulators_disable(usbphyc); - -- if (readl_relaxed(pll_reg) & PLLEN) { -- dev_err(usbphyc->dev, "PLL not reset\n"); -- return -EIO; -- } -+dec_n_pll_cons: -+ atomic_dec(&usbphyc->n_pll_cons); - -- return 0; -+ return ret; - } - - static int stm32_usbphyc_phy_init(struct phy *phy) - { - struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); - struct stm32_usbphyc *usbphyc = usbphyc_phy->usbphyc; -+ u32 reg_mon = STM32_USBPHYC_MONITOR(usbphyc_phy->index); -+ u32 monsel = FIELD_PREP(STM32_USBPHYC_MON_SEL, -+ STM32_USBPHYC_MON_SEL_LOCKP); -+ u32 monout; - int ret; - - ret = stm32_usbphyc_pll_enable(usbphyc); - if (ret) - return ret; - -+ /* Check that PLL Lock input to PHY is High */ -+ writel_relaxed(monsel, usbphyc->base + reg_mon); -+ ret = readl_relaxed_poll_timeout(usbphyc->base + reg_mon, monout, -+ monout & STM32_USBPHYC_MON_OUT_LOCKP, -+ 100, 1000); -+ if (ret) { -+ dev_err(usbphyc->dev, "PLL Lock input to PHY is Low (val=%x)\n", -+ (u32)(monout & STM32_USBPHYC_MON_OUT)); -+ goto pll_disable; -+ } -+ - usbphyc_phy->active = true; - - return 0; -+ -+pll_disable: -+ return stm32_usbphyc_pll_disable(usbphyc); - } - - static int stm32_usbphyc_phy_exit(struct phy *phy) -@@ -235,14 +374,20 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy) - { - struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); - -- return regulator_bulk_enable(NUM_SUPPLIES, usbphyc_phy->supplies); -+ if (usbphyc_phy->vbus) -+ return regulator_enable(usbphyc_phy->vbus); -+ -+ return 0; - } - - static int stm32_usbphyc_phy_power_off(struct phy *phy) - { - struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); - -- return regulator_bulk_disable(NUM_SUPPLIES, usbphyc_phy->supplies); -+ if (usbphyc_phy->vbus) -+ return regulator_disable(usbphyc_phy->vbus); -+ -+ return 0; - } - - static const struct phy_ops stm32_usbphyc_phy_ops = { -@@ -253,6 +398,163 @@ static const struct phy_ops stm32_usbphyc_phy_ops = { - .owner = THIS_MODULE, - }; - -+static int stm32_usbphyc_clk48_prepare(struct clk_hw *hw) -+{ -+ struct stm32_usbphyc *usbphyc = container_of(hw, struct stm32_usbphyc, -+ clk48_hw); -+ -+ return stm32_usbphyc_pll_enable(usbphyc); -+} -+ -+static void stm32_usbphyc_clk48_unprepare(struct clk_hw *hw) -+{ -+ struct stm32_usbphyc *usbphyc = container_of(hw, struct stm32_usbphyc, -+ clk48_hw); -+ -+ stm32_usbphyc_pll_disable(usbphyc); -+} -+ -+static unsigned long stm32_usbphyc_clk48_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ return 48000000; -+} -+ -+static const struct clk_ops usbphyc_clk48_ops = { -+ .prepare = stm32_usbphyc_clk48_prepare, -+ .unprepare = stm32_usbphyc_clk48_unprepare, -+ .recalc_rate = stm32_usbphyc_clk48_recalc_rate, -+}; -+ -+static void stm32_usbphyc_clk48_unregister(void *data) -+{ -+ struct stm32_usbphyc *usbphyc = data; -+ -+ of_clk_del_provider(usbphyc->dev->of_node); -+ clk_hw_unregister(&usbphyc->clk48_hw); -+} -+ -+static int stm32_usbphyc_clk48_register(struct stm32_usbphyc *usbphyc) -+{ -+ struct device_node *node = usbphyc->dev->of_node; -+ struct clk_init_data init = { }; -+ int ret = 0; -+ -+ init.name = "ck_usbo_48m"; -+ init.ops = &usbphyc_clk48_ops; -+ init.flags = CLK_IGNORE_UNUSED | CLK_IS_CRITICAL; -+ -+ usbphyc->clk48_hw.init = &init; -+ -+ ret = clk_hw_register(usbphyc->dev, &usbphyc->clk48_hw); -+ if (ret) -+ return ret; -+ -+ ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, -+ &usbphyc->clk48_hw); -+ if (ret) -+ clk_hw_unregister(&usbphyc->clk48_hw); -+ -+ return ret; -+} -+ -+static void stm32_usbphyc_phy_tuning(struct stm32_usbphyc *usbphyc, -+ struct device_node *np, u32 index) -+{ -+ struct device_node *tune_np; -+ u32 reg = STM32_USBPHYC_TUNE(index); -+ u32 otpcomp, val, tune = 0; -+ int ret; -+ -+ tune_np = of_parse_phandle(np, "st,phy-tuning", 0); -+ if (!tune_np) -+ return; -+ -+ /* Backup OTP compensation code */ -+ otpcomp = FIELD_GET(OTPCOMP, readl_relaxed(usbphyc->base + reg)); -+ -+ ret = of_property_read_u32(tune_np, "st,current-boost", &val); -+ if (!ret && val < BOOST_MAX) { -+ val = (val == BOOST_2_MA) ? 1 : 0; -+ tune |= INCURREN | FIELD_PREP(INCURRINT, val); -+ } else if (ret != -EINVAL) { -+ dev_warn(usbphyc->dev, -+ "phy%d: invalid st,current-boost value\n", index); -+ } -+ -+ if (!of_property_read_bool(tune_np, "st,no-lsfs-fb-cap")) -+ tune |= LFSCAPEN; -+ -+ if (of_property_read_bool(tune_np, "st,hs-slew-ctrl")) -+ tune |= HSDRVSLEW; -+ -+ ret = of_property_read_u32(tune_np, "st,hs-dc-level", &val); -+ if (!ret && val < DC_MAX) { -+ if (val == DC_MINUS_5_TO_7_MV) { -+ tune |= HSDRVDCCUR; -+ } else { -+ val = (val == DC_PLUS_10_TO_14_MV) ? 1 : 0; -+ tune |= HSDRVCURINCR | FIELD_PREP(HSDRVDCLEV, val); -+ } -+ } else if (ret != -EINVAL) { -+ dev_warn(usbphyc->dev, -+ "phy%d: invalid st,hs-dc-level value\n", index); -+ } -+ -+ if (of_property_read_bool(tune_np, "st,fs-rftime-tuning")) -+ tune |= FSDRVRFADJ; -+ -+ if (of_property_read_bool(tune_np, "st,hs-rftime-reduction")) -+ tune |= HSDRVRFRED; -+ -+ ret = of_property_read_u32(tune_np, "st,hs-current-trim", &val); -+ if (!ret && val < CUR_MAX) -+ tune |= FIELD_PREP(HSDRVCHKITRM, val); -+ else if (ret != -EINVAL) -+ dev_warn(usbphyc->dev, -+ "phy%d: invalid st,hs-current-trim value\n", index); -+ -+ ret = of_property_read_u32(tune_np, "st,hs-impedance-trim", &val); -+ if (!ret && val < IMP_MAX) -+ tune |= FIELD_PREP(HSDRVCHKZTRM, val); -+ else if (ret != -EINVAL) -+ dev_warn(usbphyc->dev, -+ "phy%d: invalid hs-impedance-trim value\n", index); -+ -+ ret = of_property_read_u32(tune_np, "st,squelch-level", &val); -+ if (!ret && val < SQLCH_MAX) -+ tune |= FIELD_PREP(SQLCHCTL, val); -+ else if (ret != -EINVAL) -+ dev_warn(usbphyc->dev, -+ "phy%d: invalid st,squelch-level value\n", index); -+ -+ if (of_property_read_bool(tune_np, "st,hs-rx-gain-eq")) -+ tune |= HDRXGNEQEN; -+ -+ ret = of_property_read_u32(tune_np, "st,hs-rx-offset", &val); -+ if (!ret && val < RX_OFFSET_MAX) -+ tune |= FIELD_PREP(HSRXOFF, val); -+ else if (ret != -EINVAL) -+ dev_warn(usbphyc->dev, -+ "phy%d: invalid st,hs-rx-offset value\n", index); -+ -+ if (of_property_read_bool(tune_np, "st,no-hs-ftime-ctrl")) -+ tune |= HSFALLPREEM; -+ -+ if (!of_property_read_bool(tune_np, "st,no-lsfs-sc")) -+ tune |= SHTCCTCTLPROT; -+ -+ if (of_property_read_bool(tune_np, "st,hs-tx-staggering")) -+ tune |= STAGSEL; -+ -+ of_node_put(tune_np); -+ -+ /* Restore OTP compensation code */ -+ tune |= FIELD_PREP(OTPCOMP, otpcomp); -+ -+ writel_relaxed(tune, usbphyc->base + reg); -+} -+ - static void stm32_usbphyc_switch_setup(struct stm32_usbphyc *usbphyc, - u32 utmi_switch) - { -@@ -313,7 +615,7 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - struct device_node *child, *np = dev->of_node; - struct resource *res; - struct phy_provider *phy_provider; -- u32 version; -+ u32 pllen, version; - int ret, port = 0; - - usbphyc = devm_kzalloc(dev, sizeof(*usbphyc), GFP_KERNEL); -@@ -330,7 +632,8 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - usbphyc->clk = devm_clk_get(dev, 0); - if (IS_ERR(usbphyc->clk)) { - ret = PTR_ERR(usbphyc->clk); -- dev_err(dev, "clk get failed: %d\n", ret); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "clk get failed: %d\n", ret); - return ret; - } - -@@ -345,6 +648,24 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - reset_control_assert(usbphyc->rst); - udelay(2); - reset_control_deassert(usbphyc->rst); -+ } else { -+ ret = PTR_ERR(usbphyc->rst); -+ if (ret == -EPROBE_DEFER) -+ goto clk_disable; -+ -+ stm32_usbphyc_clr_bits(usbphyc->base + STM32_USBPHYC_PLL, -+ PLLEN); -+ } -+ -+ /* -+ * Wait for minimum width of powerdown pulse (ENABLE = Low): -+ * we have to ensure the PLL is disabled before phys initialization. -+ */ -+ if (readl_relaxed_poll_timeout(usbphyc->base + STM32_USBPHYC_PLL, -+ pllen, !(pllen & PLLEN), 5, 50)) { -+ dev_warn(usbphyc->dev, "PLL not reset\n"); -+ ret = -EPROBE_DEFER; -+ goto clk_disable; - } - - usbphyc->switch_setup = -EINVAL; -@@ -356,11 +677,26 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - goto clk_disable; - } - -+ usbphyc->vdda1v1 = devm_regulator_get(dev, "vdda1v1"); -+ if (IS_ERR(usbphyc->vdda1v1)) { -+ ret = PTR_ERR(usbphyc->vdda1v1); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "failed to get vdda1v1 supply: %d\n", ret); -+ goto clk_disable; -+ } -+ -+ usbphyc->vdda1v8 = devm_regulator_get(dev, "vdda1v8"); -+ if (IS_ERR(usbphyc->vdda1v8)) { -+ ret = PTR_ERR(usbphyc->vdda1v8); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "failed to get vdda1v8 supply: %d\n", ret); -+ goto clk_disable; -+ } -+ - for_each_child_of_node(np, child) { - struct stm32_usbphyc_phy *usbphyc_phy; - struct phy *phy; - u32 index; -- int i; - - phy = devm_phy_create(dev, child, &stm32_usbphyc_phy_ops); - if (IS_ERR(phy)) { -@@ -378,24 +714,15 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - goto put_child; - } - -- for (i = 0; i < NUM_SUPPLIES; i++) -- usbphyc_phy->supplies[i].supply = supplies_names[i]; -- -- ret = devm_regulator_bulk_get(&phy->dev, NUM_SUPPLIES, -- usbphyc_phy->supplies); -- if (ret) { -- if (ret != -EPROBE_DEFER) -- dev_err(&phy->dev, -- "failed to get regulators: %d\n", ret); -- goto put_child; -- } -- - ret = of_property_read_u32(child, "reg", &index); - if (ret || index > usbphyc->nphys) { - dev_err(&phy->dev, "invalid reg property: %d\n", ret); - goto put_child; - } - -+ /* Configure phy tuning */ -+ stm32_usbphyc_phy_tuning(usbphyc, child, index); -+ - usbphyc->phys[port] = usbphyc_phy; - phy_set_bus_width(phy, 8); - phy_set_drvdata(phy, usbphyc_phy); -@@ -405,6 +732,14 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - usbphyc->phys[port]->index = index; - usbphyc->phys[port]->active = false; - -+ usbphyc->phys[port]->vbus = devm_regulator_get_optional(&phy->dev, "vbus"); -+ if (IS_ERR(usbphyc->phys[port]->vbus)) { -+ ret = PTR_ERR(usbphyc->phys[port]->vbus); -+ if (ret == -EPROBE_DEFER) -+ goto put_child; -+ usbphyc->phys[port]->vbus = NULL; -+ } -+ - port++; - } - -@@ -416,6 +751,13 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - goto clk_disable; - } - -+ ret = stm32_usbphyc_clk48_register(usbphyc); -+ if (ret) { -+ dev_err(dev, -+ "failed to register ck_usbo_48m clock: %d\n", ret); -+ goto clk_disable; -+ } -+ - version = readl_relaxed(usbphyc->base + STM32_USBPHYC_VERSION); - dev_info(dev, "registered rev:%lu.%lu\n", - FIELD_GET(MAJREV, version), FIELD_GET(MINREV, version)); -@@ -433,12 +775,34 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) - static int stm32_usbphyc_remove(struct platform_device *pdev) - { - struct stm32_usbphyc *usbphyc = dev_get_drvdata(&pdev->dev); -+ int port; -+ -+ stm32_usbphyc_clk48_unregister(usbphyc); -+ -+ /* Ensure PHYs are not active, to allow PLL disabling */ -+ for (port = 0; port < usbphyc->nphys; port++) -+ if (usbphyc->phys[port]->active) -+ stm32_usbphyc_phy_exit(usbphyc->phys[port]->phy); - - clk_disable_unprepare(usbphyc->clk); - - return 0; - } - -+#ifdef CONFIG_PM_SLEEP -+static int stm32_usbphyc_resume(struct device *dev) -+{ -+ struct stm32_usbphyc *usbphyc = dev_get_drvdata(dev); -+ -+ if (usbphyc->switch_setup >= 0) -+ stm32_usbphyc_switch_setup(usbphyc, usbphyc->switch_setup); -+ -+ return 0; -+} -+#endif -+ -+static SIMPLE_DEV_PM_OPS(stm32_usbphyc_pm_ops, NULL, stm32_usbphyc_resume); -+ - static const struct of_device_id stm32_usbphyc_of_match[] = { - { .compatible = "st,stm32mp1-usbphyc", }, - { }, -@@ -451,6 +815,7 @@ static struct platform_driver stm32_usbphyc_driver = { - .driver = { - .of_match_table = stm32_usbphyc_of_match, - .name = "stm32-usbphyc", -+ .pm = &stm32_usbphyc_pm_ops, - } - }; - module_platform_driver(stm32_usbphyc_driver); -diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig -index 16e1aa304edc4..c131719367eca 100644 ---- a/drivers/usb/dwc2/Kconfig -+++ b/drivers/usb/dwc2/Kconfig -@@ -5,6 +5,7 @@ config USB_DWC2 - depends on HAS_DMA - depends on USB || USB_GADGET - depends on HAS_IOMEM -+ select USB_ROLE_SWITCH - help - Say Y here if your system has a Dual Role Hi-Speed USB - controller based on the DesignWare HSOTG IP Core. -diff --git a/drivers/usb/dwc2/Makefile b/drivers/usb/dwc2/Makefile -index 440320cc20a47..2bcd6945df461 100644 ---- a/drivers/usb/dwc2/Makefile -+++ b/drivers/usb/dwc2/Makefile -@@ -3,7 +3,7 @@ ccflags-$(CONFIG_USB_DWC2_DEBUG) += -DDEBUG - ccflags-$(CONFIG_USB_DWC2_VERBOSE) += -DVERBOSE_DEBUG - - obj-$(CONFIG_USB_DWC2) += dwc2.o --dwc2-y := core.o core_intr.o platform.o -+dwc2-y := core.o core_intr.o platform.o drd.o - dwc2-y += params.o - - ifneq ($(filter y,$(CONFIG_USB_DWC2_HOST) $(CONFIG_USB_DWC2_DUAL_ROLE)),) -diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c -index 78a4925aa1185..d1c6a8a9d9789 100644 ---- a/drivers/usb/dwc2/core.c -+++ b/drivers/usb/dwc2/core.c -@@ -83,6 +83,7 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) - gr->pcgcctl1 = dwc2_readl(hsotg, PCGCCTL1); - gr->glpmcfg = dwc2_readl(hsotg, GLPMCFG); - gr->gi2cctl = dwc2_readl(hsotg, GI2CCTL); -+ gr->ggpio = dwc2_readl(hsotg, GGPIO); - gr->pcgcctl = dwc2_readl(hsotg, PCGCTL); - - gr->valid = true; -@@ -112,21 +113,82 @@ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) - gr->valid = false; - - dwc2_writel(hsotg, 0xffffffff, GINTSTS); -+ dwc2_writel(hsotg, gr->gahbcfg, GAHBCFG); -+ dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG); - dwc2_writel(hsotg, gr->gotgctl, GOTGCTL); - dwc2_writel(hsotg, gr->gintmsk, GINTMSK); -- dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG); -- dwc2_writel(hsotg, gr->gahbcfg, GAHBCFG); - dwc2_writel(hsotg, gr->grxfsiz, GRXFSIZ); - dwc2_writel(hsotg, gr->gnptxfsiz, GNPTXFSIZ); - dwc2_writel(hsotg, gr->gdfifocfg, GDFIFOCFG); - dwc2_writel(hsotg, gr->pcgcctl1, PCGCCTL1); - dwc2_writel(hsotg, gr->glpmcfg, GLPMCFG); - dwc2_writel(hsotg, gr->pcgcctl, PCGCTL); -+ dwc2_writel(hsotg, gr->ggpio, GGPIO); - dwc2_writel(hsotg, gr->gi2cctl, GI2CCTL); - - return 0; - } - -+int dwc2_backup_registers(struct dwc2_hsotg *hsotg) -+{ -+ int ret; -+ -+ /* Backup all registers */ -+ ret = dwc2_backup_global_registers(hsotg); -+ if (ret) { -+ dev_err(hsotg->dev, "%s: failed to backup global registers\n", -+ __func__); -+ return ret; -+ } -+ -+ if (dwc2_is_host_mode(hsotg)) { -+ ret = dwc2_backup_host_registers(hsotg); -+ if (ret) { -+ dev_err(hsotg->dev, "%s: failed to backup host registers\n", -+ __func__); -+ return ret; -+ } -+ } else { -+ ret = dwc2_backup_device_registers(hsotg); -+ if (ret) { -+ dev_err(hsotg->dev, "%s: failed to backup device registers\n", -+ __func__); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+int dwc2_restore_registers(struct dwc2_hsotg *hsotg) -+{ -+ int ret; -+ -+ ret = dwc2_restore_global_registers(hsotg); -+ if (ret) { -+ dev_err(hsotg->dev, "%s: failed to restore registers\n", -+ __func__); -+ return ret; -+ } -+ if (dwc2_is_host_mode(hsotg)) { -+ ret = dwc2_restore_host_registers(hsotg); -+ if (ret) { -+ dev_err(hsotg->dev, "%s: failed to restore host registers\n", -+ __func__); -+ return ret; -+ } -+ } else { -+ ret = dwc2_restore_device_registers(hsotg, 0); -+ if (ret) { -+ dev_err(hsotg->dev, "%s: failed to restore device registers\n", -+ __func__); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ - /** - * dwc2_exit_partial_power_down() - Exit controller from Partial Power Down. - * -@@ -136,7 +198,6 @@ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) - int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore) - { - u32 pcgcctl; -- int ret = 0; - - if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) - return -ENOTSUPP; -@@ -154,31 +215,11 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore) - dwc2_writel(hsotg, pcgcctl, PCGCTL); - - udelay(100); -- if (restore) { -- ret = dwc2_restore_global_registers(hsotg); -- if (ret) { -- dev_err(hsotg->dev, "%s: failed to restore registers\n", -- __func__); -- return ret; -- } -- if (dwc2_is_host_mode(hsotg)) { -- ret = dwc2_restore_host_registers(hsotg); -- if (ret) { -- dev_err(hsotg->dev, "%s: failed to restore host registers\n", -- __func__); -- return ret; -- } -- } else { -- ret = dwc2_restore_device_registers(hsotg, 0); -- if (ret) { -- dev_err(hsotg->dev, "%s: failed to restore device registers\n", -- __func__); -- return ret; -- } -- } -- } - -- return ret; -+ if (restore) -+ return dwc2_restore_registers(hsotg); -+ -+ return 0; - } - - /** -@@ -189,34 +230,14 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore) - int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg) - { - u32 pcgcctl; -- int ret = 0; -+ int ret; - - if (!hsotg->params.power_down) - return -ENOTSUPP; - -- /* Backup all registers */ -- ret = dwc2_backup_global_registers(hsotg); -- if (ret) { -- dev_err(hsotg->dev, "%s: failed to backup global registers\n", -- __func__); -+ ret = dwc2_backup_registers(hsotg); -+ if (ret) - return ret; -- } -- -- if (dwc2_is_host_mode(hsotg)) { -- ret = dwc2_backup_host_registers(hsotg); -- if (ret) { -- dev_err(hsotg->dev, "%s: failed to backup host registers\n", -- __func__); -- return ret; -- } -- } else { -- ret = dwc2_backup_device_registers(hsotg); -- if (ret) { -- dev_err(hsotg->dev, "%s: failed to backup device registers\n", -- __func__); -- return ret; -- } -- } - - /* - * Clear any pending interrupts since dwc2 will not be able to -@@ -238,7 +259,7 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg) - pcgcctl |= PCGCTL_STOPPCLK; - dwc2_writel(hsotg, pcgcctl, PCGCTL); - -- return ret; -+ return 0; - } - - /** -diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h -index d08d070a0fb6f..04d6b4937d769 100644 ---- a/drivers/usb/dwc2/core.h -+++ b/drivers/usb/dwc2/core.h -@@ -411,6 +411,10 @@ enum dwc2_ep0_state { - * register. - * 0 - Deactivate the transceiver (default) - * 1 - Activate the transceiver -+ * @activate_stm_id_vb_detection: Activate external ID pin and Vbuslevel -+ * detection using GGPIO register. -+ * 0 - Deactivate the external level detection (default) -+ * 1 - Activate the external level detection - * @g_dma: Enables gadget dma usage (default: autodetect). - * @g_dma_desc: Enables gadget descriptor DMA (default: autodetect). - * @g_rx_fifo_size: The periodic rx fifo size for the device, in -@@ -481,6 +485,7 @@ struct dwc2_core_params { - bool service_interval; - u8 hird_threshold; - bool activate_stm_fs_transceiver; -+ bool activate_stm_id_vb_detection; - bool ipg_isoc_en; - u16 max_packet_count; - u32 max_transfer_size; -@@ -680,6 +685,7 @@ struct dwc2_hw_params { - * @grxfsiz: Backup of GRXFSIZ register - * @gnptxfsiz: Backup of GNPTXFSIZ register - * @gi2cctl: Backup of GI2CCTL register -+ * @ggpio: Backup of GGPIO register - * @glpmcfg: Backup of GLPMCFG register - * @gdfifocfg: Backup of GDFIFOCFG register - * @pcgcctl: Backup of PCGCCTL register -@@ -696,6 +702,7 @@ struct dwc2_gregs_backup { - u32 grxfsiz; - u32 gnptxfsiz; - u32 gi2cctl; -+ u32 ggpio; - u32 glpmcfg; - u32 pcgcctl; - u32 pcgcctl1; -@@ -855,6 +862,7 @@ struct dwc2_hregs_backup { - * - USB_DR_MODE_PERIPHERAL - * - USB_DR_MODE_HOST - * - USB_DR_MODE_OTG -+ * @role_sw: usb_role_switch handle - * @hcd_enabled: Host mode sub-driver initialization indicator. - * @gadget_enabled: Peripheral mode sub-driver initialization indicator. - * @ll_hw_enabled: Status of low-level hardware resources. -@@ -874,6 +882,8 @@ struct dwc2_hregs_backup { - * removed once all SoCs support usb transceiver. - * @supplies: Definition of USB power supplies - * @vbus_supply: Regulator supplying vbus. -+ * @usb33d: Optional 3.3v regulator used on some stm32 devices to -+ * supply ID and VBUS detection hardware. - * @lock: Spinlock that protects all the driver data structures - * @priv: Stores a pointer to the struct usb_hcd - * @queuing_high_bandwidth: True if multiple packets of a high-bandwidth -@@ -1047,6 +1057,7 @@ struct dwc2_hsotg { - struct dwc2_core_params params; - enum usb_otg_state op_state; - enum usb_dr_mode dr_mode; -+ struct usb_role_switch *role_sw; - unsigned int hcd_enabled:1; - unsigned int gadget_enabled:1; - unsigned int ll_hw_enabled:1; -@@ -1061,6 +1072,7 @@ struct dwc2_hsotg { - struct dwc2_hsotg_plat *plat; - struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES]; - struct regulator *vbus_supply; -+ struct regulator *usb33d; - - spinlock_t lock; - void *priv; -@@ -1315,6 +1327,8 @@ void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd); - - void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup, - int is_host); -+int dwc2_backup_registers(struct dwc2_hsotg *hsotg); -+int dwc2_restore_registers(struct dwc2_hsotg *hsotg); - int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg); - int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg); - -@@ -1364,6 +1378,11 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) - return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) == 0; - } - -+int dwc2_drd_init(struct dwc2_hsotg *hsotg); -+void dwc2_drd_suspend(struct dwc2_hsotg *hsotg); -+void dwc2_drd_resume(struct dwc2_hsotg *hsotg); -+void dwc2_drd_exit(struct dwc2_hsotg *hsotg); -+ - /* - * Dump core registers and SPRAM - */ -@@ -1380,6 +1399,7 @@ int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2); - int dwc2_gadget_init(struct dwc2_hsotg *hsotg); - void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, - bool reset); -+void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg); - void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); - void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); - int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); -@@ -1405,6 +1425,7 @@ static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg) - { return 0; } - static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, - bool reset) {} -+static inline void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) {} - static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {} - static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} - static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, -diff --git a/drivers/usb/dwc2/drd.c b/drivers/usb/dwc2/drd.c -new file mode 100644 -index 0000000000000..728ca64450960 ---- /dev/null -+++ b/drivers/usb/dwc2/drd.c -@@ -0,0 +1,196 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * drd.c - DesignWare USB2 DRD Controller Dual-role support -+ * -+ * Copyright (C) 2019 STMicroelectronics -+ * -+ * Author(s): Amelie Delaunay -+ */ -+ -+#include -+#include -+#include -+#include -+#include "core.h" -+ -+static void dwc2_ovr_init(struct dwc2_hsotg *hsotg) -+{ -+ unsigned long flags; -+ u32 gotgctl; -+ -+ spin_lock_irqsave(&hsotg->lock, flags); -+ -+ gotgctl = dwc2_readl(hsotg, GOTGCTL); -+ gotgctl |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | GOTGCTL_VBVALOEN; -+ gotgctl |= GOTGCTL_DBNCE_FLTR_BYPASS; -+ gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); -+ dwc2_writel(hsotg, gotgctl, GOTGCTL); -+ -+ spin_unlock_irqrestore(&hsotg->lock, flags); -+ -+ dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST)); -+} -+ -+static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) -+{ -+ u32 gotgctl = dwc2_readl(hsotg, GOTGCTL); -+ -+ /* Check if A-Session is already in the right state */ -+ if ((valid && (gotgctl & GOTGCTL_ASESVLD)) || -+ (!valid && !(gotgctl & GOTGCTL_ASESVLD))) -+ return -EALREADY; -+ -+ if (valid) -+ gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL; -+ else -+ gotgctl &= ~(GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); -+ dwc2_writel(hsotg, gotgctl, GOTGCTL); -+ -+ return 0; -+} -+ -+static int dwc2_ovr_bvalid(struct dwc2_hsotg *hsotg, bool valid) -+{ -+ u32 gotgctl = dwc2_readl(hsotg, GOTGCTL); -+ -+ /* Check if B-Session is already in the right state */ -+ if ((valid && (gotgctl & GOTGCTL_BSESVLD)) || -+ (!valid && !(gotgctl & GOTGCTL_BSESVLD))) -+ return -EALREADY; -+ -+ if (valid) -+ gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL; -+ else -+ gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL); -+ dwc2_writel(hsotg, gotgctl, GOTGCTL); -+ -+ return 0; -+} -+ -+static int dwc2_drd_role_sw_set(struct device *dev, enum usb_role role) -+{ -+ struct dwc2_hsotg *hsotg = dev_get_drvdata(dev); -+ unsigned long flags; -+ int already = 0; -+ -+ /* Skip session not in line with dr_mode */ -+ if ((role == USB_ROLE_DEVICE && hsotg->dr_mode == USB_DR_MODE_HOST) || -+ (role == USB_ROLE_HOST && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)) -+ return -EINVAL; -+ -+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ -+ IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) -+ /* Skip session if core is in test mode */ -+ if (role == USB_ROLE_NONE && hsotg->test_mode) { -+ dev_dbg(hsotg->dev, "Core is in test mode\n"); -+ return -EBUSY; -+ } -+#endif -+ -+ /* -+ * In case of USB_DR_MODE_PERIPHERAL, clock is disabled at the end of -+ * the probe and enabled on udc_start. -+ * If role-switch set is called before the udc_start, we need to enable -+ * the clock to read/write GOTGCTL and GUSBCFG registers to override -+ * mode and sessions. It is the case if cable is plugged at boot. -+ */ -+ if (!hsotg->ll_hw_enabled && hsotg->clk) { -+ int ret = clk_prepare_enable(hsotg->clk); -+ if (ret) -+ return ret; -+ } -+ -+ spin_lock_irqsave(&hsotg->lock, flags); -+ -+ if (role == USB_ROLE_HOST) { -+ already = dwc2_ovr_avalid(hsotg, true); -+ } else if (role == USB_ROLE_DEVICE) { -+ already = dwc2_ovr_bvalid(hsotg, true); -+ /* This clear DCTL.SFTDISCON bit */ -+ dwc2_hsotg_core_connect(hsotg); -+ } else { -+ if (dwc2_is_device_mode(hsotg)) { -+ if (!dwc2_ovr_bvalid(hsotg, false)) -+ /* This set DCTL.SFTDISCON bit */ -+ dwc2_hsotg_core_disconnect(hsotg); -+ } else { -+ dwc2_ovr_avalid(hsotg, false); -+ } -+ } -+ -+ spin_unlock_irqrestore(&hsotg->lock, flags); -+ -+ if (!already && hsotg->dr_mode == USB_DR_MODE_OTG) -+ /* This will raise a Connector ID Status Change Interrupt */ -+ dwc2_force_mode(hsotg, role == USB_ROLE_HOST); -+ -+ if (!hsotg->ll_hw_enabled && hsotg->clk) -+ clk_disable_unprepare(hsotg->clk); -+ -+ dev_dbg(hsotg->dev, "%s-session valid\n", -+ role == USB_ROLE_NONE ? "No" : -+ role == USB_ROLE_HOST ? "A" : "B"); -+ -+ return 0; -+} -+ -+int dwc2_drd_init(struct dwc2_hsotg *hsotg) -+{ -+ int ret; -+ -+ if (device_property_read_bool(hsotg->dev, "usb-role-switch")) { -+ struct usb_role_switch_desc role_sw_desc = {0}; -+ struct usb_role_switch *role_sw; -+ -+ role_sw_desc.fwnode = dev_fwnode(hsotg->dev); -+ role_sw_desc.set = dwc2_drd_role_sw_set; -+ role_sw_desc.allow_userspace_control = true; -+ -+ role_sw = usb_role_switch_register(hsotg->dev, &role_sw_desc); -+ if (IS_ERR(role_sw)) { -+ ret = PTR_ERR(role_sw); -+ dev_err(hsotg->dev, -+ "unable to register role switch: %d\n", ret); -+ return ret; -+ } -+ -+ hsotg->role_sw = role_sw; -+ -+ /* Enable override and initialize values */ -+ dwc2_ovr_init(hsotg); -+ } -+ -+ return 0; -+} -+ -+void dwc2_drd_suspend(struct dwc2_hsotg *hsotg) -+{ -+ u32 gintsts, gintmsk; -+ -+ if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) { -+ gintmsk = dwc2_readl(hsotg, GINTMSK); -+ gintmsk &= ~GINTSTS_CONIDSTSCHNG; -+ dwc2_writel(hsotg, gintmsk, GINTMSK); -+ gintsts = dwc2_readl(hsotg, GINTSTS); -+ dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS); -+ } -+} -+ -+void dwc2_drd_resume(struct dwc2_hsotg *hsotg) -+{ -+ u32 gintsts, gintmsk; -+ -+ if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) { -+ gintsts = dwc2_readl(hsotg, GINTSTS); -+ dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS); -+ gintmsk = dwc2_readl(hsotg, GINTMSK); -+ gintmsk |= GINTSTS_CONIDSTSCHNG; -+ dwc2_writel(hsotg, gintmsk, GINTMSK); -+ } -+} -+ -+void dwc2_drd_exit(struct dwc2_hsotg *hsotg) -+{ -+ if (hsotg->role_sw) -+ usb_role_switch_unregister(hsotg->role_sw); -+} -diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c -index f7528f732b2aa..8e448e8b1fe4b 100644 ---- a/drivers/usb/dwc2/gadget.c -+++ b/drivers/usb/dwc2/gadget.c -@@ -3531,7 +3531,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, - dwc2_readl(hsotg, DOEPCTL0)); - } - --static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) -+void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) - { - /* set the soft-disconnect bit */ - dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON); -@@ -3540,7 +3540,8 @@ static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) - void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) - { - /* remove the soft-disconnect and let's go */ -- dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON); -+ if (!hsotg->role_sw || (dwc2_readl(hsotg, GOTGCTL) & GOTGCTL_BSESVLD)) -+ dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON); - } - - /** -@@ -4924,7 +4925,7 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) - hsotg->gadget.speed = USB_SPEED_UNKNOWN; - spin_unlock_irqrestore(&hsotg->lock, flags); - -- for (ep = 0; ep < hsotg->num_of_eps; ep++) { -+ for (ep = 1; ep < hsotg->num_of_eps; ep++) { - if (hsotg->eps_in[ep]) - dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep); - if (hsotg->eps_out[ep]) -diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c -index 81afe553aa666..f89e6d003ec8b 100644 ---- a/drivers/usb/dwc2/hcd.c -+++ b/drivers/usb/dwc2/hcd.c -@@ -1735,7 +1735,8 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) - * release_channel_ddma(), which is called from ep_disable when - * device disconnects - */ -- channel->qh = NULL; -+ if (hsotg->params.host_dma && hsotg->params.dma_desc_enable) -+ channel->qh = NULL; - } - /* All channels have been freed, mark them available */ - if (hsotg->params.uframe_sched) { -@@ -3611,7 +3612,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, - if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1)) - goto error; - -- if (!hsotg->flags.b.port_connect_status) { -+ if (!hsotg->flags.b.port_connect_status && -+ !dwc2_is_host_mode(hsotg)) { - /* - * The port is disconnected, which means the core is - * either in device mode or it soon will be. Just -diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h -index 510e87ec0be84..c4027bbcedec4 100644 ---- a/drivers/usb/dwc2/hw.h -+++ b/drivers/usb/dwc2/hw.h -@@ -54,6 +54,12 @@ - #define GOTGCTL_HSTSETHNPEN BIT(10) - #define GOTGCTL_HNPREQ BIT(9) - #define GOTGCTL_HSTNEGSCS BIT(8) -+#define GOTGCTL_BVALOVAL BIT(7) -+#define GOTGCTL_BVALOEN BIT(6) -+#define GOTGCTL_AVALOVAL BIT(5) -+#define GOTGCTL_AVALOEN BIT(4) -+#define GOTGCTL_VBVALOVAL BIT(3) -+#define GOTGCTL_VBVALOEN BIT(2) - #define GOTGCTL_SESREQ BIT(1) - #define GOTGCTL_SESREQSCS BIT(0) - -@@ -227,6 +233,8 @@ - #define GPVNDCTL HSOTG_REG(0x0034) - #define GGPIO HSOTG_REG(0x0038) - #define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16) -+#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21) -+#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22) - - #define GUID HSOTG_REG(0x003c) - #define GSNPSID HSOTG_REG(0x0040) -diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c -index 31e090ac9f1ec..b4cff8b079ec2 100644 ---- a/drivers/usb/dwc2/params.c -+++ b/drivers/usb/dwc2/params.c -@@ -163,6 +163,45 @@ static void dwc2_set_stm32f7_hsotg_params(struct dwc2_hsotg *hsotg) - p->host_perio_tx_fifo_size = 256; - } - -+static void dwc2_set_stm32mp1_fsotg_params(struct dwc2_hsotg *hsotg) -+{ -+ struct dwc2_core_params *p = &hsotg->params; -+ -+ p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; -+ p->speed = DWC2_SPEED_PARAM_FULL; -+ p->host_rx_fifo_size = 128; -+ p->host_nperio_tx_fifo_size = 96; -+ p->host_perio_tx_fifo_size = 96; -+ p->max_packet_count = 256; -+ p->phy_type = DWC2_PHY_TYPE_PARAM_FS; -+ p->i2c_enable = false; -+ p->activate_stm_fs_transceiver = true; -+ p->activate_stm_id_vb_detection = true; -+ p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; -+ p->power_down = DWC2_POWER_DOWN_PARAM_NONE; -+ p->host_support_fs_ls_low_power = true; -+ p->host_ls_low_power_phy_clk = true; -+} -+ -+static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_hsotg *hsotg) -+{ -+ struct dwc2_core_params *p = &hsotg->params; -+ struct device_node *np = hsotg->dev->of_node; -+ -+ p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; -+ p->activate_stm_id_vb_detection = -+ !of_property_read_bool(np, "usb-role-switch"); -+ p->host_rx_fifo_size = 440; -+ p->host_nperio_tx_fifo_size = 256; -+ p->host_perio_tx_fifo_size = 256; -+ p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; -+ p->power_down = DWC2_POWER_DOWN_PARAM_NONE; -+ p->lpm = false; -+ p->lpm_clock_gating = false; -+ p->besl = false; -+ p->hird_threshold_en = false; -+} -+ - const struct of_device_id dwc2_of_match_table[] = { - { .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params }, - { .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params }, -@@ -186,6 +225,10 @@ const struct of_device_id dwc2_of_match_table[] = { - { .compatible = "st,stm32f4x9-hsotg" }, - { .compatible = "st,stm32f7-hsotg", - .data = dwc2_set_stm32f7_hsotg_params }, -+ { .compatible = "st,stm32mp1-fsotg", -+ .data = dwc2_set_stm32mp1_fsotg_params }, -+ { .compatible = "st,stm32mp1-hsotg", -+ .data = dwc2_set_stm32mp1_hsotg_params }, - {}, - }; - MODULE_DEVICE_TABLE(of, dwc2_of_match_table); -diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c -index 4e14c4f7fed7a..0acbf58020ea8 100644 ---- a/drivers/usb/dwc2/platform.c -+++ b/drivers/usb/dwc2/platform.c -@@ -312,6 +312,11 @@ static int dwc2_driver_remove(struct platform_device *dev) - if (hsotg->gadget_enabled) - dwc2_hsotg_remove(hsotg); - -+ dwc2_drd_exit(hsotg); -+ -+ if (hsotg->params.activate_stm_id_vb_detection) -+ regulator_disable(hsotg->usb33d); -+ - if (hsotg->ll_hw_enabled) - dwc2_lowlevel_hw_disable(hsotg); - -@@ -465,10 +470,40 @@ static int dwc2_driver_probe(struct platform_device *dev) - if (retval) - goto error; - -+ if (hsotg->params.activate_stm_id_vb_detection) { -+ u32 ggpio; -+ -+ hsotg->usb33d = devm_regulator_get(hsotg->dev, "usb33d"); -+ if (IS_ERR(hsotg->usb33d)) { -+ retval = PTR_ERR(hsotg->usb33d); -+ dev_err(hsotg->dev, -+ "can't get voltage level detector supply\n"); -+ goto error; -+ } -+ retval = regulator_enable(hsotg->usb33d); -+ if (retval) { -+ dev_err(hsotg->dev, -+ "can't enable voltage level detector supply\n"); -+ goto error; -+ } -+ -+ ggpio = dwc2_readl(hsotg, GGPIO); -+ ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN; -+ ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN; -+ dwc2_writel(hsotg, ggpio, GGPIO); -+ } -+ -+ retval = dwc2_drd_init(hsotg); -+ if (retval) { -+ if (retval != -EPROBE_DEFER) -+ dev_err(hsotg->dev, "failed to initialize dual-role\n"); -+ goto error_init; -+ } -+ - if (hsotg->dr_mode != USB_DR_MODE_HOST) { - retval = dwc2_gadget_init(hsotg); - if (retval) -- goto error; -+ goto error_drd; - hsotg->gadget_enabled = 1; - } - -@@ -494,7 +529,7 @@ static int dwc2_driver_probe(struct platform_device *dev) - if (retval) { - if (hsotg->gadget_enabled) - dwc2_hsotg_remove(hsotg); -- goto error; -+ goto error_drd; - } - hsotg->hcd_enabled = 1; - } -@@ -521,6 +556,11 @@ static int dwc2_driver_probe(struct platform_device *dev) - #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */ - return 0; - -+error_drd: -+ dwc2_drd_exit(hsotg); -+error_init: -+ if (hsotg->params.activate_stm_id_vb_detection) -+ regulator_disable(hsotg->usb33d); - error: - dwc2_lowlevel_hw_disable(hsotg); - return retval; -@@ -535,12 +575,61 @@ static int __maybe_unused dwc2_suspend(struct device *dev) - if (is_device_mode) - dwc2_hsotg_suspend(dwc2); - -+ dwc2_drd_suspend(dwc2); -+ -+ if (dwc2->params.power_down == DWC2_POWER_DOWN_PARAM_NONE) { -+ /* -+ * Backup host registers when power_down param is 'none', if -+ * controller power is disabled. -+ * This shouldn't be needed, when using other power_down modes. -+ */ -+ ret = dwc2_backup_registers(dwc2); -+ if (ret) { -+ dev_err(dwc2->dev, "backup regs failed %d\n", ret); -+ return ret; -+ } -+ } -+ -+ if (dwc2->params.activate_stm_id_vb_detection) { -+ unsigned long flags; -+ u32 ggpio, gotgctl; -+ -+ /* -+ * Need to force the mode to the current mode to avoid Mode -+ * Mismatch Interrupt when ID detection will be disabled. -+ */ -+ dwc2_force_mode(dwc2, !is_device_mode); -+ -+ spin_lock_irqsave(&dwc2->lock, flags); -+ gotgctl = dwc2_readl(dwc2, GOTGCTL); -+ /* bypass debounce filter, enable overrides */ -+ gotgctl |= GOTGCTL_DBNCE_FLTR_BYPASS; -+ gotgctl |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN; -+ /* Force A / B session if needed */ -+ if (gotgctl & GOTGCTL_ASESVLD) -+ gotgctl |= GOTGCTL_AVALOVAL; -+ if (gotgctl & GOTGCTL_BSESVLD) -+ gotgctl |= GOTGCTL_BVALOVAL; -+ dwc2_writel(dwc2, gotgctl, GOTGCTL); -+ spin_unlock_irqrestore(&dwc2->lock, flags); -+ -+ ggpio = dwc2_readl(dwc2, GGPIO); -+ ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN; -+ ggpio &= ~GGPIO_STM32_OTG_GCCFG_VBDEN; -+ dwc2_writel(dwc2, ggpio, GGPIO); -+ -+ regulator_disable(dwc2->usb33d); -+ } -+ - if (dwc2->ll_hw_enabled && - (is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) { - ret = __dwc2_lowlevel_hw_disable(dwc2); - dwc2->phy_off_for_suspend = true; - } - -+ if (device_may_wakeup(dev) || device_wakeup_path(dev)) -+ enable_irq_wake(dwc2->irq); -+ - return ret; - } - -@@ -549,6 +638,9 @@ static int __maybe_unused dwc2_resume(struct device *dev) - struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); - int ret = 0; - -+ if (device_may_wakeup(dev) || device_wakeup_path(dev)) -+ disable_irq_wake(dwc2->irq); -+ - if (dwc2->phy_off_for_suspend && dwc2->ll_hw_enabled) { - ret = __dwc2_lowlevel_hw_enable(dwc2); - if (ret) -@@ -556,6 +648,41 @@ static int __maybe_unused dwc2_resume(struct device *dev) - } - dwc2->phy_off_for_suspend = false; - -+ if (dwc2->params.activate_stm_id_vb_detection) { -+ unsigned long flags; -+ u32 ggpio, gotgctl; -+ -+ ret = regulator_enable(dwc2->usb33d); -+ if (ret) -+ return ret; -+ -+ ggpio = dwc2_readl(dwc2, GGPIO); -+ ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN; -+ ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN; -+ dwc2_writel(dwc2, ggpio, GGPIO); -+ -+ /* ID/VBUS detection startup time */ -+ usleep_range(5000, 7000); -+ -+ spin_lock_irqsave(&dwc2->lock, flags); -+ gotgctl = dwc2_readl(dwc2, GOTGCTL); -+ gotgctl &= ~GOTGCTL_DBNCE_FLTR_BYPASS; -+ gotgctl &= ~(GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | -+ GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL); -+ dwc2_writel(dwc2, gotgctl, GOTGCTL); -+ spin_unlock_irqrestore(&dwc2->lock, flags); -+ } -+ -+ if (dwc2->params.power_down == DWC2_POWER_DOWN_PARAM_NONE) { -+ ret = dwc2_restore_registers(dwc2); -+ if (ret) { -+ dev_err(dwc2->dev, "restore regs failed %d\n", ret); -+ return ret; -+ } -+ } -+ -+ dwc2_drd_resume(dwc2); -+ - if (dwc2_is_device_mode(dwc2)) - ret = dwc2_hsotg_resume(dwc2); - -diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c -index 9fc98de836249..7800593735659 100644 ---- a/drivers/usb/gadget/function/f_acm.c -+++ b/drivers/usb/gadget/function/f_acm.c -@@ -723,6 +723,20 @@ static void acm_free_func(struct usb_function *f) - kfree(acm); - } - -+static void acm_resume(struct usb_function *f) -+{ -+ struct f_acm *acm = func_to_acm(f); -+ -+ gserial_resume(&acm->port); -+} -+ -+static void acm_suspend(struct usb_function *f) -+{ -+ struct f_acm *acm = func_to_acm(f); -+ -+ gserial_suspend(&acm->port); -+} -+ - static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) - { - struct f_serial_opts *opts; -@@ -750,6 +764,8 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) - acm->port_num = opts->port_num; - acm->port.func.unbind = acm_unbind; - acm->port.func.free_func = acm_free_func; -+ acm->port.func.resume = acm_resume; -+ acm->port.func.suspend = acm_suspend; - - return &acm->port.func; - } -diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c -index c860f30a0ea2b..b2fb6b7424e98 100644 ---- a/drivers/usb/gadget/function/f_serial.c -+++ b/drivers/usb/gadget/function/f_serial.c -@@ -327,6 +327,20 @@ static void gser_unbind(struct usb_configuration *c, struct usb_function *f) - usb_free_all_descriptors(f); - } - -+static void gser_resume(struct usb_function *f) -+{ -+ struct f_gser *gser = func_to_gser(f); -+ -+ gserial_resume(&gser->port); -+} -+ -+static void gser_suspend(struct usb_function *f) -+{ -+ struct f_gser *gser = func_to_gser(f); -+ -+ gserial_suspend(&gser->port); -+} -+ - static struct usb_function *gser_alloc(struct usb_function_instance *fi) - { - struct f_gser *gser; -@@ -348,6 +362,8 @@ static struct usb_function *gser_alloc(struct usb_function_instance *fi) - gser->port.func.set_alt = gser_set_alt; - gser->port.func.disable = gser_disable; - gser->port.func.free_func = gser_free; -+ gser->port.func.resume = gser_resume; -+ gser->port.func.suspend = gser_suspend; - - return &gser->port.func; - } -diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c -index 038c445a4e9b5..3c144621ad935 100644 ---- a/drivers/usb/gadget/function/u_serial.c -+++ b/drivers/usb/gadget/function/u_serial.c -@@ -119,6 +119,8 @@ struct gs_port { - wait_queue_head_t drain_wait; /* wait while writes drain */ - bool write_busy; - wait_queue_head_t close_wait; -+ bool suspended; /* port suspended */ -+ bool start_delayed; /* delay start when suspended */ - - /* REVISIT this state ... */ - struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ -@@ -666,13 +668,19 @@ static int gs_open(struct tty_struct *tty, struct file *file) - - /* if connected, start the I/O stream */ - if (port->port_usb) { -- struct gserial *gser = port->port_usb; -+ /* if port is suspended, wait resume to start I/0 stream */ -+ if (!port->suspended) { -+ struct gserial *gser = port->port_usb; - -- pr_debug("gs_open: start ttyGS%d\n", port->port_num); -- gs_start_io(port); -+ pr_debug("gs_open: start ttyGS%d\n", port->port_num); -+ gs_start_io(port); - -- if (gser->connect) -- gser->connect(gser); -+ if (gser->connect) -+ gser->connect(gser); -+ } else { -+ pr_debug("delay start of ttyGS%d\n", port->port_num); -+ port->start_delayed = true; -+ } - } - - pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file); -@@ -720,7 +728,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) - port->port.count = 0; - - gser = port->port_usb; -- if (gser && gser->disconnect) -+ if (gser && !port->suspended && gser->disconnect) - gser->disconnect(gser); - - /* wait for circular write buffer to drain, disconnect, or at -@@ -744,6 +752,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) - else - kfifo_reset(&port->port_write_buf); - -+ port->start_delayed = false; - port->port.tty = NULL; - - port->openclose = false; -@@ -1395,6 +1404,38 @@ void gserial_disconnect(struct gserial *gser) - } - EXPORT_SYMBOL_GPL(gserial_disconnect); - -+void gserial_suspend(struct gserial *gser) -+{ -+ struct gs_port *port = gser->ioport; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&port->port_lock, flags); -+ port->suspended = true; -+ spin_unlock_irqrestore(&port->port_lock, flags); -+} -+EXPORT_SYMBOL_GPL(gserial_suspend); -+ -+void gserial_resume(struct gserial *gser) -+{ -+ struct gs_port *port = gser->ioport; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&port->port_lock, flags); -+ port->suspended = false; -+ if (!port->start_delayed) { -+ spin_unlock_irqrestore(&port->port_lock, flags); -+ return; -+ } -+ -+ pr_debug("delayed start ttyGS%d\n", port->port_num); -+ gs_start_io(port); -+ if (gser->connect) -+ gser->connect(gser); -+ port->start_delayed = false; -+ spin_unlock_irqrestore(&port->port_lock, flags); -+} -+EXPORT_SYMBOL_GPL(gserial_resume); -+ - static int userial_init(void) - { - unsigned i; -diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h -index 9acaac1cbb75a..223a4be05afe7 100644 ---- a/drivers/usb/gadget/function/u_serial.h -+++ b/drivers/usb/gadget/function/u_serial.h -@@ -60,6 +60,8 @@ void gserial_free_line(unsigned char port_line); - /* connect/disconnect is handled by individual functions */ - int gserial_connect(struct gserial *, u8 port_num); - void gserial_disconnect(struct gserial *); -+void gserial_suspend(struct gserial *p); -+void gserial_resume(struct gserial *p); - - /* functions are bound to configurations by a config or gadget driver */ - int gser_bind_config(struct usb_configuration *c, u8 port_num); -diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c -index e4fc3f66d43bf..db436d432e723 100644 ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - - #include "ehci.h" - -@@ -430,6 +431,9 @@ static int ehci_platform_suspend(struct device *dev) - if (pdata->power_suspend) - pdata->power_suspend(pdev); - -+ if (device_may_wakeup(dev) || device_wakeup_path(dev)) -+ enable_irq_wake(hcd->irq); -+ - return ret; - } - -@@ -441,6 +445,9 @@ static int ehci_platform_resume(struct device *dev) - struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); - struct device *companion_dev; - -+ if (device_may_wakeup(dev) || device_wakeup_path(dev)) -+ disable_irq_wake(hcd->irq); -+ - if (pdata->power_on) { - int err = pdata->power_on(pdev); - if (err < 0) -diff --git a/drivers/usb/renesas_usbhs/rcar2.c b/drivers/usb/renesas_usbhs/rcar2.c -index 440d213e1749d..791908f8cf73e 100644 ---- a/drivers/usb/renesas_usbhs/rcar2.c -+++ b/drivers/usb/renesas_usbhs/rcar2.c -@@ -34,7 +34,7 @@ static int usbhs_rcar2_hardware_exit(struct platform_device *pdev) - struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); - - if (priv->phy) { -- phy_put(priv->phy); -+ phy_put(&pdev->dev, priv->phy); - priv->phy = NULL; - } - -diff --git a/drivers/usb/renesas_usbhs/rza2.c b/drivers/usb/renesas_usbhs/rza2.c -index 021749594389e..3eed3334a17f1 100644 ---- a/drivers/usb/renesas_usbhs/rza2.c -+++ b/drivers/usb/renesas_usbhs/rza2.c -@@ -29,7 +29,7 @@ static int usbhs_rza2_hardware_exit(struct platform_device *pdev) - { - struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); - -- phy_put(priv->phy); -+ phy_put(&pdev->dev, priv->phy); - priv->phy = NULL; - - return 0; -diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig -index 895e2418de53b..3a1ee89be74e4 100644 ---- a/drivers/usb/typec/Kconfig -+++ b/drivers/usb/typec/Kconfig -@@ -61,6 +61,15 @@ config TYPEC_TPS6598X - If you choose to build this driver as a dynamically linked module, the - module will be called tps6598x.ko. - -+config TYPEC_STUSB -+ tristate "STMicroelectronics STUSB Type-C controller driver" -+ depends on I2C -+ select USB_ROLE_SWITCH -+ help -+ The STMicroelectronics STUSB Type-C controller driver that works -+ with Type-C Port Controller Manager to provide USB Type-C -+ functionalities. -+ - source "drivers/usb/typec/mux/Kconfig" - - source "drivers/usb/typec/altmodes/Kconfig" -diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile -index 6696b7263d61a..c9136020e4f3e 100644 ---- a/drivers/usb/typec/Makefile -+++ b/drivers/usb/typec/Makefile -@@ -5,4 +5,5 @@ obj-$(CONFIG_TYPEC) += altmodes/ - obj-$(CONFIG_TYPEC_TCPM) += tcpm/ - obj-$(CONFIG_TYPEC_UCSI) += ucsi/ - obj-$(CONFIG_TYPEC_TPS6598X) += tps6598x.o -+obj-$(CONFIG_TYPEC_STUSB) += typec_stusb.o - obj-$(CONFIG_TYPEC) += mux/ -diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c -index a400b65cf17bb..6391d01015d17 100644 ---- a/drivers/usb/typec/class.c -+++ b/drivers/usb/typec/class.c -@@ -1387,6 +1387,21 @@ void typec_set_pwr_opmode(struct typec_port *port, - } - EXPORT_SYMBOL_GPL(typec_set_pwr_opmode); - -+/** -+ * typec_find_power_opmode - Get the typec port power operation mode -+ * @name: port power operation mode string -+ * -+ * This routine is used to find the typec_pwr_opmodes by its string name. -+ * -+ * Returns typec_pwr_opmodes if success, otherwise negative error code. -+ */ -+int typec_find_port_power_opmode(const char *name) -+{ -+ return match_string(typec_pwr_opmodes, -+ ARRAY_SIZE(typec_pwr_opmodes), name); -+} -+EXPORT_SYMBOL_GPL(typec_find_port_power_opmode); -+ - /** - * typec_find_port_power_role - Get the typec port power capability - * @name: port power capability string -diff --git a/drivers/usb/typec/typec_stusb.c b/drivers/usb/typec/typec_stusb.c -new file mode 100644 -index 0000000000000..e760ba304f854 ---- /dev/null -+++ b/drivers/usb/typec/typec_stusb.c -@@ -0,0 +1,910 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * STMicroelectronics STUSB Type-C controller family driver -+ * -+ * Copyright (C) 2019, STMicroelectronics -+ * Author(s): Amelie Delaunay -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define STUSB_ALERT_STATUS 0x0B /* RC */ -+#define STUSB_ALERT_STATUS_MASK_CTRL 0x0C /* RW */ -+#define STUSB_CC_CONNECTION_STATUS_TRANS 0x0D /* RC */ -+#define STUSB_CC_CONNECTION_STATUS 0x0E /* RO */ -+#define STUSB_MONITORING_STATUS_TRANS 0x0F /* RC */ -+#define STUSB_MONITORING_STATUS 0x10 /* RO */ -+#define STUSB_CC_OPERATION_STATUS 0x11 /* RO */ -+#define STUSB_HW_FAULT_STATUS_TRANS 0x12 /* RC */ -+#define STUSB_HW_FAULT_STATUS 0x13 /* RO */ -+#define STUSB_CC_CAPABILITY_CTRL 0x18 /* RW */ -+#define STUSB_CC_VCONN_SWITCH_CTRL 0x1E /* RW */ -+#define STUSB_VCONN_MONITORING_CTRL 0x20 /* RW */ -+#define STUSB_VBUS_MONITORING_RANGE_CTRL 0x22 /* RW */ -+#define STUSB_RESET_CTRL 0x23 /* RW */ -+#define STUSB_VBUS_DISCHARGE_TIME_CTRL 0x25 /* RW */ -+#define STUSB_VBUS_DISCHARGE_STATUS 0x26 /* RO */ -+#define STUSB_VBUS_ENABLE_STATUS 0x27 /* RO */ -+#define STUSB_CC_POWER_MODE_CTRL 0x28 /* RW */ -+#define STUSB_VBUS_MONITORING_CTRL 0x2E /* RW */ -+#define STUSB1600_REG_MAX 0x2F /* RO - Reserved */ -+ -+/* STUSB_ALERT_STATUS/STUSB_ALERT_STATUS_MASK_CTRL bitfields */ -+#define STUSB_HW_FAULT BIT(4) -+#define STUSB_MONITORING BIT(5) -+#define STUSB_CC_CONNECTION BIT(6) -+#define STUSB_ALL_ALERTS GENMASK(6, 4) -+ -+/* STUSB_CC_CONNECTION_STATUS_TRANS bitfields */ -+#define STUSB_CC_ATTACH_TRANS BIT(0) -+ -+/* STUSB_CC_CONNECTION_STATUS bitfields */ -+#define STUSB_CC_ATTACH BIT(0) -+#define STUSB_CC_VCONN_SUPPLY BIT(1) -+#define STUSB_CC_DATA_ROLE(s) (!!((s) & BIT(2))) -+#define STUSB_CC_POWER_ROLE(s) (!!((s) & BIT(3))) -+#define STUSB_CC_ATTACHED_MODE GENMASK(7, 5) -+ -+/* STUSB_MONITORING_STATUS_TRANS bitfields */ -+#define STUSB_VCONN_PRESENCE_TRANS BIT(0) -+#define STUSB_VBUS_PRESENCE_TRANS BIT(1) -+#define STUSB_VBUS_VSAFE0V_TRANS BIT(2) -+#define STUSB_VBUS_VALID_TRANS BIT(3) -+ -+/* STUSB_MONITORING_STATUS bitfields */ -+#define STUSB_VCONN_PRESENCE BIT(0) -+#define STUSB_VBUS_PRESENCE BIT(1) -+#define STUSB_VBUS_VSAFE0V BIT(2) -+#define STUSB_VBUS_VALID BIT(3) -+ -+/* STUSB_CC_OPERATION_STATUS bitfields */ -+#define STUSB_TYPEC_FSM_STATE GENMASK(4, 0) -+#define STUSB_SINK_POWER_STATE GENMASK(6, 5) -+#define STUSB_CC_ATTACHED BIT(7) -+ -+/* STUSB_HW_FAULT_STATUS_TRANS bitfields */ -+#define STUSB_VCONN_SW_OVP_FAULT_TRANS BIT(0) -+#define STUSB_VCONN_SW_OCP_FAULT_TRANS BIT(1) -+#define STUSB_VCONN_SW_RVP_FAULT_TRANS BIT(2) -+#define STUSB_VPU_VALID_TRANS BIT(4) -+#define STUSB_VPU_OVP_FAULT_TRANS BIT(5) -+#define STUSB_THERMAL_FAULT BIT(7) -+ -+/* STUSB_HW_FAULT_STATUS bitfields */ -+#define STUSB_VCONN_SW_OVP_FAULT_CC2 BIT(0) -+#define STUSB_VCONN_SW_OVP_FAULT_CC1 BIT(1) -+#define STUSB_VCONN_SW_OCP_FAULT_CC2 BIT(2) -+#define STUSB_VCONN_SW_OCP_FAULT_CC1 BIT(3) -+#define STUSB_VCONN_SW_RVP_FAULT_CC2 BIT(4) -+#define STUSB_VCONN_SW_RVP_FAULT_CC1 BIT(5) -+#define STUSB_VPU_VALID BIT(6) -+#define STUSB_VPU_OVP_FAULT BIT(7) -+ -+/* STUSB_CC_CAPABILITY_CTRL bitfields */ -+#define STUSB_CC_VCONN_SUPPLY_EN BIT(0) -+#define STUSB_CC_VCONN_DISCHARGE_EN BIT(4) -+#define STUSB_CC_CURRENT_ADVERTISED GENMASK(7, 6) -+ -+/* STUSB_VCONN_SWITCH_CTRL bitfields */ -+#define STUSB_CC_VCONN_SWITCH_ILIM GENMASK(3, 0) -+ -+/* STUSB_VCONN_MONITORING_CTRL bitfields */ -+#define STUSB_VCONN_UVLO_THRESHOLD BIT(6) -+#define STUSB_VCONN_MONITORING_EN BIT(7) -+ -+/* STUSB_VBUS_MONITORING_RANGE_CTRL bitfields */ -+#define STUSB_SHIFT_LOW_VBUS_LIMIT GENMASK(3, 0) -+#define STUSB_SHIFT_HIGH_VBUS_LIMIT GENMASK(7, 4) -+ -+/* STUSB_RESET_CTRL bitfields */ -+#define STUSB_SW_RESET_EN BIT(0) -+ -+/* STUSB_VBUS_DISCHARGE_TIME_CTRL bitfields */ -+#define STUSBXX02_VBUS_DISCHARGE_TIME_TO_PDO GENMASK(3, 0) -+#define STUSB_VBUS_DISCHARGE_TIME_TO_0V GENMASK(7, 4) -+ -+/* STUSB_VBUS_DISCHARGE_STATUS bitfields */ -+#define STUSB_VBUS_DISCHARGE_EN BIT(7) -+ -+/* STUSB_VBUS_ENABLE_STATUS bitfields */ -+#define STUSB_VBUS_SOURCE_EN BIT(0) -+#define STUSB_VBUS_SINK_EN BIT(1) -+ -+/* STUSB_CC_POWER_MODE_CTRL bitfields */ -+#define STUSB_CC_POWER_MODE GENMASK(2, 0) -+ -+/* STUSB_VBUS_MONITORING_CTRL bitfields */ -+#define STUSB_VDD_UVLO_DISABLE BIT(0) -+#define STUSB_VBUS_VSAFE0V_THRESHOLD GENMASK(2, 1) -+#define STUSB_VBUS_RANGE_DISABLE BIT(4) -+#define STUSB_VDD_OVLO_DISABLE BIT(6) -+ -+enum stusb_pwr_mode { -+ SOURCE_WITH_ACCESSORY, -+ SINK_WITH_ACCESSORY, -+ SINK_WITHOUT_ACCESSORY, -+ DUAL_WITH_ACCESSORY, -+ DUAL_WITH_ACCESSORY_AND_TRY_SRC, -+ DUAL_WITH_ACCESSORY_AND_TRY_SNK, -+}; -+ -+enum stusb_attached_mode { -+ NO_DEVICE_ATTACHED, -+ SINK_ATTACHED, -+ SOURCE_ATTACHED, -+ DEBUG_ACCESSORY_ATTACHED, -+ AUDIO_ACCESSORY_ATTACHED, -+}; -+ -+struct stusb { -+ struct device *dev; -+ struct regmap *regmap; -+ struct regulator *vdd_supply; -+ struct regulator *vsys_supply; -+ struct regulator *vconn_supply; -+ struct regulator *main_supply; -+ -+ struct typec_port *port; -+ struct typec_capability capability; -+ struct typec_partner *partner; -+ -+ enum typec_port_type port_type; -+ enum typec_pwr_opmode pwr_opmode; -+ bool vbus_on; -+ -+ struct usb_role_switch *role_sw; -+ struct work_struct wq_role_sw; -+}; -+ -+static bool stusb_reg_writeable(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case STUSB_ALERT_STATUS_MASK_CTRL: -+ case STUSB_CC_CAPABILITY_CTRL: -+ case STUSB_CC_VCONN_SWITCH_CTRL: -+ case STUSB_VCONN_MONITORING_CTRL: -+ case STUSB_VBUS_MONITORING_RANGE_CTRL: -+ case STUSB_RESET_CTRL: -+ case STUSB_VBUS_DISCHARGE_TIME_CTRL: -+ case STUSB_CC_POWER_MODE_CTRL: -+ case STUSB_VBUS_MONITORING_CTRL: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool stusb_reg_readable(struct device *dev, unsigned int reg) -+{ -+ if (reg <= 0x0A || -+ (reg >= 0x14 && reg <= 0x17) || -+ (reg >= 0x19 && reg <= 0x1D) || -+ (reg >= 0x29 && reg <= 0x2D) || -+ (reg == 0x1F || reg == 0x21 || reg == 0x24 || reg == 0x2F)) -+ return false; -+ else -+ return true; -+} -+ -+static bool stusb_reg_volatile(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case STUSB_ALERT_STATUS: -+ case STUSB_CC_CONNECTION_STATUS_TRANS: -+ case STUSB_CC_CONNECTION_STATUS: -+ case STUSB_MONITORING_STATUS_TRANS: -+ case STUSB_MONITORING_STATUS: -+ case STUSB_CC_OPERATION_STATUS: -+ case STUSB_HW_FAULT_STATUS_TRANS: -+ case STUSB_HW_FAULT_STATUS: -+ case STUSB_VBUS_DISCHARGE_STATUS: -+ case STUSB_VBUS_ENABLE_STATUS: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static bool stusb_reg_precious(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case STUSB_ALERT_STATUS: -+ case STUSB_CC_CONNECTION_STATUS_TRANS: -+ case STUSB_MONITORING_STATUS_TRANS: -+ case STUSB_HW_FAULT_STATUS_TRANS: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static const struct regmap_config stusb1600_regmap_config = { -+ .reg_bits = 8, -+ .reg_stride = 1, -+ .val_bits = 8, -+ .max_register = STUSB1600_REG_MAX, -+ .writeable_reg = stusb_reg_writeable, -+ .readable_reg = stusb_reg_readable, -+ .volatile_reg = stusb_reg_volatile, -+ .precious_reg = stusb_reg_precious, -+ .cache_type = REGCACHE_RBTREE, -+}; -+ -+static bool stusb_get_vconn(struct stusb *chip) -+{ -+ u32 val; -+ int ret; -+ -+ ret = regmap_read(chip->regmap, STUSB_CC_CAPABILITY_CTRL, &val); -+ if (ret) { -+ dev_err(chip->dev, "Unable to get Vconn status: %d\n", ret); -+ return false; -+ } -+ -+ return !!FIELD_GET(STUSB_CC_VCONN_SUPPLY_EN, val); -+} -+ -+static int stusb_set_vconn(struct stusb *chip, bool on) -+{ -+ int ret; -+ -+ /* Manage VCONN input supply */ -+ if (chip->vconn_supply) { -+ if (on) { -+ ret = regulator_enable(chip->vconn_supply); -+ if (ret) { -+ dev_err(chip->dev, -+ "failed to enable vconn supply: %d\n", -+ ret); -+ return ret; -+ } -+ } else { -+ regulator_disable(chip->vconn_supply); -+ } -+ } -+ -+ /* Manage VCONN monitoring and power path */ -+ ret = regmap_update_bits(chip->regmap, STUSB_VCONN_MONITORING_CTRL, -+ STUSB_VCONN_MONITORING_EN, -+ on ? STUSB_VCONN_MONITORING_EN : 0); -+ if (ret) -+ goto vconn_reg_disable; -+ -+ return 0; -+ -+vconn_reg_disable: -+ if (chip->vconn_supply && on) -+ regulator_disable(chip->vconn_supply); -+ -+ return ret; -+} -+ -+static enum typec_pwr_opmode stusb_get_pwr_opmode(struct stusb *chip) -+{ -+ u32 val; -+ int ret; -+ -+ ret = regmap_read(chip->regmap, STUSB_CC_CAPABILITY_CTRL, &val); -+ if (ret) { -+ dev_err(chip->dev, "Unable to get pwr opmode: %d\n", ret); -+ return TYPEC_PWR_MODE_USB; -+ } -+ -+ return FIELD_GET(STUSB_CC_CURRENT_ADVERTISED, val); -+} -+ -+static enum typec_accessory stusb_get_accessory(u32 status) -+{ -+ enum stusb_attached_mode mode; -+ -+ mode = FIELD_GET(STUSB_CC_ATTACHED_MODE, status); -+ -+ switch (mode) { -+ case DEBUG_ACCESSORY_ATTACHED: -+ return TYPEC_ACCESSORY_DEBUG; -+ case AUDIO_ACCESSORY_ATTACHED: -+ return TYPEC_ACCESSORY_AUDIO; -+ default: -+ return TYPEC_ACCESSORY_NONE; -+ } -+} -+ -+static enum typec_role stusb_get_vconn_role(u32 status) -+{ -+ if (FIELD_GET(STUSB_CC_VCONN_SUPPLY, status)) -+ return TYPEC_SOURCE; -+ else -+ return TYPEC_SINK; -+} -+ -+static void stusb_set_role_sw(struct work_struct *work) -+{ -+ struct stusb *chip = container_of(work, struct stusb, wq_role_sw); -+ enum usb_role usb_role = USB_ROLE_NONE; -+ u32 conn_status, vbus_status; -+ bool id, vbus; -+ int ret; -+ -+ /* Check ID and Vbus to update state */ -+ ret = regmap_read(chip->regmap, STUSB_CC_CONNECTION_STATUS, -+ &conn_status); -+ if (ret) -+ return; -+ -+ ret = regmap_read(chip->regmap, STUSB_VBUS_ENABLE_STATUS, -+ &vbus_status); -+ if (ret) -+ return; -+ -+ /* 0 = Device, 1 = Host */ -+ id = STUSB_CC_DATA_ROLE(conn_status); -+ -+ if (STUSB_CC_POWER_ROLE(conn_status)) /* Source */ -+ vbus = !!(vbus_status & STUSB_VBUS_SOURCE_EN); -+ else /* Sink */ -+ vbus = !!(vbus_status & STUSB_VBUS_SINK_EN); -+ -+ dev_dbg(chip->dev, "role=%s vbus=%sable\n", -+ id ? "Host" : "Device", vbus ? "en" : "dis"); -+ -+ /* -+ * !vbus = detached, so neither B-Session Valid nor A-Session Valid -+ * !vbus = USB_ROLE_NONE -+ * vbus = attached, so either B-Session Valid or A-Session Valid -+ * vbus && !id = B-Session Valid = USB_ROLE_DEVICE -+ * vbus && id = A-Session Valid = USB_ROLE_HOST -+ */ -+ if (vbus && id) /* Attached and A-Session Valid */ -+ usb_role = USB_ROLE_HOST; -+ if (vbus && !id) /* Attached and B-Session Valid */ -+ usb_role = USB_ROLE_DEVICE; -+ -+ usb_role_switch_set_role(chip->role_sw, usb_role); -+} -+ -+static int stusb_attach(struct stusb *chip, u32 status) -+{ -+ struct typec_partner_desc desc; -+ int ret; -+ -+ if ((STUSB_CC_POWER_ROLE(status) == TYPEC_SOURCE) && -+ chip->vdd_supply) { -+ ret = regulator_enable(chip->vdd_supply); -+ if (ret) { -+ dev_err(chip->dev, -+ "Failed to enable Vbus supply: %d\n", ret); -+ return ret; -+ } -+ chip->vbus_on = true; -+ } -+ -+ desc.usb_pd = false; -+ desc.accessory = stusb_get_accessory(status); -+ desc.identity = NULL; -+ -+ chip->partner = typec_register_partner(chip->port, &desc); -+ if (IS_ERR(chip->partner)) { -+ ret = PTR_ERR(chip->partner); -+ goto vbus_disable; -+ } -+ -+ typec_set_pwr_role(chip->port, STUSB_CC_POWER_ROLE(status)); -+ typec_set_pwr_opmode(chip->port, stusb_get_pwr_opmode(chip)); -+ typec_set_vconn_role(chip->port, stusb_get_vconn_role(status)); -+ typec_set_data_role(chip->port, STUSB_CC_DATA_ROLE(status)); -+ -+ if (chip->role_sw) -+ queue_work(system_power_efficient_wq, &chip->wq_role_sw); -+ -+ return 0; -+ -+vbus_disable: -+ if (chip->vbus_on) { -+ regulator_disable(chip->vdd_supply); -+ chip->vbus_on = false; -+ } -+ -+ return ret; -+} -+ -+static void stusb_detach(struct stusb *chip, u32 status) -+{ -+ typec_unregister_partner(chip->partner); -+ chip->partner = NULL; -+ -+ typec_set_pwr_role(chip->port, STUSB_CC_POWER_ROLE(status)); -+ typec_set_pwr_opmode(chip->port, TYPEC_PWR_MODE_USB); -+ typec_set_vconn_role(chip->port, stusb_get_vconn_role(status)); -+ typec_set_data_role(chip->port, STUSB_CC_DATA_ROLE(status)); -+ -+ if (chip->vbus_on) { -+ regulator_disable(chip->vdd_supply); -+ chip->vbus_on = false; -+ } -+ -+ if (chip->role_sw) -+ queue_work(system_power_efficient_wq, &chip->wq_role_sw); -+} -+ -+static irqreturn_t stusb_irq_handler(int irq, void *data) -+{ -+ struct stusb *chip = data; -+ u32 pending, trans, status; -+ int ret; -+ -+ ret = regmap_read(chip->regmap, STUSB_ALERT_STATUS, &pending); -+ if (ret) -+ return IRQ_NONE; -+ -+ if (pending & STUSB_CC_CONNECTION) { -+ ret = regmap_read(chip->regmap, -+ STUSB_CC_CONNECTION_STATUS_TRANS, &trans); -+ if (ret) -+ goto err; -+ ret = regmap_read(chip->regmap, STUSB_CC_CONNECTION_STATUS, -+ &status); -+ if (ret) -+ goto err; -+ -+ if (trans & STUSB_CC_ATTACH_TRANS) { -+ if (status & STUSB_CC_ATTACH) { -+ ret = stusb_attach(chip, status); -+ if (ret) -+ goto err; -+ } else { -+ stusb_detach(chip, status); -+ } -+ } -+ } -+err: -+ return IRQ_HANDLED; -+} -+ -+static int stusb_irq_init(struct stusb *chip, int irq) -+{ -+ u32 status; -+ int ret; -+ -+ ret = regmap_read(chip->regmap, STUSB_CC_CONNECTION_STATUS, &status); -+ if (ret) -+ return ret; -+ -+ if (status & STUSB_CC_ATTACH) { -+ ret = stusb_attach(chip, status); -+ if (ret) -+ dev_err(chip->dev, "attach failed: %d\n", ret); -+ } -+ -+ ret = devm_request_threaded_irq(chip->dev, irq, NULL, stusb_irq_handler, -+ IRQF_ONESHOT, dev_name(chip->dev), -+ chip); -+ if (ret) -+ goto partner_unregister; -+ -+ /* Unmask CC_CONNECTION events */ -+ ret = regmap_write_bits(chip->regmap, STUSB_ALERT_STATUS_MASK_CTRL, -+ STUSB_CC_CONNECTION, 0); -+ if (ret) -+ goto partner_unregister; -+ -+ return 0; -+ -+partner_unregister: -+ if (chip->partner) { -+ typec_unregister_partner(chip->partner); -+ chip->partner = NULL; -+ } -+ -+ return ret; -+} -+ -+static int stusb_init(struct stusb *chip) -+{ -+ u32 val; -+ int ret; -+ -+ /* Change the default Type-C power mode */ -+ if (chip->port_type == TYPEC_PORT_SRC) -+ ret = regmap_update_bits(chip->regmap, -+ STUSB_CC_POWER_MODE_CTRL, -+ STUSB_CC_POWER_MODE, -+ SOURCE_WITH_ACCESSORY); -+ else if (chip->port_type == TYPEC_PORT_SNK) -+ ret = regmap_update_bits(chip->regmap, -+ STUSB_CC_POWER_MODE_CTRL, -+ STUSB_CC_POWER_MODE, -+ SINK_WITH_ACCESSORY); -+ else /* (capability->type == TYPEC_PORT_DRP) */ -+ ret = regmap_update_bits(chip->regmap, -+ STUSB_CC_POWER_MODE_CTRL, -+ STUSB_CC_POWER_MODE, -+ DUAL_WITH_ACCESSORY); -+ if (ret) -+ return ret; -+ -+ if (chip->port_type == TYPEC_PORT_SNK) -+ goto skip_src; -+ -+ /* Change the default Type-C Source power operation mode capability */ -+ ret = regmap_update_bits(chip->regmap, STUSB_CC_CAPABILITY_CTRL, -+ STUSB_CC_CURRENT_ADVERTISED, -+ FIELD_PREP(STUSB_CC_CURRENT_ADVERTISED, -+ chip->pwr_opmode)); -+ if (ret) -+ return ret; -+ -+ /* Manage Type-C Source Vconn supply */ -+ if (stusb_get_vconn(chip)) { -+ ret = stusb_set_vconn(chip, true); -+ if (ret) -+ return ret; -+ } -+ -+skip_src: -+ /* Mask all events interrupts - to be unmasked with interrupt support */ -+ ret = regmap_update_bits(chip->regmap, STUSB_ALERT_STATUS_MASK_CTRL, -+ STUSB_ALL_ALERTS, STUSB_ALL_ALERTS); -+ if (ret) -+ return ret; -+ -+ /* Read status at least once to clear any stale interrupts */ -+ regmap_read(chip->regmap, STUSB_ALERT_STATUS, &val); -+ regmap_read(chip->regmap, STUSB_CC_CONNECTION_STATUS_TRANS, &val); -+ regmap_read(chip->regmap, STUSB_MONITORING_STATUS_TRANS, &val); -+ regmap_read(chip->regmap, STUSB_HW_FAULT_STATUS_TRANS, &val); -+ -+ return 0; -+} -+ -+static int stusb_fw_get_caps(struct stusb *chip) -+{ -+ struct fwnode_handle *fwnode = device_get_named_child_node(chip->dev, -+ "connector"); -+ const char *cap_str; -+ int ret; -+ -+ if (!fwnode) -+ return -EINVAL; -+ -+ chip->capability.fwnode = fwnode; -+ -+ ret = fwnode_property_read_string(fwnode, "power-role", &cap_str); -+ if (!ret) { -+ chip->port_type = typec_find_port_power_role(cap_str); -+ if (chip->port_type < 0) -+ return -EINVAL; -+ -+ chip->capability.type = chip->port_type; -+ } -+ -+ if (chip->port_type == TYPEC_PORT_SNK) -+ goto sink; -+ -+ if (chip->port_type == TYPEC_PORT_DRP) -+ chip->capability.prefer_role = TYPEC_SINK; -+ -+ ret = fwnode_property_read_string(fwnode, "power-opmode", &cap_str); -+ if (!ret) { -+ chip->pwr_opmode = typec_find_port_power_opmode(cap_str); -+ -+ /* Power delivery not yet supported */ -+ if (chip->pwr_opmode < 0 || -+ chip->pwr_opmode == TYPEC_PWR_MODE_PD) { -+ dev_err(chip->dev, "bad power operation mode: %d\n", -+ chip->pwr_opmode); -+ return -EINVAL; -+ } -+ -+ } else { -+ chip->pwr_opmode = stusb_get_pwr_opmode(chip); -+ } -+ -+sink: -+ return 0; -+} -+ -+static int stusb_get_caps(struct stusb *chip, bool *try) -+{ -+ enum typec_port_type *type = &chip->capability.type; -+ enum typec_port_data *data = &chip->capability.data; -+ enum typec_accessory *accessory = chip->capability.accessory; -+ u32 val; -+ int ret; -+ -+ chip->capability.revision = USB_TYPEC_REV_1_2; -+ -+ ret = regmap_read(chip->regmap, STUSB_CC_POWER_MODE_CTRL, &val); -+ if (ret) -+ return ret; -+ -+ *try = false; -+ -+ switch (FIELD_GET(STUSB_CC_POWER_MODE, val)) { -+ case SOURCE_WITH_ACCESSORY: -+ *type = TYPEC_PORT_SRC; -+ *data = TYPEC_PORT_DFP; -+ *accessory++ = TYPEC_ACCESSORY_AUDIO; -+ *accessory++ = TYPEC_ACCESSORY_DEBUG; -+ break; -+ case SINK_WITH_ACCESSORY: -+ *type = TYPEC_PORT_SNK; -+ *data = TYPEC_PORT_UFP; -+ *accessory++ = TYPEC_ACCESSORY_AUDIO; -+ *accessory++ = TYPEC_ACCESSORY_DEBUG; -+ break; -+ case SINK_WITHOUT_ACCESSORY: -+ *type = TYPEC_PORT_SNK; -+ *data = TYPEC_PORT_UFP; -+ break; -+ case DUAL_WITH_ACCESSORY: -+ *type = TYPEC_PORT_DRP; -+ *data = TYPEC_PORT_DRD; -+ *accessory++ = TYPEC_ACCESSORY_AUDIO; -+ *accessory++ = TYPEC_ACCESSORY_DEBUG; -+ break; -+ case DUAL_WITH_ACCESSORY_AND_TRY_SRC: -+ case DUAL_WITH_ACCESSORY_AND_TRY_SNK: -+ *type = TYPEC_PORT_DRP; -+ *data = TYPEC_PORT_DRD; -+ *accessory++ = TYPEC_ACCESSORY_AUDIO; -+ *accessory++ = TYPEC_ACCESSORY_DEBUG; -+ *try = true; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ chip->port_type = *type; -+ -+ return stusb_fw_get_caps(chip); -+} -+ -+static const struct of_device_id stusb_of_match[] = { -+ { .compatible = "st,stusb1600", .data = &stusb1600_regmap_config}, -+ {}, -+}; -+ -+static int stusb_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct stusb *chip; -+ const struct of_device_id *match; -+ struct regmap_config *regmap_config; -+ bool try_role; -+ struct fwnode_handle *fwnode; -+ int ret; -+ -+ chip = devm_kzalloc(&client->dev, sizeof(struct stusb), GFP_KERNEL); -+ if (!chip) -+ return -ENOMEM; -+ -+ i2c_set_clientdata(client, chip); -+ -+ match = i2c_of_match_device(stusb_of_match, client); -+ regmap_config = (struct regmap_config *)match->data; -+ chip->regmap = devm_regmap_init_i2c(client, regmap_config); -+ if (IS_ERR(chip->regmap)) { -+ ret = PTR_ERR(chip->regmap); -+ dev_err(&client->dev, -+ "Failed to allocate register map:%d\n", ret); -+ return ret; -+ } -+ -+ chip->dev = &client->dev; -+ -+ chip->vsys_supply = devm_regulator_get_optional(chip->dev, "vsys"); -+ if (IS_ERR(chip->vsys_supply)) { -+ ret = PTR_ERR(chip->vsys_supply); -+ if (ret != -ENODEV) -+ return ret; -+ chip->vsys_supply = NULL; -+ } -+ -+ chip->vdd_supply = devm_regulator_get_optional(chip->dev, "vdd"); -+ if (IS_ERR(chip->vdd_supply)) { -+ ret = PTR_ERR(chip->vdd_supply); -+ if (ret != -ENODEV) -+ return ret; -+ chip->vdd_supply = NULL; -+ } -+ -+ chip->vconn_supply = devm_regulator_get_optional(chip->dev, "vconn"); -+ if (IS_ERR(chip->vconn_supply)) { -+ ret = PTR_ERR(chip->vconn_supply); -+ if (ret != -ENODEV) -+ return ret; -+ chip->vconn_supply = NULL; -+ } -+ -+ /* -+ * When both VDD and VSYS power supplies are present, the low power -+ * supply VSYS is selected when VSYS voltage is above 3.1 V. -+ * Otherwise VDD is selected. -+ */ -+ if (chip->vdd_supply && -+ (!chip->vsys_supply || -+ (regulator_get_voltage(chip->vsys_supply) <= 3100000))) -+ chip->main_supply = chip->vdd_supply; -+ else -+ chip->main_supply = chip->vsys_supply; -+ -+ if (chip->main_supply) { -+ ret = regulator_enable(chip->main_supply); -+ if (ret) { -+ dev_err(chip->dev, -+ "Failed to enable main supply: %d\n", ret); -+ return ret; -+ } -+ } -+ -+ ret = stusb_get_caps(chip, &try_role); -+ if (ret) { -+ dev_err(chip->dev, "Failed to get port caps: %d\n", ret); -+ goto main_reg_disable; -+ } -+ -+ ret = stusb_init(chip); -+ if (ret) { -+ dev_err(chip->dev, "Failed to init port: %d\n", ret); -+ goto main_reg_disable; -+ } -+ -+ chip->port = typec_register_port(chip->dev, &chip->capability); -+ if (!chip->port) { -+ ret = -ENODEV; -+ goto all_reg_disable; -+ } -+ -+ /* -+ * Default power operation mode initialization: will be updated upon -+ * attach/detach interrupt -+ */ -+ typec_set_pwr_opmode(chip->port, chip->pwr_opmode); -+ -+ if (!client->irq) { -+ /* -+ * If Source or Dual power role, need to enable VDD supply -+ * providing Vbus if present. In case of interrupt support, -+ * VDD supply will be dynamically managed upon attach/detach -+ * interrupt. -+ */ -+ if ((chip->port_type != TYPEC_PORT_SNK) && chip->vdd_supply) { -+ ret = regulator_enable(chip->vdd_supply); -+ if (ret) { -+ dev_err(chip->dev, -+ "Failed to enable VDD supply: %d\n", -+ ret); -+ goto port_unregister; -+ } -+ chip->vbus_on = true; -+ } -+ -+ return 0; -+ } -+ -+ fwnode = device_get_named_child_node(chip->dev, "connector"); -+ chip->role_sw = fwnode_usb_role_switch_get(fwnode); -+ if (IS_ERR(chip->role_sw)) { -+ ret = PTR_ERR(chip->role_sw); -+ if (ret != -EPROBE_DEFER) -+ dev_err(chip->dev, -+ "Failed to get usb role switch: %d\n", ret); -+ goto port_unregister; -+ } -+ -+ if (chip->role_sw) -+ INIT_WORK(&chip->wq_role_sw, stusb_set_role_sw); -+ -+ ret = stusb_irq_init(chip, client->irq); -+ if (ret) -+ goto role_sw_put; -+ -+ return 0; -+ -+role_sw_put: -+ if (chip->role_sw) { -+ cancel_work_sync(&chip->wq_role_sw); -+ usb_role_switch_put(chip->role_sw); -+ } -+port_unregister: -+ typec_unregister_port(chip->port); -+all_reg_disable: -+ if (stusb_get_vconn(chip)) -+ stusb_set_vconn(chip, false); -+main_reg_disable: -+ if (chip->main_supply) -+ regulator_disable(chip->main_supply); -+ -+ return ret; -+} -+ -+static int stusb_remove(struct i2c_client *client) -+{ -+ struct stusb *chip = i2c_get_clientdata(client); -+ -+ if (chip->partner) { -+ typec_unregister_partner(chip->partner); -+ chip->partner = NULL; -+ } -+ -+ if (chip->vbus_on) -+ regulator_disable(chip->vdd_supply); -+ -+ if (chip->role_sw) { -+ cancel_work_sync(&chip->wq_role_sw); -+ usb_role_switch_put(chip->role_sw); -+ } -+ -+ typec_unregister_port(chip->port); -+ -+ if (stusb_get_vconn(chip)) -+ stusb_set_vconn(chip, false); -+ -+ if (chip->main_supply) -+ regulator_disable(chip->main_supply); -+ -+ return 0; -+} -+ -+static int __maybe_unused stusb_suspend(struct device *dev) -+{ -+ struct stusb *chip = dev_get_drvdata(dev); -+ -+ /* Mask interrupts */ -+ return regmap_update_bits(chip->regmap, STUSB_ALERT_STATUS_MASK_CTRL, -+ STUSB_ALL_ALERTS, STUSB_ALL_ALERTS); -+} -+ -+static int __maybe_unused stusb_resume(struct device *dev) -+{ -+ struct stusb *chip = dev_get_drvdata(dev); -+ u32 status; -+ int ret; -+ -+ ret = regcache_sync(chip->regmap); -+ if (ret) -+ return ret; -+ -+ /* Check if attach/detach occurred during low power */ -+ ret = regmap_read(chip->regmap, STUSB_CC_CONNECTION_STATUS, &status); -+ if (ret) -+ return ret; -+ -+ if (chip->partner && !(status & STUSB_CC_ATTACH)) -+ stusb_detach(chip, status); -+ -+ if (!chip->partner && (status & STUSB_CC_ATTACH)) { -+ ret = stusb_attach(chip, status); -+ if (ret) -+ dev_err(chip->dev, "attach failed: %d\n", ret); -+ } -+ -+ /* Unmask interrupts */ -+ return regmap_write_bits(chip->regmap, STUSB_ALERT_STATUS_MASK_CTRL, -+ STUSB_CC_CONNECTION, 0); -+} -+ -+static SIMPLE_DEV_PM_OPS(stusb_pm_ops, stusb_suspend, stusb_resume); -+ -+static struct i2c_driver stusb_driver = { -+ .driver = { -+ .name = "typec_stusb", -+ .pm = &stusb_pm_ops, -+ .of_match_table = stusb_of_match, -+ }, -+ .probe = stusb_probe, -+ .remove = stusb_remove, -+}; -+module_i2c_driver(stusb_driver); -+ -+MODULE_AUTHOR("Amelie Delaunay "); -+MODULE_DESCRIPTION("STMicroelectronics STUSB Type-C controller driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h -index 15032f1450631..99ec370a6ff50 100644 ---- a/include/linux/phy/phy.h -+++ b/include/linux/phy/phy.h -@@ -233,7 +233,8 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, - const char *con_id); - struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, - int index); --void phy_put(struct phy *phy); -+void of_phy_put(struct phy *phy); -+void phy_put(struct device *dev, struct phy *phy); - void devm_phy_put(struct device *dev, struct phy *phy); - struct phy *of_phy_get(struct device_node *np, const char *con_id); - struct phy *of_phy_simple_xlate(struct device *dev, -@@ -418,7 +419,11 @@ static inline struct phy *devm_of_phy_get_by_index(struct device *dev, - return ERR_PTR(-ENOSYS); - } - --static inline void phy_put(struct phy *phy) -+static inline void of_phy_put(struct phy *phy) -+{ -+} -+ -+static inline void phy_put(struct device *dev, struct phy *phy) - { - } - -diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h -index 7df4ecabc78a2..2671776a1f8ea 100644 ---- a/include/linux/usb/typec.h -+++ b/include/linux/usb/typec.h -@@ -241,6 +241,7 @@ int typec_set_orientation(struct typec_port *port, - enum typec_orientation typec_get_orientation(struct typec_port *port); - int typec_set_mode(struct typec_port *port, int mode); - -+int typec_find_port_power_opmode(const char *name); - int typec_find_port_power_role(const char *name); - int typec_find_power_role(const char *name); - int typec_find_port_data_role(const char *name); --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0017-ARM-stm32mp1-r2-PINCTRL-REGULATOR-SPI-PWM.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0017-ARM-stm32mp1-r2-PINCTRL-REGULATOR-SPI-PWM.patch deleted file mode 100644 index d51755d..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0017-ARM-stm32mp1-r2-PINCTRL-REGULATOR-SPI-PWM.patch +++ /dev/null @@ -1,2755 +0,0 @@ -From a3294658232852248461b79c8c0a532956974568 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:51 +0200 -Subject: [PATCH 17/22] ARM-stm32mp1-r2-rc8-PINCTRL-REGULATOR-SPI-PWM - ---- - .../bindings/pinctrl/st,stm32-pinctrl.yaml | 8 + - .../devicetree/bindings/pwm/pwm-stm32.txt | 8 +- - drivers/pinctrl/pinctrl-stmfx.c | 36 +- - drivers/pinctrl/stm32/pinctrl-stm32.c | 268 +++++++--- - drivers/pinctrl/stm32/pinctrl-stm32.h | 17 +- - drivers/pinctrl/stm32/pinctrl-stm32mp157.c | 1 + - drivers/pwm/pwm-stm32.c | 116 ++-- - drivers/regulator/stm32-pwr.c | 85 ++- - drivers/regulator/stpmic1_regulator.c | 203 ++++++- - drivers/spi/spi-stm32-qspi.c | 155 ++++-- - drivers/spi/spi-stm32.c | 495 ++++++++++-------- - include/dt-bindings/pinctrl/stm32-pinfunc.h | 1 + - 12 files changed, 1019 insertions(+), 374 deletions(-) - -diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml -index 400df2da018a3..4e24a8e863475 100644 ---- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml -+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml -@@ -144,9 +144,13 @@ patternProperties: - * ... - * 16 : Alternate Function 15 - * 17 : Analog -+ * 18 : Reserved - To simplify the usage, macro is available to generate "pinmux" field. - This macro is available here: - - include/dt-bindings/pinctrl/stm32-pinfunc.h -+ Setting the pinmux's function to the Reserved (RSVD) value is used to inform -+ the driver that it shall not apply the mux setting. This can be used to -+ reserve some pins, for example to a co-processor not running Linux. - Some examples of using macro: - /* GPIO A9 set as alernate function 2 */ - ... { -@@ -160,6 +164,10 @@ patternProperties: - ... { - pinmux = ; - }; -+ /* GPIO A9 reserved for co-processor */ -+ ... { -+ pinmux = ; -+ }; - - bias-disable: - type: boolean -diff --git a/Documentation/devicetree/bindings/pwm/pwm-stm32.txt b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt -index a8690bfa5e1fa..f1620c1feebfc 100644 ---- a/Documentation/devicetree/bindings/pwm/pwm-stm32.txt -+++ b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt -@@ -5,8 +5,9 @@ See ../mfd/stm32-timers.txt for details about the parent node. - - Required parameters: - - compatible: Must be "st,stm32-pwm". --- pinctrl-names: Set to "default". --- pinctrl-0: List of phandles pointing to pin configuration nodes for PWM module. -+- pinctrl-names: Set to "default". An additional "sleep" state can be -+ defined to set pins in sleep state when in low power. -+- pinctrl-n: List of phandles pointing to pin configuration nodes for PWM module. - For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt - - #pwm-cells: Should be set to 3. This PWM chip uses the default 3 cells - bindings defined in pwm.txt. -@@ -32,7 +33,8 @@ Example: - compatible = "st,stm32-pwm"; - #pwm-cells = <3>; - pinctrl-0 = <&pwm1_pins>; -- pinctrl-names = "default"; -+ pinctrl-1 = <&pwm1_sleep_pins>; -+ pinctrl-names = "default", "sleep"; - st,breakinput = <0 1 5>; - }; - }; -diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c -index ccdf0bb214149..f7958eece5e0e 100644 ---- a/drivers/pinctrl/pinctrl-stmfx.c -+++ b/drivers/pinctrl/pinctrl-stmfx.c -@@ -277,7 +277,7 @@ static int stmfx_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - struct pinctrl_gpio_range *range; - enum pin_config_param param; - u32 arg; -- int dir, i, ret; -+ int i, ret; - - range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); - if (!range) { -@@ -285,10 +285,6 @@ static int stmfx_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - return -EINVAL; - } - -- dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin); -- if (dir < 0) -- return dir; -- - for (i = 0; i < num_configs; i++) { - param = pinconf_to_config_param(configs[i]); - arg = pinconf_to_config_argument(configs[i]); -@@ -505,6 +501,34 @@ static void stmfx_pinctrl_irq_bus_sync_unlock(struct irq_data *data) - mutex_unlock(&pctl->lock); - } - -+static int stmfx_gpio_irq_request_resources(struct irq_data *data) -+{ -+ struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); -+ struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip); -+ int ret; -+ -+ ret = stmfx_gpio_direction_input(&pctl->gpio_chip, data->hwirq); -+ if (ret) -+ return ret; -+ -+ ret = gpiochip_lock_as_irq(&pctl->gpio_chip, data->hwirq); -+ if (ret) { -+ dev_err(pctl->dev, "Unable to lock gpio %lu as IRQ: %d\n", -+ data->hwirq, ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void stmfx_gpio_irq_release_resources(struct irq_data *data) -+{ -+ struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); -+ struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip); -+ -+ gpiochip_unlock_as_irq(&pctl->gpio_chip, data->hwirq); -+} -+ - static void stmfx_pinctrl_irq_toggle_trigger(struct stmfx_pinctrl *pctl, - unsigned int offset) - { -@@ -664,6 +688,8 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) - pctl->irq_chip.irq_set_type = stmfx_pinctrl_irq_set_type; - pctl->irq_chip.irq_bus_lock = stmfx_pinctrl_irq_bus_lock; - pctl->irq_chip.irq_bus_sync_unlock = stmfx_pinctrl_irq_bus_sync_unlock; -+ pctl->irq_chip.irq_request_resources = stmfx_gpio_irq_request_resources; -+ pctl->irq_chip.irq_release_resources = stmfx_gpio_irq_release_resources; - - ret = gpiochip_irqchip_add_nested(&pctl->gpio_chip, &pctl->irq_chip, - 0, handle_bad_irq, IRQ_TYPE_NONE); -diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c -index 2d5e0435af0a4..ef3b081d27983 100644 ---- a/drivers/pinctrl/stm32/pinctrl-stm32.c -+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c -@@ -64,7 +64,7 @@ - #define gpio_range_to_bank(chip) \ - container_of(chip, struct stm32_gpio_bank, range) - --#define HWSPINLOCK_TIMEOUT 5 /* msec */ -+#define HWSPNLCK_TIMEOUT 1000 /* usec */ - - static const char * const stm32_gpio_functions[] = { - "gpio", "af0", "af1", -@@ -73,6 +73,7 @@ static const char * const stm32_gpio_functions[] = { - "af8", "af9", "af10", - "af11", "af12", "af13", - "af14", "af15", "analog", -+ "reserved", - }; - - struct stm32_pinctrl_group { -@@ -84,6 +85,7 @@ struct stm32_pinctrl_group { - struct stm32_gpio_bank { - void __iomem *base; - struct clk *clk; -+ struct reset_control *rstc; - spinlock_t lock; - struct gpio_chip gpio_chip; - struct pinctrl_gpio_range range; -@@ -92,6 +94,7 @@ struct stm32_gpio_bank { - u32 bank_nr; - u32 bank_ioport_nr; - u32 pin_backup[STM32_GPIO_PINS_PER_BANK]; -+ u8 irq_type[STM32_GPIO_PINS_PER_BANK]; - }; - - struct stm32_pinctrl { -@@ -113,6 +116,7 @@ struct stm32_pinctrl { - u32 pkg; - u16 irqmux_map; - spinlock_t irqmux_lock; -+ u32 pin_base_shift; - }; - - static inline int stm32_gpio_pin(int gpio) -@@ -301,6 +305,51 @@ static const struct gpio_chip stm32_gpio_template = { - .direction_output = stm32_gpio_direction_output, - .to_irq = stm32_gpio_to_irq, - .get_direction = stm32_gpio_get_direction, -+ .set_config = gpiochip_generic_config, -+}; -+ -+static void stm32_gpio_irq_trigger(struct irq_data *d) -+{ -+ struct stm32_gpio_bank *bank = d->domain->host_data; -+ int level; -+ -+ /* If level interrupt type then retrig */ -+ level = stm32_gpio_get(&bank->gpio_chip, d->hwirq); -+ if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) || -+ (level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH)) -+ irq_chip_retrigger_hierarchy(d); -+} -+ -+static void stm32_gpio_irq_eoi(struct irq_data *d) -+{ -+ irq_chip_eoi_parent(d); -+ stm32_gpio_irq_trigger(d); -+}; -+ -+static int stm32_gpio_set_type(struct irq_data *d, unsigned int type) -+{ -+ struct stm32_gpio_bank *bank = d->domain->host_data; -+ u32 parent_type; -+ -+ switch (type) { -+ case IRQ_TYPE_EDGE_RISING: -+ case IRQ_TYPE_EDGE_FALLING: -+ case IRQ_TYPE_EDGE_BOTH: -+ parent_type = type; -+ break; -+ case IRQ_TYPE_LEVEL_HIGH: -+ parent_type = IRQ_TYPE_EDGE_RISING; -+ break; -+ case IRQ_TYPE_LEVEL_LOW: -+ parent_type = IRQ_TYPE_EDGE_FALLING; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ bank->irq_type[d->hwirq] = type; -+ -+ return irq_chip_set_type_parent(d, parent_type); - }; - - static int stm32_gpio_irq_request_resources(struct irq_data *irq_data) -@@ -330,13 +379,19 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data) - gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq); - } - -+static void stm32_gpio_irq_unmask(struct irq_data *d) -+{ -+ irq_chip_unmask_parent(d); -+ stm32_gpio_irq_trigger(d); -+} -+ - static struct irq_chip stm32_gpio_irq_chip = { - .name = "stm32gpio", -- .irq_eoi = irq_chip_eoi_parent, -+ .irq_eoi = stm32_gpio_irq_eoi, - .irq_ack = irq_chip_ack_parent, - .irq_mask = irq_chip_mask_parent, -- .irq_unmask = irq_chip_unmask_parent, -- .irq_set_type = irq_chip_set_type_parent, -+ .irq_unmask = stm32_gpio_irq_unmask, -+ .irq_set_type = stm32_gpio_set_type, - .irq_set_wake = irq_chip_set_wake_parent, - .irq_request_resources = stm32_gpio_irq_request_resources, - .irq_release_resources = stm32_gpio_irq_release_resources, -@@ -369,12 +424,14 @@ static int stm32_gpio_domain_activate(struct irq_domain *d, - * to avoid overriding. - */ - spin_lock_irqsave(&pctl->irqmux_lock, flags); -- if (pctl->hwlock) -- ret = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT); - -- if (ret) { -- dev_err(pctl->dev, "Can't get hwspinlock\n"); -- goto unlock; -+ if (pctl->hwlock) { -+ ret = hwspin_lock_timeout_in_atomic(pctl->hwlock, -+ HWSPNLCK_TIMEOUT); -+ if (ret) { -+ dev_err(pctl->dev, "Can't get hwspinlock\n"); -+ goto unlock; -+ } - } - - if (pctl->irqmux_map & BIT(irq_data->hwirq)) { -@@ -382,7 +439,7 @@ static int stm32_gpio_domain_activate(struct irq_domain *d, - irq_data->hwirq); - ret = -EBUSY; - if (pctl->hwlock) -- hwspin_unlock(pctl->hwlock); -+ hwspin_unlock_in_atomic(pctl->hwlock); - goto unlock; - } else { - pctl->irqmux_map |= BIT(irq_data->hwirq); -@@ -391,7 +448,7 @@ static int stm32_gpio_domain_activate(struct irq_domain *d, - regmap_field_write(pctl->irqmux[irq_data->hwirq], bank->bank_ioport_nr); - - if (pctl->hwlock) -- hwspin_unlock(pctl->hwlock); -+ hwspin_unlock_in_atomic(pctl->hwlock); - - unlock: - spin_unlock_irqrestore(&pctl->irqmux_lock, flags); -@@ -458,7 +515,7 @@ stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin) - static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, - u32 pin_num, u32 fnum) - { -- int i; -+ int i, k; - - for (i = 0; i < pctl->npins; i++) { - const struct stm32_desc_pin *pin = pctl->pins + i; -@@ -467,7 +524,10 @@ static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, - if (pin->pin.number != pin_num) - continue; - -- while (func && func->name) { -+ if (fnum == STM32_PIN_RSVD) -+ return true; -+ -+ for (k = 0; k < STM32_CONFIG_NUM; k++) { - if (func->num == fnum) - return true; - func++; -@@ -699,12 +759,13 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, - clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - -- if (pctl->hwlock) -- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT); -- -- if (err) { -- dev_err(pctl->dev, "Can't get hwspinlock\n"); -- goto unlock; -+ if (pctl->hwlock) { -+ err = hwspin_lock_timeout_in_atomic(pctl->hwlock, -+ HWSPNLCK_TIMEOUT); -+ if (err) { -+ dev_err(pctl->dev, "Can't get hwspinlock\n"); -+ goto unlock; -+ } - } - - val = readl_relaxed(bank->base + alt_offset); -@@ -718,7 +779,7 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, - writel_relaxed(val, bank->base + STM32_GPIO_MODER); - - if (pctl->hwlock) -- hwspin_unlock(pctl->hwlock); -+ hwspin_unlock_in_atomic(pctl->hwlock); - - stm32_gpio_backup_mode(bank, pin, mode, alt); - -@@ -777,6 +838,11 @@ static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, - return -EINVAL; - } - -+ if (function == STM32_PIN_RSVD) { -+ dev_dbg(pctl->dev, "Reserved pins, skipping HW update.\n"); -+ return 0; -+ } -+ - bank = gpiochip_get_data(range->gc); - pin = stm32_gpio_pin(g->pin); - -@@ -818,12 +884,13 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, - clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - -- if (pctl->hwlock) -- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT); -- -- if (err) { -- dev_err(pctl->dev, "Can't get hwspinlock\n"); -- goto unlock; -+ if (pctl->hwlock) { -+ err = hwspin_lock_timeout_in_atomic(pctl->hwlock, -+ HWSPNLCK_TIMEOUT); -+ if (err) { -+ dev_err(pctl->dev, "Can't get hwspinlock\n"); -+ goto unlock; -+ } - } - - val = readl_relaxed(bank->base + STM32_GPIO_TYPER); -@@ -832,7 +899,7 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, - writel_relaxed(val, bank->base + STM32_GPIO_TYPER); - - if (pctl->hwlock) -- hwspin_unlock(pctl->hwlock); -+ hwspin_unlock_in_atomic(pctl->hwlock); - - stm32_gpio_backup_driving(bank, offset, drive); - -@@ -872,12 +939,13 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, - clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - -- if (pctl->hwlock) -- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT); -- -- if (err) { -- dev_err(pctl->dev, "Can't get hwspinlock\n"); -- goto unlock; -+ if (pctl->hwlock) { -+ err = hwspin_lock_timeout_in_atomic(pctl->hwlock, -+ HWSPNLCK_TIMEOUT); -+ if (err) { -+ dev_err(pctl->dev, "Can't get hwspinlock\n"); -+ goto unlock; -+ } - } - - val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR); -@@ -886,7 +954,7 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, - writel_relaxed(val, bank->base + STM32_GPIO_SPEEDR); - - if (pctl->hwlock) -- hwspin_unlock(pctl->hwlock); -+ hwspin_unlock_in_atomic(pctl->hwlock); - - stm32_gpio_backup_speed(bank, offset, speed); - -@@ -926,12 +994,13 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, - clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - -- if (pctl->hwlock) -- err = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT); -- -- if (err) { -- dev_err(pctl->dev, "Can't get hwspinlock\n"); -- goto unlock; -+ if (pctl->hwlock) { -+ err = hwspin_lock_timeout_in_atomic(pctl->hwlock, -+ HWSPNLCK_TIMEOUT); -+ if (err) { -+ dev_err(pctl->dev, "Can't get hwspinlock\n"); -+ goto unlock; -+ } - } - - val = readl_relaxed(bank->base + STM32_GPIO_PUPDR); -@@ -940,7 +1009,7 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, - writel_relaxed(val, bank->base + STM32_GPIO_PUPDR); - - if (pctl->hwlock) -- hwspin_unlock(pctl->hwlock); -+ hwspin_unlock_in_atomic(pctl->hwlock); - - stm32_gpio_backup_bias(bank, offset, bias); - -@@ -992,20 +1061,14 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, - } - - static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, -- unsigned int pin, enum pin_config_param param, -- enum pin_config_param arg) -+ struct pinctrl_gpio_range *range, -+ unsigned int pin, -+ enum pin_config_param param, -+ enum pin_config_param arg) - { -- struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); -- struct pinctrl_gpio_range *range; - struct stm32_gpio_bank *bank; - int offset, ret = 0; - -- range = pinctrl_find_gpio_range_from_pin(pctldev, pin); -- if (!range) { -- dev_err(pctl->dev, "No gpio range defined.\n"); -- return -EINVAL; -- } -- - bank = gpiochip_get_data(range->gc); - offset = stm32_gpio_pin(pin); - -@@ -1033,7 +1096,8 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, - ret = stm32_pmx_gpio_set_direction(pctldev, range, pin, false); - break; - default: -- ret = -EINVAL; -+ dev_dbg(pctldev->dev, "configuration %d not supported.\n", -+ param); - } - - return ret; -@@ -1055,12 +1119,19 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, - { - struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); - struct stm32_pinctrl_group *g = &pctl->groups[group]; -+ struct pinctrl_gpio_range *range; - int i, ret; - -+ range = pinctrl_find_gpio_range_from_pin(pctldev, g->pin); -+ if (!range) { -+ dev_err(pctl->dev, "No gpio range defined.\n"); -+ return -EINVAL; -+ } -+ - for (i = 0; i < num_configs; i++) { -- ret = stm32_pconf_parse_conf(pctldev, g->pin, -- pinconf_to_config_param(configs[i]), -- pinconf_to_config_argument(configs[i])); -+ ret = stm32_pconf_parse_conf(pctldev, range, g->pin, -+ pinconf_to_config_param(configs[i]), -+ pinconf_to_config_argument(configs[i])); - if (ret < 0) - return ret; - -@@ -1070,10 +1141,51 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, - return 0; - } - -+static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, -+ unsigned long *configs, unsigned int num_configs) -+{ -+ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); -+ struct pinctrl_gpio_range *range; -+ int i, ret; -+ -+ range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); -+ if (!range) { -+ dev_err(pctl->dev, "No gpio range defined.\n"); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < num_configs; i++) { -+ ret = stm32_pconf_parse_conf(pctldev, range, pin, -+ pinconf_to_config_param(configs[i]), -+ pinconf_to_config_argument(configs[i])); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static struct stm32_desc_pin * -+stm32_pconf_get_pin_desc_by_pin_number(struct stm32_pinctrl *pctl, -+ unsigned int pin_number) -+{ -+ struct stm32_desc_pin *pins = pctl->pins; -+ int i; -+ -+ for (i = 0; i < pctl->npins; i++) { -+ if (pins->pin.number == pin_number) -+ return pins; -+ pins++; -+ } -+ return NULL; -+} -+ - static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, - unsigned int pin) - { -+ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); -+ const struct stm32_desc_pin *pin_desc; - struct pinctrl_gpio_range *range; - struct stm32_gpio_bank *bank; - int offset; -@@ -1123,7 +1235,12 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, - case 2: - drive = stm32_pconf_get_driving(bank, offset); - speed = stm32_pconf_get_speed(bank, offset); -- seq_printf(s, "%d - %s - %s - %s %s", alt, -+ pin_desc = stm32_pconf_get_pin_desc_by_pin_number(pctl, pin); -+ if (!pin_desc) -+ return; -+ -+ seq_printf(s, "%d (%s) - %s - %s - %s %s", alt, -+ pin_desc->functions[alt + 1].name, - drive ? "open drain" : "push pull", - biasing[bias], - speeds[speed], "speed"); -@@ -1140,6 +1257,7 @@ static const struct pinconf_ops stm32_pconf_ops = { - .pin_config_group_get = stm32_pconf_group_get, - .pin_config_group_set = stm32_pconf_group_set, - .pin_config_dbg_show = stm32_pconf_dbg_show, -+ .pin_config_set = stm32_pconf_set, - }; - - static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, -@@ -1151,13 +1269,11 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, - struct of_phandle_args args; - struct device *dev = pctl->dev; - struct resource res; -- struct reset_control *rstc; - int npins = STM32_GPIO_PINS_PER_BANK; - int bank_nr, err; - -- rstc = of_reset_control_get_exclusive(np, NULL); -- if (!IS_ERR(rstc)) -- reset_control_deassert(rstc); -+ if (!IS_ERR(bank->rstc)) -+ reset_control_deassert(bank->rstc); - - if (of_address_to_resource(np, 0, &res)) - return -ENODEV; -@@ -1166,12 +1282,6 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, - if (IS_ERR(bank->base)) - return PTR_ERR(bank->base); - -- bank->clk = of_clk_get_by_name(np, NULL); -- if (IS_ERR(bank->clk)) { -- dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(bank->clk)); -- return PTR_ERR(bank->clk); -- } -- - err = clk_prepare(bank->clk); - if (err) { - dev_err(dev, "failed to prepare clk (%d)\n", err); -@@ -1335,7 +1445,8 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, - if (pctl->pkg && !(pctl->pkg & p->pkg)) - continue; - pins->pin = p->pin; -- pins->functions = p->functions; -+ memcpy((struct stm32_desc_pin *)pins->functions, p->functions, -+ STM32_CONFIG_NUM * sizeof(struct stm32_desc_function)); - pins++; - nb_pins_available++; - } -@@ -1444,6 +1555,7 @@ int stm32_pctl_probe(struct platform_device *pdev) - pctl->pctl_desc.pctlops = &stm32_pctrl_ops; - pctl->pctl_desc.pmxops = &stm32_pmx_ops; - pctl->dev = &pdev->dev; -+ pctl->pin_base_shift = pctl->match_data->pin_base_shift; - - pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc, - pctl); -@@ -1466,6 +1578,28 @@ int stm32_pctl_probe(struct platform_device *pdev) - if (!pctl->banks) - return -ENOMEM; - -+ i = 0; -+ for_each_available_child_of_node(np, child) { -+ struct stm32_gpio_bank *bank = &pctl->banks[i]; -+ -+ if (of_property_read_bool(child, "gpio-controller")) { -+ bank->rstc = of_reset_control_get_exclusive(child, -+ NULL); -+ if (PTR_ERR(bank->rstc) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ -+ bank->clk = of_clk_get_by_name(child, NULL); -+ if (IS_ERR(bank->clk)) { -+ if (PTR_ERR(bank->clk) != -EPROBE_DEFER) -+ dev_err(dev, -+ "failed to get clk (%ld)\n", -+ PTR_ERR(bank->clk)); -+ return PTR_ERR(bank->clk); -+ } -+ i++; -+ } -+ } -+ - for_each_available_child_of_node(np, child) { - if (of_property_read_bool(child, "gpio-controller")) { - ret = stm32_gpiolib_register_bank(pctl, child); -diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h -index ec0d34c339031..b11a223f3504c 100644 ---- a/drivers/pinctrl/stm32/pinctrl-stm32.h -+++ b/drivers/pinctrl/stm32/pinctrl-stm32.h -@@ -17,6 +17,8 @@ - #define STM32_PIN_GPIO 0 - #define STM32_PIN_AF(x) ((x) + 1) - #define STM32_PIN_ANALOG (STM32_PIN_AF(15) + 1) -+#define STM32_PIN_RSVD (STM32_PIN_ANALOG + 1) -+#define STM32_CONFIG_NUM (STM32_PIN_RSVD + 1) - - /* package information */ - #define STM32MP_PKG_AA BIT(0) -@@ -24,6 +26,8 @@ - #define STM32MP_PKG_AC BIT(2) - #define STM32MP_PKG_AD BIT(3) - -+#define STM32MP157_Z_BASE_SHIFT 400 -+ - struct stm32_desc_function { - const char *name; - const unsigned char num; -@@ -31,26 +35,26 @@ struct stm32_desc_function { - - struct stm32_desc_pin { - struct pinctrl_pin_desc pin; -- const struct stm32_desc_function *functions; -+ const struct stm32_desc_function functions[STM32_CONFIG_NUM]; - const unsigned int pkg; - }; - - #define STM32_PIN(_pin, ...) \ - { \ - .pin = _pin, \ -- .functions = (struct stm32_desc_function[]){ \ -- __VA_ARGS__, { } }, \ -+ .functions = { \ -+ __VA_ARGS__}, \ - } - - #define STM32_PIN_PKG(_pin, _pkg, ...) \ - { \ - .pin = _pin, \ - .pkg = _pkg, \ -- .functions = (struct stm32_desc_function[]){ \ -- __VA_ARGS__, { } }, \ -+ .functions = { \ -+ __VA_ARGS__}, \ - } - #define STM32_FUNCTION(_num, _name) \ -- { \ -+ [_num] = { \ - .num = _num, \ - .name = _name, \ - } -@@ -58,6 +62,7 @@ struct stm32_desc_pin { - struct stm32_pinctrl_match_data { - const struct stm32_desc_pin *pins; - const unsigned int npins; -+ const unsigned int pin_base_shift; - }; - - struct stm32_gpio_bank; -diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c -index 2ccb99d64df83..86fe6d5ac54d6 100644 ---- a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c -+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c -@@ -2328,6 +2328,7 @@ static struct stm32_pinctrl_match_data stm32mp157_match_data = { - static struct stm32_pinctrl_match_data stm32mp157_z_match_data = { - .pins = stm32mp157_z_pins, - .npins = ARRAY_SIZE(stm32mp157_z_pins), -+ .pin_base_shift = STM32MP157_Z_BASE_SHIFT, - }; - - static const struct of_device_id stm32mp157_pctrl_match[] = { -diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c -index 359b08596d9e3..d3be944f2ae96 100644 ---- a/drivers/pwm/pwm-stm32.c -+++ b/drivers/pwm/pwm-stm32.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -19,6 +20,12 @@ - #define CCMR_CHANNEL_MASK 0xFF - #define MAX_BREAKINPUT 2 - -+struct stm32_breakinput { -+ u32 index; -+ u32 level; -+ u32 filter; -+}; -+ - struct stm32_pwm { - struct pwm_chip chip; - struct mutex lock; /* protect pwm config/enable */ -@@ -26,15 +33,11 @@ struct stm32_pwm { - struct regmap *regmap; - u32 max_arr; - bool have_complementary_output; -+ struct stm32_breakinput breakinputs[MAX_BREAKINPUT]; -+ unsigned int num_breakinputs; - u32 capture[4] ____cacheline_aligned; /* DMA'able buffer */ - }; - --struct stm32_breakinput { -- u32 index; -- u32 level; -- u32 filter; --}; -- - static inline struct stm32_pwm *to_stm32_pwm_dev(struct pwm_chip *chip) - { - return container_of(chip, struct stm32_pwm, chip); -@@ -374,9 +377,7 @@ static int stm32_pwm_config(struct stm32_pwm *priv, int ch, - else - regmap_update_bits(priv->regmap, TIM_CCMR2, mask, ccmr); - -- regmap_update_bits(priv->regmap, TIM_BDTR, -- TIM_BDTR_MOE | TIM_BDTR_AOE, -- TIM_BDTR_MOE | TIM_BDTR_AOE); -+ regmap_update_bits(priv->regmap, TIM_BDTR, TIM_BDTR_MOE, TIM_BDTR_MOE); - - return 0; - } -@@ -488,22 +489,19 @@ static const struct pwm_ops stm32pwm_ops = { - }; - - static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, -- int index, int level, int filter) -+ const struct stm32_breakinput *bi) - { -- u32 bke = (index == 0) ? TIM_BDTR_BKE : TIM_BDTR_BK2E; -- int shift = (index == 0) ? TIM_BDTR_BKF_SHIFT : TIM_BDTR_BK2F_SHIFT; -- u32 mask = (index == 0) ? TIM_BDTR_BKE | TIM_BDTR_BKP | TIM_BDTR_BKF -- : TIM_BDTR_BK2E | TIM_BDTR_BK2P | TIM_BDTR_BK2F; -- u32 bdtr = bke; -+ u32 shift = TIM_BDTR_BKF_SHIFT(bi->index); -+ u32 bke = TIM_BDTR_BKE(bi->index); -+ u32 bkp = TIM_BDTR_BKP(bi->index); -+ u32 bkf = TIM_BDTR_BKF(bi->index); -+ u32 mask = bkf | bkp | bke; -+ u32 bdtr; - -- /* -- * The both bits could be set since only one will be wrote -- * due to mask value. -- */ -- if (level) -- bdtr |= TIM_BDTR_BKP | TIM_BDTR_BK2P; -+ bdtr = (bi->filter & TIM_BDTR_BKF_MASK) << shift | bke; - -- bdtr |= (filter & TIM_BDTR_BKF_MASK) << shift; -+ if (bi->level) -+ bdtr |= bkp; - - regmap_update_bits(priv->regmap, TIM_BDTR, mask, bdtr); - -@@ -512,11 +510,25 @@ static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, - return (bdtr & bke) ? 0 : -EINVAL; - } - --static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv, -+static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv) -+{ -+ unsigned int i; -+ int ret; -+ -+ for (i = 0; i < priv->num_breakinputs; i++) { -+ ret = stm32_pwm_set_breakinput(priv, &priv->breakinputs[i]); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int stm32_pwm_probe_breakinputs(struct stm32_pwm *priv, - struct device_node *np) - { -- struct stm32_breakinput breakinput[MAX_BREAKINPUT]; -- int nb, ret, i, array_size; -+ int nb, ret, array_size; -+ unsigned int i; - - nb = of_property_count_elems_of_size(np, "st,breakinput", - sizeof(struct stm32_breakinput)); -@@ -531,20 +543,21 @@ static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv, - if (nb > MAX_BREAKINPUT) - return -EINVAL; - -+ priv->num_breakinputs = nb; - array_size = nb * sizeof(struct stm32_breakinput) / sizeof(u32); - ret = of_property_read_u32_array(np, "st,breakinput", -- (u32 *)breakinput, array_size); -+ (u32 *)priv->breakinputs, array_size); - if (ret) - return ret; - -- for (i = 0; i < nb && !ret; i++) { -- ret = stm32_pwm_set_breakinput(priv, -- breakinput[i].index, -- breakinput[i].level, -- breakinput[i].filter); -+ for (i = 0; i < priv->num_breakinputs; i++) { -+ if (priv->breakinputs[i].index > 1 || -+ priv->breakinputs[i].level > 1 || -+ priv->breakinputs[i].filter > 15) -+ return -EINVAL; - } - -- return ret; -+ return stm32_pwm_apply_breakinputs(priv); - } - - static void stm32_pwm_detect_complementary(struct stm32_pwm *priv) -@@ -614,7 +627,7 @@ static int stm32_pwm_probe(struct platform_device *pdev) - if (!priv->regmap || !priv->clk) - return -EINVAL; - -- ret = stm32_pwm_apply_breakinputs(priv, np); -+ ret = stm32_pwm_probe_breakinputs(priv, np); - if (ret) - return ret; - -@@ -647,6 +660,42 @@ static int stm32_pwm_remove(struct platform_device *pdev) - return 0; - } - -+static int __maybe_unused stm32_pwm_suspend(struct device *dev) -+{ -+ struct stm32_pwm *priv = dev_get_drvdata(dev); -+ unsigned int i; -+ u32 ccer, mask; -+ -+ /* Look for active channels */ -+ ccer = active_channels(priv); -+ -+ for (i = 0; i < priv->chip.npwm; i++) { -+ mask = TIM_CCER_CC1E << (i * 4); -+ if (ccer & mask) { -+ dev_err(dev, "PWM %u still in use by consumer %s\n", -+ i, priv->chip.pwms[i].label); -+ return -EBUSY; -+ } -+ } -+ -+ return pinctrl_pm_select_sleep_state(dev); -+} -+ -+static int __maybe_unused stm32_pwm_resume(struct device *dev) -+{ -+ struct stm32_pwm *priv = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = pinctrl_pm_select_default_state(dev); -+ if (ret) -+ return ret; -+ -+ /* restore breakinput registers that may have been lost in low power */ -+ return stm32_pwm_apply_breakinputs(priv); -+} -+ -+static SIMPLE_DEV_PM_OPS(stm32_pwm_pm_ops, stm32_pwm_suspend, stm32_pwm_resume); -+ - static const struct of_device_id stm32_pwm_of_match[] = { - { .compatible = "st,stm32-pwm", }, - { /* end node */ }, -@@ -659,6 +708,7 @@ static struct platform_driver stm32_pwm_driver = { - .driver = { - .name = "stm32-pwm", - .of_match_table = stm32_pwm_of_match, -+ .pm = &stm32_pwm_pm_ops, - }, - }; - module_platform_driver(stm32_pwm_driver); -diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c -index e0e627b0106e0..373d83797ea86 100644 ---- a/drivers/regulator/stm32-pwr.c -+++ b/drivers/regulator/stm32-pwr.c -@@ -3,12 +3,15 @@ - // Authors: Gabriel Fernandez - // Pascal Paillet . - -+#include - #include - #include -+#include - #include - #include - #include - #include -+#include - #include - #include - -@@ -24,6 +27,11 @@ - #define REG_1_1_EN BIT(30) - #define REG_1_1_RDY BIT(31) - -+#define STM32_SMC_PWR 0x82001001 -+#define STM32_WRITE 0x1 -+#define STM32_SMC_REG_SET 0x2 -+#define STM32_SMC_REG_CLEAR 0x3 -+ - /* list of supported regulators */ - enum { - PWR_REG11, -@@ -39,10 +47,18 @@ static u32 ready_mask_table[STM32PWR_REG_NUM_REGS] = { - }; - - struct stm32_pwr_reg { -+ int tzen; - void __iomem *base; - u32 ready_mask; - }; - -+#define SMC(class, op, address, val)\ -+ ({\ -+ struct arm_smccc_res res;\ -+ arm_smccc_smc(class, op, address, val,\ -+ 0, 0, 0, 0, &res);\ -+ }) -+ - static int stm32_pwr_reg_is_ready(struct regulator_dev *rdev) - { - struct stm32_pwr_reg *priv = rdev_get_drvdata(rdev); -@@ -69,9 +85,15 @@ static int stm32_pwr_reg_enable(struct regulator_dev *rdev) - int ret; - u32 val; - -- val = readl_relaxed(priv->base + REG_PWR_CR3); -- val |= rdev->desc->enable_mask; -- writel_relaxed(val, priv->base + REG_PWR_CR3); -+ if (priv->tzen) { -+ SMC(STM32_SMC_PWR, STM32_SMC_REG_SET, REG_PWR_CR3, -+ rdev->desc->enable_mask); -+ } else { -+ val = readl_relaxed(priv->base + REG_PWR_CR3); -+ val |= rdev->desc->enable_mask; -+ writel_relaxed(val, priv->base + REG_PWR_CR3); -+ } -+ - - /* use an arbitrary timeout of 20ms */ - ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, val, -@@ -88,9 +110,14 @@ static int stm32_pwr_reg_disable(struct regulator_dev *rdev) - int ret; - u32 val; - -- val = readl_relaxed(priv->base + REG_PWR_CR3); -- val &= ~rdev->desc->enable_mask; -- writel_relaxed(val, priv->base + REG_PWR_CR3); -+ if (priv->tzen) { -+ SMC(STM32_SMC_PWR, STM32_SMC_REG_CLEAR, REG_PWR_CR3, -+ rdev->desc->enable_mask); -+ } else { -+ val = readl_relaxed(priv->base + REG_PWR_CR3); -+ val &= ~rdev->desc->enable_mask; -+ writel_relaxed(val, priv->base + REG_PWR_CR3); -+ } - - /* use an arbitrary timeout of 20ms */ - ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, !val, -@@ -121,12 +148,50 @@ static const struct regulator_ops stm32_pwr_reg_ops = { - .supply_name = _supply, \ - } \ - --static const struct regulator_desc stm32_pwr_desc[] = { -+static struct regulator_desc stm32_pwr_desc[] = { - PWR_REG(PWR_REG11, "reg11", 1100000, REG_1_1_EN, "vdd"), - PWR_REG(PWR_REG18, "reg18", 1800000, REG_1_8_EN, "vdd"), - PWR_REG(PWR_USB33, "usb33", 3300000, USB_3_3_EN, "vdd_3v3_usbfs"), - }; - -+static int is_stm32_soc_secured(struct platform_device *pdev, int *val) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct regmap *syscon; -+ u32 reg, mask; -+ int tzc_val = 0; -+ int err; -+ -+ syscon = syscon_regmap_lookup_by_phandle(np, "st,tzcr"); -+ if (IS_ERR(syscon)) { -+ if (PTR_ERR(syscon) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "tzcr syscon required\n"); -+ return PTR_ERR(syscon); -+ } -+ -+ err = of_property_read_u32_index(np, "st,tzcr", 1, ®); -+ if (err) { -+ dev_err(&pdev->dev, "tzcr offset required !\n"); -+ return err; -+ } -+ -+ err = of_property_read_u32_index(np, "st,tzcr", 2, &mask); -+ if (err) { -+ dev_err(&pdev->dev, "tzcr mask required !\n"); -+ return err; -+ } -+ -+ err = regmap_read(syscon, reg, &tzc_val); -+ if (err) { -+ dev_err(&pdev->dev, "failed to read tzcr status !\n"); -+ return err; -+ } -+ -+ *val = tzc_val & mask; -+ -+ return 0; -+} -+ - static int stm32_pwr_regulator_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; -@@ -135,6 +200,11 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) - struct regulator_dev *rdev; - struct regulator_config config = { }; - int i, ret = 0; -+ int tzen = 0; -+ -+ ret = is_stm32_soc_secured(pdev, &tzen); -+ if (ret) -+ return ret; - - base = of_iomap(np, 0); - if (!base) { -@@ -149,6 +219,7 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) - GFP_KERNEL); - if (!priv) - return -ENOMEM; -+ priv->tzen = tzen; - priv->base = base; - priv->ready_mask = ready_mask_table[i]; - config.driver_data = priv; -diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c -index f09061473613c..4537e3ab143ca 100644 ---- a/drivers/regulator/stpmic1_regulator.c -+++ b/drivers/regulator/stpmic1_regulator.c -@@ -2,7 +2,9 @@ - // Copyright (C) STMicroelectronics 2018 - // Author: Pascal Paillet for STMicroelectronics. - -+#include - #include -+#include - #include - #include - #include -@@ -30,10 +32,26 @@ struct stpmic1_regulator_cfg { - u8 icc_mask; - }; - -+/** -+ * struct boost_data - this structure is used as driver data for the usb boost -+ * @boost_rdev: device for boost regulator -+ * @vbus_otg_rdev: device for vbus_otg regulator -+ * @sw_out_rdev: device for sw_out regulator -+ * @occ_timeout: overcurrent detection timeout -+ */ -+struct boost_data { -+ struct regulator_dev *boost_rdev; -+ struct regulator_dev *vbus_otg_rdev; -+ struct regulator_dev *sw_out_rdev; -+ ktime_t occ_timeout; -+}; -+ - static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode); - static unsigned int stpmic1_get_mode(struct regulator_dev *rdev); - static int stpmic1_set_icc(struct regulator_dev *rdev); - static unsigned int stpmic1_map_mode(unsigned int mode); -+static int regulator_enable_boost(struct regulator_dev *rdev); -+static int regulator_disable_boost(struct regulator_dev *rdev); - - enum { - STPMIC1_BUCK1 = 0, -@@ -54,6 +72,8 @@ enum { - - /* Enable time worst case is 5000mV/(2250uV/uS) */ - #define PMIC_ENABLE_TIME_US 2200 -+/* Ramp delay worst case is (2250uV/uS) */ -+#define PMIC_RAMP_DELAY 2200 - - static const struct regulator_linear_range buck1_ranges[] = { - REGULATOR_LINEAR_RANGE(725000, 0, 4, 0), -@@ -179,8 +199,8 @@ static const struct regulator_ops stpmic1_vref_ddr_ops = { - - static const struct regulator_ops stpmic1_boost_regul_ops = { - .is_enabled = regulator_is_enabled_regmap, -- .enable = regulator_enable_regmap, -- .disable = regulator_disable_regmap, -+ .enable = regulator_enable_boost, -+ .disable = regulator_disable_boost, - .set_over_current_protection = stpmic1_set_icc, - }; - -@@ -208,6 +228,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = { - .enable_val = 1, \ - .disable_val = 0, \ - .enable_time = PMIC_ENABLE_TIME_US, \ -+ .ramp_delay = PMIC_RAMP_DELAY, \ - .supply_name = #base, \ - } - -@@ -227,6 +248,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = { - .enable_val = 1, \ - .disable_val = 0, \ - .enable_time = PMIC_ENABLE_TIME_US, \ -+ .ramp_delay = PMIC_RAMP_DELAY, \ - .bypass_reg = LDO3_ACTIVE_CR, \ - .bypass_mask = LDO_BYPASS_MASK, \ - .bypass_val_on = LDO_BYPASS_MASK, \ -@@ -248,6 +270,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = { - .enable_val = 1, \ - .disable_val = 0, \ - .enable_time = PMIC_ENABLE_TIME_US, \ -+ .ramp_delay = PMIC_RAMP_DELAY, \ - .supply_name = #base, \ - } - -@@ -267,6 +290,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = { - .enable_val = 1, \ - .disable_val = 0, \ - .enable_time = PMIC_ENABLE_TIME_US, \ -+ .ramp_delay = PMIC_RAMP_DELAY, \ - .of_map_mode = stpmic1_map_mode, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ -@@ -511,6 +535,94 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) - return IRQ_HANDLED; - } - -+static int regulator_enable_boost(struct regulator_dev *rdev) -+{ -+ struct boost_data *usb_data = rdev_get_drvdata(rdev); -+ -+ usb_data->occ_timeout = ktime_add_us(ktime_get(), 100000); -+ -+ return regulator_enable_regmap(rdev); -+} -+ -+static int regulator_disable_boost(struct regulator_dev *rdev) -+{ -+ struct boost_data *usb_data = rdev_get_drvdata(rdev); -+ -+ usb_data->occ_timeout = 0; -+ -+ return regulator_disable_regmap(rdev); -+} -+ -+static void stpmic1_reset_boost(struct boost_data *usb_data) -+{ -+ int otg_on = 0; -+ int sw_out_on = 0; -+ -+ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "reset usb boost\n"); -+ -+ regulator_lock(usb_data->boost_rdev); -+ -+ /* the boost was actually disabled by the over-current protection */ -+ regulator_disable_regmap(usb_data->boost_rdev); -+ -+ if (usb_data->vbus_otg_rdev) -+ otg_on = regulator_is_enabled_regmap(usb_data->vbus_otg_rdev); -+ if (otg_on) { -+ regulator_lock(usb_data->vbus_otg_rdev); -+ regulator_disable_regmap(usb_data->vbus_otg_rdev); -+ } -+ -+ if (usb_data->sw_out_rdev) -+ sw_out_on = regulator_is_enabled_regmap(usb_data->sw_out_rdev); -+ if (sw_out_on) { -+ regulator_lock(usb_data->sw_out_rdev); -+ regulator_disable_regmap(usb_data->sw_out_rdev); -+ } -+ -+ regulator_enable_regmap(usb_data->boost_rdev); -+ -+ /* sleep at least 5ms */ -+ usleep_range(5000, 10000); -+ -+ if (otg_on) { -+ regulator_enable_regmap(usb_data->vbus_otg_rdev); -+ regulator_unlock(usb_data->vbus_otg_rdev); -+ } -+ -+ if (sw_out_on) { -+ regulator_enable_regmap(usb_data->sw_out_rdev); -+ regulator_unlock(usb_data->sw_out_rdev); -+ } -+ -+ regulator_unlock(usb_data->boost_rdev); -+} -+ -+static irqreturn_t stpmic1_boost_irq_handler(int irq, void *data) -+{ -+ struct boost_data *usb_data = (struct boost_data *)data; -+ -+ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "usb boost irq handler\n"); -+ -+ /* overcurrent detected on boost after timeout */ -+ if (usb_data->occ_timeout != 0 && -+ ktime_compare(ktime_get(), usb_data->occ_timeout) > 0) { -+ /* reset usb boost and usb power switches */ -+ stpmic1_reset_boost(usb_data); -+ return IRQ_HANDLED; -+ } -+ -+ regulator_lock(usb_data->boost_rdev); -+ -+ /* Send an overcurrent notification */ -+ regulator_notifier_call_chain(usb_data->boost_rdev, -+ REGULATOR_EVENT_OVER_CURRENT, -+ NULL); -+ -+ regulator_unlock(usb_data->boost_rdev); -+ -+ return IRQ_HANDLED; -+} -+ - #define MATCH(_name, _id) \ - [STPMIC1_##_id] = { \ - .name = #_name, \ -@@ -534,9 +646,10 @@ static struct of_regulator_match stpmic1_matches[] = { - MATCH(pwr_sw2, SW_OUT), - }; - --static int stpmic1_regulator_register(struct platform_device *pdev, int id, -- struct of_regulator_match *match, -- const struct stpmic1_regulator_cfg *cfg) -+static struct regulator_dev * -+stpmic1_regulator_register(struct platform_device *pdev, int id, -+ struct of_regulator_match *match, -+ const struct stpmic1_regulator_cfg *cfg) - { - struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); - struct regulator_dev *rdev; -@@ -554,7 +667,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, "failed to register %s regulator\n", - cfg->desc.name); -- return PTR_ERR(rdev); -+ return rdev; - } - - /* set mask reset */ -@@ -566,7 +679,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, - cfg->mask_reset_mask); - if (ret) { - dev_err(&pdev->dev, "set mask reset failed\n"); -- return ret; -+ return ERR_PTR(ret); - } - } - -@@ -580,15 +693,60 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, - pdev->name, rdev); - if (ret) { - dev_err(&pdev->dev, "Request IRQ failed\n"); -- return ret; -+ return ERR_PTR(ret); - } - } -- return 0; -+ -+ return rdev; -+} -+ -+static struct regulator_dev * -+stpmic1_boost_register(struct platform_device *pdev, int id, -+ struct of_regulator_match *match, -+ const struct stpmic1_regulator_cfg *cfg, -+ struct boost_data *usb_data) -+{ -+ struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); -+ struct regulator_dev *rdev; -+ struct regulator_config config = {}; -+ int ret = 0; -+ int irq; -+ -+ config.dev = &pdev->dev; -+ config.init_data = match->init_data; -+ config.of_node = match->of_node; -+ config.regmap = pmic_dev->regmap; -+ config.driver_data = (void *)usb_data; -+ -+ rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config); -+ if (IS_ERR(rdev)) { -+ dev_err(&pdev->dev, "failed to register %s regulator\n", -+ cfg->desc.name); -+ return rdev; -+ } -+ -+ /* setup an irq handler for over-current detection */ -+ irq = of_irq_get(config.of_node, 0); -+ if (irq > 0) { -+ ret = devm_request_threaded_irq(&pdev->dev, -+ irq, NULL, -+ stpmic1_boost_irq_handler, -+ IRQF_ONESHOT, pdev->name, -+ usb_data); -+ if (ret) { -+ dev_err(&pdev->dev, "Request IRQ failed\n"); -+ return ERR_PTR(ret); -+ } -+ } -+ -+ return rdev; - } - - static int stpmic1_regulator_probe(struct platform_device *pdev) - { - int i, ret; -+ struct boost_data *usb_data; -+ struct regulator_dev *rdev; - - ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches, - ARRAY_SIZE(stpmic1_matches)); -@@ -598,11 +756,30 @@ static int stpmic1_regulator_probe(struct platform_device *pdev) - return ret; - } - -+ usb_data = devm_kzalloc(&pdev->dev, sizeof(*usb_data), GFP_KERNEL); -+ if (!usb_data) -+ return -ENOMEM; -+ - for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) { -- ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], -- &stpmic1_regulator_cfgs[i]); -- if (ret < 0) -- return ret; -+ if (i == STPMIC1_BOOST) { -+ rdev = -+ stpmic1_boost_register(pdev, i, &stpmic1_matches[i], -+ &stpmic1_regulator_cfgs[i], -+ usb_data); -+ -+ usb_data->boost_rdev = rdev; -+ } else { -+ rdev = -+ stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], -+ &stpmic1_regulator_cfgs[i]); -+ -+ if (i == STPMIC1_VBUS_OTG) -+ usb_data->vbus_otg_rdev = rdev; -+ else if (i == STPMIC1_SW_OUT) -+ usb_data->sw_out_rdev = rdev; -+ } -+ if (IS_ERR(rdev)) -+ return PTR_ERR(rdev); - } - - dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n"); -diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c -index 4e726929bb4f5..77c1da13a3f05 100644 ---- a/drivers/spi/spi-stm32-qspi.c -+++ b/drivers/spi/spi-stm32-qspi.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -87,6 +88,7 @@ - #define STM32_BUSY_TIMEOUT_US 100000 - #define STM32_ABT_TIMEOUT_US 100000 - #define STM32_COMP_TIMEOUT_MS 1000 -+#define STM32_AUTOSUSPEND_DELAY -1 - - struct stm32_qspi_flash { - struct stm32_qspi *qspi; -@@ -431,10 +433,17 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) - struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); - int ret; - -+ ret = pm_runtime_get_sync(qspi->dev); -+ if (ret < 0) -+ return ret; -+ - mutex_lock(&qspi->lock); - ret = stm32_qspi_send(mem, op); - mutex_unlock(&qspi->lock); - -+ pm_runtime_mark_last_busy(qspi->dev); -+ pm_runtime_put_autosuspend(qspi->dev); -+ - return ret; - } - -@@ -444,6 +453,7 @@ static int stm32_qspi_setup(struct spi_device *spi) - struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl); - struct stm32_qspi_flash *flash; - u32 presc; -+ int ret; - - if (ctrl->busy) - return -EBUSY; -@@ -451,6 +461,10 @@ static int stm32_qspi_setup(struct spi_device *spi) - if (!spi->max_speed_hz) - return -EINVAL; - -+ ret = pm_runtime_get_sync(qspi->dev); -+ if (ret < 0) -+ return ret; -+ - presc = DIV_ROUND_UP(qspi->clk_rate, spi->max_speed_hz) - 1; - - flash = &qspi->flash[spi->chip_select]; -@@ -467,13 +481,17 @@ static int stm32_qspi_setup(struct spi_device *spi) - writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); - mutex_unlock(&qspi->lock); - -+ pm_runtime_mark_last_busy(qspi->dev); -+ pm_runtime_put_autosuspend(qspi->dev); -+ - return 0; - } - --static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) -+static int stm32_qspi_dma_setup(struct stm32_qspi *qspi) - { - struct dma_slave_config dma_cfg; - struct device *dev = qspi->dev; -+ int ret = 0; - - memset(&dma_cfg, 0, sizeof(dma_cfg)); - -@@ -484,8 +502,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) - dma_cfg.src_maxburst = 4; - dma_cfg.dst_maxburst = 4; - -- qspi->dma_chrx = dma_request_slave_channel(dev, "rx"); -- if (qspi->dma_chrx) { -+ qspi->dma_chrx = dma_request_chan(dev, "rx"); -+ if (IS_ERR(qspi->dma_chrx)) { -+ ret = PTR_ERR(qspi->dma_chrx); -+ qspi->dma_chrx = NULL; -+ if (ret == -EPROBE_DEFER) -+ goto out; -+ } else { - if (dmaengine_slave_config(qspi->dma_chrx, &dma_cfg)) { - dev_err(dev, "dma rx config failed\n"); - dma_release_channel(qspi->dma_chrx); -@@ -493,8 +516,11 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) - } - } - -- qspi->dma_chtx = dma_request_slave_channel(dev, "tx"); -- if (qspi->dma_chtx) { -+ qspi->dma_chtx = dma_request_chan(dev, "tx"); -+ if (IS_ERR(qspi->dma_chtx)) { -+ ret = PTR_ERR(qspi->dma_chtx); -+ qspi->dma_chtx = NULL; -+ } else { - if (dmaengine_slave_config(qspi->dma_chtx, &dma_cfg)) { - dev_err(dev, "dma tx config failed\n"); - dma_release_channel(qspi->dma_chtx); -@@ -502,7 +528,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) - } - } - -+out: - init_completion(&qspi->dma_completion); -+ -+ if (ret != -EPROBE_DEFER) -+ ret = 0; -+ -+ return ret; - } - - static void stm32_qspi_dma_free(struct stm32_qspi *qspi) -@@ -521,15 +553,6 @@ static const struct spi_controller_mem_ops stm32_qspi_mem_ops = { - .exec_op = stm32_qspi_exec_op, - }; - --static void stm32_qspi_release(struct stm32_qspi *qspi) --{ -- /* disable qspi */ -- writel_relaxed(0, qspi->io_base + QSPI_CR); -- stm32_qspi_dma_free(qspi); -- mutex_destroy(&qspi->lock); -- clk_disable_unprepare(qspi->clk); --} -- - static int stm32_qspi_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -550,7 +573,7 @@ static int stm32_qspi_probe(struct platform_device *pdev) - qspi->io_base = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->io_base)) { - ret = PTR_ERR(qspi->io_base); -- goto err; -+ goto err_master_put; - } - - qspi->phys_base = res->start; -@@ -559,24 +582,26 @@ static int stm32_qspi_probe(struct platform_device *pdev) - qspi->mm_base = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->mm_base)) { - ret = PTR_ERR(qspi->mm_base); -- goto err; -+ goto err_master_put; - } - - qspi->mm_size = resource_size(res); - if (qspi->mm_size > STM32_QSPI_MAX_MMAP_SZ) { - ret = -EINVAL; -- goto err; -+ goto err_master_put; - } - - irq = platform_get_irq(pdev, 0); -- if (irq < 0) -- return irq; -+ if (irq < 0) { -+ ret = irq; -+ goto err_master_put; -+ } - - ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0, - dev_name(dev), qspi); - if (ret) { - dev_err(dev, "failed to request irq\n"); -- goto err; -+ goto err_master_put; - } - - init_completion(&qspi->data_completion); -@@ -584,23 +609,27 @@ static int stm32_qspi_probe(struct platform_device *pdev) - qspi->clk = devm_clk_get(dev, NULL); - if (IS_ERR(qspi->clk)) { - ret = PTR_ERR(qspi->clk); -- goto err; -+ goto err_master_put; - } - - qspi->clk_rate = clk_get_rate(qspi->clk); - if (!qspi->clk_rate) { - ret = -EINVAL; -- goto err; -+ goto err_master_put; - } - - ret = clk_prepare_enable(qspi->clk); - if (ret) { - dev_err(dev, "can not enable the clock\n"); -- goto err; -+ goto err_master_put; - } - - rstc = devm_reset_control_get_exclusive(dev, NULL); -- if (!IS_ERR(rstc)) { -+ if (IS_ERR(rstc)) { -+ ret = PTR_ERR(rstc); -+ if (ret == -EPROBE_DEFER) -+ goto err_clk_disable; -+ } else { - reset_control_assert(rstc); - udelay(2); - reset_control_deassert(rstc); -@@ -608,7 +637,10 @@ static int stm32_qspi_probe(struct platform_device *pdev) - - qspi->dev = dev; - platform_set_drvdata(pdev, qspi); -- stm32_qspi_dma_setup(qspi); -+ ret = stm32_qspi_dma_setup(qspi); -+ if (ret) -+ goto err_dma_free; -+ - mutex_init(&qspi->lock); - - ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD -@@ -619,12 +651,35 @@ static int stm32_qspi_probe(struct platform_device *pdev) - ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP; - ctrl->dev.of_node = dev->of_node; - -+ pm_runtime_set_autosuspend_delay(dev, STM32_AUTOSUSPEND_DELAY); -+ pm_runtime_use_autosuspend(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ pm_runtime_get_noresume(dev); -+ - ret = devm_spi_register_master(dev, ctrl); -- if (!ret) -- return 0; -+ if (ret) -+ goto err_pm_runtime_free; -+ -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ -+ return 0; - --err: -- stm32_qspi_release(qspi); -+err_pm_runtime_free: -+ pm_runtime_get_sync(qspi->dev); -+ /* disable qspi */ -+ writel_relaxed(0, qspi->io_base + QSPI_CR); -+ mutex_destroy(&qspi->lock); -+ pm_runtime_put_noidle(qspi->dev); -+ pm_runtime_disable(qspi->dev); -+ pm_runtime_set_suspended(qspi->dev); -+ pm_runtime_dont_use_autosuspend(qspi->dev); -+err_dma_free: -+ stm32_qspi_dma_free(qspi); -+err_clk_disable: -+ clk_disable_unprepare(qspi->clk); -+err_master_put: - spi_master_put(qspi->ctrl); - - return ret; -@@ -634,15 +689,38 @@ static int stm32_qspi_remove(struct platform_device *pdev) - { - struct stm32_qspi *qspi = platform_get_drvdata(pdev); - -- stm32_qspi_release(qspi); -+ pm_runtime_get_sync(qspi->dev); -+ /* disable qspi */ -+ writel_relaxed(0, qspi->io_base + QSPI_CR); -+ stm32_qspi_dma_free(qspi); -+ mutex_destroy(&qspi->lock); -+ pm_runtime_put_noidle(qspi->dev); -+ pm_runtime_disable(qspi->dev); -+ pm_runtime_set_suspended(qspi->dev); -+ pm_runtime_dont_use_autosuspend(qspi->dev); -+ clk_disable_unprepare(qspi->clk); -+ - return 0; - } - --static int __maybe_unused stm32_qspi_suspend(struct device *dev) -+static int __maybe_unused stm32_qspi_runtime_suspend(struct device *dev) - { - struct stm32_qspi *qspi = dev_get_drvdata(dev); - - clk_disable_unprepare(qspi->clk); -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32_qspi_runtime_resume(struct device *dev) -+{ -+ struct stm32_qspi *qspi = dev_get_drvdata(dev); -+ -+ return clk_prepare_enable(qspi->clk); -+} -+ -+static int __maybe_unused stm32_qspi_suspend(struct device *dev) -+{ - pinctrl_pm_select_sleep_state(dev); - - return 0; -@@ -651,17 +729,28 @@ static int __maybe_unused stm32_qspi_suspend(struct device *dev) - static int __maybe_unused stm32_qspi_resume(struct device *dev) - { - struct stm32_qspi *qspi = dev_get_drvdata(dev); -+ int ret; - - pinctrl_pm_select_default_state(dev); -- clk_prepare_enable(qspi->clk); -+ -+ ret = pm_runtime_get_sync(qspi->dev); -+ if (ret < 0) -+ return ret; - - writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); - writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); - -+ pm_runtime_mark_last_busy(qspi->dev); -+ pm_runtime_put_autosuspend(qspi->dev); -+ - return 0; - } - --static SIMPLE_DEV_PM_OPS(stm32_qspi_pm_ops, stm32_qspi_suspend, stm32_qspi_resume); -+static const struct dev_pm_ops stm32_qspi_pm_ops = { -+ SET_RUNTIME_PM_OPS(stm32_qspi_runtime_suspend, -+ stm32_qspi_runtime_resume, NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(stm32_qspi_suspend, stm32_qspi_resume) -+}; - - static const struct of_device_id stm32_qspi_match[] = { - {.compatible = "st,stm32f469-qspi"}, -diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c -index b222ce8d083ef..feed9206323be 100644 ---- a/drivers/spi/spi-stm32.c -+++ b/drivers/spi/spi-stm32.c -@@ -5,6 +5,7 @@ - // Copyright (C) 2017, STMicroelectronics - All Rights Reserved - // Author(s): Amelie Delaunay for STMicroelectronics. - -+#include - #include - #include - #include -@@ -13,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -31,8 +33,8 @@ - #define STM32F4_SPI_CR1_CPHA BIT(0) - #define STM32F4_SPI_CR1_CPOL BIT(1) - #define STM32F4_SPI_CR1_MSTR BIT(2) --#define STM32F4_SPI_CR1_BR_SHIFT 3 - #define STM32F4_SPI_CR1_BR GENMASK(5, 3) -+#define STM32F4_SPI_CR1_BR_SHIFT 3 - #define STM32F4_SPI_CR1_SPE BIT(6) - #define STM32F4_SPI_CR1_LSBFRST BIT(7) - #define STM32F4_SPI_CR1_SSI BIT(8) -@@ -94,27 +96,22 @@ - #define STM32H7_SPI_CR1_SSI BIT(12) - - /* STM32H7_SPI_CR2 bit fields */ --#define STM32H7_SPI_CR2_TSIZE_SHIFT 0 - #define STM32H7_SPI_CR2_TSIZE GENMASK(15, 0) -+#define STM32H7_SPI_TSIZE_MAX GENMASK(15, 0) - - /* STM32H7_SPI_CFG1 bit fields */ --#define STM32H7_SPI_CFG1_DSIZE_SHIFT 0 - #define STM32H7_SPI_CFG1_DSIZE GENMASK(4, 0) --#define STM32H7_SPI_CFG1_FTHLV_SHIFT 5 - #define STM32H7_SPI_CFG1_FTHLV GENMASK(8, 5) - #define STM32H7_SPI_CFG1_RXDMAEN BIT(14) - #define STM32H7_SPI_CFG1_TXDMAEN BIT(15) --#define STM32H7_SPI_CFG1_MBR_SHIFT 28 - #define STM32H7_SPI_CFG1_MBR GENMASK(30, 28) -+#define STM32H7_SPI_CFG1_MBR_SHIFT 28 - #define STM32H7_SPI_CFG1_MBR_MIN 0 - #define STM32H7_SPI_CFG1_MBR_MAX (GENMASK(30, 28) >> 28) - - /* STM32H7_SPI_CFG2 bit fields */ --#define STM32H7_SPI_CFG2_MIDI_SHIFT 4 - #define STM32H7_SPI_CFG2_MIDI GENMASK(7, 4) --#define STM32H7_SPI_CFG2_COMM_SHIFT 17 - #define STM32H7_SPI_CFG2_COMM GENMASK(18, 17) --#define STM32H7_SPI_CFG2_SP_SHIFT 19 - #define STM32H7_SPI_CFG2_SP GENMASK(21, 19) - #define STM32H7_SPI_CFG2_MASTER BIT(22) - #define STM32H7_SPI_CFG2_LSBFRST BIT(23) -@@ -137,10 +134,10 @@ - #define STM32H7_SPI_SR_RXP BIT(0) - #define STM32H7_SPI_SR_TXP BIT(1) - #define STM32H7_SPI_SR_EOT BIT(3) -+#define STM32H7_SPI_SR_TXTF BIT(4) - #define STM32H7_SPI_SR_OVR BIT(6) - #define STM32H7_SPI_SR_MODF BIT(9) - #define STM32H7_SPI_SR_SUSP BIT(11) --#define STM32H7_SPI_SR_RXPLVL_SHIFT 13 - #define STM32H7_SPI_SR_RXPLVL GENMASK(14, 13) - #define STM32H7_SPI_SR_RXWNE BIT(15) - -@@ -167,8 +164,6 @@ - #define SPI_3WIRE_TX 3 - #define SPI_3WIRE_RX 4 - --#define SPI_1HZ_NS 1000000000 -- - /* - * use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers - * without fifo buffers. -@@ -249,7 +244,7 @@ struct stm32_spi_cfg { - int (*set_mode)(struct stm32_spi *spi, unsigned int comm_type); - void (*set_data_idleness)(struct stm32_spi *spi, u32 length); - int (*set_number_of_data)(struct stm32_spi *spi, u32 length); -- void (*transfer_one_dma_start)(struct stm32_spi *spi); -+ int (*transfer_one_dma_start)(struct stm32_spi *spi); - void (*dma_rx_cb)(void *data); - void (*dma_tx_cb)(void *data); - int (*transfer_one_irq)(struct stm32_spi *spi); -@@ -268,7 +263,6 @@ struct stm32_spi_cfg { - * @base: virtual memory area - * @clk: hw kernel clock feeding the SPI clock generator - * @clk_rate: rate of the hw kernel clock feeding the SPI clock generator -- * @rst: SPI controller reset line - * @lock: prevent I/O concurrent access - * @irq: SPI controller interrupt line - * @fifo_size: size of the embedded fifo in bytes -@@ -294,7 +288,6 @@ struct stm32_spi { - void __iomem *base; - struct clk *clk; - u32 clk_rate; -- struct reset_control *rst; - spinlock_t lock; /* prevent I/O concurrent access */ - int irq; - unsigned int fifo_size; -@@ -313,7 +306,10 @@ struct stm32_spi { - int rx_len; - struct dma_chan *dma_tx; - struct dma_chan *dma_rx; -+ struct completion dma_completion; - dma_addr_t phys_addr; -+ struct completion xfer_completion; -+ int xfer_status; - }; - - static const struct stm32_spi_regspec stm32f4_spi_regspec = { -@@ -417,9 +413,7 @@ static int stm32h7_spi_get_bpw_mask(struct stm32_spi *spi) - stm32_spi_set_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_DSIZE); - - cfg1 = readl_relaxed(spi->base + STM32H7_SPI_CFG1); -- max_bpw = (cfg1 & STM32H7_SPI_CFG1_DSIZE) >> -- STM32H7_SPI_CFG1_DSIZE_SHIFT; -- max_bpw += 1; -+ max_bpw = FIELD_GET(STM32H7_SPI_CFG1_DSIZE, cfg1) + 1; - - spin_unlock_irqrestore(&spi->lock, flags); - -@@ -442,7 +436,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, - { - u32 div, mbrdiv; - -- div = DIV_ROUND_UP(spi->clk_rate, speed_hz); -+ /* Ensure spi->clk_rate is even */ -+ div = DIV_ROUND_UP(spi->clk_rate & ~0x1, speed_hz); - - /* - * SPI framework set xfer->speed_hz to master->max_speed_hz if -@@ -469,19 +464,22 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, - * stm32h7_spi_prepare_fthlv - Determine FIFO threshold level - * @spi: pointer to the spi controller data structure - */ --static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi) -+static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len) - { -- u32 fthlv, half_fifo; -+ u32 fthlv, half_fifo, packet; - - /* data packet should not exceed 1/2 of fifo space */ - half_fifo = (spi->fifo_size / 2); - -+ /* data_packet should not exceed transfer length */ -+ packet = (half_fifo > xfer_len) ? xfer_len : half_fifo; -+ - if (spi->cur_bpw <= 8) -- fthlv = half_fifo; -+ fthlv = packet; - else if (spi->cur_bpw <= 16) -- fthlv = half_fifo / 2; -+ fthlv = packet / 2; - else -- fthlv = half_fifo / 4; -+ fthlv = packet / 4; - - /* align packet size with data registers access */ - if (spi->cur_bpw > 8) -@@ -489,6 +487,9 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi) - else - fthlv -= (fthlv % 4); /* multiple of 4 */ - -+ if (!fthlv) -+ fthlv = 1; -+ - return fthlv; - } - -@@ -592,25 +593,26 @@ static void stm32f4_spi_read_rx(struct stm32_spi *spi) - * Write in rx_buf depends on remaining bytes to avoid to write beyond - * rx_buf end. - */ --static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush) -+static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi) - { - u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR); -- u32 rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >> -- STM32H7_SPI_SR_RXPLVL_SHIFT; -+ u32 rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr); - - while ((spi->rx_len > 0) && - ((sr & STM32H7_SPI_SR_RXP) || -- (flush && ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) { -+ ((sr & STM32H7_SPI_SR_EOT) && -+ ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) { - u32 offs = spi->cur_xferlen - spi->rx_len; - - if ((spi->rx_len >= sizeof(u32)) || -- (flush && (sr & STM32H7_SPI_SR_RXWNE))) { -+ (sr & STM32H7_SPI_SR_RXWNE)) { - u32 *rx_buf32 = (u32 *)(spi->rx_buf + offs); - - *rx_buf32 = readl_relaxed(spi->base + STM32H7_SPI_RXDR); - spi->rx_len -= sizeof(u32); - } else if ((spi->rx_len >= sizeof(u16)) || -- (flush && (rxplvl >= 2 || spi->cur_bpw > 8))) { -+ (!(sr & STM32H7_SPI_SR_RXWNE) && -+ (rxplvl >= 2 || spi->cur_bpw > 8))) { - u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs); - - *rx_buf16 = readw_relaxed(spi->base + STM32H7_SPI_RXDR); -@@ -623,12 +625,11 @@ static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush) - } - - sr = readl_relaxed(spi->base + STM32H7_SPI_SR); -- rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >> -- STM32H7_SPI_SR_RXPLVL_SHIFT; -+ rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr); - } - -- dev_dbg(spi->dev, "%s%s: %d bytes left\n", __func__, -- flush ? "(flush)" : "", spi->rx_len); -+ dev_dbg(spi->dev, "%s: %d bytes left (sr=%08x)\n", -+ __func__, spi->rx_len, sr); - } - - /** -@@ -696,12 +697,7 @@ static void stm32f4_spi_disable(struct stm32_spi *spi) - * @spi: pointer to the spi controller data structure - * - * RX-Fifo is flushed when SPI controller is disabled. To prevent any data -- * loss, use stm32h7_spi_read_rxfifo(flush) to read the remaining bytes in -- * RX-Fifo. -- * Normally, if TSIZE has been configured, we should relax the hardware at the -- * reception of the EOT interrupt. But in case of error, EOT will not be -- * raised. So the subsystem unprepare_message call allows us to properly -- * complete the transfer from an hardware point of view. -+ * loss, use stm32_spi_read_rxfifo to read the remaining bytes in RX-Fifo. - */ - static void stm32h7_spi_disable(struct stm32_spi *spi) - { -@@ -736,7 +732,7 @@ static void stm32h7_spi_disable(struct stm32_spi *spi) - } - - if (!spi->cur_usedma && spi->rx_buf && (spi->rx_len > 0)) -- stm32h7_spi_read_rxfifo(spi, true); -+ stm32h7_spi_read_rxfifo(spi); - - if (spi->cur_usedma && spi->dma_tx) - dmaengine_terminate_all(spi->dma_tx); -@@ -891,7 +887,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) - { - struct spi_master *master = dev_id; - struct stm32_spi *spi = spi_master_get_devdata(master); -- u32 sr, ier, mask; -+ u32 sr, ier, mask, ifcr; - unsigned long flags; - bool end = false; - -@@ -899,77 +895,77 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) - - sr = readl_relaxed(spi->base + STM32H7_SPI_SR); - ier = readl_relaxed(spi->base + STM32H7_SPI_IER); -+ ifcr = 0; - - mask = ier; -- /* EOTIE is triggered on EOT, SUSP and TXC events. */ -+ /* -+ * EOTIE enables irq from EOT, SUSP and TXC events. We need to set -+ * SUSP to acknowledge it later. TXC is automatically cleared -+ */ - mask |= STM32H7_SPI_SR_SUSP; - /* -- * When TXTF is set, DXPIE and TXPIE are cleared. So in case of -- * Full-Duplex, need to poll RXP event to know if there are remaining -- * data, before disabling SPI. -+ * DXPIE is set in Full-Duplex, one IT will be raised if TXP and RXP -+ * are set. So in case of Full-Duplex, need to poll TXP and RXP event. - */ -- if (spi->rx_buf && !spi->cur_usedma) -- mask |= STM32H7_SPI_SR_RXP; -+ if ((spi->cur_comm == SPI_FULL_DUPLEX) && (!spi->cur_usedma)) -+ mask |= STM32H7_SPI_SR_TXP | STM32H7_SPI_SR_RXP; - -- if (!(sr & mask)) { -- dev_dbg(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", -- sr, ier); -+ mask &= sr; -+ -+ if (!mask) { -+ dev_warn(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", -+ sr, ier); - spin_unlock_irqrestore(&spi->lock, flags); - return IRQ_NONE; - } - -- if (sr & STM32H7_SPI_SR_SUSP) { -- dev_warn(spi->dev, "Communication suspended\n"); -+ if (mask & STM32H7_SPI_SR_SUSP) { -+ dev_warn_once(spi->dev, -+ "System too slow is limiting data throughput\n"); -+ - if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -- stm32h7_spi_read_rxfifo(spi, false); -- /* -- * If communication is suspended while using DMA, it means -- * that something went wrong, so stop the current transfer -- */ -- if (spi->cur_usedma) -- end = true; -+ stm32h7_spi_read_rxfifo(spi); -+ -+ ifcr |= STM32H7_SPI_SR_SUSP; - } - -- if (sr & STM32H7_SPI_SR_MODF) { -- dev_warn(spi->dev, "Mode fault: transfer aborted\n"); -+ if (mask & STM32H7_SPI_SR_OVR) { -+ dev_err(spi->dev, "Overrun: RX data lost\n"); -+ spi->xfer_status = -EIO; - end = true; -+ ifcr |= STM32H7_SPI_SR_OVR; - } - -- if (sr & STM32H7_SPI_SR_OVR) { -- dev_warn(spi->dev, "Overrun: received value discarded\n"); -- if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -- stm32h7_spi_read_rxfifo(spi, false); -- /* -- * If overrun is detected while using DMA, it means that -- * something went wrong, so stop the current transfer -- */ -- if (spi->cur_usedma) -- end = true; -- } -+ if (mask & STM32H7_SPI_SR_TXTF) -+ ifcr |= STM32H7_SPI_SR_TXTF; - -- if (sr & STM32H7_SPI_SR_EOT) { -+ if (mask & STM32H7_SPI_SR_EOT) { - if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -- stm32h7_spi_read_rxfifo(spi, true); -+ stm32h7_spi_read_rxfifo(spi); - end = true; -+ ifcr |= STM32H7_SPI_SR_EOT; - } - -- if (sr & STM32H7_SPI_SR_TXP) -+ if (mask & STM32H7_SPI_SR_TXP) - if (!spi->cur_usedma && (spi->tx_buf && (spi->tx_len > 0))) - stm32h7_spi_write_txfifo(spi); - -- if (sr & STM32H7_SPI_SR_RXP) -+ if (mask & STM32H7_SPI_SR_RXP) - if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -- stm32h7_spi_read_rxfifo(spi, false); -- -- writel_relaxed(mask, spi->base + STM32H7_SPI_IFCR); -- -- spin_unlock_irqrestore(&spi->lock, flags); -+ stm32h7_spi_read_rxfifo(spi); - - if (end) { -- spi_finalize_current_transfer(master); -- stm32h7_spi_disable(spi); -+ /* Disable interrupts and clear status flags */ -+ writel_relaxed(0, spi->base + STM32H7_SPI_IER); -+ writel_relaxed(STM32H7_SPI_IFCR_ALL, -+ spi->base + STM32H7_SPI_IFCR); -+ -+ complete(&spi->xfer_completion); -+ } else { -+ writel_relaxed(ifcr, spi->base + STM32H7_SPI_IFCR); - } - -+ spin_unlock_irqrestore(&spi->lock, flags); - return IRQ_HANDLED; - } - -@@ -980,11 +976,8 @@ static int stm32_spi_setup(struct spi_device *spi_dev) - { - int ret = 0; - -- if (!gpio_is_valid(spi_dev->cs_gpio)) { -- dev_err(&spi_dev->dev, "%d is not a valid gpio\n", -- spi_dev->cs_gpio); -- return -EINVAL; -- } -+ if (!gpio_is_valid(spi_dev->cs_gpio)) -+ return 0; - - dev_dbg(&spi_dev->dev, "%s: set gpio%d output %s\n", __func__, - spi_dev->cs_gpio, -@@ -1034,6 +1027,20 @@ static int stm32_spi_prepare_msg(struct spi_master *master, - spi_dev->mode & SPI_LSB_FIRST, - spi_dev->mode & SPI_CS_HIGH); - -+ /* On STM32H7, messages should not exceed a maximum size setted -+ * afterward via the set_number_of_data function. In order to -+ * ensure that, split large messages into several messages -+ */ -+ if (spi->cfg->set_number_of_data) { -+ int ret; -+ -+ ret = spi_split_transfers_maxsize(master, msg, -+ STM32H7_SPI_TSIZE_MAX, -+ GFP_KERNEL | GFP_DMA); -+ if (ret) -+ return ret; -+ } -+ - spin_lock_irqsave(&spi->lock, flags); - - /* CPOL, CPHA and LSB FIRST bits have common register */ -@@ -1079,25 +1086,18 @@ static void stm32f4_spi_dma_rx_cb(void *data) - /** - * stm32h7_spi_dma_cb - dma callback - * -- * DMA callback is called when the transfer is complete or when an error -- * occurs. If the transfer is complete, EOT flag is raised. -+ * DMA callback is called when the transfer is complete. - */ - static void stm32h7_spi_dma_cb(void *data) - { - struct stm32_spi *spi = data; - unsigned long flags; -- u32 sr; - - spin_lock_irqsave(&spi->lock, flags); - -- sr = readl_relaxed(spi->base + STM32H7_SPI_SR); -+ complete(&spi->dma_completion); - - spin_unlock_irqrestore(&spi->lock, flags); -- -- if (!(sr & STM32H7_SPI_SR_EOT)) -- dev_warn(spi->dev, "DMA error (sr=0x%08x)\n", sr); -- -- /* Now wait for EOT, or SUSP or OVR in case of error */ - } - - /** -@@ -1190,9 +1190,6 @@ static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi) - /** - * stm32h7_spi_transfer_one_irq - transfer a single spi_transfer using - * interrupts -- * -- * It must returns 0 if the transfer is finished or 1 if the transfer is still -- * in progress. - */ - static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) - { -@@ -1209,7 +1206,7 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) - - /* Enable the interrupts relative to the end of transfer */ - ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE | -- STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE; -+ STM32H7_SPI_IER_OVRIE; - - spin_lock_irqsave(&spi->lock, flags); - -@@ -1225,15 +1222,19 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) - - spin_unlock_irqrestore(&spi->lock, flags); - -- return 1; -+ return 0; - } - - /** - * stm32f4_spi_transfer_one_dma_start - Set SPI driver registers to start - * transfer using DMA - */ --static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) -+static int stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&spi->lock, flags); -+ - /* In DMA mode end of transfer is handled by DMA TX or RX callback. */ - if (spi->cur_comm == SPI_SIMPLEX_RX || spi->cur_comm == SPI_3WIRE_RX || - spi->cur_comm == SPI_FULL_DUPLEX) { -@@ -1246,40 +1247,56 @@ static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) - } - - stm32_spi_enable(spi); -+ -+ spin_unlock_irqrestore(&spi->lock, flags); -+ -+ return 1; - } - - /** - * stm32h7_spi_transfer_one_dma_start - Set SPI driver registers to start - * transfer using DMA - */ --static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) -+static int stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&spi->lock, flags); -+ - /* Enable the interrupts relative to the end of transfer */ - stm32_spi_set_bits(spi, STM32H7_SPI_IER, STM32H7_SPI_IER_EOTIE | - STM32H7_SPI_IER_TXTFIE | -- STM32H7_SPI_IER_OVRIE | -- STM32H7_SPI_IER_MODFIE); -+ STM32H7_SPI_IER_OVRIE); - - stm32_spi_enable(spi); - - stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); -+ -+ spin_unlock_irqrestore(&spi->lock, flags); -+ -+ return 0; - } - - /** - * stm32_spi_transfer_one_dma - transfer a single spi_transfer using DMA -- * -- * It must returns 0 if the transfer is finished or 1 if the transfer is still -- * in progress. - */ - static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, - struct spi_transfer *xfer) - { -+ dma_async_tx_callback rx_done = NULL, tx_done = NULL; - struct dma_slave_config tx_dma_conf, rx_dma_conf; - struct dma_async_tx_descriptor *tx_dma_desc, *rx_dma_desc; - unsigned long flags; - - spin_lock_irqsave(&spi->lock, flags); - -+ if (spi->rx_buf) -+ rx_done = spi->cfg->dma_rx_cb; -+ else if (spi->tx_buf) -+ tx_done = spi->cfg->dma_tx_cb; -+ -+ reinit_completion(&spi->dma_completion); -+ - rx_dma_desc = NULL; - if (spi->rx_buf && spi->dma_rx) { - stm32_spi_dma_config(spi, &rx_dma_conf, DMA_DEV_TO_MEM); -@@ -1316,7 +1333,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, - goto dma_desc_error; - - if (rx_dma_desc) { -- rx_dma_desc->callback = spi->cfg->dma_rx_cb; -+ rx_dma_desc->callback = rx_done; - rx_dma_desc->callback_param = spi; - - if (dma_submit_error(dmaengine_submit(rx_dma_desc))) { -@@ -1330,7 +1347,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, - if (tx_dma_desc) { - if (spi->cur_comm == SPI_SIMPLEX_TX || - spi->cur_comm == SPI_3WIRE_TX) { -- tx_dma_desc->callback = spi->cfg->dma_tx_cb; -+ tx_dma_desc->callback = tx_done; - tx_dma_desc->callback_param = spi; - } - -@@ -1345,12 +1362,9 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, - stm32_spi_set_bits(spi, spi->cfg->regs->dma_tx_en.reg, - spi->cfg->regs->dma_tx_en.mask); - } -- -- spi->cfg->transfer_one_dma_start(spi); -- - spin_unlock_irqrestore(&spi->lock, flags); - -- return 1; -+ return spi->cfg->transfer_one_dma_start(spi); - - dma_submit_error: - if (spi->dma_rx) -@@ -1392,15 +1406,13 @@ static void stm32h7_spi_set_bpw(struct stm32_spi *spi) - bpw = spi->cur_bpw - 1; - - cfg1_clrb |= STM32H7_SPI_CFG1_DSIZE; -- cfg1_setb |= (bpw << STM32H7_SPI_CFG1_DSIZE_SHIFT) & -- STM32H7_SPI_CFG1_DSIZE; -+ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_DSIZE, bpw); - -- spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi); -+ spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi, spi->cur_xferlen); - fthlv = spi->cur_fthlv - 1; - - cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV; -- cfg1_setb |= (fthlv << STM32H7_SPI_CFG1_FTHLV_SHIFT) & -- STM32H7_SPI_CFG1_FTHLV; -+ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_FTHLV, fthlv); - - writel_relaxed( - (readl_relaxed(spi->base + STM32H7_SPI_CFG1) & -@@ -1418,8 +1430,7 @@ static void stm32_spi_set_mbr(struct stm32_spi *spi, u32 mbrdiv) - u32 clrb = 0, setb = 0; - - clrb |= spi->cfg->regs->br.mask; -- setb |= ((u32)mbrdiv << spi->cfg->regs->br.shift) & -- spi->cfg->regs->br.mask; -+ setb |= (mbrdiv << spi->cfg->regs->br.shift) & spi->cfg->regs->br.mask; - - writel_relaxed((readl_relaxed(spi->base + spi->cfg->regs->br.reg) & - ~clrb) | setb, -@@ -1504,8 +1515,7 @@ static int stm32h7_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type) - } - - cfg2_clrb |= STM32H7_SPI_CFG2_COMM; -- cfg2_setb |= (mode << STM32H7_SPI_CFG2_COMM_SHIFT) & -- STM32H7_SPI_CFG2_COMM; -+ cfg2_setb |= FIELD_PREP(STM32H7_SPI_CFG2_COMM, mode); - - writel_relaxed( - (readl_relaxed(spi->base + STM32H7_SPI_CFG2) & -@@ -1527,15 +1537,15 @@ static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len) - - cfg2_clrb |= STM32H7_SPI_CFG2_MIDI; - if ((len > 1) && (spi->cur_midi > 0)) { -- u32 sck_period_ns = DIV_ROUND_UP(SPI_1HZ_NS, spi->cur_speed); -- u32 midi = min((u32)DIV_ROUND_UP(spi->cur_midi, sck_period_ns), -- (u32)STM32H7_SPI_CFG2_MIDI >> -- STM32H7_SPI_CFG2_MIDI_SHIFT); -+ u32 sck_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, spi->cur_speed); -+ u32 midi = min_t(u32, -+ DIV_ROUND_UP(spi->cur_midi, sck_period_ns), -+ FIELD_GET(STM32H7_SPI_CFG2_MIDI, -+ STM32H7_SPI_CFG2_MIDI)); - - dev_dbg(spi->dev, "period=%dns, midi=%d(=%dns)\n", - sck_period_ns, midi, midi * sck_period_ns); -- cfg2_setb |= (midi << STM32H7_SPI_CFG2_MIDI_SHIFT) & -- STM32H7_SPI_CFG2_MIDI; -+ cfg2_setb |= FIELD_PREP(STM32H7_SPI_CFG2_MIDI, midi); - } - - writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CFG2) & -@@ -1550,14 +1560,8 @@ static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len) - */ - static int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words) - { -- u32 cr2_clrb = 0, cr2_setb = 0; -- -- if (nb_words <= (STM32H7_SPI_CR2_TSIZE >> -- STM32H7_SPI_CR2_TSIZE_SHIFT)) { -- cr2_clrb |= STM32H7_SPI_CR2_TSIZE; -- cr2_setb = nb_words << STM32H7_SPI_CR2_TSIZE_SHIFT; -- writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CR2) & -- ~cr2_clrb) | cr2_setb, -+ if (nb_words <= STM32H7_SPI_TSIZE_MAX) { -+ writel_relaxed(FIELD_PREP(STM32H7_SPI_CR2_TSIZE, nb_words), - spi->base + STM32H7_SPI_CR2); - } else { - return -EMSGSIZE; -@@ -1578,39 +1582,33 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, - unsigned long flags; - unsigned int comm_type; - int nb_words, ret = 0; -+ int mbr; - - spin_lock_irqsave(&spi->lock, flags); - -- if (spi->cur_bpw != transfer->bits_per_word) { -- spi->cur_bpw = transfer->bits_per_word; -- spi->cfg->set_bpw(spi); -- } -+ spi->cur_xferlen = transfer->len; - -- if (spi->cur_speed != transfer->speed_hz) { -- int mbr; -+ spi->cur_bpw = transfer->bits_per_word; -+ spi->cfg->set_bpw(spi); - -- /* Update spi->cur_speed with real clock speed */ -- mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, -- spi->cfg->baud_rate_div_min, -- spi->cfg->baud_rate_div_max); -- if (mbr < 0) { -- ret = mbr; -- goto out; -- } -- -- transfer->speed_hz = spi->cur_speed; -- stm32_spi_set_mbr(spi, mbr); -+ /* Update spi->cur_speed with real clock speed */ -+ mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, -+ spi->cfg->baud_rate_div_min, -+ spi->cfg->baud_rate_div_max); -+ if (mbr < 0) { -+ ret = mbr; -+ goto out; - } - -- comm_type = stm32_spi_communication_type(spi_dev, transfer); -- if (spi->cur_comm != comm_type) { -- ret = spi->cfg->set_mode(spi, comm_type); -+ transfer->speed_hz = spi->cur_speed; -+ stm32_spi_set_mbr(spi, mbr); - -- if (ret < 0) -- goto out; -+ comm_type = stm32_spi_communication_type(spi_dev, transfer); -+ ret = spi->cfg->set_mode(spi, comm_type); -+ if (ret < 0) -+ goto out; - -- spi->cur_comm = comm_type; -- } -+ spi->cur_comm = comm_type; - - if (spi->cfg->set_data_idleness) - spi->cfg->set_data_idleness(spi, transfer->len); -@@ -1628,8 +1626,6 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, - goto out; - } - -- spi->cur_xferlen = transfer->len; -- - dev_dbg(spi->dev, "transfer communication mode set to %d\n", - spi->cur_comm); - dev_dbg(spi->dev, -@@ -1658,8 +1654,16 @@ static int stm32_spi_transfer_one(struct spi_master *master, - struct spi_transfer *transfer) - { - struct stm32_spi *spi = spi_master_get_devdata(master); -+ u32 xfer_time, midi_delay_ns; -+ unsigned long timeout; - int ret; - -+ /* Don't do anything on 0 bytes transfers */ -+ if (transfer->len == 0) { -+ spi->xfer_status = 0; -+ goto finalize; -+ } -+ - spi->tx_buf = transfer->tx_buf; - spi->rx_buf = transfer->rx_buf; - spi->tx_len = spi->tx_buf ? transfer->len : 0; -@@ -1674,10 +1678,40 @@ static int stm32_spi_transfer_one(struct spi_master *master, - return ret; - } - -+ reinit_completion(&spi->xfer_completion); -+ spi->xfer_status = 0; -+ - if (spi->cur_usedma) -- return stm32_spi_transfer_one_dma(spi, transfer); -+ ret = stm32_spi_transfer_one_dma(spi, transfer); - else -- return spi->cfg->transfer_one_irq(spi); -+ ret = spi->cfg->transfer_one_irq(spi); -+ -+ if (ret) -+ return ret; -+ -+ /* Wait for transfer to complete */ -+ xfer_time = spi->cur_xferlen * 8 * MSEC_PER_SEC / spi->cur_speed; -+ midi_delay_ns = spi->cur_xferlen * 8 / spi->cur_bpw * spi->cur_midi; -+ xfer_time += DIV_ROUND_UP(midi_delay_ns, NSEC_PER_MSEC); -+ xfer_time = max(2 * xfer_time, 100U); -+ timeout = msecs_to_jiffies(xfer_time); -+ -+ timeout = wait_for_completion_timeout(&spi->xfer_completion, timeout); -+ if (timeout && spi->cur_usedma) -+ timeout = wait_for_completion_timeout(&spi->dma_completion, -+ timeout); -+ -+ if (!timeout) { -+ dev_err(spi->dev, "SPI transfer timeout (%u ms)\n", xfer_time); -+ spi->xfer_status = -ETIMEDOUT; -+ } -+ -+ spi->cfg->disable(spi); -+ -+finalize: -+ spi_finalize_current_transfer(master); -+ -+ return spi->xfer_status; - } - - /** -@@ -1810,7 +1844,8 @@ static int stm32_spi_probe(struct platform_device *pdev) - struct spi_master *master; - struct stm32_spi *spi; - struct resource *res; -- int i, ret; -+ struct reset_control *rst; -+ int i, ret, num_cs, cs_gpio; - - master = spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); - if (!master) { -@@ -1823,6 +1858,8 @@ static int stm32_spi_probe(struct platform_device *pdev) - spi->dev = &pdev->dev; - spi->master = master; - spin_lock_init(&spi->lock); -+ init_completion(&spi->xfer_completion); -+ init_completion(&spi->dma_completion); - - spi->cfg = (const struct stm32_spi_cfg *) - of_match_device(pdev->dev.driver->of_match_table, -@@ -1873,11 +1910,20 @@ static int stm32_spi_probe(struct platform_device *pdev) - goto err_clk_disable; - } - -- spi->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -- if (!IS_ERR(spi->rst)) { -- reset_control_assert(spi->rst); -+ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); -+ if (rst) { -+ if (IS_ERR(rst)) { -+ ret = PTR_ERR(rst); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "reset get failed: %d\n", -+ ret); -+ -+ goto err_clk_disable; -+ } -+ -+ reset_control_assert(rst); - udelay(2); -- reset_control_deassert(spi->rst); -+ reset_control_deassert(rst); - } - - if (spi->cfg->has_fifo) -@@ -1903,17 +1949,29 @@ static int stm32_spi_probe(struct platform_device *pdev) - master->transfer_one = stm32_spi_transfer_one; - master->unprepare_message = stm32_spi_unprepare_msg; - -- spi->dma_tx = dma_request_slave_channel(spi->dev, "tx"); -- if (!spi->dma_tx) -- dev_warn(&pdev->dev, "failed to request tx dma channel\n"); -- else -- master->dma_tx = spi->dma_tx; -+ spi->dma_tx = dma_request_chan(spi->dev, "tx"); -+ if (IS_ERR(spi->dma_tx)) { -+ ret = PTR_ERR(spi->dma_tx); -+ spi->dma_tx = NULL; -+ if (ret == -EPROBE_DEFER) -+ goto err_dma_release; -+ else if (ret != -ENODEV) -+ dev_warn(&pdev->dev, "failed to request tx dma: %d\n", -+ ret); -+ } -+ master->dma_tx = spi->dma_tx; - -- spi->dma_rx = dma_request_slave_channel(spi->dev, "rx"); -- if (!spi->dma_rx) -- dev_warn(&pdev->dev, "failed to request rx dma channel\n"); -- else -- master->dma_rx = spi->dma_rx; -+ spi->dma_rx = dma_request_chan(spi->dev, "rx"); -+ if (IS_ERR(spi->dma_rx)) { -+ ret = PTR_ERR(spi->dma_rx); -+ spi->dma_rx = NULL; -+ if (ret == -EPROBE_DEFER) -+ goto err_dma_release; -+ else if (ret != -ENODEV) -+ dev_warn(&pdev->dev, "failed to request rx dma: %d\n", -+ ret); -+ } -+ master->dma_rx = spi->dma_rx; - - if (spi->dma_tx || spi->dma_rx) - master->can_dma = stm32_spi_can_dma; -@@ -1921,36 +1979,33 @@ static int stm32_spi_probe(struct platform_device *pdev) - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - -- ret = devm_spi_register_master(&pdev->dev, master); -- if (ret) { -- dev_err(&pdev->dev, "spi master registration failed: %d\n", -- ret); -- goto err_dma_release; -- } -+ num_cs = of_gpio_named_count(pdev->dev.of_node, "cs-gpios"); - -- if (!master->cs_gpios) { -- dev_err(&pdev->dev, "no CS gpios available\n"); -- ret = -EINVAL; -- goto err_dma_release; -- } -- -- for (i = 0; i < master->num_chipselect; i++) { -- if (!gpio_is_valid(master->cs_gpios[i])) { -- dev_err(&pdev->dev, "%i is not a valid gpio\n", -- master->cs_gpios[i]); -- ret = -EINVAL; -+ for (i = 0; i < num_cs; i++) { -+ cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i); -+ if (cs_gpio == -EPROBE_DEFER) { -+ ret = -EPROBE_DEFER; - goto err_dma_release; - } - -- ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i], -- DRIVER_NAME); -- if (ret) { -- dev_err(&pdev->dev, "can't get CS gpio %i\n", -- master->cs_gpios[i]); -- goto err_dma_release; -+ if (gpio_is_valid(cs_gpio)) { -+ ret = devm_gpio_request(&pdev->dev, cs_gpio, -+ DRIVER_NAME); -+ if (ret) { -+ dev_err(&pdev->dev, "can't get CS gpio %i\n", -+ cs_gpio); -+ goto err_dma_release; -+ } - } - } - -+ ret = spi_register_master(master); -+ if (ret) { -+ dev_err(&pdev->dev, "spi master registration failed: %d\n", -+ ret); -+ goto err_dma_release; -+ } -+ - dev_info(&pdev->dev, "driver initialized\n"); - - return 0; -@@ -1975,6 +2030,9 @@ static int stm32_spi_remove(struct platform_device *pdev) - struct spi_master *master = platform_get_drvdata(pdev); - struct stm32_spi *spi = spi_master_get_devdata(master); - -+ pm_runtime_get_sync(&pdev->dev); -+ -+ spi_unregister_master(master); - spi->cfg->disable(spi); - - if (master->dma_tx) -@@ -1984,7 +2042,12 @@ static int stm32_spi_remove(struct platform_device *pdev) - - clk_disable_unprepare(spi->clk); - -+ pm_runtime_put_noidle(&pdev->dev); - pm_runtime_disable(&pdev->dev); -+ pm_runtime_set_suspended(&pdev->dev); -+ pm_runtime_dont_use_autosuspend(&pdev->dev); -+ -+ pinctrl_pm_select_sleep_state(&pdev->dev); - - return 0; - } -@@ -1997,13 +2060,18 @@ static int stm32_spi_runtime_suspend(struct device *dev) - - clk_disable_unprepare(spi->clk); - -- return 0; -+ return pinctrl_pm_select_sleep_state(dev); - } - - static int stm32_spi_runtime_resume(struct device *dev) - { - struct spi_master *master = dev_get_drvdata(dev); - struct stm32_spi *spi = spi_master_get_devdata(master); -+ int ret; -+ -+ ret = pinctrl_pm_select_default_state(dev); -+ if (ret) -+ return ret; - - return clk_prepare_enable(spi->clk); - } -@@ -2033,10 +2101,23 @@ static int stm32_spi_resume(struct device *dev) - return ret; - - ret = spi_master_resume(master); -- if (ret) -+ if (ret) { - clk_disable_unprepare(spi->clk); -+ return ret; -+ } - -- return ret; -+ ret = pm_runtime_get_sync(dev); -+ if (ret) { -+ dev_err(dev, "Unable to power device:%d\n", ret); -+ return ret; -+ } -+ -+ spi->cfg->config(spi); -+ -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ -+ return 0; - } - #endif - -diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h -index e6fb8ada3f4d3..370a25a9366cc 100644 ---- a/include/dt-bindings/pinctrl/stm32-pinfunc.h -+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h -@@ -26,6 +26,7 @@ - #define AF14 0xf - #define AF15 0x10 - #define ANALOG 0x11 -+#define RSVD 0x12 - - /* define Pins number*/ - #define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0018-ARM-stm32mp1-r2-SOUND.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0018-ARM-stm32mp1-r2-SOUND.patch deleted file mode 100644 index e309def..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0018-ARM-stm32mp1-r2-SOUND.patch +++ /dev/null @@ -1,1268 +0,0 @@ -From 69629ada3651978075924c825648de57ad2dab11 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:51 +0200 -Subject: [PATCH 18/22] ARM-stm32mp1-r2-rc8-SOUND - ---- - .../bindings/sound/st,stm32-i2s.txt | 62 --- - .../bindings/sound/st,stm32-i2s.yaml | 91 +++++ - sound/soc/codecs/Kconfig | 2 +- - sound/soc/codecs/cs42l51.c | 17 +- - sound/soc/codecs/wm8994.c | 80 +++- - sound/soc/stm/stm32_i2s.c | 385 +++++++++++++++--- - sound/soc/stm/stm32_sai.c | 26 +- - sound/soc/stm/stm32_sai_sub.c | 21 +- - sound/soc/stm/stm32_spdifrx.c | 105 +++-- - 9 files changed, 599 insertions(+), 190 deletions(-) - delete mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt - create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml - -diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt -deleted file mode 100644 -index cbf24bcd1b8d3..0000000000000 ---- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt -+++ /dev/null -@@ -1,62 +0,0 @@ --STMicroelectronics STM32 SPI/I2S Controller -- --The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. --Only some SPI instances support I2S. -- --Required properties: -- - compatible: Must be "st,stm32h7-i2s" -- - reg: Offset and length of the device's register set. -- - interrupts: Must contain the interrupt line id. -- - clocks: Must contain phandle and clock specifier pairs for each entry -- in clock-names. -- - clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k". -- "i2sclk": clock which feeds the internal clock generator -- "pclk": clock which feeds the peripheral bus interface -- "x8k": I2S parent clock for sampling rates multiple of 8kHz. -- "x11k": I2S parent clock for sampling rates multiple of 11.025kHz. -- - dmas: DMA specifiers for tx and rx dma. -- See Documentation/devicetree/bindings/dma/stm32-dma.txt. -- - dma-names: Identifier for each DMA request line. Must be "tx" and "rx". -- - pinctrl-names: should contain only value "default" -- - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml -- --Optional properties: -- - resets: Reference to a reset controller asserting the reset controller -- --The device node should contain one 'port' child node with one child 'endpoint' --node, according to the bindings defined in Documentation/devicetree/bindings/ --graph.txt. -- --Example: --sound_card { -- compatible = "audio-graph-card"; -- dais = <&i2s2_port>; --}; -- --i2s2: audio-controller@40003800 { -- compatible = "st,stm32h7-i2s"; -- reg = <0x40003800 0x400>; -- interrupts = <36>; -- clocks = <&rcc PCLK1>, <&rcc SPI2_CK>, <&rcc PLL1_Q>, <&rcc PLL2_P>; -- clock-names = "pclk", "i2sclk", "x8k", "x11k"; -- dmas = <&dmamux2 2 39 0x400 0x1>, -- <&dmamux2 3 40 0x400 0x1>; -- dma-names = "rx", "tx"; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_i2s2>; -- -- i2s2_port: port@0 { -- cpu_endpoint: endpoint { -- remote-endpoint = <&codec_endpoint>; -- format = "i2s"; -- }; -- }; --}; -- --audio-codec { -- codec_port: port@0 { -- codec_endpoint: endpoint { -- remote-endpoint = <&cpu_endpoint>; -- }; -- }; --}; -diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml -new file mode 100644 -index 0000000000000..6feb5a09c184e ---- /dev/null -+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml -@@ -0,0 +1,91 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/sound/st,stm32-i2s.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: STMicroelectronics STM32 SPI/I2S Controller -+ -+maintainers: -+ - Olivier Moysan -+ -+description: -+ The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. -+ Only some SPI instances support I2S. -+ -+properties: -+ compatible: -+ enum: -+ - st,stm32h7-i2s -+ -+ "#sound-dai-cells": -+ const: 0 -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ items: -+ - description: clock feeding the peripheral bus interface. -+ - description: clock feeding the internal clock generator. -+ - description: I2S parent clock for sampling rates multiple of 8kHz. -+ - description: I2S parent clock for sampling rates multiple of 11.025kHz. -+ -+ clock-names: -+ items: -+ - const: pclk -+ - const: i2sclk -+ - const: x8k -+ - const: x11k -+ -+ interrupts: -+ maxItems: 1 -+ -+ dmas: -+ items: -+ - description: audio capture DMA. -+ - description: audio playback DMA. -+ -+ dma-names: -+ items: -+ - const: rx -+ - const: tx -+ -+ resets: -+ maxItems: 1 -+ -+ "#clock-cells": -+ description: Configure the I2S device as MCLK clock provider. -+ const: 0 -+ -+required: -+ - compatible -+ - "#sound-dai-cells" -+ - reg -+ - clocks -+ - clock-names -+ - interrupts -+ - dmas -+ - dma-names -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ i2s2: audio-controller@4000b000 { -+ compatible = "st,stm32h7-i2s"; -+ #sound-dai-cells = <0>; -+ reg = <0x4000b000 0x400>; -+ clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>; -+ clock-names = "pclk", "i2sclk", "x8k", "x11k"; -+ interrupts = ; -+ dmas = <&dmamux1 39 0x400 0x01>, -+ <&dmamux1 40 0x400 0x01>; -+ dma-names = "rx", "tx"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s2_pins_a>; -+ }; -+ -+... -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 229cc89f8c5a5..e5d231a6331b4 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -1395,7 +1395,7 @@ config SND_SOC_WM8993 - tristate - - config SND_SOC_WM8994 -- tristate -+ tristate "Wolfson Microelectronics WM8994 codec" - - config SND_SOC_WM8995 - tristate -diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c -index 55408c8fcb4e3..01a4d93e11dd8 100644 ---- a/sound/soc/codecs/cs42l51.c -+++ b/sound/soc/codecs/cs42l51.c -@@ -174,6 +174,7 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, - case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, CS42L51_POWER_CTL1, - CS42L51_POWER_CTL1_PDN, 0); -+ msleep(20); - break; - } - -@@ -214,12 +215,10 @@ static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = { - SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture", - CS42L51_POWER_CTL1, 2, 1, - cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), -- SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback", -- CS42L51_POWER_CTL1, 5, 1, -- cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), -- SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback", -- CS42L51_POWER_CTL1, 6, 1, -- cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), -+ SND_SOC_DAPM_DAC_E("Left DAC", NULL, CS42L51_POWER_CTL1, 5, 1, -+ cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), -+ SND_SOC_DAPM_DAC_E("Right DAC", NULL, CS42L51_POWER_CTL1, 6, 1, -+ cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), - - /* analog/mic */ - SND_SOC_DAPM_INPUT("AIN1L"), -@@ -255,6 +254,12 @@ static const struct snd_soc_dapm_route cs42l51_routes[] = { - {"HPL", NULL, "Left DAC"}, - {"HPR", NULL, "Right DAC"}, - -+ {"Right DAC", NULL, "DAC Mux"}, -+ {"Left DAC", NULL, "DAC Mux"}, -+ -+ {"DAC Mux", "Direct PCM", "Playback"}, -+ {"DAC Mux", "DSP PCM", "Playback"}, -+ - {"Left ADC", NULL, "Left PGA"}, - {"Right ADC", NULL, "Right PGA"}, - -diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c -index d5fb7f5dd551c..a166ab1f34e1e 100644 ---- a/sound/soc/codecs/wm8994.c -+++ b/sound/soc/codecs/wm8994.c -@@ -7,6 +7,7 @@ - * Author: Mark Brown - */ - -+#include - #include - #include - #include -@@ -840,6 +841,42 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, - return 0; - } - -+static int mclk_event(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) -+{ -+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); -+ struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(comp); -+ struct wm8994 *control = wm8994->wm8994; -+ struct wm8994_pdata *pdata = &control->pdata; -+ struct clk *mclk = pdata->mclk1; -+ int ret, mclk_id = 0; -+ -+ if (!strncmp(w->name, "MCLK2", 5)) { -+ mclk_id = 1; -+ mclk = pdata->mclk2; -+ } -+ -+ switch (event) { -+ case SND_SOC_DAPM_PRE_PMU: -+ dev_dbg(comp->dev, "Enable master clock %s\n", -+ mclk_id ? "MCLK2" : "MCLK1"); -+ -+ ret = clk_prepare_enable(mclk); -+ if (ret < 0) { -+ dev_err(comp->dev, "Failed to enable clock: %d\n", ret); -+ return ret; -+ } -+ break; -+ case SND_SOC_DAPM_POST_PMD: -+ dev_dbg(comp->dev, "Disable master clock %s\n", -+ mclk_id ? "MCLK2" : "MCLK1"); -+ clk_disable_unprepare(mclk); -+ break; -+ } -+ -+ return 0; -+} -+ - static void vmid_reference(struct snd_soc_component *component) - { - struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); -@@ -1157,7 +1194,6 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, - else - adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; - -- - val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_2); - if ((val & WM8994_AIF2DACL_SRC) && - (val & WM8994_AIF2DACR_SRC)) -@@ -1776,6 +1812,16 @@ static const struct snd_soc_dapm_widget wm8994_specific_dapm_widgets[] = { - SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &wm8994_aif3adc_mux), - }; - -+static const struct snd_soc_dapm_widget wm8994_mclk1_dapm_widgets[] = { -+SND_SOC_DAPM_SUPPLY("MCLK1", SND_SOC_NOPM, 0, 0, mclk_event, -+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -+}; -+ -+static const struct snd_soc_dapm_widget wm8994_mclk2_dapm_widgets[] = { -+SND_SOC_DAPM_SUPPLY("MCLK2", SND_SOC_NOPM, 0, 0, mclk_event, -+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -+}; -+ - static const struct snd_soc_dapm_widget wm8958_dapm_widgets[] = { - SND_SOC_DAPM_SUPPLY("AIF3", WM8994_POWER_MANAGEMENT_6, 5, 1, NULL, 0), - SND_SOC_DAPM_MUX("Mono PCM Out Mux", SND_SOC_NOPM, 0, 0, &mono_pcm_out_mux), -@@ -2000,10 +2046,10 @@ static const struct snd_soc_dapm_route wm8994_lateclk_intercon[] = { - }; - - static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { -- { "AIF1DACDAT", NULL, "AIF2DACDAT" }, -- { "AIF2DACDAT", NULL, "AIF1DACDAT" }, -- { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, -- { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, -+// { "AIF1DACDAT", NULL, "AIF2DACDAT" }, -+// { "AIF2DACDAT", NULL, "AIF1DACDAT" }, -+// { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, -+// { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, - { "MICBIAS1", NULL, "CLK_SYS" }, - { "MICBIAS1", NULL, "MICBIAS Supply" }, - { "MICBIAS2", NULL, "CLK_SYS" }, -@@ -2377,11 +2423,26 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, - { - struct snd_soc_component *component = dai->component; - struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); -+ struct wm8994 *control = wm8994->wm8994; -+ struct wm8994_pdata *pdata = &control->pdata; - int i; - -+ /* -+ * Simple card provides unconditionnaly clock_id = 0. -+ * Workaround to select master clock for aif1/2 -+ */ - switch (dai->id) { - case 1: -+ if (pdata->mclk1) -+ clk_id = WM8994_SYSCLK_MCLK1; -+ else if (pdata->mclk2) -+ clk_id = WM8994_SYSCLK_MCLK2; -+ break; - case 2: -+ if (pdata->mclk2) -+ clk_id = WM8994_SYSCLK_MCLK2; -+ else if (pdata->mclk1) -+ clk_id = WM8994_SYSCLK_MCLK1; - break; - - default: -@@ -3991,6 +4052,7 @@ static int wm8994_component_probe(struct snd_soc_component *component) - { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - struct wm8994 *control = dev_get_drvdata(component->dev->parent); -+ struct wm8994_pdata *pdata = &control->pdata; - struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); - unsigned int reg; - int ret, i; -@@ -4274,6 +4336,14 @@ static int wm8994_component_probe(struct snd_soc_component *component) - ARRAY_SIZE(wm8994_snd_controls)); - snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, - ARRAY_SIZE(wm8994_specific_dapm_widgets)); -+ if (pdata->mclk1) -+ snd_soc_dapm_new_controls(dapm, wm8994_mclk1_dapm_widgets, -+ ARRAY_SIZE(wm8994_mclk1_dapm_widgets)); -+ -+ if (pdata->mclk2) -+ snd_soc_dapm_new_controls(dapm, wm8994_mclk2_dapm_widgets, -+ ARRAY_SIZE(wm8994_mclk2_dapm_widgets)); -+ - if (control->revision < 4) { - snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, - ARRAY_SIZE(wm8994_lateclk_revd_widgets)); -diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c -index 3e7226a53e53a..7d1672cf78cc5 100644 ---- a/sound/soc/stm/stm32_i2s.c -+++ b/sound/soc/stm/stm32_i2s.c -@@ -8,6 +8,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -196,6 +197,9 @@ enum i2s_datlen { - #define STM32_I2S_IS_MASTER(x) ((x)->ms_flg == I2S_MS_MASTER) - #define STM32_I2S_IS_SLAVE(x) ((x)->ms_flg == I2S_MS_SLAVE) - -+#define STM32_I2S_NAME_LEN 32 -+#define STM32_I2S_RATE_11K 11025 -+ - /** - * struct stm32_i2s_data - private data of I2S - * @regmap_conf: I2S register map configuration pointer -@@ -206,6 +210,7 @@ enum i2s_datlen { - * @dma_data_rx: dma configuration data for tx channel - * @substream: PCM substream data pointer - * @i2sclk: kernel clock feeding the I2S clock generator -+ * @i2smclk: master clock from I2S mclk provider - * @pclk: peripheral clock driving bus interface - * @x8kclk: I2S parent clock for sampling frequencies multiple of 8kHz - * @x11kclk: I2S parent clock for sampling frequencies multiple of 11kHz -@@ -215,6 +220,9 @@ enum i2s_datlen { - * @irq_lock: prevent race condition with IRQ - * @mclk_rate: master clock frequency (Hz) - * @fmt: DAI protocol -+ * @divider: prescaler division ratio -+ * @div: prescaler div field -+ * @odd: prescaler odd field - * @refcount: keep count of opened streams on I2S - * @ms_flg: master mode flag. - */ -@@ -227,6 +235,7 @@ struct stm32_i2s_data { - struct snd_dmaengine_dai_dma_data dma_data_rx; - struct snd_pcm_substream *substream; - struct clk *i2sclk; -+ struct clk *i2smclk; - struct clk *pclk; - struct clk *x8kclk; - struct clk *x11kclk; -@@ -236,10 +245,210 @@ struct stm32_i2s_data { - spinlock_t irq_lock; /* used to prevent race condition with IRQ */ - unsigned int mclk_rate; - unsigned int fmt; -+ unsigned int divider; -+ unsigned int div; -+ bool odd; - int refcount; - int ms_flg; - }; - -+struct stm32_i2smclk_data { -+ struct clk_hw hw; -+ unsigned long freq; -+ struct stm32_i2s_data *i2s_data; -+}; -+ -+#define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw) -+ -+static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s, -+ unsigned long input_rate, -+ unsigned long output_rate) -+{ -+ unsigned int ratio, div, divider = 1; -+ bool odd; -+ -+ ratio = DIV_ROUND_CLOSEST(input_rate, output_rate); -+ -+ /* Check the parity of the divider */ -+ odd = ratio & 0x1; -+ -+ /* Compute the div prescaler */ -+ div = ratio >> 1; -+ -+ /* If div is 0 actual divider is 1 */ -+ if (div) { -+ divider = ((2 * div) + odd); -+ dev_dbg(&i2s->pdev->dev, "Divider: 2*%d(div)+%d(odd) = %d\n", -+ div, odd, divider); -+ } -+ -+ /* Division by three is not allowed by I2S prescaler */ -+ if ((div == 1 && odd) || div > I2S_CGFR_I2SDIV_MAX) { -+ dev_err(&i2s->pdev->dev, "Wrong divider setting\n"); -+ return -EINVAL; -+ } -+ -+ if (input_rate % divider) -+ dev_dbg(&i2s->pdev->dev, -+ "Rate not accurate. requested (%ld), actual (%ld)\n", -+ output_rate, input_rate / divider); -+ -+ i2s->div = div; -+ i2s->odd = odd; -+ i2s->divider = divider; -+ -+ return 0; -+} -+ -+static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s) -+{ -+ u32 cgfr, cgfr_mask; -+ -+ cgfr = I2S_CGFR_I2SDIV_SET(i2s->div) | (i2s->odd << I2S_CGFR_ODD_SHIFT); -+ cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD; -+ -+ return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, -+ cgfr_mask, cgfr); -+} -+ -+static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, -+ unsigned int rate) -+{ -+ struct platform_device *pdev = i2s->pdev; -+ struct clk *parent_clk; -+ int ret; -+ -+ if (!(rate % STM32_I2S_RATE_11K)) -+ parent_clk = i2s->x11kclk; -+ else -+ parent_clk = i2s->x8kclk; -+ -+ ret = clk_set_parent(i2s->i2sclk, parent_clk); -+ if (ret) -+ dev_err(&pdev->dev, -+ "Error %d setting i2sclk parent clock\n", ret); -+ -+ return ret; -+} -+ -+static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *prate) -+{ -+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); -+ struct stm32_i2s_data *i2s = mclk->i2s_data; -+ int ret; -+ -+ ret = stm32_i2s_calc_clk_div(i2s, *prate, rate); -+ if (ret) -+ return ret; -+ -+ mclk->freq = *prate / i2s->divider; -+ -+ return mclk->freq; -+} -+ -+static unsigned long stm32_i2smclk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); -+ -+ return mclk->freq; -+} -+ -+static int stm32_i2smclk_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); -+ struct stm32_i2s_data *i2s = mclk->i2s_data; -+ int ret; -+ -+ ret = stm32_i2s_calc_clk_div(i2s, parent_rate, rate); -+ if (ret) -+ return ret; -+ -+ ret = stm32_i2s_set_clk_div(i2s); -+ if (ret) -+ return ret; -+ -+ mclk->freq = rate; -+ -+ return 0; -+} -+ -+static int stm32_i2smclk_enable(struct clk_hw *hw) -+{ -+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); -+ struct stm32_i2s_data *i2s = mclk->i2s_data; -+ -+ dev_dbg(&i2s->pdev->dev, "Enable master clock\n"); -+ -+ return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, -+ I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); -+} -+ -+static void stm32_i2smclk_disable(struct clk_hw *hw) -+{ -+ struct stm32_i2smclk_data *mclk = to_mclk_data(hw); -+ struct stm32_i2s_data *i2s = mclk->i2s_data; -+ -+ dev_dbg(&i2s->pdev->dev, "Disable master clock\n"); -+ -+ regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0); -+} -+ -+static const struct clk_ops mclk_ops = { -+ .enable = stm32_i2smclk_enable, -+ .disable = stm32_i2smclk_disable, -+ .recalc_rate = stm32_i2smclk_recalc_rate, -+ .round_rate = stm32_i2smclk_round_rate, -+ .set_rate = stm32_i2smclk_set_rate, -+}; -+ -+static int stm32_i2s_add_mclk_provider(struct stm32_i2s_data *i2s) -+{ -+ struct clk_hw *hw; -+ struct stm32_i2smclk_data *mclk; -+ struct device *dev = &i2s->pdev->dev; -+ const char *pname = __clk_get_name(i2s->i2sclk); -+ char *mclk_name, *p, *s = (char *)pname; -+ int ret, i = 0; -+ -+ mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL); -+ if (!mclk) -+ return -ENOMEM; -+ -+ mclk_name = devm_kcalloc(dev, sizeof(char), -+ STM32_I2S_NAME_LEN, GFP_KERNEL); -+ if (!mclk_name) -+ return -ENOMEM; -+ -+ /* -+ * Forge mclk clock name from parent clock name and suffix. -+ * String after "_" char is stripped in parent name. -+ */ -+ p = mclk_name; -+ while (*s && *s != '_' && (i < (STM32_I2S_NAME_LEN - 7))) { -+ *p++ = *s++; -+ i++; -+ } -+ strcat(p, "_mclk"); -+ -+ mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0); -+ mclk->i2s_data = i2s; -+ hw = &mclk->hw; -+ -+ dev_dbg(dev, "Register master clock %s\n", mclk_name); -+ ret = devm_clk_hw_register(&i2s->pdev->dev, hw); -+ if (ret) { -+ dev_err(dev, "mclk register fails with error %d\n", ret); -+ return ret; -+ } -+ i2s->i2smclk = hw->clk; -+ -+ /* register mclk provider */ -+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); -+} -+ - static irqreturn_t stm32_i2s_isr(int irq, void *devid) - { - struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid; -@@ -405,18 +614,46 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) - { - struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); -+ int ret = 0; - -- dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz\n", freq); -+ dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz. mode: %s, dir: %s\n", -+ freq, STM32_I2S_IS_MASTER(i2s) ? "master" : "slave", -+ dir ? "output" : "input"); - -- if ((dir == SND_SOC_CLOCK_OUT) && STM32_I2S_IS_MASTER(i2s)) { -- i2s->mclk_rate = freq; -+ /* MCLK generation is available only in master mode */ -+ if (dir == SND_SOC_CLOCK_OUT && STM32_I2S_IS_MASTER(i2s)) { -+ if (!i2s->i2smclk) { -+ dev_dbg(cpu_dai->dev, "No MCLK registered\n"); -+ return 0; -+ } - -- /* Enable master clock if master mode and mclk-fs are set */ -- return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, -- I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); -+ /* Assume shutdown if requested frequency is 0Hz */ -+ if (!freq) { -+ /* Release mclk rate only if rate was actually set */ -+ if (i2s->mclk_rate) { -+ clk_rate_exclusive_put(i2s->i2smclk); -+ i2s->mclk_rate = 0; -+ } -+ return regmap_update_bits(i2s->regmap, -+ STM32_I2S_CGFR_REG, -+ I2S_CGFR_MCKOE, 0); -+ } -+ /* If master clock is used, set parent clock now */ -+ ret = stm32_i2s_set_parent_clock(i2s, freq); -+ if (ret) -+ return ret; -+ ret = clk_set_rate_exclusive(i2s->i2smclk, freq); -+ if (ret) { -+ dev_err(cpu_dai->dev, "Could not set mclk rate\n"); -+ return ret; -+ } -+ ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, -+ I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); -+ if (!ret) -+ i2s->mclk_rate = freq; - } - -- return 0; -+ return ret; - } - - static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, -@@ -424,11 +661,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, - { - struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long i2s_clock_rate; -- unsigned int tmp, div, real_div, nb_bits, frame_len; -+ unsigned int nb_bits, frame_len; - unsigned int rate = params_rate(params); -+ u32 cgfr; - int ret; -- u32 cgfr, cgfr_mask; -- bool odd; - - if (!(rate % 11025)) - clk_set_parent(i2s->i2sclk, i2s->x11kclk); -@@ -449,7 +685,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, - * dsp mode : div = i2s_clk / (nb_bits x ws) - */ - if (i2s->mclk_rate) { -- tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, i2s->mclk_rate); -+ ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, -+ i2s->mclk_rate); -+ if (ret) -+ return ret; - } else { - frame_len = 32; - if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == -@@ -462,34 +701,13 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, - return ret; - - nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1); -- tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, (nb_bits * rate)); -- } -- -- /* Check the parity of the divider */ -- odd = tmp & 0x1; -- -- /* Compute the div prescaler */ -- div = tmp >> 1; -- -- cgfr = I2S_CGFR_I2SDIV_SET(div) | (odd << I2S_CGFR_ODD_SHIFT); -- cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD; -- -- real_div = ((2 * div) + odd); -- dev_dbg(cpu_dai->dev, "I2S clk: %ld, SCLK: %d\n", -- i2s_clock_rate, rate); -- dev_dbg(cpu_dai->dev, "Divider: 2*%d(div)+%d(odd) = %d\n", -- div, odd, real_div); -- -- if (((div == 1) && odd) || (div > I2S_CGFR_I2SDIV_MAX)) { -- dev_err(cpu_dai->dev, "Wrong divider setting\n"); -- return -EINVAL; -+ ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, -+ (nb_bits * rate)); -+ if (ret) -+ return ret; - } - -- if (!div && !odd) -- dev_warn(cpu_dai->dev, "real divider forced to 1\n"); -- -- ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, -- cgfr_mask, cgfr); -+ ret = stm32_i2s_set_clk_div(i2s); - if (ret < 0) - return ret; - -@@ -694,9 +912,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, - struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; - -- regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, -- I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE); -- - clk_disable_unprepare(i2s->i2sclk); - - spin_lock_irqsave(&i2s->irq_lock, flags); -@@ -831,28 +1046,43 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, - /* Get clocks */ - i2s->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(i2s->pclk)) { -- dev_err(&pdev->dev, "Could not get pclk\n"); -+ if (PTR_ERR(i2s->pclk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Could not get pclk: %ld\n", -+ PTR_ERR(i2s->pclk)); - return PTR_ERR(i2s->pclk); - } - - i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk"); - if (IS_ERR(i2s->i2sclk)) { -- dev_err(&pdev->dev, "Could not get i2sclk\n"); -+ if (PTR_ERR(i2s->i2sclk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Could not get i2sclk: %ld\n", -+ PTR_ERR(i2s->i2sclk)); - return PTR_ERR(i2s->i2sclk); - } - - i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k"); - if (IS_ERR(i2s->x8kclk)) { -- dev_err(&pdev->dev, "missing x8k parent clock\n"); -+ if (PTR_ERR(i2s->x8kclk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Could not get x8k parent clock: %ld\n", -+ PTR_ERR(i2s->x8kclk)); - return PTR_ERR(i2s->x8kclk); - } - - i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k"); - if (IS_ERR(i2s->x11kclk)) { -- dev_err(&pdev->dev, "missing x11k parent clock\n"); -+ if (PTR_ERR(i2s->x11kclk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Could not get x11k parent clock: %ld\n", -+ PTR_ERR(i2s->x11kclk)); - return PTR_ERR(i2s->x11kclk); - } - -+ /* Register mclk provider if requested */ -+ if (of_find_property(np, "#clock-cells", NULL)) { -+ ret = stm32_i2s_add_mclk_provider(i2s); -+ if (ret < 0) -+ return ret; -+ } -+ - /* Get irqs */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) -@@ -866,12 +1096,24 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, - } - - /* Reset */ -- rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -- if (!IS_ERR(rst)) { -- reset_control_assert(rst); -- udelay(2); -- reset_control_deassert(rst); -+ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); -+ if (IS_ERR(rst)) { -+ if (PTR_ERR(rst) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Reset controller error %ld\n", -+ PTR_ERR(rst)); -+ return PTR_ERR(rst); - } -+ reset_control_assert(rst); -+ udelay(2); -+ reset_control_deassert(rst); -+ -+ return 0; -+} -+ -+static int stm32_i2s_remove(struct platform_device *pdev) -+{ -+ snd_dmaengine_pcm_unregister(&pdev->dev); -+ snd_soc_unregister_component(&pdev->dev); - - return 0; - } -@@ -886,16 +1128,16 @@ static int stm32_i2s_probe(struct platform_device *pdev) - if (!i2s) - return -ENOMEM; - -- ret = stm32_i2s_parse_dt(pdev, i2s); -- if (ret) -- return ret; -- - i2s->pdev = pdev; - i2s->ms_flg = I2S_MS_NOT_SET; - spin_lock_init(&i2s->lock_fd); - spin_lock_init(&i2s->irq_lock); - platform_set_drvdata(pdev, i2s); - -+ ret = stm32_i2s_parse_dt(pdev, i2s); -+ if (ret) -+ return ret; -+ - ret = stm32_i2s_dais_init(pdev, i2s); - if (ret) - return ret; -@@ -903,48 +1145,62 @@ static int stm32_i2s_probe(struct platform_device *pdev) - i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk", - i2s->base, i2s->regmap_conf); - if (IS_ERR(i2s->regmap)) { -- dev_err(&pdev->dev, "regmap init failed\n"); -+ if (PTR_ERR(i2s->regmap) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Regmap init error %ld\n", -+ PTR_ERR(i2s->regmap)); - return PTR_ERR(i2s->regmap); - } - -- ret = devm_snd_soc_register_component(&pdev->dev, &stm32_i2s_component, -- i2s->dai_drv, 1); -- if (ret) -+ ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0); -+ if (ret) { -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); - return ret; -+ } - -- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, -- &stm32_i2s_pcm_config, 0); -- if (ret) -+ ret = snd_soc_register_component(&pdev->dev, &stm32_i2s_component, -+ i2s->dai_drv, 1); -+ if (ret) { -+ snd_dmaengine_pcm_unregister(&pdev->dev); - return ret; -+ } - - /* Set SPI/I2S in i2s mode */ - ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, - I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD); - if (ret) -- return ret; -+ goto error; - - ret = regmap_read(i2s->regmap, STM32_I2S_IPIDR_REG, &val); - if (ret) -- return ret; -+ goto error; - - if (val == I2S_IPIDR_NUMBER) { - ret = regmap_read(i2s->regmap, STM32_I2S_HWCFGR_REG, &val); - if (ret) -- return ret; -+ goto error; - - if (!FIELD_GET(I2S_HWCFGR_I2S_SUPPORT_MASK, val)) { - dev_err(&pdev->dev, - "Device does not support i2s mode\n"); -- return -EPERM; -+ ret = -EPERM; -+ goto error; - } - - ret = regmap_read(i2s->regmap, STM32_I2S_VERR_REG, &val); -+ if (ret) -+ goto error; - - dev_dbg(&pdev->dev, "I2S version: %lu.%lu registered\n", - FIELD_GET(I2S_VERR_MAJ_MASK, val), - FIELD_GET(I2S_VERR_MIN_MASK, val)); - } - -+ return ret; -+ -+error: -+ stm32_i2s_remove(pdev); -+ - return ret; - } - -@@ -981,6 +1237,7 @@ static struct platform_driver stm32_i2s_driver = { - .pm = &stm32_i2s_pm_ops, - }, - .probe = stm32_i2s_probe, -+ .remove = stm32_i2s_remove, - }; - - module_platform_driver(stm32_i2s_driver); -diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c -index ef4273361d0d8..820ae27e7e2e9 100644 ---- a/sound/soc/stm/stm32_sai.c -+++ b/sound/soc/stm/stm32_sai.c -@@ -174,20 +174,26 @@ static int stm32_sai_probe(struct platform_device *pdev) - if (!STM_SAI_IS_F4(sai)) { - sai->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(sai->pclk)) { -- dev_err(&pdev->dev, "missing bus clock pclk\n"); -+ if (PTR_ERR(sai->pclk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "missing bus clock pclk: %ld\n", -+ PTR_ERR(sai->pclk)); - return PTR_ERR(sai->pclk); - } - } - - sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k"); - if (IS_ERR(sai->clk_x8k)) { -- dev_err(&pdev->dev, "missing x8k parent clock\n"); -+ if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "missing x8k parent clock: %ld\n", -+ PTR_ERR(sai->clk_x8k)); - return PTR_ERR(sai->clk_x8k); - } - - sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k"); - if (IS_ERR(sai->clk_x11k)) { -- dev_err(&pdev->dev, "missing x11k parent clock\n"); -+ if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "missing x11k parent clock: %ld\n", -+ PTR_ERR(sai->clk_x11k)); - return PTR_ERR(sai->clk_x11k); - } - -@@ -197,12 +203,16 @@ static int stm32_sai_probe(struct platform_device *pdev) - return sai->irq; - - /* reset */ -- rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -- if (!IS_ERR(rst)) { -- reset_control_assert(rst); -- udelay(2); -- reset_control_deassert(rst); -+ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); -+ if (IS_ERR(rst)) { -+ if (PTR_ERR(rst) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Reset controller error %ld\n", -+ PTR_ERR(rst)); -+ return PTR_ERR(rst); - } -+ reset_control_assert(rst); -+ udelay(2); -+ reset_control_deassert(rst); - - /* Enable peripheral clock to allow register access */ - ret = clk_prepare_enable(sai->pclk); -diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c -index 7e965848796c3..a7c39d1794a7b 100644 ---- a/sound/soc/stm/stm32_sai_sub.c -+++ b/sound/soc/stm/stm32_sai_sub.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -1380,7 +1381,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, - sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, - sai->regmap_config); - if (IS_ERR(sai->regmap)) { -- dev_err(&pdev->dev, "Failed to initialize MMIO\n"); -+ if (PTR_ERR(sai->regmap) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Regmap init error %ld\n", -+ PTR_ERR(sai->regmap)); - return PTR_ERR(sai->regmap); - } - -@@ -1471,7 +1474,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, - of_node_put(args.np); - sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); - if (IS_ERR(sai->sai_ck)) { -- dev_err(&pdev->dev, "Missing kernel clock sai_ck\n"); -+ if (PTR_ERR(sai->sai_ck) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Missing kernel clock sai_ck: %ld\n", -+ PTR_ERR(sai->sai_ck)); - return PTR_ERR(sai->sai_ck); - } - -@@ -1548,16 +1553,21 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) - - ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0); - if (ret) { -- dev_err(&pdev->dev, "Could not register pcm dma\n"); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); - return ret; - } - - ret = snd_soc_register_component(&pdev->dev, &stm32_component, - &sai->cpu_dai_drv, 1); -- if (ret) -+ if (ret) { - snd_dmaengine_pcm_unregister(&pdev->dev); -+ return ret; -+ } - -- return ret; -+ pm_runtime_enable(&pdev->dev); -+ -+ return 0; - } - - static int stm32_sai_sub_remove(struct platform_device *pdev) -@@ -1567,6 +1577,7 @@ static int stm32_sai_sub_remove(struct platform_device *pdev) - clk_unprepare(sai->pdata->pclk); - snd_dmaengine_pcm_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); - - return 0; - } -diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c -index 9fc2a1767eb1d..1bfa3b2ba9744 100644 ---- a/sound/soc/stm/stm32_spdifrx.c -+++ b/sound/soc/stm/stm32_spdifrx.c -@@ -353,6 +353,8 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) - SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK | SPDIFRX_CR_RXSTEO; - cr_mask = cr; - -+ cr |= SPDIFRX_CR_NBTRSET(SPDIFRX_NBTR_63); -+ cr_mask |= SPDIFRX_CR_NBTR_MASK; - cr |= SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC); - cr_mask |= SPDIFRX_CR_SPDIFEN_MASK; - ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, -@@ -404,7 +406,9 @@ static int stm32_spdifrx_dma_ctrl_register(struct device *dev, - - spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); - if (IS_ERR(spdifrx->ctrl_chan)) { -- dev_err(dev, "dma_request_slave_channel failed\n"); -+ if (PTR_ERR(spdifrx->ctrl_chan) != -EPROBE_DEFER) -+ dev_err(dev, "dma_request_slave_channel error %ld\n", -+ PTR_ERR(spdifrx->ctrl_chan)); - return PTR_ERR(spdifrx->ctrl_chan); - } - -@@ -665,7 +669,7 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) - struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; - struct platform_device *pdev = spdifrx->pdev; - unsigned int cr, mask, sr, imr; -- unsigned int flags; -+ unsigned int flags, sync_state; - int err = 0, err_xrun = 0; - - regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr); -@@ -725,11 +729,23 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) - } - - if (err) { -- /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */ -+ regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr); -+ sync_state = FIELD_GET(SPDIFRX_CR_SPDIFEN_MASK, cr) && -+ SPDIFRX_SPDIFEN_SYNC; -+ -+ /* SPDIFRX is in STATE_STOP. Disable SPDIFRX to clear errors */ - cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); - regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, - SPDIFRX_CR_SPDIFEN_MASK, cr); - -+ /* If SPDIFRX was in STATE_SYNC, retry synchro */ -+ if (sync_state) { -+ cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC); -+ regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, -+ SPDIFRX_CR_SPDIFEN_MASK, cr); -+ return IRQ_HANDLED; -+ } -+ - spin_lock(&spdifrx->irq_lock); - if (spdifrx->substream) - snd_pcm_stop(spdifrx->substream, -@@ -915,7 +931,9 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, - - spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); - if (IS_ERR(spdifrx->kclk)) { -- dev_err(&pdev->dev, "Could not get kclk\n"); -+ if (PTR_ERR(spdifrx->kclk) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Could not get kclk: %ld\n", -+ PTR_ERR(spdifrx->kclk)); - return PTR_ERR(spdifrx->kclk); - } - -@@ -926,6 +944,22 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, - return 0; - } - -+static int stm32_spdifrx_remove(struct platform_device *pdev) -+{ -+ struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); -+ -+ if (spdifrx->ctrl_chan) -+ dma_release_channel(spdifrx->ctrl_chan); -+ -+ if (spdifrx->dmab) -+ snd_dma_free_pages(spdifrx->dmab); -+ -+ snd_dmaengine_pcm_unregister(&pdev->dev); -+ snd_soc_unregister_component(&pdev->dev); -+ -+ return 0; -+} -+ - static int stm32_spdifrx_probe(struct platform_device *pdev) - { - struct stm32_spdifrx_data *spdifrx; -@@ -953,7 +987,9 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) - spdifrx->base, - spdifrx->regmap_conf); - if (IS_ERR(spdifrx->regmap)) { -- dev_err(&pdev->dev, "Regmap init failed\n"); -+ if (PTR_ERR(spdifrx->regmap) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Regmap init error %ld\n", -+ PTR_ERR(spdifrx->regmap)); - return PTR_ERR(spdifrx->regmap); - } - -@@ -964,31 +1000,38 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) - return ret; - } - -- rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -- if (!IS_ERR(rst)) { -- reset_control_assert(rst); -- udelay(2); -- reset_control_deassert(rst); -+ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); -+ if (IS_ERR(rst)) { -+ if (PTR_ERR(rst) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Reset controller error %ld\n", -+ PTR_ERR(rst)); -+ return PTR_ERR(rst); - } -+ reset_control_assert(rst); -+ udelay(2); -+ reset_control_deassert(rst); - -- ret = devm_snd_soc_register_component(&pdev->dev, -- &stm32_spdifrx_component, -- stm32_spdifrx_dai, -- ARRAY_SIZE(stm32_spdifrx_dai)); -- if (ret) -+ pcm_config = &stm32_spdifrx_pcm_config; -+ ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); -+ if (ret) { -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); -+ return ret; -+ } -+ -+ ret = snd_soc_register_component(&pdev->dev, -+ &stm32_spdifrx_component, -+ stm32_spdifrx_dai, -+ ARRAY_SIZE(stm32_spdifrx_dai)); -+ if (ret) { -+ snd_dmaengine_pcm_unregister(&pdev->dev); - return ret; -+ } - - ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx); - if (ret) - goto error; - -- pcm_config = &stm32_spdifrx_pcm_config; -- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); -- if (ret) { -- dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret); -- goto error; -- } -- - ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_IDR, &idr); - if (ret) - goto error; -@@ -1006,27 +1049,11 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) - return ret; - - error: -- if (!IS_ERR(spdifrx->ctrl_chan)) -- dma_release_channel(spdifrx->ctrl_chan); -- if (spdifrx->dmab) -- snd_dma_free_pages(spdifrx->dmab); -+ stm32_spdifrx_remove(pdev); - - return ret; - } - --static int stm32_spdifrx_remove(struct platform_device *pdev) --{ -- struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); -- -- if (spdifrx->ctrl_chan) -- dma_release_channel(spdifrx->ctrl_chan); -- -- if (spdifrx->dmab) -- snd_dma_free_pages(spdifrx->dmab); -- -- return 0; --} -- - MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); - - #ifdef CONFIG_PM_SLEEP --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0019-ARM-stm32mp1-r2-MISC-CPUIDLE-MM.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0019-ARM-stm32mp1-r2-MISC-CPUIDLE-MM.patch deleted file mode 100644 index 79ae87a..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0019-ARM-stm32mp1-r2-MISC-CPUIDLE-MM.patch +++ /dev/null @@ -1,1943 +0,0 @@ -From d2f5d4b3ec672e5ded9270780386098a0d34ce89 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:52 +0200 -Subject: [PATCH 19/22] ARM-stm32mp1-r2-rc8-MISC-CPUIDLE-MM - ---- - CONTRIBUTING.md | 30 + - .../memory-controllers/st,stm32-fmc2-ebi.yaml | 252 ++++ - drivers/block/loop.c | 7 +- - drivers/cpuidle/Kconfig.arm | 8 + - drivers/cpuidle/Makefile | 1 + - drivers/cpuidle/cpuidle-stm32.c | 276 ++++ - drivers/memory/Kconfig | 10 + - drivers/memory/Makefile | 1 + - drivers/memory/stm32-fmc2-ebi.c | 1206 +++++++++++++++++ - include/linux/pm_wakeup.h | 10 + - kernel/power/suspend.c | 1 - - 11 files changed, 1799 insertions(+), 3 deletions(-) - create mode 100644 CONTRIBUTING.md - create mode 100644 Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml - create mode 100644 drivers/cpuidle/cpuidle-stm32.c - create mode 100644 drivers/memory/stm32-fmc2-ebi.c - -diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md -new file mode 100644 -index 0000000000000..3d1bacd78a543 ---- /dev/null -+++ b/CONTRIBUTING.md -@@ -0,0 +1,30 @@ -+# Contributing guide -+ -+This document serves as a checklist before contributing to this repository. It includes links to read up on if topics are unclear to you. -+ -+This guide mainly focuses on the proper use of Git. -+ -+## 1. Issues -+ -+STM32MPU projects do not activate "Github issues" feature for the time being. If you need to report an issue or question about this project deliverables, you can report them using [ ST Support Center ](https://my.st.com/ols#/ols/newrequest) or [ ST Community MPU Forum ](https://community.st.com/s/topic/0TO0X0000003u2AWAQ/stm32-mpus). -+ -+## 2. Pull Requests -+ -+STMicrolectronics is happy to receive contributions from the community, based on an initial Contributor License Agreement (CLA) procedure. -+ -+* If you are an individual writing original source code and you are sure **you own the intellectual property**, then you need to sign an Individual CLA (https://cla.st.com). -+* If you work for a company that wants also to allow you to contribute with your work, your company needs to provide a Corporate CLA (https://cla.st.com) mentioning your GitHub account name. -+* If you are not sure that a CLA (Individual or Corporate) has been signed for your GitHub account you can check here (https://cla.st.com). -+ -+Please note that: -+* The Corporate CLA will always take precedence over the Individual CLA. -+* One CLA submission is sufficient, for any project proposed by STMicroelectronics. -+ -+__How to proceed__ -+ -+* We recommend to fork the project in your GitHub account to further develop your contribution. Please use the latest commit version. -+* Please, submit one Pull Request for one new feature or proposal. This will ease the analysis and final merge if accepted. -+ -+__Note__ -+ -+Merge will not be done directly in GitHub but it will need first to follow internal integration process before public deliver in a standard release. The Pull request will stay open until it is merged and delivered. -diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml -new file mode 100644 -index 0000000000000..70eaf739036bc ---- /dev/null -+++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml -@@ -0,0 +1,252 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/memory-controllers/st,stm32-fmc2-ebi.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: STMicroelectronics Flexible Memory Controller 2 (FMC2) Bindings -+ -+description: | -+ The FMC2 functional block makes the interface with: synchronous and -+ asynchronous static devices (such as PSNOR, PSRAM or other memory-mapped -+ peripherals) and NAND flash memories. -+ Its main purposes are: -+ - to translate AXI transactions into the appropriate external device -+ protocol -+ - to meet the access time requirements of the external devices -+ All external devices share the addresses, data and control signals with the -+ controller. Each external device is accessed by means of a unique Chip -+ Select. The FMC2 performs only one access at a time to an external device. -+ -+maintainers: -+ - Christophe Kerello -+ -+properties: -+ compatible: -+ const: st,stm32mp1-fmc2-ebi -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ maxItems: 1 -+ -+ resets: -+ maxItems: 1 -+ -+ "#address-cells": -+ const: 2 -+ -+ "#size-cells": -+ const: 1 -+ -+ ranges: -+ description: | -+ Reflects the memory layout with four integer values per bank. Format: -+ 0
-+ -+patternProperties: -+ "^.*@[0-4],[a-f0-9]+$": -+ type: object -+ -+ properties: -+ reg: -+ description: Bank number, base address and size of the device. -+ -+ st,fmc2-ebi-cs-transaction-type: -+ description: | -+ Select one of the transactions type supported -+ 0: Asynchronous mode 1 SRAM/FRAM. -+ 1: Asynchronous mode 1 PSRAM. -+ 2: Asynchronous mode A SRAM/FRAM. -+ 3: Asynchronous mode A PSRAM. -+ 4: Asynchronous mode 2 NOR. -+ 5: Asynchronous mode B NOR. -+ 6: Asynchronous mode C NOR. -+ 7: Asynchronous mode D NOR. -+ 8: Synchronous read synchronous write PSRAM. -+ 9: Synchronous read asynchronous write PSRAM. -+ 10: Synchronous read synchronous write NOR. -+ 11: Synchronous read asynchronous write NOR. -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ minimum: 0 -+ maximum: 11 -+ -+ st,fmc2-ebi-cs-cclk-enable: -+ description: Continuous clock enable (first bank must be configured -+ in synchronous mode). The FMC_CLK is generated continuously -+ during asynchronous and synchronous access. By default, the -+ FMC_CLK is only generated during synchronous access. -+ $ref: /schemas/types.yaml#/definitions/flag -+ -+ st,fmc2-ebi-cs-mux-enable: -+ description: Address/Data multiplexed on databus (valid only with -+ NOR and PSRAM transactions type). By default, Address/Data -+ are not multiplexed. -+ $ref: /schemas/types.yaml#/definitions/flag -+ -+ st,fmc2-ebi-cs-buswidth: -+ description: Data bus width -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ enum: [ 8, 16 ] -+ default: 16 -+ -+ st,fmc2-ebi-cs-waitpol-high: -+ description: Wait signal polarity (NWAIT signal active high). -+ By default, NWAIT is active low. -+ $ref: /schemas/types.yaml#/definitions/flag -+ -+ st,fmc2-ebi-cs-waitcfg-enable: -+ description: The NWAIT signal indicates wheither the data from the -+ device are valid or if a wait state must be inserted when accessing -+ the device in synchronous mode. By default, the NWAIT signal is -+ active one data cycle before wait state. -+ $ref: /schemas/types.yaml#/definitions/flag -+ -+ st,fmc2-ebi-cs-wait-enable: -+ description: The NWAIT signal is enabled (its level is taken into -+ account after the programmed latency period to insert wait states -+ if asserted). By default, the NWAIT signal is disabled. -+ $ref: /schemas/types.yaml#/definitions/flag -+ -+ st,fmc2-ebi-cs-asyncwait-enable: -+ description: The NWAIT signal is taken into account during asynchronous -+ transactions. By default, the NWAIT signal is not taken into account -+ during asynchronous transactions. -+ $ref: /schemas/types.yaml#/definitions/flag -+ -+ st,fmc2-ebi-cs-cpsize: -+ description: CRAM page size. The controller splits the burst access -+ when the memory page is reached. By default, no burst split when -+ crossing page boundary. -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ enum: [ 0, 128, 256, 512, 1024 ] -+ default: 0 -+ -+ st,fmc2-ebi-cs-byte-lane-setup-ns: -+ description: This property configures the byte lane setup timing -+ defined in nanoseconds from NBLx low to Chip Select NEx low. -+ -+ st,fmc2-ebi-cs-address-setup-ns: -+ description: This property defines the duration of the address setup -+ phase in nanoseconds used for asynchronous read/write transactions. -+ -+ st,fmc2-ebi-cs-address-hold-ns: -+ description: This property defines the duration of the address hold -+ phase in nanoseconds used for asynchronous multiplexed read/write -+ transactions. -+ -+ st,fmc2-ebi-cs-data-setup-ns: -+ description: This property defines the duration of the data setup phase -+ in nanoseconds used for asynchronous read/write transactions. -+ -+ st,fmc2-ebi-cs-bus-turnaround-ns: -+ description: This property defines the delay in nanoseconds between the -+ end of current read/write transaction and the next transaction. -+ -+ st,fmc2-ebi-cs-data-hold-ns: -+ description: This property defines the duration of the data hold phase -+ in nanoseconds used for asynchronous read/write transactions. -+ -+ st,fmc2-ebi-cs-clk-period-ns: -+ description: This property defines the FMC_CLK output signal period in -+ nanoseconds. -+ -+ st,fmc2-ebi-cs-data-latency-ns: -+ description: This property defines the data latency before reading or -+ writing the first data in nanoseconds. -+ -+ st,fmc2_ebi-cs-write-address-setup-ns: -+ description: This property defines the duration of the address setup -+ phase in nanoseconds used for asynchronous write transactions. -+ -+ st,fmc2-ebi-cs-write-address-hold-ns: -+ description: This property defines the duration of the address hold -+ phase in nanoseconds used for asynchronous multiplexed write -+ transactions. -+ -+ st,fmc2-ebi-cs-write-data-setup-ns: -+ description: This property defines the duration of the data setup -+ phase in nanoseconds used for asynchronous write transactions. -+ -+ st,fmc2-ebi-cs-write-bus-turnaround-ns: -+ description: This property defines the delay between the end of current -+ write transaction and the next transaction in nanoseconds. -+ -+ st,fmc2-ebi-cs-write-data-hold-ns: -+ description: This property defines the duration of the data hold phase -+ in nanoseconds used for asynchronous write transactions. -+ -+ st,fmc2-ebi-cs-max-low-pulse-ns: -+ description: This property defines the maximum chip select low pulse -+ duration in nanoseconds for synchronous transactions. When this timing -+ reaches 0, the controller splits the current access, toggles NE to -+ allow device refresh and restarts a new access. -+ -+ required: -+ - reg -+ -+required: -+ - "#address-cells" -+ - "#size-cells" -+ - compatible -+ - reg -+ - clocks -+ - ranges -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ memory-controller@58002000 { -+ #address-cells = <2>; -+ #size-cells = <1>; -+ compatible = "st,stm32mp1-fmc2-ebi"; -+ reg = <0x58002000 0x1000>; -+ clocks = <&rcc FMC_K>; -+ resets = <&rcc FMC_R>; -+ -+ ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ -+ <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ -+ <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ -+ <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ -+ <4 0 0x80000000 0x10000000>; /* NAND */ -+ -+ psram@0,0 { -+ compatible = "mtd-ram"; -+ reg = <0 0x00000000 0x100000>; -+ bank-width = <2>; -+ -+ st,fmc2-ebi-cs-transaction-type = <1>; -+ st,fmc2-ebi-cs-address-setup-ns = <60>; -+ st,fmc2-ebi-cs-data-setup-ns = <30>; -+ st,fmc2-ebi-cs-bus-turnaround-ns = <5>; -+ }; -+ -+ nand-controller@4,0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32mp1-fmc2-nfc"; -+ reg = <4 0x00000000 0x1000>, -+ <4 0x08010000 0x1000>, -+ <4 0x08020000 0x1000>, -+ <4 0x01000000 0x1000>, -+ <4 0x09010000 0x1000>, -+ <4 0x09020000 0x1000>; -+ interrupts = ; -+ dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>, -+ <&mdma1 20 0x2 0x12000a08 0x0 0x0>, -+ <&mdma1 21 0x2 0x12000a0a 0x0 0x0>; -+ dma-names = "tx", "rx", "ecc"; -+ -+ nand@0 { -+ reg = <0>; -+ nand-on-flash-bbt; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+ }; -+ }; -+ -+... -diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 565e35e69f249..d5c969284e42d 100644 ---- a/drivers/block/loop.c -+++ b/drivers/block/loop.c -@@ -462,7 +462,7 @@ static void lo_complete_rq(struct request *rq) - if (!cmd->use_aio || cmd->ret < 0 || cmd->ret == blk_rq_bytes(rq) || - req_op(rq) != REQ_OP_READ) { - if (cmd->ret < 0) -- ret = BLK_STS_IOERR; -+ ret = errno_to_blk_status(cmd->ret); - goto end_io; - } - -@@ -1970,7 +1970,10 @@ static void loop_handle_cmd(struct loop_cmd *cmd) - failed: - /* complete non-aio request */ - if (!cmd->use_aio || ret) { -- cmd->ret = ret ? -EIO : 0; -+ if (ret == -EOPNOTSUPP) -+ cmd->ret = ret; -+ else -+ cmd->ret = ret ? -EIO : 0; - blk_mq_complete_request(rq); - } - } -diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm -index d8530475493cb..5e5cdbe7ed3cb 100644 ---- a/drivers/cpuidle/Kconfig.arm -+++ b/drivers/cpuidle/Kconfig.arm -@@ -81,6 +81,14 @@ config ARM_EXYNOS_CPUIDLE - help - Select this to enable cpuidle for Exynos processors - -+config ARM_STM32_CPUIDLE -+ bool "Cpu Idle Driver for the STM32 processors" -+ depends on MACH_STM32MP157 -+ select DT_IDLE_STATES -+ select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP -+ help -+ Select this to enable cpuidle for STM32 processors. -+ - config ARM_MVEBU_V7_CPUIDLE - bool "CPU Idle Driver for mvebu v7 family processors" - depends on ARCH_MVEBU && !ARM64 -diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile -index ee70d5cc5b996..0b198896b61a0 100644 ---- a/drivers/cpuidle/Makefile -+++ b/drivers/cpuidle/Makefile -@@ -22,6 +22,7 @@ obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o - obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o - obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o - obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o -+obj-$(CONFIG_ARM_STM32_CPUIDLE) += cpuidle-stm32.o - - ############################################################################### - # MIPS drivers -diff --git a/drivers/cpuidle/cpuidle-stm32.c b/drivers/cpuidle/cpuidle-stm32.c -new file mode 100644 -index 0000000000000..d3413386cc7fe ---- /dev/null -+++ b/drivers/cpuidle/cpuidle-stm32.c -@@ -0,0 +1,276 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) STMicroelectronics 2019 -+// Author: -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "dt_idle_states.h" -+ -+#define SMC_AUTOSTOP() \ -+{ \ -+ struct arm_smccc_res res; \ -+ arm_smccc_smc(0x8200100a, 0, 0, 0, \ -+ 0, 0, 0, 0, &res); \ -+} -+ -+struct stm32_pm_domain { -+ struct device *dev; -+ struct generic_pm_domain genpd; -+ int id; -+}; -+ -+static atomic_t stm_idle_barrier; -+ -+static int stm32_enter_idle(struct cpuidle_device *dev, -+ struct cpuidle_driver *drv, int index) -+{ -+ /* -+ * Call idle CPU PM enter notifier chain so that -+ * VFP and per CPU interrupt context is saved. -+ */ -+ cpu_pm_enter(); -+ -+ /* -+ * be sure that both cpu enter at the same time -+ * normally not needed is the state is declared as coupled -+ */ -+ cpuidle_coupled_parallel_barrier(dev, &stm_idle_barrier); -+ -+ /* Enter broadcast mode for periodic timers */ -+ tick_broadcast_enable(); -+ -+ /* Enter broadcast mode for one-shot timers */ -+ tick_broadcast_enter(); -+ -+ if (dev->cpu == 0) -+ cpu_cluster_pm_enter(); -+ -+ SMC_AUTOSTOP(); -+ -+ if (dev->cpu == 0) -+ cpu_cluster_pm_exit(); -+ -+ tick_broadcast_exit(); -+ -+ cpuidle_coupled_parallel_barrier(dev, &stm_idle_barrier); -+ -+ /* -+ * Call idle CPU PM exit notifier chain to restore -+ * VFP and per CPU IRQ context. -+ */ -+ cpu_pm_exit(); -+ -+ return index; -+} -+ -+static const struct of_device_id stm32_idle_state_match[] __initconst = { -+ { .compatible = "arm,idle-state", -+ .data = stm32_enter_idle }, -+ { }, -+}; -+ -+static struct cpuidle_driver stm32_idle_driver = { -+ .name = "stm32_idle", -+ .states = { -+ ARM_CPUIDLE_WFI_STATE, -+ { -+ .enter = stm32_enter_idle, -+ .exit_latency = 620, -+ .target_residency = 700, -+ .flags = /*CPUIDLE_FLAG_TIMER_STOP | */ -+ CPUIDLE_FLAG_COUPLED, -+ .name = "CStop", -+ .desc = "Clocks off", -+ }, -+ }, -+ .safe_state_index = 0, -+ .state_count = 2, -+}; -+ -+static int stm32_pd_cpuidle_off(struct generic_pm_domain *domain) -+{ -+ struct stm32_pm_domain *priv = container_of(domain, -+ struct stm32_pm_domain, -+ genpd); -+ int cpu; -+ -+ for_each_possible_cpu(cpu) { -+ struct cpuidle_device *cpuidle_dev = per_cpu(cpuidle_devices, -+ cpu); -+ -+ cpuidle_dev->states_usage[1].disable = false; -+ } -+ -+ dev_dbg(priv->dev, "%s OFF\n", domain->name); -+ -+ return 0; -+} -+ -+static int stm32_pd_cpuidle_on(struct generic_pm_domain *domain) -+{ -+ struct stm32_pm_domain *priv = container_of(domain, -+ struct stm32_pm_domain, -+ genpd); -+ int cpu; -+ -+ for_each_possible_cpu(cpu) { -+ struct cpuidle_device *cpuidle_dev = per_cpu(cpuidle_devices, -+ cpu); -+ -+ cpuidle_dev->states_usage[1].disable = true; -+ } -+ -+ dev_dbg(priv->dev, "%s ON\n", domain->name); -+ -+ return 0; -+} -+ -+static void stm32_cpuidle_domain_remove(struct stm32_pm_domain *domain) -+{ -+ int ret; -+ -+ ret = pm_genpd_remove(&domain->genpd); -+ if (ret) -+ dev_err(domain->dev, "failed to remove PM domain %s: %d\n", -+ domain->genpd.name, ret); -+} -+ -+static int stm32_cpuidle_domain_add(struct stm32_pm_domain *domain, -+ struct device *dev, -+ struct device_node *np) -+{ -+ int ret; -+ -+ domain->dev = dev; -+ domain->genpd.name = np->name; -+ domain->genpd.power_off = stm32_pd_cpuidle_off; -+ domain->genpd.power_on = stm32_pd_cpuidle_on; -+ -+ ret = pm_genpd_init(&domain->genpd, NULL, 0); -+ if (ret < 0) { -+ dev_err(domain->dev, "failed to initialise PM domain %s: %d\n", -+ np->name, ret); -+ return ret; -+ } -+ -+ ret = of_genpd_add_provider_simple(np, &domain->genpd); -+ if (ret < 0) { -+ dev_err(domain->dev, "failed to register PM domain %s: %d\n", -+ np->name, ret); -+ stm32_cpuidle_domain_remove(domain); -+ return ret; -+ } -+ -+ dev_info(domain->dev, "domain %s registered\n", np->name); -+ -+ return 0; -+} -+ -+static int stm32_cpuidle_probe(struct platform_device *pdev) -+{ -+ struct cpuidle_driver *drv; -+ struct stm32_pm_domain *domain; -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct of_phandle_args child, parent; -+ struct device_node *np_child; -+ int cpu, ret; -+ -+ drv = devm_kmemdup(dev, &stm32_idle_driver, sizeof(*drv), GFP_KERNEL); -+ if (!drv) -+ return -ENOMEM; -+ -+ /* Start at index 1, index 0 standard WFI */ -+ ret = dt_init_idle_driver(drv, stm32_idle_state_match, 1); -+ if (ret < 0) -+ return ret; -+ -+ /* all the cpus of the system are coupled */ -+ ret = cpuidle_register(drv, cpu_possible_mask); -+ if (ret) -+ return ret; -+ -+ /* Declare cpuidle domain */ -+ domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL); -+ if (!domain) -+ return -ENOMEM; -+ -+ ret = stm32_cpuidle_domain_add(domain, dev, np); -+ if (ret) { -+ devm_kfree(dev, domain); -+ return ret; -+ } -+ -+ /* disable cpu idle */ -+ for_each_possible_cpu(cpu) { -+ struct cpuidle_device *cpuidle_dev = per_cpu(cpuidle_devices, -+ cpu); -+ -+ cpuidle_dev->states_usage[1].disable = true; -+ } -+ -+ /* link main cpuidle domain to consumer domain */ -+ for_each_child_of_node(np, np_child) { -+ if (!of_parse_phandle_with_args(np_child, "power-domains", -+ "#power-domain-cells", -+ 0, &child)) { -+ struct device_node *np_test = child.np; -+ -+ parent.np = np; -+ parent.args_count = 0; -+ -+ ret = of_genpd_add_subdomain(&parent, &child); -+ if (ret < 0) -+ dev_err(dev, "failed to add Sub PM domain %d\n", -+ ret); -+ -+ dev_dbg(dev, "%s, add sub cpuidle of %s, with child %s\n", -+ __func__, np->name, np_test->name); -+ -+ pm_runtime_put(dev); -+ } -+ } -+ -+ dev_info(dev, "cpuidle domain probed\n"); -+ -+ return 0; -+} -+ -+int stm32_cpuidle_remove(struct platform_device *pdev) -+{ -+ cpuidle_unregister(&stm32_idle_driver); -+ return 0; -+} -+ -+static const struct of_device_id stm32_cpuidle_of_match[] = { -+ { -+ .compatible = "stm32,cpuidle", -+ }, -+}; -+ -+static struct platform_driver stm32_cpuidle_driver = { -+ .probe = stm32_cpuidle_probe, -+ .remove = stm32_cpuidle_remove, -+ .driver = { -+ .name = "stm32_cpuidle", -+ .owner = THIS_MODULE, -+ .of_match_table = stm32_cpuidle_of_match, -+ }, -+}; -+ -+module_platform_driver(stm32_cpuidle_driver); -+ -+MODULE_AUTHOR("<>"); -+MODULE_DESCRIPTION("STM32 cpu idle driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig -index 9bddca2923301..c651aaf7d72bc 100644 ---- a/drivers/memory/Kconfig -+++ b/drivers/memory/Kconfig -@@ -163,6 +163,16 @@ config PL353_SMC - This driver is for the ARM PL351/PL353 Static Memory - Controller(SMC) module. - -+config STM32_FMC2_EBI -+ tristate "Support for FMC2 External Bus Interface on STM32MP SoCs" -+ depends on MACH_STM32MP157 || COMPILE_TEST -+ select MFD_SYSCON -+ help -+ Select this option to enable the STM32 FMC2 External Bus Interface -+ controller. This driver configures the transactions with external -+ devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on -+ SOCs containing the FMC2 External Bus Interface. -+ - source "drivers/memory/samsung/Kconfig" - source "drivers/memory/tegra/Kconfig" - -diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile -index 27b493435e61c..c7d36db6a5e9f 100644 ---- a/drivers/memory/Makefile -+++ b/drivers/memory/Makefile -@@ -21,6 +21,7 @@ obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o - obj-$(CONFIG_MTK_SMI) += mtk-smi.o - obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o - obj-$(CONFIG_PL353_SMC) += pl353-smc.o -+obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o - - obj-$(CONFIG_SAMSUNG_MC) += samsung/ - obj-$(CONFIG_TEGRA_MC) += tegra/ -diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c -new file mode 100644 -index 0000000000000..4d5758c419c55 ---- /dev/null -+++ b/drivers/memory/stm32-fmc2-ebi.c -@@ -0,0 +1,1206 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) STMicroelectronics 2020 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* FMC2 Controller Registers */ -+#define FMC2_BCR1 0x0 -+#define FMC2_BTR1 0x4 -+#define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1) -+#define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1) -+#define FMC2_PCSCNTR 0x20 -+#define FMC2_BWTR1 0x104 -+#define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1) -+ -+/* Register: FMC2_BCR1 */ -+#define FMC2_BCR1_CCLKEN BIT(20) -+#define FMC2_BCR1_FMC2EN BIT(31) -+ -+/* Register: FMC2_BCRx */ -+#define FMC2_BCR_MBKEN BIT(0) -+#define FMC2_BCR_MUXEN BIT(1) -+#define FMC2_BCR_MTYP GENMASK(3, 2) -+#define FMC2_BCR_MWID GENMASK(5, 4) -+#define FMC2_BCR_FACCEN BIT(6) -+#define FMC2_BCR_BURSTEN BIT(8) -+#define FMC2_BCR_WAITPOL BIT(9) -+#define FMC2_BCR_WAITCFG BIT(11) -+#define FMC2_BCR_WREN BIT(12) -+#define FMC2_BCR_WAITEN BIT(13) -+#define FMC2_BCR_EXTMOD BIT(14) -+#define FMC2_BCR_ASYNCWAIT BIT(15) -+#define FMC2_BCR_CPSIZE GENMASK(18, 16) -+#define FMC2_BCR_CBURSTRW BIT(19) -+#define FMC2_BCR_NBLSET GENMASK(23, 22) -+ -+/* Register: FMC2_BTRx/FMC2_BWTRx */ -+#define FMC2_BXTR_ADDSET GENMASK(3, 0) -+#define FMC2_BXTR_ADDHLD GENMASK(7, 4) -+#define FMC2_BXTR_DATAST GENMASK(15, 8) -+#define FMC2_BXTR_BUSTURN GENMASK(19, 16) -+#define FMC2_BTR_CLKDIV GENMASK(23, 20) -+#define FMC2_BTR_DATLAT GENMASK(27, 24) -+#define FMC2_BXTR_ACCMOD GENMASK(29, 28) -+#define FMC2_BXTR_DATAHLD GENMASK(31, 30) -+ -+/* Register: FMC2_PCSCNTR */ -+#define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0) -+#define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16) -+ -+#define FMC2_MAX_EBI_CE 4 -+#define FMC2_MAX_BANKS 5 -+ -+#define FMC2_BCR_CPSIZE_0 0x0 -+#define FMC2_BCR_CPSIZE_128 0x1 -+#define FMC2_BCR_CPSIZE_256 0x2 -+#define FMC2_BCR_CPSIZE_512 0x3 -+#define FMC2_BCR_CPSIZE_1024 0x4 -+ -+#define FMC2_BCR_MWID_8 0x0 -+#define FMC2_BCR_MWID_16 0x1 -+ -+#define FMC2_BCR_MTYP_SRAM 0x0 -+#define FMC2_BCR_MTYP_PSRAM 0x1 -+#define FMC2_BCR_MTYP_NOR 0x2 -+ -+#define FMC2_BXTR_EXTMOD_A 0x0 -+#define FMC2_BXTR_EXTMOD_B 0x1 -+#define FMC2_BXTR_EXTMOD_C 0x2 -+#define FMC2_BXTR_EXTMOD_D 0x3 -+ -+#define FMC2_BCR_NBLSET_MAX 0x3 -+#define FMC2_BXTR_ADDSET_MAX 0xf -+#define FMC2_BXTR_ADDHLD_MAX 0xf -+#define FMC2_BXTR_DATAST_MAX 0xff -+#define FMC2_BXTR_BUSTURN_MAX 0xf -+#define FMC2_BXTR_DATAHLD_MAX 0x3 -+#define FMC2_BTR_CLKDIV_MAX 0xf -+#define FMC2_BTR_DATLAT_MAX 0xf -+#define FMC2_PCSCNTR_CSCOUNT_MAX 0xff -+ -+enum stm32_fmc2_ebi_bank { -+ FMC2_EBI1 = 0, -+ FMC2_EBI2, -+ FMC2_EBI3, -+ FMC2_EBI4, -+ FMC2_NAND -+}; -+ -+enum stm32_fmc2_ebi_register_type { -+ FMC2_REG_BCR = 1, -+ FMC2_REG_BTR, -+ FMC2_REG_BWTR, -+ FMC2_REG_PCSCNTR -+}; -+ -+enum stm32_fmc2_ebi_transaction_type { -+ FMC2_ASYNC_MODE_1_SRAM = 0, -+ FMC2_ASYNC_MODE_1_PSRAM, -+ FMC2_ASYNC_MODE_A_SRAM, -+ FMC2_ASYNC_MODE_A_PSRAM, -+ FMC2_ASYNC_MODE_2_NOR, -+ FMC2_ASYNC_MODE_B_NOR, -+ FMC2_ASYNC_MODE_C_NOR, -+ FMC2_ASYNC_MODE_D_NOR, -+ FMC2_SYNC_READ_SYNC_WRITE_PSRAM, -+ FMC2_SYNC_READ_ASYNC_WRITE_PSRAM, -+ FMC2_SYNC_READ_SYNC_WRITE_NOR, -+ FMC2_SYNC_READ_ASYNC_WRITE_NOR -+}; -+ -+enum stm32_fmc2_ebi_buswidth { -+ FMC2_BUSWIDTH_8 = 8, -+ FMC2_BUSWIDTH_16 = 16 -+}; -+ -+enum stm32_fmc2_ebi_cpsize { -+ FMC2_CPSIZE_0 = 0, -+ FMC2_CPSIZE_128 = 128, -+ FMC2_CPSIZE_256 = 256, -+ FMC2_CPSIZE_512 = 512, -+ FMC2_CPSIZE_1024 = 1024 -+}; -+ -+struct stm32_fmc2_ebi { -+ struct device *dev; -+ struct clk *clk; -+ struct regmap *regmap; -+ u8 bank_assigned; -+ -+ u32 bcr[FMC2_MAX_EBI_CE]; -+ u32 btr[FMC2_MAX_EBI_CE]; -+ u32 bwtr[FMC2_MAX_EBI_CE]; -+ u32 pcscntr; -+}; -+ -+/* -+ * struct stm32_fmc2_prop - STM32 FMC2 EBI property -+ * @name: the device tree binding name of the property -+ * @bprop: indicate that it is a boolean property -+ * @mprop: indicate that it is a mandatory property -+ * @reg_type: the register that have to be modified -+ * @reg_mask: the bit that have to be modified in the selected register -+ * in case of it is a boolean property -+ * @reset_val: the default value that have to be set in case the property -+ * has not been defined in the device tree -+ * @check: this callback ckecks that the property is compliant with the -+ * transaction type selected -+ * @calculate: this callback is called to calculate for exemple a timing -+ * set in nanoseconds in the device tree in clock cycles or in -+ * clock period -+ * @set: this callback applies the values in the registers -+ */ -+struct stm32_fmc2_prop { -+ const char *name; -+ bool bprop; -+ bool mprop; -+ int reg_type; -+ u32 reg_mask; -+ u32 reset_val; -+ int (*check)(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, int cs); -+ u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup); -+ int (*set)(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup); -+}; -+ -+static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ u32 bcr; -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ -+ if (bcr & FMC2_BCR_MTYP) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ -+ if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ u32 bcr; -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ -+ if (bcr & FMC2_BCR_BURSTEN) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ u32 bcr; -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ -+ if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ -+ if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ u32 bcr, bxtr, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ if (prop->reg_type == FMC2_REG_BWTR) -+ regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr); -+ else -+ regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr); -+ -+ if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) && -+ ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ u32 bcr, bcr1; -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ if (cs) -+ regmap_read(ebi->regmap, FMC2_BCR1, &bcr1); -+ else -+ bcr1 = bcr; -+ -+ if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN))) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ if (cs) -+ return -EINVAL; -+ -+ return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs); -+} -+ -+static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi, -+ int cs, u32 setup) -+{ -+ unsigned long hclk = clk_get_rate(ebi->clk); -+ unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000); -+ -+ return DIV_ROUND_UP(setup * 1000, hclkp); -+} -+ -+static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi, -+ int cs, u32 setup) -+{ -+ u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup); -+ u32 bcr, btr, clk_period; -+ -+ regmap_read(ebi->regmap, FMC2_BCR1, &bcr); -+ if (bcr & FMC2_BCR1_CCLKEN || !cs) -+ regmap_read(ebi->regmap, FMC2_BTR1, &btr); -+ else -+ regmap_read(ebi->regmap, FMC2_BTR(cs), &btr); -+ -+ clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1; -+ -+ return DIV_ROUND_UP(nb_clk_cycles, clk_period); -+} -+ -+static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg) -+{ -+ switch (reg_type) { -+ case FMC2_REG_BCR: -+ *reg = FMC2_BCR(cs); -+ break; -+ case FMC2_REG_BTR: -+ *reg = FMC2_BTR(cs); -+ break; -+ case FMC2_REG_BWTR: -+ *reg = FMC2_BWTR(cs); -+ break; -+ case FMC2_REG_PCSCNTR: -+ *reg = FMC2_PCSCNTR; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 reg; -+ int ret; -+ -+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®); -+ if (ret) -+ return ret; -+ -+ regmap_update_bits(ebi->regmap, reg, prop->reg_mask, -+ setup ? prop->reg_mask : 0); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 bcr_mask, bcr = FMC2_BCR_WREN; -+ u32 btr_mask, btr = 0; -+ u32 bwtr_mask, bwtr = 0; -+ -+ bwtr_mask = FMC2_BXTR_ACCMOD; -+ btr_mask = FMC2_BXTR_ACCMOD; -+ bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN | -+ FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN | -+ FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW; -+ -+ switch (setup) { -+ case FMC2_ASYNC_MODE_1_SRAM: -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM); -+ /* -+ * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 -+ */ -+ break; -+ case FMC2_ASYNC_MODE_1_PSRAM: -+ /* -+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); -+ break; -+ case FMC2_ASYNC_MODE_A_SRAM: -+ /* -+ * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM); -+ bcr |= FMC2_BCR_EXTMOD; -+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); -+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); -+ break; -+ case FMC2_ASYNC_MODE_A_PSRAM: -+ /* -+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); -+ bcr |= FMC2_BCR_EXTMOD; -+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); -+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); -+ break; -+ case FMC2_ASYNC_MODE_2_NOR: -+ /* -+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); -+ bcr |= FMC2_BCR_FACCEN; -+ break; -+ case FMC2_ASYNC_MODE_B_NOR: -+ /* -+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); -+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD; -+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B); -+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B); -+ break; -+ case FMC2_ASYNC_MODE_C_NOR: -+ /* -+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); -+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD; -+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C); -+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C); -+ break; -+ case FMC2_ASYNC_MODE_D_NOR: -+ /* -+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, -+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); -+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD; -+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); -+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); -+ break; -+ case FMC2_SYNC_READ_SYNC_WRITE_PSRAM: -+ /* -+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0, -+ * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); -+ bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW; -+ break; -+ case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM: -+ /* -+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0, -+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); -+ bcr |= FMC2_BCR_BURSTEN; -+ break; -+ case FMC2_SYNC_READ_SYNC_WRITE_NOR: -+ /* -+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0, -+ * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); -+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW; -+ break; -+ case FMC2_SYNC_READ_ASYNC_WRITE_NOR: -+ /* -+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0, -+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 -+ */ -+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); -+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN; -+ break; -+ default: -+ /* Type of transaction not supported */ -+ return -EINVAL; -+ } -+ -+ if (bcr & FMC2_BCR_EXTMOD) -+ regmap_update_bits(ebi->regmap, FMC2_BWTR(cs), -+ bwtr_mask, bwtr); -+ regmap_update_bits(ebi->regmap, FMC2_BTR(cs), btr_mask, btr); -+ regmap_update_bits(ebi->regmap, FMC2_BCR(cs), bcr_mask, bcr); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val; -+ -+ switch (setup) { -+ case FMC2_BUSWIDTH_8: -+ val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8); -+ break; -+ case FMC2_BUSWIDTH_16: -+ val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16); -+ break; -+ default: -+ /* Buswidth not supported */ -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_MWID, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val; -+ -+ switch (setup) { -+ case FMC2_CPSIZE_0: -+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0); -+ break; -+ case FMC2_CPSIZE_128: -+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128); -+ break; -+ case FMC2_CPSIZE_256: -+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256); -+ break; -+ case FMC2_CPSIZE_512: -+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512); -+ break; -+ case FMC2_CPSIZE_1024: -+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024); -+ break; -+ default: -+ /* Cpsize not supported */ -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_CPSIZE, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val; -+ -+ val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX); -+ val = FIELD_PREP(FMC2_BCR_NBLSET, val); -+ regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_NBLSET, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 bcr, bxtr, reg; -+ u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); -+ int ret; -+ -+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®); -+ if (ret) -+ return ret; -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ if (prop->reg_type == FMC2_REG_BWTR) -+ regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr); -+ else -+ regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr); -+ -+ if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN) -+ val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX); -+ else -+ val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX); -+ val = FIELD_PREP(FMC2_BXTR_ADDSET, val); -+ regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_ADDSET, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val, reg; -+ int ret; -+ -+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®); -+ if (ret) -+ return ret; -+ -+ val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX); -+ val = FIELD_PREP(FMC2_BXTR_ADDHLD, val); -+ regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_ADDHLD, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val, reg; -+ int ret; -+ -+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®); -+ if (ret) -+ return ret; -+ -+ val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX); -+ val = FIELD_PREP(FMC2_BXTR_DATAST, val); -+ regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_DATAST, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val, reg; -+ int ret; -+ -+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®); -+ if (ret) -+ return ret; -+ -+ val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0; -+ val = FIELD_PREP(FMC2_BXTR_BUSTURN, val); -+ regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_BUSTURN, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val, reg; -+ int ret; -+ -+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®); -+ if (ret) -+ return ret; -+ -+ if (prop->reg_type == FMC2_REG_BWTR) -+ val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0; -+ else -+ val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX); -+ val = FIELD_PREP(FMC2_BXTR_DATAHLD, val); -+ regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_DATAHLD, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val; -+ -+ val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1; -+ val = FIELD_PREP(FMC2_BTR_CLKDIV, val); -+ regmap_update_bits(ebi->regmap, FMC2_BTR(cs), FMC2_BTR_CLKDIV, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 val; -+ -+ val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0; -+ val = FIELD_PREP(FMC2_BTR_DATLAT, val); -+ regmap_update_bits(ebi->regmap, FMC2_BTR(cs), FMC2_BTR_DATLAT, val); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, -+ const struct stm32_fmc2_prop *prop, -+ int cs, u32 setup) -+{ -+ u32 old_val, new_val, pcscntr; -+ -+ if (setup < 1) -+ return 0; -+ -+ regmap_read(ebi->regmap, FMC2_PCSCNTR, &pcscntr); -+ -+ /* Enable counter for the bank */ -+ regmap_update_bits(ebi->regmap, FMC2_PCSCNTR, -+ FMC2_PCSCNTR_CNTBEN(cs), -+ FMC2_PCSCNTR_CNTBEN(cs)); -+ -+ new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX); -+ old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr); -+ if (old_val && new_val > old_val) -+ /* Keep current counter value */ -+ return 0; -+ -+ new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val); -+ regmap_update_bits(ebi->regmap, FMC2_PCSCNTR, -+ FMC2_PCSCNTR_CSCOUNT, new_val); -+ -+ return 0; -+} -+ -+static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = { -+ /* st,fmc2-ebi-cs-trans-type must be the first property */ -+ { -+ .name = "st,fmc2-ebi-cs-transaction-type", -+ .mprop = true, -+ .set = stm32_fmc2_ebi_set_trans_type, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-cclk-enable", -+ .bprop = true, -+ .reg_type = FMC2_REG_BCR, -+ .reg_mask = FMC2_BCR1_CCLKEN, -+ .check = stm32_fmc2_ebi_check_cclk, -+ .set = stm32_fmc2_ebi_set_bit_field, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-mux-enable", -+ .bprop = true, -+ .reg_type = FMC2_REG_BCR, -+ .reg_mask = FMC2_BCR_MUXEN, -+ .check = stm32_fmc2_ebi_check_mux, -+ .set = stm32_fmc2_ebi_set_bit_field, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-buswidth", -+ .reset_val = FMC2_BUSWIDTH_16, -+ .set = stm32_fmc2_ebi_set_buswidth, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-waitpol-high", -+ .bprop = true, -+ .reg_type = FMC2_REG_BCR, -+ .reg_mask = FMC2_BCR_WAITPOL, -+ .set = stm32_fmc2_ebi_set_bit_field, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-waitcfg-enable", -+ .bprop = true, -+ .reg_type = FMC2_REG_BCR, -+ .reg_mask = FMC2_BCR_WAITCFG, -+ .check = stm32_fmc2_ebi_check_waitcfg, -+ .set = stm32_fmc2_ebi_set_bit_field, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-wait-enable", -+ .bprop = true, -+ .reg_type = FMC2_REG_BCR, -+ .reg_mask = FMC2_BCR_WAITEN, -+ .check = stm32_fmc2_ebi_check_sync_trans, -+ .set = stm32_fmc2_ebi_set_bit_field, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-asyncwait-enable", -+ .bprop = true, -+ .reg_type = FMC2_REG_BCR, -+ .reg_mask = FMC2_BCR_ASYNCWAIT, -+ .check = stm32_fmc2_ebi_check_async_trans, -+ .set = stm32_fmc2_ebi_set_bit_field, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-cpsize", -+ .check = stm32_fmc2_ebi_check_cpsize, -+ .set = stm32_fmc2_ebi_set_cpsize, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-byte-lane-setup-ns", -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_bl_setup, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-address-setup-ns", -+ .reg_type = FMC2_REG_BTR, -+ .reset_val = FMC2_BXTR_ADDSET_MAX, -+ .check = stm32_fmc2_ebi_check_async_trans, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_address_setup, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-address-hold-ns", -+ .reg_type = FMC2_REG_BTR, -+ .reset_val = FMC2_BXTR_ADDHLD_MAX, -+ .check = stm32_fmc2_ebi_check_address_hold, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_address_hold, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-data-setup-ns", -+ .reg_type = FMC2_REG_BTR, -+ .reset_val = FMC2_BXTR_DATAST_MAX, -+ .check = stm32_fmc2_ebi_check_async_trans, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_data_setup, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-bus-turnaround-ns", -+ .reg_type = FMC2_REG_BTR, -+ .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_bus_turnaround, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-data-hold-ns", -+ .reg_type = FMC2_REG_BTR, -+ .check = stm32_fmc2_ebi_check_async_trans, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_data_hold, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-clk-period-ns", -+ .reset_val = FMC2_BTR_CLKDIV_MAX + 1, -+ .check = stm32_fmc2_ebi_check_clk_period, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_clk_period, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-data-latency-ns", -+ .check = stm32_fmc2_ebi_check_sync_trans, -+ .calculate = stm32_fmc2_ebi_ns_to_clk_period, -+ .set = stm32_fmc2_ebi_set_data_latency, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-write-address-setup-ns", -+ .reg_type = FMC2_REG_BWTR, -+ .reset_val = FMC2_BXTR_ADDSET_MAX, -+ .check = stm32_fmc2_ebi_check_async_trans, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_address_setup, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-write-address-hold-ns", -+ .reg_type = FMC2_REG_BWTR, -+ .reset_val = FMC2_BXTR_ADDHLD_MAX, -+ .check = stm32_fmc2_ebi_check_address_hold, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_address_hold, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-write-data-setup-ns", -+ .reg_type = FMC2_REG_BWTR, -+ .reset_val = FMC2_BXTR_DATAST_MAX, -+ .check = stm32_fmc2_ebi_check_async_trans, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_data_setup, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-write-bus-turnaround-ns", -+ .reg_type = FMC2_REG_BWTR, -+ .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_bus_turnaround, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-write-data-hold-ns", -+ .reg_type = FMC2_REG_BWTR, -+ .check = stm32_fmc2_ebi_check_async_trans, -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_data_hold, -+ }, -+ { -+ .name = "st,fmc2-ebi-cs-max-low-pulse-ns", -+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, -+ .set = stm32_fmc2_ebi_set_max_low_pulse, -+ }, -+}; -+ -+static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi, -+ struct device_node *dev_node, -+ const struct stm32_fmc2_prop *prop, -+ int cs) -+{ -+ struct device *dev = ebi->dev; -+ u32 setup = 0; -+ -+ if (!prop->set) { -+ dev_err(dev, "property %s is not well defined\n", prop->name); -+ return -EINVAL; -+ } -+ -+ if (prop->check && prop->check(ebi, prop, cs)) -+ /* Skeep this property */ -+ return 0; -+ -+ if (prop->bprop) { -+ bool bprop; -+ -+ bprop = of_property_read_bool(dev_node, prop->name); -+ if (prop->mprop && !bprop) { -+ dev_err(dev, "mandatory property %s not defined in the device tree\n", -+ prop->name); -+ return -EINVAL; -+ } -+ -+ if (bprop) -+ setup = 1; -+ } else { -+ u32 val; -+ int ret; -+ -+ ret = of_property_read_u32(dev_node, prop->name, &val); -+ if (prop->mprop && ret) { -+ dev_err(dev, "mandatory property %s not defined in the device tree\n", -+ prop->name); -+ return ret; -+ } -+ -+ if (ret) -+ setup = prop->reset_val; -+ else if (prop->calculate) -+ setup = prop->calculate(ebi, cs, val); -+ else -+ setup = val; -+ } -+ -+ return prop->set(ebi, prop, cs, setup); -+} -+ -+static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs) -+{ -+ regmap_update_bits(ebi->regmap, FMC2_BCR(cs), -+ FMC2_BCR_MBKEN, FMC2_BCR_MBKEN); -+} -+ -+static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs) -+{ -+ regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_MBKEN, 0); -+} -+ -+static void stm32_fmc2_ebi_save_setup(struct stm32_fmc2_ebi *ebi) -+{ -+ unsigned int cs; -+ -+ for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &ebi->bcr[cs]); -+ regmap_read(ebi->regmap, FMC2_BTR(cs), &ebi->btr[cs]); -+ regmap_read(ebi->regmap, FMC2_BWTR(cs), &ebi->bwtr[cs]); -+ } -+ -+ regmap_read(ebi->regmap, FMC2_PCSCNTR, &ebi->pcscntr); -+} -+ -+static void stm32_fmc2_ebi_set_setup(struct stm32_fmc2_ebi *ebi) -+{ -+ unsigned int cs; -+ -+ for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { -+ regmap_write(ebi->regmap, FMC2_BCR(cs), ebi->bcr[cs]); -+ regmap_write(ebi->regmap, FMC2_BTR(cs), ebi->btr[cs]); -+ regmap_write(ebi->regmap, FMC2_BWTR(cs), ebi->bwtr[cs]); -+ } -+ -+ regmap_write(ebi->regmap, FMC2_PCSCNTR, ebi->pcscntr); -+} -+ -+static void stm32_fmc2_ebi_disable_banks(struct stm32_fmc2_ebi *ebi) -+{ -+ unsigned int cs; -+ -+ for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { -+ if (!(ebi->bank_assigned & BIT(cs))) -+ continue; -+ -+ stm32_fmc2_ebi_disable_bank(ebi, cs); -+ } -+} -+ -+/* NWAIT signal can not be connected to EBI controller and NAND controller */ -+static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) -+{ -+ unsigned int cs; -+ u32 bcr; -+ -+ for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { -+ if (!(ebi->bank_assigned & BIT(cs))) -+ continue; -+ -+ regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr); -+ if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) && -+ ebi->bank_assigned & BIT(FMC2_NAND)) -+ return true; -+ } -+ -+ return false; -+} -+ -+static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi) -+{ -+ regmap_update_bits(ebi->regmap, FMC2_BCR1, -+ FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN); -+} -+ -+static void stm32_fmc2_ebi_disable(struct stm32_fmc2_ebi *ebi) -+{ -+ regmap_update_bits(ebi->regmap, FMC2_BCR1, FMC2_BCR1_FMC2EN, 0); -+} -+ -+static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi, -+ struct device_node *dev_node, -+ u32 cs) -+{ -+ unsigned int i; -+ int ret; -+ -+ stm32_fmc2_ebi_disable_bank(ebi, cs); -+ -+ for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) { -+ const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i]; -+ -+ ret = stm32_fmc2_ebi_parse_prop(ebi, dev_node, p, cs); -+ if (ret) { -+ dev_err(ebi->dev, "property %s could not be set: %d\n", -+ p->name, ret); -+ return ret; -+ } -+ } -+ -+ stm32_fmc2_ebi_enable_bank(ebi, cs); -+ -+ return 0; -+} -+ -+static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi) -+{ -+ struct device *dev = ebi->dev; -+ struct device_node *child; -+ bool child_found = false; -+ u32 bank; -+ int ret; -+ -+ for_each_available_child_of_node(dev->of_node, child) { -+ ret = of_property_read_u32(child, "reg", &bank); -+ if (ret) { -+ dev_err(dev, "could not retrieve reg property: %d\n", -+ ret); -+ return ret; -+ } -+ -+ if (bank >= FMC2_MAX_BANKS) { -+ dev_err(dev, "invalid reg value: %d\n", bank); -+ return -EINVAL; -+ } -+ -+ if (ebi->bank_assigned & BIT(bank)) { -+ dev_err(dev, "bank already assigned: %d\n", bank); -+ return -EINVAL; -+ } -+ -+ if (bank < FMC2_MAX_EBI_CE) { -+ ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank); -+ if (ret) { -+ dev_err(dev, "setup chip select %d failed: %d\n", -+ bank, ret); -+ return ret; -+ } -+ } -+ -+ ebi->bank_assigned |= BIT(bank); -+ child_found = true; -+ } -+ -+ if (!child_found) { -+ dev_warn(dev, "no subnodes found, disable the driver.\n"); -+ return -ENODEV; -+ } -+ -+ if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) { -+ dev_err(dev, "NWAIT signal connected to EBI and NAND controllers\n"); -+ return -EINVAL; -+ } -+ -+ stm32_fmc2_ebi_enable(ebi); -+ -+ return of_platform_populate(dev->of_node, NULL, NULL, dev); -+} -+ -+static int stm32_fmc2_ebi_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct stm32_fmc2_ebi *ebi; -+ struct reset_control *rstc; -+ int ret; -+ -+ ebi = devm_kzalloc(&pdev->dev, sizeof(*ebi), GFP_KERNEL); -+ if (!ebi) -+ return -ENOMEM; -+ -+ ebi->dev = dev; -+ -+ ebi->regmap = device_node_to_regmap(dev->of_node); -+ if (IS_ERR(ebi->regmap)) -+ return PTR_ERR(ebi->regmap); -+ -+ ebi->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(ebi->clk)) -+ return PTR_ERR(ebi->clk); -+ -+ rstc = devm_reset_control_get(dev, NULL); -+ if (PTR_ERR(rstc) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ -+ ret = clk_prepare_enable(ebi->clk); -+ if (ret) -+ return ret; -+ -+ if (!IS_ERR(rstc)) { -+ reset_control_assert(rstc); -+ reset_control_deassert(rstc); -+ } -+ -+ ret = stm32_fmc2_ebi_parse_dt(ebi); -+ if (ret) -+ goto err_release; -+ -+ stm32_fmc2_ebi_save_setup(ebi); -+ platform_set_drvdata(pdev, ebi); -+ -+ return 0; -+ -+err_release: -+ stm32_fmc2_ebi_disable_banks(ebi); -+ stm32_fmc2_ebi_disable(ebi); -+ clk_disable_unprepare(ebi->clk); -+ -+ return ret; -+} -+ -+static int stm32_fmc2_ebi_remove(struct platform_device *pdev) -+{ -+ struct stm32_fmc2_ebi *ebi = platform_get_drvdata(pdev); -+ -+ of_platform_depopulate(&pdev->dev); -+ stm32_fmc2_ebi_disable_banks(ebi); -+ stm32_fmc2_ebi_disable(ebi); -+ clk_disable_unprepare(ebi->clk); -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32_fmc2_ebi_suspend(struct device *dev) -+{ -+ struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev); -+ -+ stm32_fmc2_ebi_disable(ebi); -+ clk_disable_unprepare(ebi->clk); -+ pinctrl_pm_select_sleep_state(dev); -+ -+ return 0; -+} -+ -+static int __maybe_unused stm32_fmc2_ebi_resume(struct device *dev) -+{ -+ struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev); -+ int ret; -+ -+ pinctrl_pm_select_default_state(dev); -+ -+ ret = clk_prepare_enable(ebi->clk); -+ if (ret) -+ return ret; -+ -+ stm32_fmc2_ebi_set_setup(ebi); -+ stm32_fmc2_ebi_enable(ebi); -+ -+ return 0; -+} -+ -+static SIMPLE_DEV_PM_OPS(stm32_fmc2_ebi_pm_ops, stm32_fmc2_ebi_suspend, -+ stm32_fmc2_ebi_resume); -+ -+static const struct of_device_id stm32_fmc2_ebi_match[] = { -+ {.compatible = "st,stm32mp1-fmc2-ebi"}, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, stm32_fmc2_ebi_match); -+ -+static struct platform_driver stm32_fmc2_ebi_driver = { -+ .probe = stm32_fmc2_ebi_probe, -+ .remove = stm32_fmc2_ebi_remove, -+ .driver = { -+ .name = "stm32_fmc2_ebi", -+ .of_match_table = stm32_fmc2_ebi_match, -+ .pm = &stm32_fmc2_ebi_pm_ops, -+ }, -+}; -+module_platform_driver(stm32_fmc2_ebi_driver); -+ -+MODULE_ALIAS("platform:stm32_fmc2_ebi"); -+MODULE_AUTHOR("Christophe Kerello "); -+MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 ebi driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h -index 661efa029c963..faee74f369e78 100644 ---- a/include/linux/pm_wakeup.h -+++ b/include/linux/pm_wakeup.h -@@ -79,6 +79,11 @@ static inline bool device_may_wakeup(struct device *dev) - return dev->power.can_wakeup && !!dev->power.wakeup; - } - -+static inline bool device_wakeup_path(struct device *dev) -+{ -+ return !!dev->power.wakeup_path; -+} -+ - static inline void device_set_wakeup_path(struct device *dev) - { - dev->power.wakeup_path = true; -@@ -165,6 +170,11 @@ static inline bool device_may_wakeup(struct device *dev) - return dev->power.can_wakeup && dev->power.should_wakeup; - } - -+static inline bool device_wakeup_path(struct device *dev) -+{ -+ return false; -+} -+ - static inline void device_set_wakeup_path(struct device *dev) {} - - static inline void __pm_stay_awake(struct wakeup_source *ws) {} -diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c -index 27f149f5d4a9f..4581702e8cdd2 100644 ---- a/kernel/power/suspend.c -+++ b/kernel/power/suspend.c -@@ -34,7 +34,6 @@ - #include "power.h" - - const char * const pm_labels[] = { -- [PM_SUSPEND_TO_IDLE] = "freeze", - [PM_SUSPEND_STANDBY] = "standby", - [PM_SUSPEND_MEM] = "mem", - }; --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0020-ARM-stm32mp1-r2-DEVICETREE.patch b/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0020-ARM-stm32mp1-r2-DEVICETREE.patch deleted file mode 100644 index 597a203..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/5.4.56/0020-ARM-stm32mp1-r2-DEVICETREE.patch +++ /dev/null @@ -1,11602 +0,0 @@ -From 1c76b63cabbc962d7974d624cf41e8e655ce44a9 Mon Sep 17 00:00:00 2001 -From: Lionel VITTE -Date: Mon, 5 Oct 2020 13:19:55 +0200 -Subject: [PATCH 20/22] ARM-stm32mp1-r2-rc8-DEVICETREE - ---- - .../devicetree/bindings/arm/stm32/stm32.yaml | 5 +- - .../bindings/clock/st,stm32mp1-rcc.txt | 5 +- - .../bindings/cpufreq/stm32-cpufreq.txt | 61 + - .../devicetree/bindings/dma/stm32-dma.txt | 36 +- - .../devicetree/bindings/dma/stm32-dmamux.txt | 5 +- - .../devicetree/bindings/dma/stm32-mdma.txt | 66 +- - .../devicetree/bindings/hwlock/hwlock.txt | 27 +- - .../bindings/hwlock/st,stm32-hwspinlock.txt | 6 +- - .../devicetree/bindings/i2c/i2c-stm32.txt | 12 +- - .../iio/adc/sigma-delta-modulator.txt | 3 + - .../bindings/iio/adc/st,stm32-adc.txt | 2 + - .../iio/timer/stm32-timer-trigger.txt | 9 + - .../interrupt-controller/st,stm32-exti.txt | 30 +- - .../devicetree/bindings/mailbox/arm-smc.yaml | 96 ++ - .../bindings/perf/stm32-ddr-pmu.txt | 18 + - .../devicetree/bindings/serial/rs485.txt | 7 + - .../bindings/serial/st,stm32-usart.txt | 64 +- - arch/arm/boot/dts/Makefile | 51 +- - arch/arm/boot/dts/stm32mp15-no-scmi.dtsi | 156 ++ - arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 1411 +++++++++++++++++ - .../dts/{stm32mp157c.dtsi => stm32mp151.dtsi} | 986 +++++++++--- - arch/arm/boot/dts/stm32mp153.dtsi | 54 + - .../boot/dts/stm32mp157-m4-srm-pinctrl.dtsi | 524 ++++++ - arch/arm/boot/dts/stm32mp157-m4-srm.dtsi | 442 ++++++ - arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 925 ----------- - arch/arm/boot/dts/stm32mp157.dtsi | 32 + - arch/arm/boot/dts/stm32mp157a-avenger96.dts | 17 +- - arch/arm/boot/dts/stm32mp157a-dk1.dts | 434 +---- - arch/arm/boot/dts/stm32mp157a-ed1.dts | 43 + - arch/arm/boot/dts/stm32mp157a-ev1.dts | 86 + - .../boot/dts/stm32mp157c-dk2-a7-examples.dts | 60 + - .../boot/dts/stm32mp157c-dk2-m4-examples.dts | 129 ++ - arch/arm/boot/dts/stm32mp157c-dk2.dts | 113 +- - arch/arm/boot/dts/stm32mp157c-ed1.dts | 320 +--- - .../boot/dts/stm32mp157c-ev1-a7-examples.dts | 57 + - .../boot/dts/stm32mp157c-ev1-m4-examples.dts | 146 ++ - arch/arm/boot/dts/stm32mp157c-ev1.dts | 293 +--- - arch/arm/boot/dts/stm32mp157d-dk1.dts | 35 + - arch/arm/boot/dts/stm32mp157d-ed1.dts | 43 + - arch/arm/boot/dts/stm32mp157d-ev1.dts | 86 + - .../boot/dts/stm32mp157f-dk2-a7-examples.dts | 52 + - .../boot/dts/stm32mp157f-dk2-m4-examples.dts | 129 ++ - arch/arm/boot/dts/stm32mp157f-dk2.dts | 171 ++ - arch/arm/boot/dts/stm32mp157f-ed1.dts | 47 + - .../boot/dts/stm32mp157f-ev1-a7-examples.dts | 53 + - .../boot/dts/stm32mp157f-ev1-m4-examples.dts | 146 ++ - arch/arm/boot/dts/stm32mp157f-ev1.dts | 86 + - arch/arm/boot/dts/stm32mp157xaa-pinctrl.dtsi | 90 -- - arch/arm/boot/dts/stm32mp157xab-pinctrl.dtsi | 62 - - arch/arm/boot/dts/stm32mp157xac-pinctrl.dtsi | 78 - - arch/arm/boot/dts/stm32mp157xad-pinctrl.dtsi | 62 - - arch/arm/boot/dts/stm32mp15xa.dtsi | 13 + - arch/arm/boot/dts/stm32mp15xc.dtsi | 20 + - arch/arm/boot/dts/stm32mp15xd.dtsi | 42 + - arch/arm/boot/dts/stm32mp15xf.dtsi | 20 + - arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 770 +++++++++ - arch/arm/boot/dts/stm32mp15xx-edx.dtsi | 407 +++++ - arch/arm/boot/dts/stm32mp15xx-evx.dtsi | 687 ++++++++ - arch/arm/boot/dts/stm32mp15xxaa-pinctrl.dtsi | 85 + - arch/arm/boot/dts/stm32mp15xxab-pinctrl.dtsi | 57 + - arch/arm/boot/dts/stm32mp15xxac-pinctrl.dtsi | 73 + - arch/arm/boot/dts/stm32mp15xxad-pinctrl.dtsi | 57 + - 62 files changed, 7555 insertions(+), 2547 deletions(-) - create mode 100644 Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt - create mode 100644 Documentation/devicetree/bindings/mailbox/arm-smc.yaml - create mode 100644 Documentation/devicetree/bindings/perf/stm32-ddr-pmu.txt - create mode 100644 arch/arm/boot/dts/stm32mp15-no-scmi.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15-pinctrl.dtsi - rename arch/arm/boot/dts/{stm32mp157c.dtsi => stm32mp151.dtsi} (57%) - create mode 100644 arch/arm/boot/dts/stm32mp153.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp157-m4-srm-pinctrl.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp157-m4-srm.dtsi - delete mode 100644 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp157.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp157a-ed1.dts - create mode 100644 arch/arm/boot/dts/stm32mp157a-ev1.dts - create mode 100644 arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157d-dk1.dts - create mode 100644 arch/arm/boot/dts/stm32mp157d-ed1.dts - create mode 100644 arch/arm/boot/dts/stm32mp157d-ev1.dts - create mode 100644 arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157f-dk2.dts - create mode 100644 arch/arm/boot/dts/stm32mp157f-ed1.dts - create mode 100644 arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp157f-ev1.dts - delete mode 100644 arch/arm/boot/dts/stm32mp157xaa-pinctrl.dtsi - delete mode 100644 arch/arm/boot/dts/stm32mp157xab-pinctrl.dtsi - delete mode 100644 arch/arm/boot/dts/stm32mp157xac-pinctrl.dtsi - delete mode 100644 arch/arm/boot/dts/stm32mp157xad-pinctrl.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xa.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xc.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xd.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xf.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xx-dkx.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xx-edx.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xx-evx.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xxaa-pinctrl.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xxab-pinctrl.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xxac-pinctrl.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp15xxad-pinctrl.dtsi - -diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml -index 4d194f1eb03a4..c9d74357b9415 100644 ---- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml -+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml -@@ -27,5 +27,8 @@ properties: - - items: - - enum: - - arrow,stm32mp157a-avenger96 # Avenger96 -- - const: st,stm32mp157 -+ - enum: -+ - st,stm32mp157 -+ - st,stm32mp153 -+ - st,stm32mp151 - ... -diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt -index fb9495ea582c4..1f1ec3446ca52 100644 ---- a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt -+++ b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt -@@ -12,7 +12,7 @@ binding usage. - - - Required properties: --- compatible: "st,stm32mp1-rcc", "syscon" -+- compatible: "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", "syscon" - - reg: should be register base and length as documented in the datasheet - - #clock-cells: 1, device nodes should specify the clock in their - "clocks" property, containing a phandle to the clock device node, -@@ -23,7 +23,8 @@ Required properties: - - Example: - rcc: rcc@50000000 { -- compatible = "st,stm32mp1-rcc", "syscon"; -+ compatible = "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", -+ "syscon"; - reg = <0x50000000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; -diff --git a/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt -new file mode 100644 -index 0000000000000..1292eb2612a05 ---- /dev/null -+++ b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt -@@ -0,0 +1,61 @@ -+STM32 CPUFreq and OPP bindings -+============================== -+ -+STM32 CPUFreq driver needs to read chip information from the SoC to list -+available OPPs. Then it depends on cpufreq-dt bindings. -+ -+Required properties: -+-------------------- -+- clocks: Phandle to the cpu clock "cpu". -+- clocks-name: Should contain "cpu". -+- nvmem-cells: Phandle to nvmem cell that contains "part_number". -+- nvmem-cell-names: Must be "part_number". -+- operating-points-v2: Phandle to operating points table. See ../power/opp.txt -+ for more details. -+ -+Optional properties: -+-------------------- -+See cpufreq-dt.txt for optional properties. -+ -+Examples: -+--------- -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu0: cpu@0 { -+ compatible = "arm,cortex-a7"; -+ device_type = "cpu"; -+ reg = <0>; -+ clocks = <&rcc CK_MPU>; -+ clock-names = "cpu"; -+ operating-points-v2 = <&cpu0_opp_table>; -+ nvmem-cells = <&part_number_otp>; -+ nvmem-cell-names = "part_number"; -+ }; -+ -+ cpu1: cpu@1 { -+ compatible = "arm,cortex-a7"; -+ device_type = "cpu"; -+ reg = <1>; -+ clocks = <&rcc CK_MPU>; -+ clock-names = "cpu"; -+ operating-points-v2 = <&cpu0_opp_table>; -+ }; -+ }; -+ -+ cpu0_opp_table: cpu0-opp-table { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-650000000 { -+ opp-hz = /bits/ 64 <650000000>; -+ opp-microvolt = <1200000>; -+ opp-supported-hw = <0x1>; -+ }; -+ opp-800000000 { -+ opp-hz = /bits/ 64 <800000000>; -+ opp-microvolt = <1350000>; -+ opp-supported-hw = <0x2>; -+ }; -+ }; -diff --git a/Documentation/devicetree/bindings/dma/stm32-dma.txt b/Documentation/devicetree/bindings/dma/stm32-dma.txt -index c5f519097204f..11ee1e9f85cc6 100644 ---- a/Documentation/devicetree/bindings/dma/stm32-dma.txt -+++ b/Documentation/devicetree/bindings/dma/stm32-dma.txt -@@ -17,6 +17,12 @@ Optional properties: - - resets: Reference to a reset controller asserting the DMA controller - - st,mem2mem: boolean; if defined, it indicates that the controller supports - memory-to-memory transfer -+- dmas: A list of eight dma specifiers, one for each entry in dma-names. -+ Refer to stm32-mdma.txt for more details. -+- dma-names: should contain "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6" and -+ "ch7" and represents each STM32 DMA channel connected to a STM32 MDMA one. -+- memory-region : phandle to a node describing memory to be used for -+ M2M intermediate transfer between DMA and MDMA. - - Example: - -@@ -36,6 +42,16 @@ Example: - st,mem2mem; - resets = <&rcc 150>; - dma-requests = <8>; -+ dmas = <&mdma1 8 0x10 0x1200000a 0x40026408 0x00000020 1>, -+ <&mdma1 9 0x10 0x1200000a 0x40026408 0x00000800 1>, -+ <&mdma1 10 0x10 0x1200000a 0x40026408 0x00200000 1>, -+ <&mdma1 11 0x10 0x1200000a 0x40026408 0x08000000 1>, -+ <&mdma1 12 0x10 0x1200000a 0x4002640C 0x00000020 1>, -+ <&mdma1 13 0x10 0x1200000a 0x4002640C 0x00000800 1>, -+ <&mdma1 14 0x10 0x1200000a 0x4002640C 0x00200000 1>, -+ <&mdma1 15 0x10 0x1200000a 0x4002640C 0x08000000 1>; -+ dma-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6", "ch7"; -+ memory-region = <&sram_dmapool>; - }; - - * DMA client -@@ -62,13 +78,25 @@ channel: a phandle to the DMA controller plus the following four integer cells: - 0x1: medium - 0x2: high - 0x3: very high --4. A 32bit bitfield value specifying DMA features which are device dependent: -+4. A bitfield value specifying DMA features which are device dependent: - -bit 0-1: DMA FIFO threshold selection - 0x0: 1/4 full FIFO - 0x1: 1/2 full FIFO - 0x2: 3/4 full FIFO - 0x3: full FIFO -- -+ -bit 2: DMA direct mode -+ 0: FIFO mode: with threshold level selectable with bit 0-1 -+ 1: Direct mode: each DMA request immediately initiates a transfer -+ from/to the memory. -+ -bit 30-29: indicated SRAM Buffer size in (2^order)*PAGE_SIZE. -+ Order is given by those 2 bits starting at 0. -+ Valid only whether Intermediate M2M transfer is set. -+ For cyclic, whether Intermediate M2M transfer is chosen, any value can -+ be set: SRAM buffer size will rely on period size and not on this DT -+ value. -+ -bit 31: Intermediate M2M transfer from/to DDR to/from SRAM throughout MDMA -+ 0: MDMA not used to generate an intermediate M2M transfer -+ 1: MDMA used to generate an intermediate M2M transfer. - - Example: - -@@ -77,7 +105,7 @@ Example: - reg = <0x40011000 0x400>; - interrupts = <37>; - clocks = <&clk_pclk2>; -- dmas = <&dma2 2 4 0x10400 0x3>, -- <&dma2 7 5 0x10200 0x3>; -+ dmas = <&dma2 2 4 0x10400 0x1>, -+ <&dma2 7 5 0x10200 0x1>; - dma-names = "rx", "tx"; - }; -diff --git a/Documentation/devicetree/bindings/dma/stm32-dmamux.txt b/Documentation/devicetree/bindings/dma/stm32-dmamux.txt -index 1b893b2355072..8e092d29b6146 100644 ---- a/Documentation/devicetree/bindings/dma/stm32-dmamux.txt -+++ b/Documentation/devicetree/bindings/dma/stm32-dmamux.txt -@@ -4,9 +4,6 @@ Required properties: - - compatible: "st,stm32h7-dmamux" - - reg: Memory map for accessing module - - #dma-cells: Should be set to <3>. -- First parameter is request line number. -- Second is DMA channel configuration -- Third is Fifo threshold - For more details about the three cells, please see - stm32-dma.txt documentation binding file - - dma-masters: Phandle pointing to the DMA controllers. -@@ -53,7 +50,7 @@ dma2: dma@40020400 { - <68>, - <69>, - <70>; -- clocks = <&timer_clk>; -+ clocks = <&clk_hclk>; - #dma-cells = <4>; - st,mem2mem; - resets = <&rcc 150>; -diff --git a/Documentation/devicetree/bindings/dma/stm32-mdma.txt b/Documentation/devicetree/bindings/dma/stm32-mdma.txt -index d18772d6bc656..077c819a54b0e 100644 ---- a/Documentation/devicetree/bindings/dma/stm32-mdma.txt -+++ b/Documentation/devicetree/bindings/dma/stm32-mdma.txt -@@ -10,7 +10,7 @@ Required properties: - - interrupts: Should contain the MDMA interrupt. - - clocks: Should contain the input clock of the DMA instance. - - resets: Reference to a reset controller asserting the DMA controller. --- #dma-cells : Must be <5>. See DMA client paragraph for more details. -+- #dma-cells : Must be <6>. See DMA client paragraph for more details. - - Optional properties: - - dma-channels: Number of DMA channels supported by the controller. -@@ -26,7 +26,7 @@ Example: - interrupts = <122>; - clocks = <&timer_clk>; - resets = <&rcc 992>; -- #dma-cells = <5>; -+ #dma-cells = <6>; - dma-channels = <16>; - dma-requests = <32>; - st,ahb-addr-masks = <0x20000000>, <0x00000000>; -@@ -35,60 +35,64 @@ Example: - * DMA client - - DMA clients connected to the STM32 MDMA controller must use the format --described in the dma.txt file, using a five-cell specifier for each channel: --a phandle to the MDMA controller plus the following five integer cells: -+described in the dma.txt file, using a six-cell specifier for each channel: -+a phandle to the MDMA controller plus the following six integer cells: - - 1. The request line number - 2. The priority level -- 0x00: Low -- 0x01: Medium -- 0x10: High -- 0x11: Very high -+ 0x0: Low -+ 0x1: Medium -+ 0x2: High -+ 0x3: Very high - 3. A 32bit mask specifying the DMA channel configuration - -bit 0-1: Source increment mode -- 0x00: Source address pointer is fixed -- 0x10: Source address pointer is incremented after each data transfer -- 0x11: Source address pointer is decremented after each data transfer -+ 0x0: Source address pointer is fixed -+ 0x2: Source address pointer is incremented after each data transfer -+ 0x3: Source address pointer is decremented after each data transfer - -bit 2-3: Destination increment mode -- 0x00: Destination address pointer is fixed -- 0x10: Destination address pointer is incremented after each data -+ 0x0: Destination address pointer is fixed -+ 0x2: Destination address pointer is incremented after each data - transfer -- 0x11: Destination address pointer is decremented after each data -+ 0x3: Destination address pointer is decremented after each data - transfer - -bit 8-9: Source increment offset size -- 0x00: byte (8bit) -- 0x01: half-word (16bit) -- 0x10: word (32bit) -- 0x11: double-word (64bit) -+ 0x0: byte (8bit) -+ 0x1: half-word (16bit) -+ 0x2: word (32bit) -+ 0x3: double-word (64bit) - -bit 10-11: Destination increment offset size -- 0x00: byte (8bit) -- 0x01: half-word (16bit) -- 0x10: word (32bit) -- 0x11: double-word (64bit) -+ 0x0: byte (8bit) -+ 0x1: half-word (16bit) -+ 0x2: word (32bit) -+ 0x3: double-word (64bit) - -bit 25-18: The number of bytes to be transferred in a single transfer - (min = 1 byte, max = 128 bytes) - -bit 29:28: Trigger Mode -- 0x00: Each MDMA request triggers a buffer transfer (max 128 bytes) -- 0x01: Each MDMA request triggers a block transfer (max 64K bytes) -- 0x10: Each MDMA request triggers a repeated block transfer -- 0x11: Each MDMA request triggers a linked list transfer -+ 0x0: Each MDMA request triggers a buffer transfer (max 128 bytes) -+ 0x1: Each MDMA request triggers a block transfer (max 64K bytes) -+ 0x2: Each MDMA request triggers a repeated block transfer -+ 0x3: Each MDMA request triggers a linked list transfer - 4. A 32bit value specifying the register to be used to acknowledge the request - if no HW ack signal is used by the MDMA client - 5. A 32bit mask specifying the value to be written to acknowledge the request - if no HW ack signal is used by the MDMA client -+6. A bitfield value specifying if the MDMA client wants to generate M2M -+ transfer with HW trigger (1) or not (0). This bitfield should be only -+ enabled for M2M transfer triggered by STM32 DMA client. The memory devices -+ involved in this kind of transfer are SRAM and DDR. - - Example: - - i2c4: i2c@5c002000 { - compatible = "st,stm32f7-i2c"; - reg = <0x5c002000 0x400>; -- interrupts = <95>, -- <96>; -- clocks = <&timer_clk>; -+ interrupts = , -+ ; -+ clocks = <&clk_hsi>; - #address-cells = <1>; - #size-cells = <0>; -- dmas = <&mdma1 36 0x0 0x40008 0x0 0x0>, -- <&mdma1 37 0x0 0x40002 0x0 0x0>; -+ dmas = <&mdma1 36 0x0 0x40008 0x0 0x0 0>, -+ <&mdma1 37 0x0 0x40002 0x0 0x0 0>; - dma-names = "rx", "tx"; - status = "disabled"; - }; -diff --git a/Documentation/devicetree/bindings/hwlock/hwlock.txt b/Documentation/devicetree/bindings/hwlock/hwlock.txt -index 085d1f5c916a4..e98088a409bac 100644 ---- a/Documentation/devicetree/bindings/hwlock/hwlock.txt -+++ b/Documentation/devicetree/bindings/hwlock/hwlock.txt -@@ -13,7 +13,7 @@ hwlock providers: - - Required properties: - - #hwlock-cells: Specifies the number of cells needed to represent a -- specific lock. -+ specific lock. Shall be 1 or 2 (see hwlocks below). - - hwlock users: - ============= -@@ -27,6 +27,11 @@ Required properties: - #hwlock-cells. The list can have just a single hwlock - or multiple hwlocks, with each hwlock represented by - a phandle and a corresponding args specifier. -+ If #hwlock-cells is 1, all of the locks are exclusive -+ (cannot be used by several users). -+ If #hwlock-cells is 2, the value of the second cell -+ defines whether the lock is for exclusive usage (0) or -+ shared (1) i.e. can be used by several users. - - Optional properties: - - hwlock-names: List of hwlock name strings defined in the same order -@@ -46,14 +51,22 @@ of length 1. - ... - }; - --2. Example of a node using multiple specific hwlocks: -+2. Example of nodes using multiple and shared specific hwlocks: - --The following example has a node requesting two hwlocks, a hwlock within --the hwlock device node 'hwlock1' with #hwlock-cells value of 1, and another --hwlock within the hwlock device node 'hwlock2' with #hwlock-cells value of 2. -+The following example has a nodeA requesting two hwlocks: -+- an exclusive one (#hwlock-cells = 1) within the hwlock device node 'hwlock1' -+- a shared one (#hwlock-cells = 2, second cell = 1) within the hwlock device -+ node 'hwlock2'. -+The shared lock is also be used by nodeB. - -- node { -+ nodeA { - ... -- hwlocks = <&hwlock1 2>, <&hwlock2 0 3>; -+ hwlocks = <&hwlock1 2>, <&hwlock2 0 1>; - ... - }; -+ -+ nodeB { -+ ... -+ hwlocks = <&hwlock2 0 1>; -+ ... -+ }; -\ No newline at end of file -diff --git a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.txt b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.txt -index adf4f000ea3db..60a37163b16dd 100644 ---- a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.txt -+++ b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.txt -@@ -4,8 +4,8 @@ STM32 Hardware Spinlock Device Binding - Required properties : - - compatible : should be "st,stm32-hwspinlock". - - reg : the register address of hwspinlock. --- #hwlock-cells : hwlock users only use the hwlock id to represent a specific -- hwlock, so the number of cells should be <1> here. -+- #hwlock-cells : should be <2> so the hwlock users use the hwlock id to -+ represent a specific hwlock and define its shared / exclusive attribute. - - clock-names : Must contain "hsem". - - clocks : Must contain a phandle entry for the clock in clock-names, see the - common clock bindings. -@@ -16,7 +16,7 @@ Please look at the generic hwlock binding for usage information for consumers, - Example of hwlock provider: - hwspinlock@4c000000 { - compatible = "st,stm32-hwspinlock"; -- #hwlock-cells = <1>; -+ #hwlock-cells = <2>; - reg = <0x4c000000 0x400>; - clocks = <&rcc HSEM>; - clock-names = "hsem"; -diff --git a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt -index ce3df2fff6c88..62ccd03fa549d 100644 ---- a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt -+++ b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt -@@ -4,13 +4,15 @@ Required properties: - - compatible: Must be one of the following - - "st,stm32f4-i2c" - - "st,stm32f7-i2c" -+ - "st,stm32mp15-i2c" - - reg: Offset and length of the register set for the device - - interrupts: Must contain the interrupt id for I2C event and then the - interrupt id for I2C error. - - resets: Must contain the phandle to the reset controller. - - clocks: Must contain the input clock of the I2C instance. - - A pinctrl state named "default" must be defined to set pins in mode of -- operation for I2C transfer -+ operation for I2C transfer. An optional pinctrl state named "sleep" has to -+ be defined as well as to put I2C in low power mode in suspend mode. - - #address-cells = <1>; - - #size-cells = <0>; - -@@ -34,6 +36,10 @@ Optional properties: - 2nd cell: register offset within SYSCFG - 3rd cell: register bitmask for FMP bit - For STM32F7, STM32H7 and STM32MP1 only. -+- st,smbus-alert: enable the SMBus Alert feature -+- st,smbus-host-notify: enable the SMBus Host-Notify feature -+- wakeup-source: Enable the possibility to use the I2C as a wakeup-source -+ For STM32H7 and STM32MP1 only. - - Example: - -@@ -60,6 +66,8 @@ Example: - resets = <&rcc STM32F7_APB1_RESET(I2C1)>; - clocks = <&rcc 1 CLK_I2C1>; - pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>; -- pinctrl-names = "default"; -+ pinctrl-1 = <&i2c1_sda_pin_sleep>, <&i2c1_scl_pin_sleep>; -+ pinctrl-names = "default", "sleep"; - st,syscfg-fmp = <&syscfg 0x4 0x1>; -+ st,syscfg-fmp-clr = <&syscfg 0x44 0x1>; - }; -diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt -index 59b92cd325527..fa70fda13bdb9 100644 ---- a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt -+++ b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt -@@ -5,6 +5,9 @@ Required properties: - as a generic SD modulator if modulator not specified in compatible list. - - #io-channel-cells = <0>: See the IIO bindings section "IIO consumers". - -+Optional properties: -+- vref-supply: Phandle to the vref input analog reference voltage. -+ - Example node: - - ads1202: adc { -diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt -index 4c0da8c74bb2c..8de9331467717 100644 ---- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt -+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt -@@ -53,6 +53,8 @@ Optional properties: - analog input switches on stm32mp1. - - st,syscfg: Phandle to system configuration controller. It can be used to - control the analog circuitry on stm32mp1. -+- st,max-clk-rate-hz: Allow to specify desired max clock rate used by analog -+ circuitry. - - Contents of a stm32 adc child node: - ----------------------------------- -diff --git a/Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt b/Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt -index b8e8c769d4343..4713ff1f55599 100644 ---- a/Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt -+++ b/Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt -@@ -9,6 +9,12 @@ Required parameters: - "st,stm32h7-timer-trigger" - - reg: Identify trigger hardware block. - -+Optional properties: -+- pinctrl-names: Set to "default". An additional "sleep" state can be -+ defined to set pins in sleep state when in low power. -+- pinctrl-n: Phandle(s) pointing to pin configuration node for PWM, -+ respectively for "default" and "sleep" states. -+ - Example: - timers@40010000 { - #address-cells = <1>; -@@ -21,5 +27,8 @@ Example: - timer@0 { - compatible = "st,stm32-timer-trigger"; - reg = <0>; -+ pinctrl-0 = <&tim1_pins>; -+ pinctrl-1 = <&tim1_sleep_pins>; -+ pinctrl-names = "default", "sleep"; - }; - }; -diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt -index cd01b2292ec68..abcf816d621c1 100644 ---- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt -+++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt -@@ -18,7 +18,19 @@ Optional properties: - - - hwlocks: reference to a phandle of a hardware spinlock provider node. - --Example: -+Exti could have several parent interrupt controllers. In this case child nodes -+are used to describe those "extra" parent controllers. Properties to use are: -+ -+- interrupt-controller: Indentifies the node as an interrupt controller -+- #interrupt-cells: Specifies the number of cells to encode an interrupt -+ specifier, shall be 2 -+- interrupt-parent: Phandle to the interrupt parent node. -+- st,irq-number: Interrupt number mapped on the parent. -+ -+See example 2. -+ -+ -+Example 1: - - exti: interrupt-controller@40013c00 { - compatible = "st,stm32-exti"; -@@ -27,3 +39,19 @@ exti: interrupt-controller@40013c00 { - reg = <0x40013C00 0x400>; - interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>; - }; -+ -+Example 2: -+ -+exti: interrupt-controller@5000d000 { -+ compatible = "st,stm32mp1-exti", "syscon"; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x5000d000 0x400>; -+ -+ exti_pwr: exti-pwr { -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupt-parent = <&pwr>; -+ st,irq-number = <6>; -+ }; -+}; -diff --git a/Documentation/devicetree/bindings/mailbox/arm-smc.yaml b/Documentation/devicetree/bindings/mailbox/arm-smc.yaml -new file mode 100644 -index 0000000000000..c165946a64e4e ---- /dev/null -+++ b/Documentation/devicetree/bindings/mailbox/arm-smc.yaml -@@ -0,0 +1,96 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mailbox/arm-smc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: ARM SMC Mailbox Interface -+ -+maintainers: -+ - Peng Fan -+ -+description: | -+ This mailbox uses the ARM smc (secure monitor call) or hvc (hypervisor -+ call) instruction to trigger a mailbox-connected activity in firmware, -+ executing on the very same core as the caller. The value of r0/w0/x0 -+ the firmware returns after the smc call is delivered as a received -+ message to the mailbox framework, so synchronous communication can be -+ established. The exact meaning of the action the mailbox triggers as -+ well as the return value is defined by their users and is not subject -+ to this binding. -+ -+ One example use case of this mailbox is the SCMI interface, which uses -+ shared memory to transfer commands and parameters, and a mailbox to -+ trigger a function call. This allows SoCs without a separate management -+ processor (or when such a processor is not available or used) to use -+ this standardized interface anyway. -+ -+ This binding describes no hardware, but establishes a firmware interface. -+ Upon receiving an SMC using the described SMC function identifier, the -+ firmware is expected to trigger some mailbox connected functionality. -+ The communication follows the ARM SMC calling convention. -+ Firmware expects an SMC function identifier in r0 or w0. The supported -+ identifier is listed in the the arm,func-id property as described below. -+ The firmware can return one value in the first SMC result register, -+ it is expected to be an error value, which shall be propagated to the -+ mailbox client. -+ -+ Any core which supports the SMC or HVC instruction can be used, as long -+ as a firmware component running in EL3 or EL2 is handling these calls. -+ -+properties: -+ compatible: -+ oneOf: -+ - description: -+ For implementations using ARM SMC instruction. -+ const: arm,smc-mbox -+ -+ - description: -+ For implementations using ARM HVC instruction. -+ const: arm,hvc-mbox -+ -+ "#mbox-cells": -+ const: 0 -+ -+ arm,func-id: -+ description: | -+ An single 32-bit value specifying the function ID used by the mailbox. -+ The function ID follows the ARM SMC calling convention standard. -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ -+required: -+ - compatible -+ - "#mbox-cells" -+ - arm,func-id -+ -+examples: -+ - | -+ sram@93f000 { -+ compatible = "mmio-sram"; -+ reg = <0x0 0x93f000 0x0 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x0 0x93f000 0x1000>; -+ -+ cpu_scp_lpri: scp-shmem@0 { -+ compatible = "arm,scmi-shmem"; -+ reg = <0x0 0x200>; -+ }; -+ }; -+ -+ smc_tx_mbox: tx_mbox { -+ #mbox-cells = <0>; -+ compatible = "arm,smc-mbox"; -+ arm,func-id = <0xc20000fe>; -+ }; -+ -+ firmware { -+ scmi { -+ compatible = "arm,scmi"; -+ mboxes = <&smc_tx_mbox>; -+ mbox-names = "tx"; -+ shmem = <&cpu_scp_lpri>; -+ }; -+ }; -+ -+... -diff --git a/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.txt b/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.txt -new file mode 100644 -index 0000000000000..7533b89646539 ---- /dev/null -+++ b/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.txt -@@ -0,0 +1,18 @@ -+* STM32 DDR Performance Monitor (DDRPERFM) -+ -+Required properties: -+- compatible: must be "st,stm32-ddr-pmu". -+- reg: physical address and length of the registers set. -+- clocks: list of phandles and specifiers to all input clocks listed in -+ clock-names property. -+- clock-names: "bus" corresponds to the DDRPERFM bus clock and "ddr" to -+ the DDR frequency. -+ -+Example: -+ ddrperfm: perf@5a007000 { -+ compatible = "st,stm32-ddr-pmu"; -+ reg = <0x5a007000 0x400>; -+ clocks = <&rcc DDRPERFM>, <&scmi0_clk CK_SCMI0_PLL2_R>; -+ clock-names = "bus", "ddr"; -+ }; -+ -diff --git a/Documentation/devicetree/bindings/serial/rs485.txt b/Documentation/devicetree/bindings/serial/rs485.txt -index b92592dff6dd9..f838439e4fe05 100644 ---- a/Documentation/devicetree/bindings/serial/rs485.txt -+++ b/Documentation/devicetree/bindings/serial/rs485.txt -@@ -12,6 +12,13 @@ Optional properties: - * b is the delay between end of data sent and rts signal in milliseconds - it corresponds to the delay after sending data and actual release of the line. - If this property is not specified, <0 0> is assumed. -+- rs485-rts-delay-ns: prop-encoded-array where: -+ * a is the delay between rts signal and beginning of data sent in nanoseconds. -+ it corresponds to the delay before sending data. -+ * b is the delay between end of data sent and rts signal in nanoseconds -+ it corresponds to the delay after sending data and actual release of the line. -+ If this property is not specified, <0 0> is assumed. -+ This property is used to define delays lower than 1ms. - - rs485-rts-active-low: drive RTS low when sending (default is high). - - linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485 - feature at boot time. It can be disabled later with proper ioctl. -diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt -index 8620f7fcbd50f..6263fe1bb85ce 100644 ---- a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt -+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt -@@ -1,7 +1,7 @@ - * STMicroelectronics STM32 USART - - Required properties: --- compatible: can be either: -+- compatible: Can be either: - - "st,stm32-uart", - - "st,stm32f7-uart", - - "st,stm32h7-uart". -@@ -9,22 +9,59 @@ Required properties: - - reg: The address and length of the peripheral registers space - - interrupts: - - The interrupt line for the USART instance, -- - An optional wake-up interrupt. - - clocks: The input clock of the USART instance - - Optional properties: - - resets: Must contain the phandle to the reset controller. --- pinctrl: The reference on the pins configuration --- st,hw-flow-ctrl: bool flag to enable hardware flow control. --- rs485-rts-delay, rs485-rx-during-tx, rs485-rts-active-low, -- linux,rs485-enabled-at-boot-time: see rs485.txt. --- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt -+- pinctrl-names: Set to "default". An additional "sleep" state can be defined -+ to set pins in sleep state when in low power. In case the device is used as -+ a wakeup source, "idle" state is defined in order to keep RX pin active. -+- pinctrl-n: Phandle(s) pointing to pin configuration nodes. -+ For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt -+- uart-has-rtscts: See description in serial.txt binding. -+- cts-gpios: CTS gpios for flow control. -+- rts-gpios: RTS gpios for flow control. -+- rs485-rts-delay, rs485-rts-delay-ns, rs485-rx-during-tx, rs485-rts-active-low, -+ linux,rs485-enabled-at-boot-time: See rs485.txt. -+- dmas: Phandle(s) to DMA controller node(s). Refer to stm32-dma.txt - - dma-names: "rx" and/or "tx" --- wakeup-source: bool flag to indicate this device has wakeup capabilities --- interrupt-names, if optional wake-up interrupt is used, should be: -- - "event": the name for the interrupt line of the USART instance -- - "wakeup" the name for the optional wake-up interrupt -+- wakeup-source: Bool flag to indicate this device has wakeup capabilities -+- st,rx-fifo-threshold-bytes: RX FIFO threshold configuration in bytes, only -+ available with stm32h7 compatible. -+ Valid values are 1, 2, 4, 8, 12, 14, 16. Default value is 8. If value is -+ set to 1, RX FIFO threshold is disabled. -+- st,tx-fifo-threshold-bytes: TX FIFO threshold configuration in bytes, only -+ available with stm32h7 compatible. -+ Valid values are 1, 2, 4, 8, 12, 14, 16. Default value is 8. If value is -+ set to 1, TX FIFO threshold is disabled. - -+Note for cts-gpios and rts-gpios: -+ - These properties can be used instead of 'uart-has-rtscts' or -+ 'st,hw-flow-ctrl' (deprecated) for making use of any gpio pins for flow -+ control instead of dedicated pins. It should be noted that both CTS/RTS -+ and 'uart-has-rtscts' properties cannot co-exist in a design. -+ -+Note for dma using: -+- "tx" dma can be used without any constraint since it uses single -+dma transfers. -+- "rx" dma using requires some attention: -+ 1) if you cannot anticipate the length of your received packets -+ and if your usart device embeds an internal fifo, then DON'T use -+ dma mode. -+ 2) if you enable dma mode WITHOUT mdma intermediate copy (cf. -+ stm32-dma.txt), then the availability of the received data will -+ depend on the dma driver policy and it may be delayed until dma -+ internal fifo is full. The usart driver will see this checking -+ the dma residue when rx interrupt (RXNE or RTO) occurs. -+ 3) if you enable dma mode WITH mdma intermediate copy (cf. -+ stm32-dma.txt) then the usart driver will never see the dma -+ residue becoming smaller than RX_BUF_P but it will get its -+ rx dma complete callback called when the cyclic transfer period -+ (RX_BUF_P) is reached. -+The three possibilities above are ordered from the most cpu time -+consuming one to the least one. The counterpart of this optimisation -+is the reception granularity achievable by the usart driver, from -+one byte up to RX_BUF_P. - - Examples: - usart4: serial@40004c00 { -@@ -32,8 +69,11 @@ usart4: serial@40004c00 { - reg = <0x40004c00 0x400>; - interrupts = <52>; - clocks = <&clk_pclk1>; -- pinctrl-names = "default"; -+ pinctrl-names = "default", "sleep", "idle"; - pinctrl-0 = <&pinctrl_usart4>; -+ pinctrl-1 = <&pinctrl_usart4_sleep>; -+ pinctrl-2 = <&pinctrl_usart4_idle>; -+ pinctrl-3 = <&pinctrl_usart4>; - }; - - usart2: serial@40004400 { -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index b21b3a64641a7..1c5d5b0278b2d 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -1,4 +1,36 @@ - # SPDX-License-Identifier: GPL-2.0 -+ -+# board-specific dtc flags -+DTC_FLAGS_stm32mp157c-dk2 += -@ -+DTC_FLAGS_stm32f429-disco += -@ -+DTC_FLAGS_stm32f469-disco += -@ -+DTC_FLAGS_stm32f746-disco += -@ -+DTC_FLAGS_stm32f769-disco += -@ -+DTC_FLAGS_stm32429i-eval += -@ -+DTC_FLAGS_stm32746g-eval += -@ -+DTC_FLAGS_stm32h743i-eval += -@ -+DTC_FLAGS_stm32h743i-disco += -@ -+DTC_FLAGS_stm32mp157a-dk1 += -@ -+DTC_FLAGS_stm32mp157d-dk1 += -@ -+DTC_FLAGS_stm32mp157c-dk2 += -@ -+DTC_FLAGS_stm32mp157f-dk2 += -@ -+DTC_FLAGS_stm32mp157c-dk2-a7-examples += -@ -+DTC_FLAGS_stm32mp157c-dk2-m4-examples += -@ -+DTC_FLAGS_stm32mp157f-dk2-a7-examples += -@ -+DTC_FLAGS_stm32mp157f-dk2-m4-examples += -@ -+DTC_FLAGS_stm32mp157a-ed1 += -@ -+DTC_FLAGS_stm32mp157c-ed1 += -@ -+DTC_FLAGS_stm32mp157d-ed1 += -@ -+DTC_FLAGS_stm32mp157f-ed1 += -@ -+DTC_FLAGS_stm32mp157a-ev1 += -@ -+DTC_FLAGS_stm32mp157c-ev1 += -@ -+DTC_FLAGS_stm32mp157d-ev1 += -@ -+DTC_FLAGS_stm32mp157f-ev1 += -@ -+DTC_FLAGS_stm32mp157c-ev1-a7-examples += -@ -+DTC_FLAGS_stm32mp157c-ev1-m4-examples += -@ -+DTC_FLAGS_stm32mp157f-ev1-a7-examples += -@ -+DTC_FLAGS_stm32mp157f-ev1-m4-examples += -@ -+ - dtb-$(CONFIG_ARCH_ALPINE) += \ - alpine-db.dtb - dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -989,9 +1021,26 @@ dtb-$(CONFIG_ARCH_STM32) += \ - stm32h743i-disco.dtb \ - stm32mp157a-avenger96.dtb \ - stm32mp157a-dk1.dtb \ -+ stm32mp157d-dk1.dtb \ - stm32mp157c-dk2.dtb \ -+ stm32mp157f-dk2.dtb \ -+ stm32mp157c-dk2-a7-examples.dtb \ -+ stm32mp157c-dk2-m4-examples.dtb \ -+ stm32mp157f-dk2-a7-examples.dtb \ -+ stm32mp157f-dk2-m4-examples.dtb \ -+ stm32mp157a-ed1.dtb \ - stm32mp157c-ed1.dtb \ -- stm32mp157c-ev1.dtb -+ stm32mp157d-ed1.dtb \ -+ stm32mp157f-ed1.dtb \ -+ stm32mp157a-ev1.dtb \ -+ stm32mp157c-ev1.dtb \ -+ stm32mp157d-ev1.dtb \ -+ stm32mp157f-ev1.dtb \ -+ stm32mp157c-ev1-a7-examples.dtb \ -+ stm32mp157c-ev1-m4-examples.dtb \ -+ stm32mp157f-ev1-a7-examples.dtb \ -+ stm32mp157f-ev1-m4-examples.dtb -+ - dtb-$(CONFIG_MACH_SUN4I) += \ - sun4i-a10-a1000.dtb \ - sun4i-a10-ba10-tvbox.dtb \ -diff --git a/arch/arm/boot/dts/stm32mp15-no-scmi.dtsi b/arch/arm/boot/dts/stm32mp15-no-scmi.dtsi -new file mode 100644 -index 0000000000000..b58b4b0526a20 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15-no-scmi.dtsi -@@ -0,0 +1,156 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved -+ * Author: Gabriel Fernandez for STMicroelectronics. -+ */ -+ -+/ { -+ -+ clocks { -+ clk_hse: clk-hse { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <24000000>; -+ }; -+ -+ clk_hsi: clk-hsi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <64000000>; -+ }; -+ -+ clk_lse: clk-lse { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32768>; -+ }; -+ -+ clk_lsi: clk-lsi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32000>; -+ }; -+ -+ clk_csi: clk-csi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <4000000>; -+ }; -+ }; -+ -+ cpus { -+ cpu0: cpu@0 { -+ clocks = <&rcc CK_MPU>; -+ }; -+ -+ cpu1: cpu@1 { -+ clocks = <&rcc CK_MPU>; -+ }; -+ }; -+ -+ soc { -+ m_can1: can@4400e000 { -+ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; -+ }; -+ -+ m_can2: can@4400f000 { -+ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; -+ }; -+ -+ cryp1: cryp@54001000 { -+ clocks = <&rcc CRYP1>; -+ resets = <&rcc CRYP1_R>; -+ }; -+ -+ dsi: dsi@5a000000 { -+ clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>; -+ }; -+ }; -+ -+ mlahb { -+ m4_rproc: m4@10000000 { -+ resets = <&rcc MCU_R>, <&rcc MCU_HOLD_BOOT_R>; -+ -+ m4_system_resources { -+ m4_cec: cec@40016000 { -+ clocks = <&rcc CEC_K>, <&rcc CK_LSE>; -+ }; -+ -+ m4_m_can1: can@4400e000 { -+ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; -+ }; -+ -+ m4_m_can2: can@4400f000 { -+ clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; -+ }; -+ }; -+ }; -+ }; -+ -+ firmware { -+ /delete-node/ scmi-0; -+ /delete-node/ scmi-1; -+ }; -+ /delete-node/ sram@2ffff000; -+ /delete-node/ mailbox-0; -+ /delete-node/ mailbox-1; -+}; -+ -+&cec { -+ clocks = <&rcc CEC_K>, <&clk_lse>; -+}; -+ -+&ddrperfm { -+ clocks = <&rcc DDRPERFM>, <&rcc PLL2_R>; -+}; -+ -+&gpioz { -+ clocks = <&rcc GPIOZ>; -+}; -+ -+&hash1 { -+ clocks = <&rcc HASH1>; -+ resets = <&rcc HASH1_R>; -+}; -+ -+&i2c4 { -+ clocks = <&rcc I2C4_K>; -+ resets = <&rcc I2C4_R>; -+}; -+ -+&i2c6 { -+ clocks = <&rcc I2C6_K>; -+ resets = <&rcc I2C6_R>; -+}; -+ -+&iwdg2 { -+ clocks = <&rcc IWDG2>, <&rcc CK_LSI>; -+}; -+ -+&mdma1 { -+ clocks = <&rcc MDMA>; -+ resets = <&rcc MDMA_R>; -+}; -+ -+&rcc { -+ compatible = "st,stm32mp1-rcc", "syscon"; -+ clocks = <&clk_hse>, <&clk_hsi>, <&clk_csi>, <&clk_lse>, <&clk_lsi>; -+}; -+ -+&rng1 { -+ clocks = <&rcc RNG1_K>; -+ resets = <&rcc RNG1_R>; -+}; -+ -+&rtc { -+ clocks = <&rcc RTCAPB>, <&rcc RTC>; -+}; -+ -+&spi6 { -+ clocks = <&rcc SPI6_K>; -+ resets = <&rcc SPI6_R>; -+}; -+ -+&usart1 { -+ clocks = <&rcc USART1_K>; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi -new file mode 100644 -index 0000000000000..8035044b8c399 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi -@@ -0,0 +1,1411 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Ludovic Barre for STMicroelectronics. -+ */ -+#include -+ -+&pinctrl { -+ adc1_in6_pins_a: adc1-in6 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ adc12_ain_pins_a: adc12-ain-0 { -+ pins { -+ pinmux = , /* ADC1 in13 */ -+ , /* ADC1 in6 */ -+ , /* ADC2 in2 */ -+ ; /* ADC2 in6 */ -+ }; -+ }; -+ -+ adc12_usb_cc_pins_a: adc12-usb-cc-pins-0 { -+ pins { -+ pinmux = , /* ADC12 in18 */ -+ ; /* ADC12 in19 */ -+ }; -+ }; -+ -+ cec_pins_a: cec-0 { -+ pins { -+ pinmux = ; -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ cec_pins_sleep_a: cec-sleep-0 { -+ pins { -+ pinmux = ; /* HDMI_CEC */ -+ }; -+ }; -+ -+ cec_pins_b: cec-1 { -+ pins { -+ pinmux = ; -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ cec_pins_sleep_b: cec-sleep-1 { -+ pins { -+ pinmux = ; /* HDMI_CEC */ -+ }; -+ }; -+ -+ dac_ch1_pins_a: dac-ch1 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ dac_ch2_pins_a: dac-ch2 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ dcmi_pins_a: dcmi-0 { -+ pins { -+ pinmux = ,/* DCMI_HSYNC */ -+ ,/* DCMI_VSYNC */ -+ ,/* DCMI_PIXCLK */ -+ ,/* DCMI_D0 */ -+ ,/* DCMI_D1 */ -+ ,/* DCMI_D2 */ -+ ,/* DCMI_D3 */ -+ ,/* DCMI_D4 */ -+ ,/* DCMI_D5 */ -+ ,/* DCMI_D6 */ -+ ,/* DCMI_D7 */ -+ ,/* DCMI_D8 */ -+ ,/* DCMI_D9 */ -+ ,/* DCMI_D10 */ -+ ;/* DCMI_D11 */ -+ bias-disable; -+ }; -+ }; -+ -+ dcmi_sleep_pins_a: dcmi-sleep-0 { -+ pins { -+ pinmux = ,/* DCMI_HSYNC */ -+ ,/* DCMI_VSYNC */ -+ ,/* DCMI_PIXCLK */ -+ ,/* DCMI_D0 */ -+ ,/* DCMI_D1 */ -+ ,/* DCMI_D2 */ -+ ,/* DCMI_D3 */ -+ ,/* DCMI_D4 */ -+ ,/* DCMI_D5 */ -+ ,/* DCMI_D6 */ -+ ,/* DCMI_D7 */ -+ ,/* DCMI_D8 */ -+ ,/* DCMI_D9 */ -+ ,/* DCMI_D10 */ -+ ;/* DCMI_D11 */ -+ }; -+ }; -+ -+ dfsdm_clkout_pins_a: dfsdm-clkout-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_CKOUT */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ dfsdm_clkout_sleep_pins_a: dfsdm-clkout-sleep-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_CKOUT */ -+ }; -+ }; -+ -+ dfsdm_data1_pins_a: dfsdm-data1-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_DATA1 */ -+ }; -+ }; -+ -+ dfsdm_data1_sleep_pins_a: dfsdm-data1-sleep-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_DATA1 */ -+ }; -+ }; -+ -+ dfsdm_data3_pins_a: dfsdm-data3-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_DATA3 */ -+ }; -+ }; -+ -+ dfsdm_data3_sleep_pins_a: dfsdm-data3-sleep-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_DATA3 */ -+ }; -+ }; -+ -+ ethernet0_rgmii_pins_a: rgmii-0 { -+ pins1 { -+ pinmux = , /* ETH_RGMII_CLK125 */ -+ , /* ETH_RGMII_GTX_CLK */ -+ , /* ETH_RGMII_TXD0 */ -+ , /* ETH_RGMII_TXD1 */ -+ , /* ETH_RGMII_TXD2 */ -+ , /* ETH_RGMII_TXD3 */ -+ , /* ETH_RGMII_TX_CTL */ -+ ; /* ETH_MDC */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <2>; -+ }; -+ pins2 { -+ pinmux = ; /* ETH_MDIO */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins3 { -+ pinmux = , /* ETH_RGMII_RXD0 */ -+ , /* ETH_RGMII_RXD1 */ -+ , /* ETH_RGMII_RXD2 */ -+ , /* ETH_RGMII_RXD3 */ -+ , /* ETH_RGMII_RX_CLK */ -+ ; /* ETH_RGMII_RX_CTL */ -+ bias-disable; -+ }; -+ }; -+ -+ ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 { -+ pins1 { -+ pinmux = , /* ETH_RGMII_CLK125 */ -+ , /* ETH_RGMII_GTX_CLK */ -+ , /* ETH_RGMII_TXD0 */ -+ , /* ETH_RGMII_TXD1 */ -+ , /* ETH_RGMII_TXD2 */ -+ , /* ETH_RGMII_TXD3 */ -+ , /* ETH_RGMII_TX_CTL */ -+ , /* ETH_MDIO */ -+ , /* ETH_MDC */ -+ , /* ETH_RGMII_RXD0 */ -+ , /* ETH_RGMII_RXD1 */ -+ , /* ETH_RGMII_RXD2 */ -+ , /* ETH_RGMII_RXD3 */ -+ , /* ETH_RGMII_RX_CLK */ -+ ; /* ETH_RGMII_RX_CTL */ -+ }; -+ }; -+ -+ fmc_pins_a: fmc-0 { -+ pins1 { -+ pinmux = , /* FMC_NOE */ -+ , /* FMC_NWE */ -+ , /* FMC_A16_FMC_CLE */ -+ , /* FMC_A17_FMC_ALE */ -+ , /* FMC_D0 */ -+ , /* FMC_D1 */ -+ , /* FMC_D2 */ -+ , /* FMC_D3 */ -+ , /* FMC_D4 */ -+ , /* FMC_D5 */ -+ , /* FMC_D6 */ -+ , /* FMC_D7 */ -+ ; /* FMC_NE2_FMC_NCE */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ pins2 { -+ pinmux = ; /* FMC_NWAIT */ -+ bias-pull-up; -+ }; -+ }; -+ -+ fmc_sleep_pins_a: fmc-sleep-0 { -+ pins { -+ pinmux = , /* FMC_NOE */ -+ , /* FMC_NWE */ -+ , /* FMC_A16_FMC_CLE */ -+ , /* FMC_A17_FMC_ALE */ -+ , /* FMC_D0 */ -+ , /* FMC_D1 */ -+ , /* FMC_D2 */ -+ , /* FMC_D3 */ -+ , /* FMC_D4 */ -+ , /* FMC_D5 */ -+ , /* FMC_D6 */ -+ , /* FMC_D7 */ -+ , /* FMC_NWAIT */ -+ ; /* FMC_NE2_FMC_NCE */ -+ }; -+ }; -+ -+ hdp0_pins_a: hdp0-0 { -+ pins { -+ pinmux = ; /* HDP0 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <2>; -+ }; -+ }; -+ -+ hdp0_pins_sleep_a: hdp0-sleep-0 { -+ pins { -+ pinmux = ; /* HDP0 */ -+ }; -+ }; -+ -+ hdp6_pins_a: hdp6-0 { -+ pins { -+ pinmux = ; /* HDP6 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <2>; -+ }; -+ }; -+ -+ hdp6_pins_sleep_a: hdp6-sleep-0 { -+ pins { -+ pinmux = ; /* HDP6 */ -+ }; -+ }; -+ -+ hdp7_pins_a: hdp7-0 { -+ pins { -+ pinmux = ; /* HDP7 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <2>; -+ }; -+ }; -+ -+ hdp7_pins_sleep_a: hdp7-sleep-0 { -+ pins { -+ pinmux = ; /* HDP7 */ -+ }; -+ }; -+ -+ i2c1_pins_a: i2c1-0 { -+ pins { -+ pinmux = , /* I2C1_SCL */ -+ ; /* I2C1_SDA */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ i2c1_pins_sleep_a: i2c1-1 { -+ pins { -+ pinmux = , /* I2C1_SCL */ -+ ; /* I2C1_SDA */ -+ }; -+ }; -+ -+ i2c1_pins_b: i2c1-2 { -+ pins { -+ pinmux = , /* I2C1_SCL */ -+ ; /* I2C1_SDA */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ i2c1_pins_sleep_b: i2c1-3 { -+ pins { -+ pinmux = , /* I2C1_SCL */ -+ ; /* I2C1_SDA */ -+ }; -+ }; -+ -+ i2c2_pins_a: i2c2-0 { -+ pins { -+ pinmux = , /* I2C2_SCL */ -+ ; /* I2C2_SDA */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ i2c2_pins_sleep_a: i2c2-1 { -+ pins { -+ pinmux = , /* I2C2_SCL */ -+ ; /* I2C2_SDA */ -+ }; -+ }; -+ -+ i2c2_pins_b1: i2c2-2 { -+ pins { -+ pinmux = ; /* I2C2_SDA */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ i2c2_pins_sleep_b1: i2c2-3 { -+ pins { -+ pinmux = ; /* I2C2_SDA */ -+ }; -+ }; -+ -+ i2c5_pins_a: i2c5-0 { -+ pins { -+ pinmux = , /* I2C5_SCL */ -+ ; /* I2C5_SDA */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ i2c5_pins_sleep_a: i2c5-1 { -+ pins { -+ pinmux = , /* I2C5_SCL */ -+ ; /* I2C5_SDA */ -+ -+ }; -+ }; -+ -+ i2s2_pins_a: i2s2-0 { -+ pins { -+ pinmux = , /* I2S2_SDO */ -+ , /* I2S2_WS */ -+ ; /* I2S2_CK */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ }; -+ -+ i2s2_pins_sleep_a: i2s2-1 { -+ pins { -+ pinmux = , /* I2S2_SDO */ -+ , /* I2S2_WS */ -+ ; /* I2S2_CK */ -+ }; -+ }; -+ -+ ltdc_pins_a: ltdc-a-0 { -+ pins { -+ pinmux = , /* LCD_CLK */ -+ , /* LCD_HSYNC */ -+ , /* LCD_VSYNC */ -+ , /* LCD_DE */ -+ , /* LCD_R0 */ -+ , /* LCD_R1 */ -+ , /* LCD_R2 */ -+ , /* LCD_R3 */ -+ , /* LCD_R4 */ -+ , /* LCD_R5 */ -+ , /* LCD_R6 */ -+ , /* LCD_R7 */ -+ , /* LCD_G0 */ -+ , /* LCD_G1 */ -+ , /* LCD_G2 */ -+ , /* LCD_G3 */ -+ , /* LCD_G4 */ -+ , /* LCD_G5 */ -+ , /* LCD_G6 */ -+ , /* LCD_G7 */ -+ , /* LCD_B0 */ -+ , /* LCD_B1 */ -+ , /* LCD_B2 */ -+ , /* LCD_B3 */ -+ , /* LCD_B4 */ -+ , /* LCD_B5 */ -+ , /* LCD_B6 */ -+ ; /* LCD_B7 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ }; -+ -+ ltdc_pins_sleep_a: ltdc-a-1 { -+ pins { -+ pinmux = , /* LCD_CLK */ -+ , /* LCD_HSYNC */ -+ , /* LCD_VSYNC */ -+ , /* LCD_DE */ -+ , /* LCD_R0 */ -+ , /* LCD_R1 */ -+ , /* LCD_R2 */ -+ , /* LCD_R3 */ -+ , /* LCD_R4 */ -+ , /* LCD_R5 */ -+ , /* LCD_R6 */ -+ , /* LCD_R7 */ -+ , /* LCD_G0 */ -+ , /* LCD_G1 */ -+ , /* LCD_G2 */ -+ , /* LCD_G3 */ -+ , /* LCD_G4 */ -+ , /* LCD_G5 */ -+ , /* LCD_G6 */ -+ , /* LCD_G7 */ -+ , /* LCD_B0 */ -+ , /* LCD_B1 */ -+ , /* LCD_B2 */ -+ , /* LCD_B3 */ -+ , /* LCD_B4 */ -+ , /* LCD_B5 */ -+ , /* LCD_B6 */ -+ ; /* LCD_B7 */ -+ }; -+ }; -+ -+ ltdc_pins_b: ltdc-b-0 { -+ pins { -+ pinmux = , /* LCD_CLK */ -+ , /* LCD_HSYNC */ -+ , /* LCD_VSYNC */ -+ , /* LCD_DE */ -+ , /* LCD_R0 */ -+ , /* LCD_R1 */ -+ , /* LCD_R2 */ -+ , /* LCD_R3 */ -+ , /* LCD_R4 */ -+ , /* LCD_R5 */ -+ , /* LCD_R6 */ -+ , /* LCD_R7 */ -+ , /* LCD_G0 */ -+ , /* LCD_G1 */ -+ , /* LCD_G2 */ -+ , /* LCD_G3 */ -+ , /* LCD_G4 */ -+ , /* LCD_G5 */ -+ , /* LCD_G6 */ -+ , /* LCD_G7 */ -+ , /* LCD_B0 */ -+ , /* LCD_B1 */ -+ , /* LCD_B2 */ -+ , /* LCD_B3 */ -+ , /* LCD_B4 */ -+ , /* LCD_B5 */ -+ , /* LCD_B6 */ -+ ; /* LCD_B7 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ }; -+ -+ ltdc_pins_sleep_b: ltdc-b-1 { -+ pins { -+ pinmux = , /* LCD_CLK */ -+ , /* LCD_HSYNC */ -+ , /* LCD_VSYNC */ -+ , /* LCD_DE */ -+ , /* LCD_R0 */ -+ , /* LCD_R1 */ -+ , /* LCD_R2 */ -+ , /* LCD_R3 */ -+ , /* LCD_R4 */ -+ , /* LCD_R5 */ -+ , /* LCD_R6 */ -+ , /* LCD_R7 */ -+ , /* LCD_G0 */ -+ , /* LCD_G1 */ -+ , /* LCD_G2 */ -+ , /* LCD_G3 */ -+ , /* LCD_G4 */ -+ , /* LCD_G5 */ -+ , /* LCD_G6 */ -+ , /* LCD_G7 */ -+ , /* LCD_B0 */ -+ , /* LCD_B1 */ -+ , /* LCD_B2 */ -+ , /* LCD_B3 */ -+ , /* LCD_B4 */ -+ , /* LCD_B5 */ -+ , /* LCD_B6 */ -+ ; /* LCD_B7 */ -+ }; -+ }; -+ -+ m_can1_pins_a: m-can1-0 { -+ pins1 { -+ pinmux = ; /* CAN1_TX */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* CAN1_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ m_can1_sleep_pins_a: m_can1-sleep-0 { -+ pins { -+ pinmux = , /* CAN1_TX */ -+ ; /* CAN1_RX */ -+ }; -+ }; -+ -+ pwm1_pins_a: pwm1-0 { -+ pins { -+ pinmux = , /* TIM1_CH1 */ -+ , /* TIM1_CH2 */ -+ ; /* TIM1_CH4 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm1_sleep_pins_a: pwm1-sleep-0 { -+ pins { -+ pinmux = , /* TIM1_CH1 */ -+ , /* TIM1_CH2 */ -+ ; /* TIM1_CH4 */ -+ }; -+ }; -+ -+ pwm2_pins_a: pwm2-0 { -+ pins { -+ pinmux = ; /* TIM2_CH4 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm2_sleep_pins_a: pwm2-sleep-0 { -+ pins { -+ pinmux = ; /* TIM2_CH4 */ -+ }; -+ }; -+ -+ pwm3_pins_a: pwm3-0 { -+ pins { -+ pinmux = ; /* TIM3_CH2 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm3_sleep_pins_a: pwm3-sleep-0 { -+ pins { -+ pinmux = ; /* TIM3_CH2 */ -+ }; -+ }; -+ -+ pwm4_pins_a: pwm4-0 { -+ pins { -+ pinmux = , /* TIM4_CH3 */ -+ ; /* TIM4_CH4 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm4_sleep_pins_a: pwm4-sleep-0 { -+ pins { -+ pinmux = , /* TIM4_CH3 */ -+ ; /* TIM4_CH4 */ -+ }; -+ }; -+ -+ pwm4_pins_b: pwm4-1 { -+ pins { -+ pinmux = ; /* TIM4_CH2 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm4_sleep_pins_b: pwm4-sleep-1 { -+ pins { -+ pinmux = ; /* TIM4_CH2 */ -+ }; -+ }; -+ -+ pwm5_pins_a: pwm5-0 { -+ pins { -+ pinmux = ; /* TIM5_CH2 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm5_sleep_pins_a: pwm5-sleep-0 { -+ pins { -+ pinmux = ; /* TIM5_CH2 */ -+ }; -+ }; -+ -+ pwm8_pins_a: pwm8-0 { -+ pins { -+ pinmux = ; /* TIM8_CH4 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm8_sleep_pins_a: pwm8-sleep-0 { -+ pins { -+ pinmux = ; /* TIM8_CH4 */ -+ }; -+ }; -+ -+ pwm12_pins_a: pwm12-0 { -+ pins { -+ pinmux = ; /* TIM12_CH1 */ -+ bias-pull-down; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ pwm12_sleep_pins_a: pwm12-sleep-0 { -+ pins { -+ pinmux = ; /* TIM12_CH1 */ -+ }; -+ }; -+ -+ qspi_clk_pins_a: qspi-clk-0 { -+ pins { -+ pinmux = ; /* QSPI_CLK */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <3>; -+ }; -+ }; -+ -+ qspi_clk_sleep_pins_a: qspi-clk-sleep-0 { -+ pins { -+ pinmux = ; /* QSPI_CLK */ -+ }; -+ }; -+ -+ qspi_bk1_pins_a: qspi-bk1-0 { -+ pins1 { -+ pinmux = , /* QSPI_BK1_IO0 */ -+ , /* QSPI_BK1_IO1 */ -+ , /* QSPI_BK1_IO2 */ -+ ; /* QSPI_BK1_IO3 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ pins2 { -+ pinmux = ; /* QSPI_BK1_NCS */ -+ bias-pull-up; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ }; -+ -+ qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 { -+ pins { -+ pinmux = , /* QSPI_BK1_IO0 */ -+ , /* QSPI_BK1_IO1 */ -+ , /* QSPI_BK1_IO2 */ -+ , /* QSPI_BK1_IO3 */ -+ ; /* QSPI_BK1_NCS */ -+ }; -+ }; -+ -+ qspi_bk2_pins_a: qspi-bk2-0 { -+ pins1 { -+ pinmux = , /* QSPI_BK2_IO0 */ -+ , /* QSPI_BK2_IO1 */ -+ , /* QSPI_BK2_IO2 */ -+ ; /* QSPI_BK2_IO3 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ pins2 { -+ pinmux = ; /* QSPI_BK2_NCS */ -+ bias-pull-up; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ }; -+ -+ qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 { -+ pins { -+ pinmux = , /* QSPI_BK2_IO0 */ -+ , /* QSPI_BK2_IO1 */ -+ , /* QSPI_BK2_IO2 */ -+ , /* QSPI_BK2_IO3 */ -+ ; /* QSPI_BK2_NCS */ -+ }; -+ }; -+ -+ rtc_out2_rmp_pins_a: rtc-out2-rmp-pins-0 { -+ pins { -+ pinmux = ; /* RTC_OUT2_RMP */ -+ }; -+ }; -+ -+ sai2a_pins_a: sai2a-0 { -+ pins { -+ pinmux = , /* SAI2_SCK_A */ -+ , /* SAI2_SD_A */ -+ , /* SAI2_FS_A */ -+ ; /* SAI2_MCLK_A */ -+ slew-rate = <0>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ }; -+ -+ sai2a_sleep_pins_a: sai2a-1 { -+ pins { -+ pinmux = , /* SAI2_SCK_A */ -+ , /* SAI2_SD_A */ -+ , /* SAI2_FS_A */ -+ ; /* SAI2_MCLK_A */ -+ }; -+ }; -+ -+ sai2b_pins_a: sai2b-0 { -+ pins1 { -+ pinmux = , /* SAI2_SCK_B */ -+ , /* SAI2_FS_B */ -+ ; /* SAI2_MCLK_B */ -+ slew-rate = <0>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* SAI2_SD_B */ -+ bias-disable; -+ }; -+ }; -+ -+ sai2b_sleep_pins_a: sai2b-1 { -+ pins { -+ pinmux = , /* SAI2_SD_B */ -+ , /* SAI2_SCK_B */ -+ , /* SAI2_FS_B */ -+ ; /* SAI2_MCLK_B */ -+ }; -+ }; -+ -+ sai2b_pins_b: sai2b-2 { -+ pins { -+ pinmux = ; /* SAI2_SD_B */ -+ bias-disable; -+ }; -+ }; -+ -+ sai2b_sleep_pins_b: sai2b-3 { -+ pins { -+ pinmux = ; /* SAI2_SD_B */ -+ }; -+ }; -+ -+ sai4a_pins_a: sai4a-0 { -+ pins { -+ pinmux = ; /* SAI4_SD_A */ -+ slew-rate = <0>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ }; -+ -+ sai4a_sleep_pins_a: sai4a-1 { -+ pins { -+ pinmux = ; /* SAI4_SD_A */ -+ }; -+ }; -+ -+ sdmmc1_b4_pins_a: sdmmc1-b4-0 { -+ pins1 { -+ pinmux = , /* SDMMC1_D0 */ -+ , /* SDMMC1_D1 */ -+ , /* SDMMC1_D2 */ -+ , /* SDMMC1_D3 */ -+ ; /* SDMMC1_CMD */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC1_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ }; -+ -+ sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 { -+ pins1 { -+ pinmux = , /* SDMMC1_D0 */ -+ , /* SDMMC1_D1 */ -+ , /* SDMMC1_D2 */ -+ ; /* SDMMC1_D3 */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC1_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins3 { -+ pinmux = ; /* SDMMC1_CMD */ -+ slew-rate = <1>; -+ drive-open-drain; -+ bias-disable; -+ }; -+ }; -+ -+ sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 { -+ pins { -+ pinmux = , /* SDMMC1_D0 */ -+ , /* SDMMC1_D1 */ -+ , /* SDMMC1_D2 */ -+ , /* SDMMC1_D3 */ -+ , /* SDMMC1_CK */ -+ ; /* SDMMC1_CMD */ -+ }; -+ }; -+ -+ sdmmc1_dir_pins_a: sdmmc1-dir-0 { -+ pins1 { -+ pinmux = , /* SDMMC1_D0DIR */ -+ , /* SDMMC1_D123DIR */ -+ ; /* SDMMC1_CDIR */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2{ -+ pinmux = ; /* SDMMC1_CKIN */ -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 { -+ pins { -+ pinmux = , /* SDMMC1_D0DIR */ -+ , /* SDMMC1_D123DIR */ -+ , /* SDMMC1_CDIR */ -+ ; /* SDMMC1_CKIN */ -+ }; -+ }; -+ -+ sdmmc2_b4_pins_a: sdmmc2-b4-0 { -+ pins1 { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ , /* SDMMC2_D3 */ -+ ; /* SDMMC2_CMD */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC2_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 { -+ pins1 { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ ; /* SDMMC2_D3 */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC2_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins3 { -+ pinmux = ; /* SDMMC2_CMD */ -+ slew-rate = <1>; -+ drive-open-drain; -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 { -+ pins { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ , /* SDMMC2_D3 */ -+ , /* SDMMC2_CK */ -+ ; /* SDMMC2_CMD */ -+ }; -+ }; -+ -+ sdmmc2_b4_pins_b: sdmmc2-b4-1 { -+ pins1 { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ , /* SDMMC2_D3 */ -+ ; /* SDMMC2_CMD */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC2_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ }; -+ -+ sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 { -+ pins1 { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ ; /* SDMMC2_D3 */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC2_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins3 { -+ pinmux = ; /* SDMMC2_CMD */ -+ slew-rate = <1>; -+ drive-open-drain; -+ bias-disable; -+ }; -+ }; -+ -+ sdmmc2_d47_pins_a: sdmmc2-d47-0 { -+ pins { -+ pinmux = , /* SDMMC2_D4 */ -+ , /* SDMMC2_D5 */ -+ , /* SDMMC2_D6 */ -+ ; /* SDMMC2_D7 */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 { -+ pins { -+ pinmux = , /* SDMMC2_D4 */ -+ , /* SDMMC2_D5 */ -+ , /* SDMMC2_D6 */ -+ ; /* SDMMC2_D7 */ -+ }; -+ }; -+ -+ sdmmc3_b4_pins_a: sdmmc3-b4-0 { -+ pins1 { -+ pinmux = , /* SDMMC3_D0 */ -+ , /* SDMMC3_D1 */ -+ , /* SDMMC3_D2 */ -+ , /* SDMMC3_D3 */ -+ ; /* SDMMC3_CMD */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC3_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc3_b4_od_pins_a: sdmmc3-b4-od-0 { -+ pins1 { -+ pinmux = , /* SDMMC3_D0 */ -+ , /* SDMMC3_D1 */ -+ , /* SDMMC3_D2 */ -+ ; /* SDMMC3_D3 */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC3_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins3 { -+ pinmux = ; /* SDMMC2_CMD */ -+ slew-rate = <1>; -+ drive-open-drain; -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc3_b4_sleep_pins_a: sdmmc3-b4-sleep-0 { -+ pins { -+ pinmux = , /* SDMMC3_D0 */ -+ , /* SDMMC3_D1 */ -+ , /* SDMMC3_D2 */ -+ , /* SDMMC3_D3 */ -+ , /* SDMMC3_CK */ -+ ; /* SDMMC3_CMD */ -+ }; -+ }; -+ -+ spdifrx_pins_a: spdifrx-0 { -+ pins { -+ pinmux = ; /* SPDIF_IN1 */ -+ bias-disable; -+ }; -+ }; -+ -+ spdifrx_sleep_pins_a: spdifrx-1 { -+ pins { -+ pinmux = ; /* SPDIF_IN1 */ -+ }; -+ }; -+ -+ spi4_pins_a: spi4-0 { -+ pins1 { -+ pinmux = , /* SPI4_SCK */ -+ ; /* SPI4_MOSI */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ -+ pins2 { -+ pinmux = ; /* SPI4_MISO */ -+ bias-disable; -+ }; -+ }; -+ -+ spi4_sleep_pins_a: spi4-sleep-0 { -+ pins { -+ pinmux = , /* SPI4_SCK */ -+ , /* SPI4_MISO */ -+ ; /* SPI4_MOSI */ -+ }; -+ }; -+ -+ spi5_pins_a: spi5-0 { -+ pins1 { -+ pinmux = , /* SPI5_SCK */ -+ ; /* SPI5_MOSI */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ -+ pins2 { -+ pinmux = ; /* SPI5_MISO */ -+ bias-disable; -+ }; -+ }; -+ -+ spi5_sleep_pins_a: spi5-sleep-0 { -+ pins { -+ pinmux = , /* SPI5_SCK */ -+ , /* SPI5_MISO */ -+ ; /* SPI5_MOSI */ -+ }; -+ }; -+ -+ stusb1600_pins_a: stusb1600-0 { -+ pins { -+ pinmux = ; -+ bias-pull-up; -+ }; -+ }; -+ -+ uart4_pins_a: uart4-0 { -+ pins1 { -+ pinmux = ; /* UART4_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* UART4_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ uart4_idle_pins_a: uart4-idle-0 { -+ pins1 { -+ pinmux = ; /* UART4_TX */ -+ }; -+ pins2 { -+ pinmux = ; /* UART4_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ uart4_sleep_pins_a: uart4-sleep-0 { -+ pins { -+ pinmux = , /* UART4_TX */ -+ ; /* UART4_RX */ -+ }; -+ }; -+ -+ uart4_pins_b: uart4-1 { -+ pins1 { -+ pinmux = ; /* UART4_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* UART4_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ uart7_pins_a: uart7-0 { -+ pins1 { -+ pinmux = ; /* UART4_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* UART4_RX */ -+ , /* UART4_CTS */ -+ ; /* UART4_RTS */ -+ bias-disable; -+ }; -+ }; -+ -+ uart7_pins_b: uart7-1 { -+ pins1 { -+ pinmux = ; /* USART7_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* USART7_RX */ -+ bias-pull-up; -+ }; -+ }; -+ -+ uart7_idle_pins_b: uart7-idle-1 { -+ pins1 { -+ pinmux = ; /* USART7_TX */ -+ }; -+ pins2 { -+ pinmux = ; /* USART7_RX */ -+ bias-pull-up; -+ }; -+ }; -+ -+ uart7_sleep_pins_b: uart7-sleep-1 { -+ pins { -+ pinmux = , /* USART7_TX */ -+ ; /* USART7_RX */ -+ }; -+ }; -+ -+ usart2_pins_a: usart2-0 { -+ pins1 { -+ pinmux = , /* USART2_TX */ -+ ; /* USART2_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <3>; -+ }; -+ pins2 { -+ pinmux = , /* USART2_RX */ -+ ; /* USART2_CTS_NSS */ -+ bias-disable; -+ }; -+ }; -+ -+ usart2_idle_pins_a: usart2-idle-0 { -+ pins1 { -+ pinmux = , /* USART2_TX */ -+ , /* USART2_RTS */ -+ ; /* USART2_CTS_NSS */ -+ }; -+ pins2 { -+ pinmux = ; /* USART2_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ usart2_sleep_pins_a: usart2-sleep-0 { -+ pins { -+ pinmux = , /* USART2_TX */ -+ , /* USART2_RTS */ -+ , /* USART2_RX */ -+ ; /* USART2_CTS_NSS */ -+ }; -+ }; -+ -+ usart3_pins_a: usart3-0 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ ; /* USART3_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ bias-disable; -+ }; -+ }; -+ -+ usart3_idle_pins_a: usart3-idle-0 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ , /* USART3_RTS */ -+ ; /* USART3_CTS_NSS */ -+ }; -+ pins2 { -+ pinmux = ; /* USART3_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ usart3_sleep_pins_a: usart3-sleep-0 { -+ pins { -+ pinmux = , /* USART3_TX */ -+ , /* USART3_RTS */ -+ , /* USART3_CTS_NSS */ -+ ; /* USART3_RX */ -+ }; -+ }; -+ -+ usart3_pins_b: usart3-1 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ ; /* USART3_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ bias-pull-up; -+ }; -+ }; -+ -+ usart3_idle_pins_b: usart3-idle-1 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ , /* USART3_RTS */ -+ ; /* USART3_CTS_NSS */ -+ }; -+ pins2 { -+ pinmux = ; /* USART3_RX */ -+ bias-pull-up; -+ }; -+ }; -+ -+ usart3_sleep_pins_b: usart3-sleep-1 { -+ pins { -+ pinmux = , /* USART3_TX */ -+ , /* USART3_RTS */ -+ , /* USART3_CTS_NSS */ -+ ; /* USART3_RX */ -+ }; -+ }; -+ -+ usbotg_hs_pins_a: usbotg_hs-0 { -+ pins { -+ pinmux = ; /* OTG_ID */ -+ }; -+ }; -+ -+ usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { -+ pins { -+ pinmux = , /* OTG_FS_DM */ -+ ; /* OTG_FS_DP */ -+ }; -+ }; -+}; -+ -+&pinctrl_z { -+ i2c2_pins_b2: i2c2-0 { -+ pins { -+ pinmux = ; /* I2C2_SCL */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ i2c2_pins_sleep_b2: i2c2-1 { -+ pins { -+ pinmux = ; /* I2C2_SCL */ -+ }; -+ }; -+ -+ i2c4_pins_a: i2c4-0 { -+ pins { -+ pinmux = , /* I2C4_SCL */ -+ ; /* I2C4_SDA */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ -+ i2c4_pins_sleep_a: i2c4-1 { -+ pins { -+ pinmux = , /* I2C4_SCL */ -+ ; /* I2C4_SDA */ -+ }; -+ }; -+ -+ spi1_pins_a: spi1-0 { -+ pins1 { -+ pinmux = , /* SPI1_SCK */ -+ ; /* SPI1_MOSI */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ -+ pins2 { -+ pinmux = ; /* SPI1_MISO */ -+ bias-disable; -+ }; -+ }; -+ -+ spi1_sleep_pins_a: spi1-sleep-0 { -+ pins { -+ pinmux = , /* SPI1_SCK */ -+ , /* SPI1_MISO */ -+ ; /* SPI1_MOSI */ -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi -similarity index 57% -rename from arch/arm/boot/dts/stm32mp157c.dtsi -rename to arch/arm/boot/dts/stm32mp151.dtsi -index f98e0370c0bce..f0211917bb680 100644 ---- a/arch/arm/boot/dts/stm32mp157c.dtsi -+++ b/arch/arm/boot/dts/stm32mp151.dtsi -@@ -5,7 +5,10 @@ - */ - #include - #include -+#include - #include -+#include -+ - - / { - #address-cells = <1>; -@@ -19,20 +22,95 @@ - compatible = "arm,cortex-a7"; - device_type = "cpu"; - reg = <0>; -+ clocks = <&scmi0_clk CK_SCMI0_MPU>; -+ clock-names = "cpu"; -+ operating-points-v2 = <&cpu0_opp_table>; -+ nvmem-cells = <&part_number_otp>; -+ nvmem-cell-names = "part_number"; -+ #cooling-cells = <2>; - }; -+ }; - -- cpu1: cpu@1 { -- compatible = "arm,cortex-a7"; -- device_type = "cpu"; -- reg = <1>; -+ cpu0_opp_table: cpu0-opp-table { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ }; -+ -+ arm-pmu { -+ compatible = "arm,cortex-a7-pmu"; -+ interrupts = ; -+ interrupt-affinity = <&cpu0>; -+ interrupt-parent = <&intc>; -+ }; -+ -+ scmi_sram: sram@2ffff000 { -+ compatible = "mmio-sram"; -+ reg = <0x2ffff000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0x2ffff000 0x1000>; -+ -+ scmi0_shm: scmi_shm@0 { -+ reg = <0 0x80>; -+ }; -+ -+ scmi1_shm: scmi_shm@200 { -+ reg = <0x200 0x80>; -+ }; -+ }; -+ -+ scmi0_mbox: mailbox-0 { -+ #mbox-cells = <0>; -+ compatible = "arm,smc-mbox"; -+ arm,func-id = <0x82002000>; -+ }; -+ -+ scmi1_mbox: mailbox-1 { -+ #mbox-cells = <0>; -+ compatible = "arm,smc-mbox"; -+ arm,func-id = <0x82002001>; -+ }; -+ -+ firmware { -+ scmi0: scmi-0 { -+ compatible = "arm,scmi"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mboxes = <&scmi0_mbox 0>; -+ mbox-names = "txrx"; -+ shmem = <&scmi0_shm>; -+ -+ scmi0_clk: protocol@14 { -+ reg = <0x14>; -+ #clock-cells = <1>; -+ }; -+ scmi0_reset: protocol@16 { -+ reg = <0x16>; -+ #reset-cells = <1>; -+ }; -+ }; -+ -+ scmi1: scmi-1 { -+ compatible = "arm,scmi"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ status = "disabled"; -+ mboxes = <&scmi1_mbox 0>; -+ mbox-names = "txrx"; -+ shmem = <&scmi1_shm>; -+ -+ scmi1_clk: protocol@14 { -+ reg = <0x14>; -+ #clock-cells = <1>; -+ }; - }; - }; - - psci { -- compatible = "arm,psci"; -+ compatible = "arm,psci-1.0"; - method = "smc"; -- cpu_off = <0x84000002>; -- cpu_on = <0x84000003>; - }; - - intc: interrupt-controller@a0021000 { -@@ -50,38 +128,7 @@ - , - ; - interrupt-parent = <&intc>; -- }; -- -- clocks { -- clk_hse: clk-hse { -- #clock-cells = <0>; -- compatible = "fixed-clock"; -- clock-frequency = <24000000>; -- }; -- -- clk_hsi: clk-hsi { -- #clock-cells = <0>; -- compatible = "fixed-clock"; -- clock-frequency = <64000000>; -- }; -- -- clk_lse: clk-lse { -- #clock-cells = <0>; -- compatible = "fixed-clock"; -- clock-frequency = <32768>; -- }; -- -- clk_lsi: clk-lsi { -- #clock-cells = <0>; -- compatible = "fixed-clock"; -- clock-frequency = <32000>; -- }; -- -- clk_csi: clk-csi { -- #clock-cells = <0>; -- compatible = "fixed-clock"; -- clock-frequency = <4000000>; -- }; -+ always-on; - }; - - thermal-zones { -@@ -91,12 +138,6 @@ - thermal-sensors = <&dts>; - - trips { -- cpu_alert1: cpu-alert1 { -- temperature = <85000>; -- hysteresis = <0>; -- type = "passive"; -- }; -- - cpu-crit { - temperature = <120000>; - hysteresis = <0>; -@@ -115,6 +156,33 @@ - status = "disabled"; - }; - -+ pm_domain { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32mp157c-pd"; -+ -+ pd_core_ret: core-ret-power-domain@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <1>; -+ #power-domain-cells = <0>; -+ label = "CORE-RETENTION"; -+ -+ pd_core: core-power-domain@2 { -+ reg = <2>; -+ #power-domain-cells = <0>; -+ label = "CORE"; -+ }; -+ }; -+ }; -+ -+ reboot { -+ compatible = "syscon-reboot"; -+ regmap = <&rcc>; -+ offset = <0x404>; -+ mask = <0x1>; -+ }; -+ - soc { - compatible = "simple-bus"; - #address-cells = <1>; -@@ -122,6 +190,14 @@ - interrupt-parent = <&intc>; - ranges; - -+ sram: sram@10000000 { -+ compatible = "mmio-sram"; -+ reg = <0x10000000 0x60000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0x10000000 0x60000>; -+ }; -+ - timers2: timer@40000000 { - #address-cells = <1>; - #size-cells = <0>; -@@ -129,11 +205,11 @@ - reg = <0x40000000 0x400>; - clocks = <&rcc TIM2_K>; - clock-names = "int"; -- dmas = <&dmamux1 18 0x400 0x1>, -- <&dmamux1 19 0x400 0x1>, -- <&dmamux1 20 0x400 0x1>, -- <&dmamux1 21 0x400 0x1>, -- <&dmamux1 22 0x400 0x1>; -+ dmas = <&dmamux1 18 0x400 0x80000001>, -+ <&dmamux1 19 0x400 0x80000001>, -+ <&dmamux1 20 0x400 0x80000001>, -+ <&dmamux1 21 0x400 0x80000001>, -+ <&dmamux1 22 0x400 0x80000001>; - dma-names = "ch1", "ch2", "ch3", "ch4", "up"; - status = "disabled"; - -@@ -148,6 +224,11 @@ - reg = <1>; - status = "disabled"; - }; -+ -+ counter { -+ compatible = "st,stm32-timer-counter"; -+ status = "disabled"; -+ }; - }; - - timers3: timer@40001000 { -@@ -157,12 +238,12 @@ - reg = <0x40001000 0x400>; - clocks = <&rcc TIM3_K>; - clock-names = "int"; -- dmas = <&dmamux1 23 0x400 0x1>, -- <&dmamux1 24 0x400 0x1>, -- <&dmamux1 25 0x400 0x1>, -- <&dmamux1 26 0x400 0x1>, -- <&dmamux1 27 0x400 0x1>, -- <&dmamux1 28 0x400 0x1>; -+ dmas = <&dmamux1 23 0x400 0x80000001>, -+ <&dmamux1 24 0x400 0x80000001>, -+ <&dmamux1 25 0x400 0x80000001>, -+ <&dmamux1 26 0x400 0x80000001>, -+ <&dmamux1 27 0x400 0x80000001>, -+ <&dmamux1 28 0x400 0x80000001>; - dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; - status = "disabled"; - -@@ -177,6 +258,11 @@ - reg = <2>; - status = "disabled"; - }; -+ -+ counter { -+ compatible = "st,stm32-timer-counter"; -+ status = "disabled"; -+ }; - }; - - timers4: timer@40002000 { -@@ -186,10 +272,10 @@ - reg = <0x40002000 0x400>; - clocks = <&rcc TIM4_K>; - clock-names = "int"; -- dmas = <&dmamux1 29 0x400 0x1>, -- <&dmamux1 30 0x400 0x1>, -- <&dmamux1 31 0x400 0x1>, -- <&dmamux1 32 0x400 0x1>; -+ dmas = <&dmamux1 29 0x400 0x80000001>, -+ <&dmamux1 30 0x400 0x80000001>, -+ <&dmamux1 31 0x400 0x80000001>, -+ <&dmamux1 32 0x400 0x80000001>; - dma-names = "ch1", "ch2", "ch3", "ch4"; - status = "disabled"; - -@@ -204,6 +290,11 @@ - reg = <3>; - status = "disabled"; - }; -+ -+ counter { -+ compatible = "st,stm32-timer-counter"; -+ status = "disabled"; -+ }; - }; - - timers5: timer@40003000 { -@@ -213,12 +304,12 @@ - reg = <0x40003000 0x400>; - clocks = <&rcc TIM5_K>; - clock-names = "int"; -- dmas = <&dmamux1 55 0x400 0x1>, -- <&dmamux1 56 0x400 0x1>, -- <&dmamux1 57 0x400 0x1>, -- <&dmamux1 58 0x400 0x1>, -- <&dmamux1 59 0x400 0x1>, -- <&dmamux1 60 0x400 0x1>; -+ dmas = <&dmamux1 55 0x400 0x80000001>, -+ <&dmamux1 56 0x400 0x80000001>, -+ <&dmamux1 57 0x400 0x80000001>, -+ <&dmamux1 58 0x400 0x80000001>, -+ <&dmamux1 59 0x400 0x80000001>, -+ <&dmamux1 60 0x400 0x80000001>; - dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; - status = "disabled"; - -@@ -233,6 +324,11 @@ - reg = <4>; - status = "disabled"; - }; -+ -+ counter { -+ compatible = "st,stm32-timer-counter"; -+ status = "disabled"; -+ }; - }; - - timers6: timer@40004000 { -@@ -242,7 +338,7 @@ - reg = <0x40004000 0x400>; - clocks = <&rcc TIM6_K>; - clock-names = "int"; -- dmas = <&dmamux1 69 0x400 0x1>; -+ dmas = <&dmamux1 69 0x400 0x80000001>; - dma-names = "up"; - status = "disabled"; - -@@ -260,7 +356,7 @@ - reg = <0x40005000 0x400>; - clocks = <&rcc TIM7_K>; - clock-names = "int"; -- dmas = <&dmamux1 70 0x400 0x1>; -+ dmas = <&dmamux1 70 0x400 0x80000001>; - dma-names = "up"; - status = "disabled"; - -@@ -342,8 +438,11 @@ - #size-cells = <0>; - compatible = "st,stm32-lptimer"; - reg = <0x40009000 0x400>; -+ interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc LPTIM1_K>; - clock-names = "mux"; -+ power-domains = <&pd_core>; -+ wakeup-source; - status = "disabled"; - - pwm { -@@ -372,9 +471,10 @@ - interrupts = ; - clocks = <&rcc SPI2_K>; - resets = <&rcc SPI2_R>; -- dmas = <&dmamux1 39 0x400 0x05>, -- <&dmamux1 40 0x400 0x05>; -+ dmas = <&dmamux1 39 0x400 0x01>, -+ <&dmamux1 40 0x400 0x01>; - dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -397,9 +497,10 @@ - interrupts = ; - clocks = <&rcc SPI3_K>; - resets = <&rcc SPI3_R>; -- dmas = <&dmamux1 61 0x400 0x05>, -- <&dmamux1 62 0x400 0x05>; -+ dmas = <&dmamux1 61 0x400 0x01>, -+ <&dmamux1 62 0x400 0x01>; - dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -430,84 +531,128 @@ - usart2: serial@4000e000 { - compatible = "st,stm32h7-uart"; - reg = <0x4000e000 0x400>; -- interrupts = ; -+ interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc USART2_K>; -+ wakeup-source; -+ power-domains = <&pd_core>; -+ dmas = <&dmamux1 43 0x400 0x5>, -+ <&dmamux1 44 0x400 0x1>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - - usart3: serial@4000f000 { - compatible = "st,stm32h7-uart"; - reg = <0x4000f000 0x400>; -- interrupts = ; -+ interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc USART3_K>; -+ wakeup-source; -+ power-domains = <&pd_core>; -+ dmas = <&dmamux1 45 0x400 0x5>, -+ <&dmamux1 46 0x400 0x1>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - - uart4: serial@40010000 { - compatible = "st,stm32h7-uart"; - reg = <0x40010000 0x400>; -- interrupts = ; -+ interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc UART4_K>; -+ wakeup-source; -+ power-domains = <&pd_core>; -+ dmas = <&dmamux1 63 0x400 0x5>, -+ <&dmamux1 64 0x400 0x1>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - - uart5: serial@40011000 { - compatible = "st,stm32h7-uart"; - reg = <0x40011000 0x400>; -- interrupts = ; -+ interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc UART5_K>; -+ wakeup-source; -+ power-domains = <&pd_core>; -+ dmas = <&dmamux1 65 0x400 0x5>, -+ <&dmamux1 66 0x400 0x1>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - - i2c1: i2c@40012000 { -- compatible = "st,stm32f7-i2c"; -+ compatible = "st,stm32mp15-i2c"; - reg = <0x40012000 0x400>; - interrupt-names = "event", "error"; -- interrupts = , -- ; -+ interrupts-extended = <&exti 21 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc I2C1_K>; - resets = <&rcc I2C1_R>; - #address-cells = <1>; - #size-cells = <0>; -+ dmas = <&dmamux1 33 0x400 0x80000001>, -+ <&dmamux1 34 0x400 0x80000001>; -+ dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; -+ st,syscfg-fmp = <&syscfg 0x4 0x1>; -+ wakeup-source; - status = "disabled"; - }; - - i2c2: i2c@40013000 { -- compatible = "st,stm32f7-i2c"; -+ compatible = "st,stm32mp15-i2c"; - reg = <0x40013000 0x400>; - interrupt-names = "event", "error"; -- interrupts = , -- ; -+ interrupts-extended = <&exti 22 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc I2C2_K>; - resets = <&rcc I2C2_R>; - #address-cells = <1>; - #size-cells = <0>; -+ dmas = <&dmamux1 35 0x400 0x80000001>, -+ <&dmamux1 36 0x400 0x80000001>; -+ dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; -+ st,syscfg-fmp = <&syscfg 0x4 0x2>; -+ wakeup-source; - status = "disabled"; - }; - - i2c3: i2c@40014000 { -- compatible = "st,stm32f7-i2c"; -+ compatible = "st,stm32mp15-i2c"; - reg = <0x40014000 0x400>; - interrupt-names = "event", "error"; -- interrupts = , -- ; -+ interrupts-extended = <&exti 23 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc I2C3_K>; - resets = <&rcc I2C3_R>; - #address-cells = <1>; - #size-cells = <0>; -+ dmas = <&dmamux1 73 0x400 0x80000001>, -+ <&dmamux1 74 0x400 0x80000001>; -+ dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; -+ st,syscfg-fmp = <&syscfg 0x4 0x4>; -+ wakeup-source; - status = "disabled"; - }; - - i2c5: i2c@40015000 { -- compatible = "st,stm32f7-i2c"; -+ compatible = "st,stm32mp15-i2c"; - reg = <0x40015000 0x400>; - interrupt-names = "event", "error"; -- interrupts = , -- ; -+ interrupts-extended = <&exti 25 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc I2C5_K>; - resets = <&rcc I2C5_R>; - #address-cells = <1>; - #size-cells = <0>; -+ dmas = <&dmamux1 115 0x400 0x80000001>, -+ <&dmamux1 116 0x400 0x80000001>; -+ dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; -+ st,syscfg-fmp = <&syscfg 0x4 0x10>; -+ wakeup-source; - status = "disabled"; - }; - -@@ -515,7 +660,7 @@ - compatible = "st,stm32-cec"; - reg = <0x40016000 0x400>; - interrupts = ; -- clocks = <&rcc CEC_K>, <&clk_lse>; -+ clocks = <&rcc CEC_K>, <&scmi0_clk CK_SCMI0_LSE>; - clock-names = "cec", "hdmi-cec"; - status = "disabled"; - }; -@@ -531,14 +676,14 @@ - - dac1: dac@1 { - compatible = "st,stm32-dac"; -- #io-channels-cells = <1>; -+ #io-channel-cells = <1>; - reg = <1>; - status = "disabled"; - }; - - dac2: dac@2 { - compatible = "st,stm32-dac"; -- #io-channels-cells = <1>; -+ #io-channel-cells = <1>; - reg = <2>; - status = "disabled"; - }; -@@ -547,16 +692,26 @@ - uart7: serial@40018000 { - compatible = "st,stm32h7-uart"; - reg = <0x40018000 0x400>; -- interrupts = ; -+ interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc UART7_K>; -+ wakeup-source; -+ power-domains = <&pd_core>; -+ dmas = <&dmamux1 79 0x400 0x5>, -+ <&dmamux1 80 0x400 0x1>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - - uart8: serial@40019000 { - compatible = "st,stm32h7-uart"; - reg = <0x40019000 0x400>; -- interrupts = ; -+ interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc UART8_K>; -+ wakeup-source; -+ power-domains = <&pd_core>; -+ dmas = <&dmamux1 81 0x400 0x5>, -+ <&dmamux1 82 0x400 0x1>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - -@@ -567,13 +722,13 @@ - reg = <0x44000000 0x400>; - clocks = <&rcc TIM1_K>; - clock-names = "int"; -- dmas = <&dmamux1 11 0x400 0x1>, -- <&dmamux1 12 0x400 0x1>, -- <&dmamux1 13 0x400 0x1>, -- <&dmamux1 14 0x400 0x1>, -- <&dmamux1 15 0x400 0x1>, -- <&dmamux1 16 0x400 0x1>, -- <&dmamux1 17 0x400 0x1>; -+ dmas = <&dmamux1 11 0x400 0x80000001>, -+ <&dmamux1 12 0x400 0x80000001>, -+ <&dmamux1 13 0x400 0x80000001>, -+ <&dmamux1 14 0x400 0x80000001>, -+ <&dmamux1 15 0x400 0x80000001>, -+ <&dmamux1 16 0x400 0x80000001>, -+ <&dmamux1 17 0x400 0x80000001>; - dma-names = "ch1", "ch2", "ch3", "ch4", - "up", "trig", "com"; - status = "disabled"; -@@ -589,6 +744,11 @@ - reg = <0>; - status = "disabled"; - }; -+ -+ counter { -+ compatible = "st,stm32-timer-counter"; -+ status = "disabled"; -+ }; - }; - - timers8: timer@44001000 { -@@ -598,13 +758,13 @@ - reg = <0x44001000 0x400>; - clocks = <&rcc TIM8_K>; - clock-names = "int"; -- dmas = <&dmamux1 47 0x400 0x1>, -- <&dmamux1 48 0x400 0x1>, -- <&dmamux1 49 0x400 0x1>, -- <&dmamux1 50 0x400 0x1>, -- <&dmamux1 51 0x400 0x1>, -- <&dmamux1 52 0x400 0x1>, -- <&dmamux1 53 0x400 0x1>; -+ dmas = <&dmamux1 47 0x400 0x80000001>, -+ <&dmamux1 48 0x400 0x80000001>, -+ <&dmamux1 49 0x400 0x80000001>, -+ <&dmamux1 50 0x400 0x80000001>, -+ <&dmamux1 51 0x400 0x80000001>, -+ <&dmamux1 52 0x400 0x80000001>, -+ <&dmamux1 53 0x400 0x80000001>; - dma-names = "ch1", "ch2", "ch3", "ch4", - "up", "trig", "com"; - status = "disabled"; -@@ -620,13 +780,23 @@ - reg = <7>; - status = "disabled"; - }; -+ -+ counter { -+ compatible = "st,stm32-timer-counter"; -+ status = "disabled"; -+ }; - }; - - usart6: serial@44003000 { - compatible = "st,stm32h7-uart"; - reg = <0x44003000 0x400>; -- interrupts = ; -+ interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc USART6_K>; -+ wakeup-source; -+ power-domains = <&pd_core>; -+ dmas = <&dmamux1 71 0x400 0x5>, -+ <&dmamux1 72 0x400 0x1>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - -@@ -638,9 +808,10 @@ - interrupts = ; - clocks = <&rcc SPI1_K>; - resets = <&rcc SPI1_R>; -- dmas = <&dmamux1 37 0x400 0x05>, -- <&dmamux1 38 0x400 0x05>; -+ dmas = <&dmamux1 37 0x400 0x01>, -+ <&dmamux1 38 0x400 0x01>; - dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -663,9 +834,10 @@ - interrupts = ; - clocks = <&rcc SPI4_K>; - resets = <&rcc SPI4_R>; -- dmas = <&dmamux1 83 0x400 0x05>, -- <&dmamux1 84 0x400 0x05>; -+ dmas = <&dmamux1 83 0x400 0x01>, -+ <&dmamux1 84 0x400 0x01>; - dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -676,10 +848,10 @@ - reg = <0x44006000 0x400>; - clocks = <&rcc TIM15_K>; - clock-names = "int"; -- dmas = <&dmamux1 105 0x400 0x1>, -- <&dmamux1 106 0x400 0x1>, -- <&dmamux1 107 0x400 0x1>, -- <&dmamux1 108 0x400 0x1>; -+ dmas = <&dmamux1 105 0x400 0x80000001>, -+ <&dmamux1 106 0x400 0x80000001>, -+ <&dmamux1 107 0x400 0x80000001>, -+ <&dmamux1 108 0x400 0x80000001>; - dma-names = "ch1", "up", "trig", "com"; - status = "disabled"; - -@@ -703,8 +875,8 @@ - reg = <0x44007000 0x400>; - clocks = <&rcc TIM16_K>; - clock-names = "int"; -- dmas = <&dmamux1 109 0x400 0x1>, -- <&dmamux1 110 0x400 0x1>; -+ dmas = <&dmamux1 109 0x400 0x80000001>, -+ <&dmamux1 110 0x400 0x80000001>; - dma-names = "ch1", "up"; - status = "disabled"; - -@@ -727,8 +899,8 @@ - reg = <0x44008000 0x400>; - clocks = <&rcc TIM17_K>; - clock-names = "int"; -- dmas = <&dmamux1 111 0x400 0x1>, -- <&dmamux1 112 0x400 0x1>; -+ dmas = <&dmamux1 111 0x400 0x80000001>, -+ <&dmamux1 112 0x400 0x80000001>; - dma-names = "ch1", "up"; - status = "disabled"; - -@@ -753,9 +925,10 @@ - interrupts = ; - clocks = <&rcc SPI5_K>; - resets = <&rcc SPI5_R>; -- dmas = <&dmamux1 85 0x400 0x05>, -- <&dmamux1 86 0x400 0x05>; -+ dmas = <&dmamux1 85 0x400 0x01>, -+ <&dmamux1 86 0x400 0x01>; - dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -923,32 +1096,6 @@ - }; - }; - -- m_can1: can@4400e000 { -- compatible = "bosch,m_can"; -- reg = <0x4400e000 0x400>, <0x44011000 0x1400>; -- reg-names = "m_can", "message_ram"; -- interrupts = , -- ; -- interrupt-names = "int0", "int1"; -- clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; -- clock-names = "hclk", "cclk"; -- bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; -- status = "disabled"; -- }; -- -- m_can2: can@4400f000 { -- compatible = "bosch,m_can"; -- reg = <0x4400f000 0x400>, <0x44011000 0x2800>; -- reg-names = "m_can", "message_ram"; -- interrupts = , -- ; -- interrupt-names = "int0", "int1"; -- clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; -- clock-names = "hclk", "cclk"; -- bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; -- status = "disabled"; -- }; -- - dma1: dma@48000000 { - compatible = "st,stm32-dma"; - reg = <0x48000000 0x400>; -@@ -961,9 +1108,19 @@ - , - ; - clocks = <&rcc DMA1>; -+ resets = <&rcc DMA1_R>; - #dma-cells = <4>; - st,mem2mem; - dma-requests = <8>; -+ dmas = <&mdma1 0 0x3 0x1200000a 0x48000008 0x00000020 1>, -+ <&mdma1 1 0x3 0x1200000a 0x48000008 0x00000800 1>, -+ <&mdma1 2 0x3 0x1200000a 0x48000008 0x00200000 1>, -+ <&mdma1 3 0x3 0x1200000a 0x48000008 0x08000000 1>, -+ <&mdma1 4 0x3 0x1200000a 0x4800000C 0x00000020 1>, -+ <&mdma1 5 0x3 0x1200000a 0x4800000C 0x00000800 1>, -+ <&mdma1 6 0x3 0x1200000a 0x4800000C 0x00200000 1>, -+ <&mdma1 7 0x3 0x1200000a 0x4800000C 0x08000000 1>; -+ dma-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6", "ch7"; - }; - - dma2: dma@48001000 { -@@ -978,19 +1135,30 @@ - , - ; - clocks = <&rcc DMA2>; -+ resets = <&rcc DMA2_R>; - #dma-cells = <4>; - st,mem2mem; - dma-requests = <8>; -+ dmas = <&mdma1 8 0x3 0x1200000a 0x48001008 0x00000020 1>, -+ <&mdma1 9 0x3 0x1200000a 0x48001008 0x00000800 1>, -+ <&mdma1 10 0x3 0x1200000a 0x48001008 0x00200000 1>, -+ <&mdma1 11 0x3 0x1200000a 0x48001008 0x08000000 1>, -+ <&mdma1 12 0x3 0x1200000a 0x4800100C 0x00000020 1>, -+ <&mdma1 13 0x3 0x1200000a 0x4800100C 0x00000800 1>, -+ <&mdma1 14 0x3 0x1200000a 0x4800100C 0x00200000 1>, -+ <&mdma1 15 0x3 0x1200000a 0x4800100C 0x08000000 1>; -+ dma-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6", "ch7"; - }; - - dmamux1: dma-router@48002000 { - compatible = "st,stm32h7-dmamux"; -- reg = <0x48002000 0x1c>; -+ reg = <0x48002000 0x40>; - #dma-cells = <3>; - dma-requests = <128>; - dma-masters = <&dma1 &dma2>; - dma-channels = <16>; - clocks = <&rcc DMAMUX>; -+ resets = <&rcc DMAMUX_R>; - }; - - adc: adc@48003000 { -@@ -1013,7 +1181,7 @@ - reg = <0x0>; - interrupt-parent = <&adc>; - interrupts = <0>; -- dmas = <&dmamux1 9 0x400 0x01>; -+ dmas = <&dmamux1 9 0x400 0x80000001>; - dma-names = "rx"; - status = "disabled"; - }; -@@ -1024,39 +1192,65 @@ - reg = <0x100>; - interrupt-parent = <&adc>; - interrupts = <1>; -- dmas = <&dmamux1 10 0x400 0x01>; -+ dmas = <&dmamux1 10 0x400 0x80000001>; - dma-names = "rx"; - status = "disabled"; - }; - }; - -+ sdmmc3: sdmmc@48004000 { -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; -+ reg = <0x48004000 0x400>, <0x48005000 0x400>; -+ interrupts = ; -+ interrupt-names = "cmd_irq"; -+ clocks = <&rcc SDMMC3_K>; -+ clock-names = "apb_pclk"; -+ resets = <&rcc SDMMC3_R>; -+ cap-sd-highspeed; -+ cap-mmc-highspeed; -+ max-frequency = <120000000>; -+ status = "disabled"; -+ }; -+ - usbotg_hs: usb-otg@49000000 { -- compatible = "snps,dwc2"; -+ compatible = "st,stm32mp1-hsotg", "snps,dwc2"; - reg = <0x49000000 0x10000>; - clocks = <&rcc USBO_K>; - clock-names = "otg"; - resets = <&rcc USBO_R>; - reset-names = "dwc2"; -- interrupts = ; -- g-rx-fifo-size = <256>; -+ interrupts-extended = <&exti 44 IRQ_TYPE_LEVEL_HIGH>; -+ g-rx-fifo-size = <512>; - g-np-tx-fifo-size = <32>; -- g-tx-fifo-size = <128 128 64 64 64 64 32 32>; -+ g-tx-fifo-size = <256 16 16 16 16 16 16 16>; - dr_mode = "otg"; -+ usb33d-supply = <&usb33>; -+ power-domains = <&pd_core>; -+ wakeup-source; - status = "disabled"; - }; - -+ hsem: hwspinlock@4c000000 { -+ compatible = "st,stm32-hwspinlock"; -+ #hwlock-cells = <2>; -+ reg = <0x4c000000 0x400>; -+ clocks = <&rcc HSEM>; -+ clock-names = "hsem"; -+ }; -+ - ipcc: mailbox@4c001000 { - compatible = "st,stm32mp1-ipcc"; - #mbox-cells = <1>; - reg = <0x4c001000 0x400>; - st,proc-id = <0>; - interrupts-extended = -- <&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, -- <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, -- <&exti 61 1>; -- interrupt-names = "rx", "tx", "wakeup"; -+ <&exti 61 1>, -+ <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; -+ interrupt-names = "rx", "tx"; - clocks = <&rcc IPCC>; - wakeup-source; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -1067,16 +1261,68 @@ - resets = <&rcc CAMITF_R>; - clocks = <&rcc DCMI>; - clock-names = "mclk"; -- dmas = <&dmamux1 75 0x400 0x0d>; -+ dmas = <&dmamux1 75 0x400 0xe0000001>; - dma-names = "tx"; - status = "disabled"; - }; - - rcc: rcc@50000000 { -- compatible = "st,stm32mp1-rcc", "syscon"; -+ compatible = "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", "syscon"; - reg = <0x50000000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; -+ interrupts = ; -+ -+ clock-names = "hse", "hsi", "csi", "lse", "lsi"; -+ clocks = <&scmi0_clk CK_SCMI0_HSE>, -+ <&scmi0_clk CK_SCMI0_HSI>, -+ <&scmi0_clk CK_SCMI0_CSI>, -+ <&scmi0_clk CK_SCMI0_LSE>, -+ <&scmi0_clk CK_SCMI0_LSI>; -+ }; -+ -+ pwr_regulators: pwr@50001000 { -+ compatible = "st,stm32mp1,pwr-reg"; -+ reg = <0x50001000 0x10>; -+ st,tzcr = <&rcc 0x0 0x1>; -+ -+ reg11: reg11 { -+ regulator-name = "reg11"; -+ regulator-min-microvolt = <1100000>; -+ regulator-max-microvolt = <1100000>; -+ }; -+ -+ reg18: reg18 { -+ regulator-name = "reg18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ -+ usb33: usb33 { -+ regulator-name = "usb33"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ }; -+ -+ pwr_mcu: pwr_mcu@50001014 { -+ compatible = "syscon"; -+ reg = <0x50001014 0x4>; -+ }; -+ -+ pwr_irq: pwr@50001020 { -+ compatible = "st,stm32mp1-pwr"; -+ reg = <0x50001020 0x100>; -+ interrupts = ; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ -+ wakeup-gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>, -+ <&gpioa 2 GPIO_ACTIVE_HIGH>, -+ <&gpioc 13 GPIO_ACTIVE_HIGH>, -+ <&gpioi 8 GPIO_ACTIVE_HIGH>, -+ <&gpioi 11 GPIO_ACTIVE_HIGH>, -+ <&gpioc 1 GPIO_ACTIVE_HIGH>; - }; - - exti: interrupt-controller@5000d000 { -@@ -1084,6 +1330,18 @@ - interrupt-controller; - #interrupt-cells = <2>; - reg = <0x5000d000 0x400>; -+ hwlocks = <&hsem 1 1>; -+ -+ /* exti_pwr is an extra interrupt controller used for -+ * EXTI 55 to 60. It's mapped on pwr interrupt -+ * controller. -+ */ -+ exti_pwr: exti-pwr { -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupt-parent = <&pwr_irq>; -+ st,irq-number = <6>; -+ }; - }; - - syscfg: syscon@50020000 { -@@ -1097,8 +1355,11 @@ - #size-cells = <0>; - compatible = "st,stm32-lptimer"; - reg = <0x50021000 0x400>; -+ interrupts-extended = <&exti 48 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc LPTIM2_K>; - clock-names = "mux"; -+ power-domains = <&pd_core>; -+ wakeup-source; - status = "disabled"; - - pwm { -@@ -1124,8 +1385,11 @@ - #size-cells = <0>; - compatible = "st,stm32-lptimer"; - reg = <0x50022000 0x400>; -+ interrupts-extended = <&exti 50 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc LPTIM3_K>; - clock-names = "mux"; -+ power-domains = <&pd_core>; -+ wakeup-source; - status = "disabled"; - - pwm { -@@ -1144,8 +1408,11 @@ - lptimer4: timer@50023000 { - compatible = "st,stm32-lptimer"; - reg = <0x50023000 0x400>; -+ interrupts-extended = <&exti 52 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc LPTIM4_K>; - clock-names = "mux"; -+ power-domains = <&pd_core>; -+ wakeup-source; - status = "disabled"; - - pwm { -@@ -1158,8 +1425,11 @@ - lptimer5: timer@50024000 { - compatible = "st,stm32-lptimer"; - reg = <0x50024000 0x400>; -+ interrupts-extended = <&exti 53 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc LPTIM5_K>; - clock-names = "mux"; -+ power-domains = <&pd_core>; -+ wakeup-source; - status = "disabled"; - - pwm { -@@ -1219,12 +1489,11 @@ - status = "disabled"; - }; - -- cryp1: cryp@54001000 { -- compatible = "st,stm32mp1-cryp"; -- reg = <0x54001000 0x400>; -- interrupts = ; -- clocks = <&rcc CRYP1>; -- resets = <&rcc CRYP1_R>; -+ hdp: hdp@5002a000 { -+ compatible = "st,stm32mp1-hdp"; -+ reg = <0x5002a000 0x400>; -+ clocks = <&rcc HDP>; -+ clock-names = "hdp"; - status = "disabled"; - }; - -@@ -1232,9 +1501,9 @@ - compatible = "st,stm32f756-hash"; - reg = <0x54002000 0x400>; - interrupts = ; -- clocks = <&rcc HASH1>; -- resets = <&rcc HASH1_R>; -- dmas = <&mdma1 31 0x10 0x1000A02 0x0 0x0>; -+ clocks = <&scmi0_clk CK_SCMI0_HASH1>; -+ resets = <&scmi0_reset RST_SCMI0_HASH1>; -+ dmas = <&mdma1 31 0x2 0x1000A02 0x0 0x0 0x0>; - dma-names = "in"; - dma-maxburst = <2>; - status = "disabled"; -@@ -1243,8 +1512,8 @@ - rng1: rng@54003000 { - compatible = "st,stm32-rng"; - reg = <0x54003000 0x400>; -- clocks = <&rcc RNG1_K>; -- resets = <&rcc RNG1_R>; -+ clocks = <&scmi0_clk CK_SCMI0_RNG1>; -+ resets = <&scmi0_reset RST_SCMI0_RNG1>; - status = "disabled"; - }; - -@@ -1253,28 +1522,44 @@ - reg = <0x58000000 0x1000>; - interrupts = ; - clocks = <&rcc MDMA>; -- #dma-cells = <5>; -+ resets = <&scmi0_reset RST_SCMI0_MDMA>; -+ #dma-cells = <6>; - dma-channels = <32>; - dma-requests = <48>; - }; - -- fmc: nand-controller@58002000 { -- compatible = "st,stm32mp15-fmc2"; -- reg = <0x58002000 0x1000>, -- <0x80000000 0x1000>, -- <0x88010000 0x1000>, -- <0x88020000 0x1000>, -- <0x81000000 0x1000>, -- <0x89010000 0x1000>, -- <0x89020000 0x1000>; -- interrupts = ; -- dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>, -- <&mdma1 20 0x10 0x12000a08 0x0 0x0>, -- <&mdma1 21 0x10 0x12000a0a 0x0 0x0>; -- dma-names = "tx", "rx", "ecc"; -+ fmc: memory-controller@58002000 { -+ #address-cells = <2>; -+ #size-cells = <1>; -+ compatible = "st,stm32mp1-fmc2-ebi"; -+ reg = <0x58002000 0x1000>; - clocks = <&rcc FMC_K>; - resets = <&rcc FMC_R>; - status = "disabled"; -+ -+ ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ -+ <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ -+ <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ -+ <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ -+ <4 0 0x80000000 0x10000000>; /* NAND */ -+ -+ nand-controller@4,0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32mp1-fmc2-nfc"; -+ reg = <4 0x00000000 0x1000>, -+ <4 0x08010000 0x1000>, -+ <4 0x08020000 0x1000>, -+ <4 0x01000000 0x1000>, -+ <4 0x09010000 0x1000>, -+ <4 0x09020000 0x1000>; -+ interrupts = ; -+ dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0 0x0>, -+ <&mdma1 20 0x2 0x12000a08 0x0 0x0 0x0>, -+ <&mdma1 21 0x2 0x12000a0a 0x0 0x0 0x0>; -+ dma-names = "tx", "rx", "ecc"; -+ status = "disabled"; -+ }; - }; - - qspi: spi@58003000 { -@@ -1282,8 +1567,8 @@ - reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; - reg-names = "qspi", "qspi_mm"; - interrupts = ; -- dmas = <&mdma1 22 0x10 0x100002 0x0 0x0>, -- <&mdma1 22 0x10 0x100008 0x0 0x0>; -+ dmas = <&mdma1 22 0x2 0x100002 0x0 0x0 0x0>, -+ <&mdma1 22 0x2 0x100008 0x0 0x0 0x0>; - dma-names = "tx", "rx"; - clocks = <&rcc QSPI_K>; - resets = <&rcc QSPI_R>; -@@ -1292,16 +1577,32 @@ - - sdmmc1: sdmmc@58005000 { - compatible = "arm,pl18x", "arm,primecell"; -- arm,primecell-periphid = <0x10153180>; -- reg = <0x58005000 0x1000>; -+ arm,primecell-periphid = <0x00253180>; -+ reg = <0x58005000 0x1000>, <0x58006000 0x1000>; - interrupts = ; -- interrupt-names = "cmd_irq"; -+ interrupt-names = "cmd_irq"; - clocks = <&rcc SDMMC1_K>; - clock-names = "apb_pclk"; - resets = <&rcc SDMMC1_R>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <120000000>; -+ status = "disabled"; -+ }; -+ -+ sdmmc2: sdmmc@58007000 { -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; -+ reg = <0x58007000 0x1000>, <0x58008000 0x1000>; -+ interrupts = ; -+ interrupt-names = "cmd_irq"; -+ clocks = <&rcc SDMMC2_K>; -+ clock-names = "apb_pclk"; -+ resets = <&rcc SDMMC2_R>; -+ cap-sd-highspeed; -+ cap-mmc-highspeed; -+ max-frequency = <120000000>; -+ status = "disabled"; - }; - - crc1: crc@58009000 { -@@ -1321,23 +1622,25 @@ - compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; - reg = <0x5800a000 0x2000>; - reg-names = "stmmaceth"; -- interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; -- interrupt-names = "macirq"; -+ interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 70 IRQ_TYPE_LEVEL_HIGH>; -+ interrupt-names = "macirq", -+ "eth_wake_irq"; - clock-names = "stmmaceth", - "mac-clk-tx", - "mac-clk-rx", -- "ethstp", -- "syscfg-clk"; -+ "ethstp"; - clocks = <&rcc ETHMAC>, - <&rcc ETHTX>, - <&rcc ETHRX>, -- <&rcc ETHSTP>, -- <&rcc SYSCFG>; -+ <&rcc ETHSTP>; - st,syscon = <&syscfg 0x4>; - snps,mixed-burst; - snps,pbl = <2>; -+ snps,en-tx-lpi-clockgating; - snps,axi-config = <&stmmac_axi_config_0>; - snps,tso; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -1355,28 +1658,10 @@ - reg = <0x5800d000 0x1000>; - clocks = <&rcc USBH>; - resets = <&rcc USBH_R>; -- interrupts = ; -+ interrupts-extended = <&exti 43 IRQ_TYPE_LEVEL_HIGH>; - companion = <&usbh_ohci>; -- status = "disabled"; -- }; -- -- gpu: gpu@59000000 { -- compatible = "vivante,gc"; -- reg = <0x59000000 0x800>; -- interrupts = ; -- clocks = <&rcc GPU>, <&rcc GPU_K>; -- clock-names = "bus" ,"core"; -- resets = <&rcc GPU_R>; -- status = "disabled"; -- }; -- -- dsi: dsi@5a000000 { -- compatible = "st,stm32-dsi"; -- reg = <0x5a000000 0x800>; -- clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>; -- clock-names = "pclk", "ref", "px_clk"; -- resets = <&rcc DSI_R>; -- reset-names = "apb"; -+ power-domains = <&pd_core>; -+ wakeup-source; - status = "disabled"; - }; - -@@ -1394,7 +1679,7 @@ - iwdg2: watchdog@5a002000 { - compatible = "st,stm32mp1-iwdg"; - reg = <0x5a002000 0x400>; -- clocks = <&rcc IWDG2>, <&rcc CK_LSI>; -+ clocks = <&rcc IWDG2>, <&scmi0_clk CK_SCMI0_LSI>; - clock-names = "pclk", "lsi"; - status = "disabled"; - }; -@@ -1402,10 +1687,13 @@ - usbphyc: usbphyc@5a006000 { - #address-cells = <1>; - #size-cells = <0>; -+ #clock-cells = <0>; - compatible = "st,stm32mp1-usbphyc"; - reg = <0x5a006000 0x1000>; - clocks = <&rcc USBPHY_K>; - resets = <&rcc USBPHY_R>; -+ vdda1v1-supply = <®11>; -+ vdda1v8-supply = <®18>; - status = "disabled"; - - usbphyc_port0: usb-phy@0 { -@@ -1419,11 +1707,21 @@ - }; - }; - -+ ddrperfm: perf@5a007000 { -+ compatible = "st,stm32-ddr-pmu"; -+ reg = <0x5a007000 0x400>; -+ clocks = <&rcc DDRPERFM>, <&scmi0_clk CK_SCMI0_PLL2_R>; -+ clock-names = "bus", "ddr"; -+ resets = <&rcc DDRPERFM_R>; -+ }; -+ - usart1: serial@5c000000 { - compatible = "st,stm32h7-uart"; - reg = <0x5c000000 0x400>; -- interrupts = ; -- clocks = <&rcc USART1_K>; -+ interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&scmi0_clk CK_SCMI0_USART1>; -+ wakeup-source; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - -@@ -1433,33 +1731,41 @@ - compatible = "st,stm32h7-spi"; - reg = <0x5c001000 0x400>; - interrupts = ; -- clocks = <&rcc SPI6_K>; -- resets = <&rcc SPI6_R>; -- dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>, -- <&mdma1 35 0x0 0x40002 0x0 0x0>; -+ clocks = <&scmi0_clk CK_SCMI0_SPI6>; -+ resets = <&scmi0_reset RST_SCMI0_SPI6>; -+ dmas = <&mdma1 34 0x0 0x40008 0x0 0x0 0x0>, -+ <&mdma1 35 0x0 0x40002 0x0 0x0 0x0>; - dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; - status = "disabled"; - }; - - i2c4: i2c@5c002000 { -- compatible = "st,stm32f7-i2c"; -+ compatible = "st,stm32mp15-i2c"; - reg = <0x5c002000 0x400>; - interrupt-names = "event", "error"; -- interrupts = , -- ; -- clocks = <&rcc I2C4_K>; -- resets = <&rcc I2C4_R>; -+ interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&scmi0_clk CK_SCMI0_I2C4>; -+ resets = <&scmi0_reset RST_SCMI0_I2C4>; - #address-cells = <1>; - #size-cells = <0>; -+ dmas = <&mdma1 36 0x0 0x40008 0x0 0x0 0>, -+ <&mdma1 37 0x0 0x40002 0x0 0x0 0>; -+ dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; -+ st,syscfg-fmp = <&syscfg 0x4 0x8>; -+ wakeup-source; - status = "disabled"; - }; - - rtc: rtc@5c004000 { - compatible = "st,stm32mp1-rtc"; - reg = <0x5c004000 0x400>; -- clocks = <&rcc RTCAPB>, <&rcc RTC>; -+ clocks = <&scmi0_clk CK_SCMI0_RTCAPB>, -+ <&scmi0_clk CK_SCMI0_RTC>; - clock-names = "pclk", "rtc_ck"; -- interrupts = ; -+ interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; - status = "disabled"; - }; - -@@ -1468,26 +1774,216 @@ - reg = <0x5c005000 0x400>; - #address-cells = <1>; - #size-cells = <1>; -+ -+ part_number_otp: part_number_otp@4 { -+ reg = <0x4 0x1>; -+ }; - ts_cal1: calib@5c { - reg = <0x5c 0x2>; - }; - ts_cal2: calib@5e { - reg = <0x5e 0x2>; - }; -+ ethernet_mac_address: mac@e4 { -+ reg = <0xe4 0x6>; -+ }; - }; - - i2c6: i2c@5c009000 { -- compatible = "st,stm32f7-i2c"; -+ compatible = "st,stm32mp15-i2c"; - reg = <0x5c009000 0x400>; - interrupt-names = "event", "error"; -- interrupts = , -- ; -- clocks = <&rcc I2C6_K>; -- resets = <&rcc I2C6_R>; -+ interrupts-extended = <&exti 54 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&scmi0_clk CK_SCMI0_I2C6>; -+ resets = <&scmi0_reset RST_SCMI0_I2C6>; - #address-cells = <1>; - #size-cells = <0>; -+ dmas = <&mdma1 38 0x0 0x40008 0x0 0x0 0>, -+ <&mdma1 39 0x0 0x40002 0x0 0x0 0>; -+ dma-names = "rx", "tx"; -+ power-domains = <&pd_core>; -+ st,syscfg-fmp = <&syscfg 0x4 0x20>; -+ wakeup-source; - status = "disabled"; - }; -+ -+ tamp: tamp@5c00a000 { -+ compatible = "simple-bus", "syscon", "simple-mfd"; -+ reg = <0x5c00a000 0x400>; -+ -+ reboot-mode { -+ compatible = "syscon-reboot-mode"; -+ offset = <0x150>; /* reg20 */ -+ mask = <0xff>; -+ mode-normal = <0>; -+ mode-fastboot = <0x1>; -+ mode-recovery = <0x2>; -+ mode-stm32cubeprogrammer = <0x3>; -+ mode-ums_mmc0 = <0x10>; -+ mode-ums_mmc1 = <0x11>; -+ mode-ums_mmc2 = <0x12>; -+ }; -+ }; -+ -+ /* -+ * Break node order to solve dependency probe issue between -+ * pinctrl and exti. -+ */ -+ pinctrl: pin-controller@50002000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "st,stm32mp157-pinctrl"; -+ ranges = <0 0x50002000 0xa400>; -+ interrupt-parent = <&exti>; -+ st,syscfg = <&exti 0x60 0xff>; -+ hwlocks = <&hsem 0 1>; -+ pins-are-numbered; -+ -+ gpioa: gpio@50002000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x0 0x400>; -+ clocks = <&rcc GPIOA>; -+ st,bank-name = "GPIOA"; -+ status = "disabled"; -+ }; -+ -+ gpiob: gpio@50003000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x1000 0x400>; -+ clocks = <&rcc GPIOB>; -+ st,bank-name = "GPIOB"; -+ status = "disabled"; -+ }; -+ -+ gpioc: gpio@50004000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x2000 0x400>; -+ clocks = <&rcc GPIOC>; -+ st,bank-name = "GPIOC"; -+ status = "disabled"; -+ }; -+ -+ gpiod: gpio@50005000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x3000 0x400>; -+ clocks = <&rcc GPIOD>; -+ st,bank-name = "GPIOD"; -+ status = "disabled"; -+ }; -+ -+ gpioe: gpio@50006000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x4000 0x400>; -+ clocks = <&rcc GPIOE>; -+ st,bank-name = "GPIOE"; -+ status = "disabled"; -+ }; -+ -+ gpiof: gpio@50007000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x5000 0x400>; -+ clocks = <&rcc GPIOF>; -+ st,bank-name = "GPIOF"; -+ status = "disabled"; -+ }; -+ -+ gpiog: gpio@50008000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x6000 0x400>; -+ clocks = <&rcc GPIOG>; -+ st,bank-name = "GPIOG"; -+ status = "disabled"; -+ }; -+ -+ gpioh: gpio@50009000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x7000 0x400>; -+ clocks = <&rcc GPIOH>; -+ st,bank-name = "GPIOH"; -+ status = "disabled"; -+ }; -+ -+ gpioi: gpio@5000a000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x8000 0x400>; -+ clocks = <&rcc GPIOI>; -+ st,bank-name = "GPIOI"; -+ status = "disabled"; -+ }; -+ -+ gpioj: gpio@5000b000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x9000 0x400>; -+ clocks = <&rcc GPIOJ>; -+ st,bank-name = "GPIOJ"; -+ status = "disabled"; -+ }; -+ -+ gpiok: gpio@5000c000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0xa000 0x400>; -+ clocks = <&rcc GPIOK>; -+ st,bank-name = "GPIOK"; -+ status = "disabled"; -+ }; -+ }; -+ -+ pinctrl_z: pin-controller-z@54004000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "st,stm32mp157-z-pinctrl"; -+ ranges = <0 0x54004000 0x400>; -+ pins-are-numbered; -+ interrupt-parent = <&exti>; -+ st,syscfg = <&exti 0x60 0xff>; -+ hwlocks = <&hsem 0 1>; -+ -+ gpioz: gpio@54004000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0 0x400>; -+ clocks = <&scmi0_clk CK_SCMI0_GPIOZ>; -+ st,bank-name = "GPIOZ"; -+ st,bank-ioport = <11>; -+ status = "disabled"; -+ }; -+ }; - }; - - mlahb { -@@ -1503,10 +1999,18 @@ - reg = <0x10000000 0x40000>, - <0x30000000 0x40000>, - <0x38000000 0x10000>; -- resets = <&rcc MCU_R>; -- st,syscfg-holdboot = <&rcc 0x10C 0x1>; -- st,syscfg-tz = <&rcc 0x000 0x1>; -+ resets = <&scmi0_reset RST_SCMI0_MCU>, -+ <&scmi0_reset RST_SCMI0_MCU_HOLD_BOOT>; -+ reset-names = "mcu_rst", "hold_boot"; -+ st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; -+ st,syscfg-copro-state = <&tamp 0x148 0xFFFFFFFF>; -+ st,syscfg-pdds = <&pwr_mcu 0x0 0x1>; - status = "disabled"; -+ -+ m4_system_resources { -+ compatible = "rproc-srm-core"; -+ status = "disabled"; -+ }; - }; - }; - }; -diff --git a/arch/arm/boot/dts/stm32mp153.dtsi b/arch/arm/boot/dts/stm32mp153.dtsi -new file mode 100644 -index 0000000000000..cf16b843c6b55 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp153.dtsi -@@ -0,0 +1,54 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+#include "stm32mp151.dtsi" -+ -+/ { -+ cpus { -+ cpu1: cpu@1 { -+ compatible = "arm,cortex-a7"; -+ device_type = "cpu"; -+ reg = <1>; -+ clocks = <&scmi0_clk CK_SCMI0_MPU>; -+ clock-names = "cpu"; -+ operating-points-v2 = <&cpu0_opp_table>; -+ }; -+ }; -+ -+ arm-pmu { -+ interrupts = , -+ ; -+ interrupt-affinity = <&cpu0>, <&cpu1>; -+ }; -+ -+ soc { -+ m_can1: can@4400e000 { -+ compatible = "bosch,m_can"; -+ reg = <0x4400e000 0x400>, <0x44011000 0x1400>; -+ reg-names = "m_can", "message_ram"; -+ interrupts = , -+ ; -+ interrupt-names = "int0", "int1"; -+ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; -+ clock-names = "hclk", "cclk"; -+ bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; -+ status = "disabled"; -+ }; -+ -+ m_can2: can@4400f000 { -+ compatible = "bosch,m_can"; -+ reg = <0x4400f000 0x400>, <0x44011000 0x2800>; -+ reg-names = "m_can", "message_ram"; -+ interrupts = , -+ ; -+ interrupt-names = "int0", "int1"; -+ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; -+ clock-names = "hclk", "cclk"; -+ bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; -+ status = "disabled"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157-m4-srm-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-m4-srm-pinctrl.dtsi -new file mode 100644 -index 0000000000000..b4030e5c9422b ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157-m4-srm-pinctrl.dtsi -@@ -0,0 +1,524 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Fabien Dessenne for STMicroelectronics. -+ */ -+ -+&pinctrl { -+ m4_adc1_in6_pins_a: m4-adc1-in6 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_adc12_ain_pins_a: m4-adc12-ain-0 { -+ pins { -+ pinmux = , /* ADC1 in13 */ -+ , /* ADC1 in6 */ -+ , /* ADC2 in2 */ -+ ; /* ADC2 in6 */ -+ }; -+ }; -+ -+ m4_adc12_usb_pwr_pins_a: m4-adc12-usb-pwr-pins-0 { -+ pins { -+ pinmux = , /* ADC12 in18 */ -+ ; /* ADC12 in19 */ -+ }; -+ }; -+ -+ m4_cec_pins_a: m4-cec-0 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_cec_pins_b: m4-cec-1 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_dac_ch1_pins_a: m4-dac-ch1 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_dac_ch2_pins_a: m4-dac-ch2 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_dcmi_pins_a: m4-dcmi-0 { -+ pins { -+ pinmux = ,/* DCMI_HSYNC */ -+ ,/* DCMI_VSYNC */ -+ ,/* DCMI_PIXCLK */ -+ ,/* DCMI_D0 */ -+ ,/* DCMI_D1 */ -+ ,/* DCMI_D2 */ -+ ,/* DCMI_D3 */ -+ ,/* DCMI_D4 */ -+ ,/* DCMI_D5 */ -+ ,/* DCMI_D6 */ -+ ,/* DCMI_D7 */ -+ ,/* DCMI_D8 */ -+ ,/* DCMI_D9 */ -+ ,/* DCMI_D10 */ -+ ;/* DCMI_D11 */ -+ }; -+ }; -+ -+ m4_dfsdm_clkout_pins_a: m4-dfsdm-clkout-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_CKOUT */ -+ }; -+ }; -+ -+ m4_dfsdm_data1_pins_a: m4-dfsdm-data1-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_DATA1 */ -+ }; -+ }; -+ -+ m4_dfsdm_data3_pins_a: m4-dfsdm-data3-pins-0 { -+ pins { -+ pinmux = ; /* DFSDM_DATA3 */ -+ }; -+ }; -+ -+ m4_ethernet0_rgmii_pins_a: m4-rgmii-0 { -+ pins { -+ pinmux = , /* ETH_RGMII_CLK125 */ -+ , /* ETH_RGMII_GTX_CLK */ -+ , /* ETH_RGMII_TXD0 */ -+ , /* ETH_RGMII_TXD1 */ -+ , /* ETH_RGMII_TXD2 */ -+ , /* ETH_RGMII_TXD3 */ -+ , /* ETH_RGMII_TX_CTL */ -+ , /* ETH_MDC */ -+ , /* ETH_MDIO */ -+ , /* ETH_RGMII_RXD0 */ -+ , /* ETH_RGMII_RXD1 */ -+ , /* ETH_RGMII_RXD2 */ -+ , /* ETH_RGMII_RXD3 */ -+ , /* ETH_RGMII_RX_CLK */ -+ ; /* ETH_RGMII_RX_CTL */ -+ }; -+ }; -+ -+ m4_fmc_pins_a: m4-fmc-0 { -+ pins { -+ pinmux = , /* FMC_NOE */ -+ , /* FMC_NWE */ -+ , /* FMC_A16_FMC_CLE */ -+ , /* FMC_A17_FMC_ALE */ -+ , /* FMC_D0 */ -+ , /* FMC_D1 */ -+ , /* FMC_D2 */ -+ , /* FMC_D3 */ -+ , /* FMC_D4 */ -+ , /* FMC_D5 */ -+ , /* FMC_D6 */ -+ , /* FMC_D7 */ -+ , /* FMC_NE2_FMC_NCE */ -+ ; /* FMC_NWAIT */ -+ }; -+ }; -+ -+ m4_hdp0_pins_a: m4-hdp0-0 { -+ pins { -+ pinmux = ; /* HDP0 */ -+ }; -+ }; -+ -+ m4_hdp6_pins_a: m4-hdp6-0 { -+ pins { -+ pinmux = ; /* HDP6 */ -+ }; -+ }; -+ -+ m4_hdp7_pins_a: m4-hdp7-0 { -+ pins { -+ pinmux = ; /* HDP7 */ -+ }; -+ }; -+ -+ m4_i2c1_pins_a: m4-i2c1-0 { -+ pins { -+ pinmux = , /* I2C1_SCL */ -+ ; /* I2C1_SDA */ -+ }; -+ }; -+ -+ m4_i2c2_pins_a: m4-i2c2-0 { -+ pins { -+ pinmux = , /* I2C2_SCL */ -+ ; /* I2C2_SDA */ -+ }; -+ }; -+ -+ m4_i2c5_pins_a: m4-i2c5-0 { -+ pins { -+ pinmux = , /* I2C5_SCL */ -+ ; /* I2C5_SDA */ -+ }; -+ }; -+ -+ m4_i2s2_pins_a: m4-i2s2-0 { -+ pins { -+ pinmux = , /* I2S2_SDO */ -+ , /* I2S2_WS */ -+ ; /* I2S2_CK */ -+ }; -+ }; -+ -+ m4_ltdc_pins_a: m4-ltdc-a-0 { -+ pins { -+ pinmux = , /* LCD_CLK */ -+ , /* LCD_HSYNC */ -+ , /* LCD_VSYNC */ -+ , /* LCD_DE */ -+ , /* LCD_R0 */ -+ , /* LCD_R1 */ -+ , /* LCD_R2 */ -+ , /* LCD_R3 */ -+ , /* LCD_R4 */ -+ , /* LCD_R5 */ -+ , /* LCD_R6 */ -+ , /* LCD_R7 */ -+ , /* LCD_G0 */ -+ , /* LCD_G1 */ -+ , /* LCD_G2 */ -+ , /* LCD_G3 */ -+ , /* LCD_G4 */ -+ , /* LCD_G5 */ -+ , /* LCD_G6 */ -+ , /* LCD_G7 */ -+ , /* LCD_B0 */ -+ , /* LCD_B1 */ -+ , /* LCD_B2 */ -+ , /* LCD_B3 */ -+ , /* LCD_B4 */ -+ , /* LCD_B5 */ -+ , /* LCD_B6 */ -+ ; /* LCD_B7 */ -+ }; -+ }; -+ -+ m4_ltdc_pins_b: m4-ltdc-b-0 { -+ pins { -+ pinmux = , /* LCD_CLK */ -+ , /* LCD_HSYNC */ -+ , /* LCD_VSYNC */ -+ , /* LCD_DE */ -+ , /* LCD_R0 */ -+ , /* LCD_R1 */ -+ , /* LCD_R2 */ -+ , /* LCD_R3 */ -+ , /* LCD_R4 */ -+ , /* LCD_R5 */ -+ , /* LCD_R6 */ -+ , /* LCD_R7 */ -+ , /* LCD_G0 */ -+ , /* LCD_G1 */ -+ , /* LCD_G2 */ -+ , /* LCD_G3 */ -+ , /* LCD_G4 */ -+ , /* LCD_G5 */ -+ , /* LCD_G6 */ -+ , /* LCD_G7 */ -+ , /* LCD_B0 */ -+ , /* LCD_B1 */ -+ , /* LCD_B2 */ -+ , /* LCD_B3 */ -+ , /* LCD_B4 */ -+ , /* LCD_B5 */ -+ , /* LCD_B6 */ -+ ; /* LCD_B7 */ -+ }; -+ }; -+ -+ m4_m_can1_pins_a: m4-m-can1-0 { -+ pins { -+ pinmux = , /* CAN1_TX */ -+ ; /* CAN1_RX */ -+ }; -+ }; -+ -+ m4_pwm1_pins_a: m4-pwm1-0 { -+ pins { -+ pinmux = , /* TIM1_CH1 */ -+ , /* TIM1_CH2 */ -+ ; /* TIM1_CH4 */ -+ }; -+ }; -+ -+ m4_pwm2_pins_a: m4-pwm2-0 { -+ pins { -+ pinmux = ; /* TIM2_CH4 */ -+ }; -+ }; -+ -+ m4_pwm3_pins_a: m4-pwm3-0 { -+ pins { -+ pinmux = ; /* TIM3_CH2 */ -+ }; -+ }; -+ -+ m4_pwm4_pins_a: m4-pwm4-0 { -+ pins { -+ pinmux = , /* TIM4_CH3 */ -+ ; /* TIM4_CH4 */ -+ }; -+ }; -+ -+ m4_pwm4_pins_b: m4-pwm4-1 { -+ pins { -+ pinmux = ; /* TIM4_CH2 */ -+ }; -+ }; -+ -+ m4_pwm5_pins_a: m4-pwm5-0 { -+ pins { -+ pinmux = ; /* TIM5_CH2 */ -+ }; -+ }; -+ -+ m4_pwm8_pins_a: m4-pwm8-0 { -+ pins { -+ pinmux = ; /* TIM8_CH4 */ -+ }; -+ }; -+ -+ m4_pwm12_pins_a: m4-pwm12-0 { -+ pins { -+ pinmux = ; /* TIM12_CH1 */ -+ }; -+ }; -+ -+ m4_qspi_bk1_pins_a: m4-qspi-bk1-0 { -+ pins { -+ pinmux = , /* QSPI_BK1_IO0 */ -+ , /* QSPI_BK1_IO1 */ -+ , /* QSPI_BK1_IO2 */ -+ , /* QSPI_BK1_IO3 */ -+ ; /* QSPI_BK1_NCS */ -+ }; -+ }; -+ -+ m4_qspi_bk2_pins_a: m4-qspi-bk2-0 { -+ pins { -+ pinmux = , /* QSPI_BK2_IO0 */ -+ , /* QSPI_BK2_IO1 */ -+ , /* QSPI_BK2_IO2 */ -+ , /* QSPI_BK2_IO3 */ -+ ; /* QSPI_BK2_NCS */ -+ }; -+ }; -+ -+ m4_qspi_clk_pins_a: m4-qspi-clk-0 { -+ pins { -+ pinmux = ; /* QSPI_CLK */ -+ }; -+ }; -+ -+ m4_rtc_out2_rmp_pins_a: m4-rtc-out2-rmp-pins-0 { -+ pins { -+ pinmux = ; /* RTC_OUT2_RMP */ -+ }; -+ }; -+ -+ m4_sai2a_pins_a: m4-sai2a-0 { -+ pins { -+ pinmux = , /* SAI2_SCK_A */ -+ , /* SAI2_SD_A */ -+ , /* SAI2_FS_A */ -+ ; /* SAI2_MCLK_A */ -+ }; -+ }; -+ -+ m4_sai2b_pins_a: m4-sai2b-0 { -+ pins { -+ pinmux = , /* SAI2_SCK_B */ -+ , /* SAI2_FS_B */ -+ , /* SAI2_MCLK_B */ -+ ; /* SAI2_SD_B */ -+ }; -+ }; -+ -+ m4_sai2b_pins_b: m4-sai2b-2 { -+ pins { -+ pinmux = ; /* SAI2_SD_B */ -+ }; -+ }; -+ -+ m4_sai4a_pins_a: m4-sai4a-0 { -+ pins { -+ pinmux = ; /* SAI4_SD_A */ -+ }; -+ }; -+ -+ m4_sdmmc1_b4_pins_a: m4-sdmmc1-b4-0 { -+ pins { -+ pinmux = , /* SDMMC1_D0 */ -+ , /* SDMMC1_D1 */ -+ , /* SDMMC1_D2 */ -+ , /* SDMMC1_D3 */ -+ , /* SDMMC1_CMD */ -+ ; /* SDMMC1_CK */ -+ }; -+ }; -+ -+ m4_sdmmc1_dir_pins_a: m4-sdmmc1-dir-0 { -+ pins { -+ pinmux = , /* SDMMC1_D0DIR */ -+ , /* SDMMC1_D123DIR */ -+ , /* SDMMC1_CDIR */ -+ ; /* SDMMC1_CKIN */ -+ }; -+ }; -+ -+ m4_sdmmc2_b4_pins_a: m4-sdmmc2-b4-0 { -+ pins { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ , /* SDMMC2_D3 */ -+ , /* SDMMC2_CMD */ -+ ; /* SDMMC2_CK */ -+ }; -+ }; -+ -+ m4_sdmmc2_b4_pins_b: m4-sdmmc2-b4-1 { -+ pins { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ , /* SDMMC2_D3 */ -+ , /* SDMMC2_CMD */ -+ ; /* SDMMC2_CK */ -+ }; -+ }; -+ -+ m4_sdmmc2_d47_pins_a: m4-sdmmc2-d47-0 { -+ pins { -+ pinmux = , /* SDMMC2_D4 */ -+ , /* SDMMC2_D5 */ -+ , /* SDMMC2_D6 */ -+ ; /* SDMMC2_D7 */ -+ }; -+ }; -+ -+ m4_sdmmc3_b4_pins_a: m4-sdmmc3-b4-0 { -+ pins { -+ pinmux = , /* SDMMC3_D0 */ -+ , /* SDMMC3_D1 */ -+ , /* SDMMC3_D2 */ -+ , /* SDMMC3_D3 */ -+ , /* SDMMC3_CMD */ -+ ; /* SDMMC3_CK */ -+ }; -+ }; -+ -+ m4_spdifrx_pins_a: m4-spdifrx-0 { -+ pins { -+ pinmux = ; /* SPDIF_IN1 */ -+ }; -+ }; -+ -+ m4_spi4_pins_a: m4-spi4-0 { -+ pins { -+ pinmux = , /* SPI4_SCK */ -+ , /* SPI4_MOSI */ -+ ; /* SPI4_MISO */ -+ }; -+ }; -+ -+ m4_spi5_pins_a: m4-spi5-0 { -+ pins { -+ pinmux = , /* SPI5_SCK */ -+ , /* SPI5_MOSI */ -+ ; /* SPI5_MISO */ -+ }; -+ }; -+ -+ m4_stusb1600_pins_a: m4-stusb1600-0 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_uart4_pins_a: m4-uart4-0 { -+ pins { -+ pinmux = , /* UART4_TX */ -+ ; /* UART4_RX */ -+ }; -+ }; -+ -+ m4_uart7_pins_a: m4-uart7-0 { -+ pins { -+ pinmux = , /* USART7_TX */ -+ ; /* USART7_RX */ -+ }; -+ }; -+ -+ m4_usart2_pins_a: m4-usart2-0 { -+ pins { -+ pinmux = , /* USART2_TX */ -+ , /* USART2_RTS */ -+ , /* USART2_RX */ -+ ; /* USART2_CTS_NSS */ -+ }; -+ }; -+ -+ m4_usart3_pins_a: m4-usart3-0 { -+ pins { -+ pinmux = , /* USART3_TX */ -+ , /* USART3_RTS */ -+ , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ }; -+ }; -+ -+ m4_usart3_pins_b: m4-usart3-1 { -+ pins { -+ pinmux = , /* USART3_TX */ -+ , /* USART3_RTS */ -+ , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ }; -+ }; -+ -+ m4_usbotg_hs_pins_a: m4-usbotg_hs-0 { -+ pins { -+ pinmux = ; /* OTG_ID */ -+ }; -+ }; -+ -+ m4_usbotg_fs_dp_dm_pins_a: m4-usbotg-fs-dp-dm-0 { -+ pins { -+ pinmux = , /* OTG_FS_DM */ -+ ; /* OTG_FS_DP */ -+ }; -+ }; -+}; -+ -+&pinctrl_z { -+ m4_i2c4_pins_a: m4-i2c4-0 { -+ pins { -+ pinmux = , /* I2C4_SCL */ -+ ; /* I2C4_SDA */ -+ }; -+ }; -+ -+ m4_spi1_pins_a: m4-spi1-0 { -+ pins { -+ pinmux = , /* SPI1_SCK */ -+ , /* SPI1_MOSI */ -+ ; /* SPI1_MISO */ -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157-m4-srm.dtsi b/arch/arm/boot/dts/stm32mp157-m4-srm.dtsi -new file mode 100644 -index 0000000000000..60454aee4123f ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157-m4-srm.dtsi -@@ -0,0 +1,442 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Fabien Dessenne for STMicroelectronics. -+ */ -+ -+&m4_rproc { -+ m4_system_resources { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ m4_timers2: timer@40000000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40000000 0x400>; -+ clocks = <&rcc TIM2_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers3: timer@40001000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40001000 0x400>; -+ clocks = <&rcc TIM3_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers4: timer@40002000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40002000 0x400>; -+ clocks = <&rcc TIM4_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers5: timer@40003000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40003000 0x400>; -+ clocks = <&rcc TIM5_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers6: timer@40004000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40004000 0x400>; -+ clocks = <&rcc TIM6_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers7: timer@40005000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40005000 0x400>; -+ clocks = <&rcc TIM7_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers12: timer@40006000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40006000 0x400>; -+ clocks = <&rcc TIM12_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers13: timer@40007000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40007000 0x400>; -+ clocks = <&rcc TIM13_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers14: timer@40008000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40008000 0x400>; -+ clocks = <&rcc TIM14_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_lptimer1: timer@40009000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40009000 0x400>; -+ clocks = <&rcc LPTIM1_K>; -+ clock-names = "mux"; -+ status = "disabled"; -+ }; -+ m4_spi2: spi@4000b000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4000b000 0x400>; -+ clocks = <&rcc SPI2_K>; -+ status = "disabled"; -+ }; -+ m4_i2s2: audio-controller@4000b000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4000b000 0x400>; -+ status = "disabled"; -+ }; -+ m4_spi3: spi@4000c000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4000c000 0x400>; -+ clocks = <&rcc SPI3_K>; -+ status = "disabled"; -+ }; -+ m4_i2s3: audio-controller@4000c000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4000c000 0x400>; -+ status = "disabled"; -+ }; -+ m4_spdifrx: audio-controller@4000d000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4000d000 0x400>; -+ clocks = <&rcc SPDIF_K>; -+ clock-names = "kclk"; -+ status = "disabled"; -+ }; -+ m4_usart2: serial@4000e000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4000e000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <27 1>; -+ clocks = <&rcc USART2_K>; -+ status = "disabled"; -+ }; -+ m4_usart3: serial@4000f000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4000f000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <28 1>; -+ clocks = <&rcc USART3_K>; -+ status = "disabled"; -+ }; -+ m4_uart4: serial@40010000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40010000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <30 1>; -+ clocks = <&rcc UART4_K>; -+ status = "disabled"; -+ }; -+ m4_uart5: serial@40011000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40011000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <31 1>; -+ clocks = <&rcc UART5_K>; -+ status = "disabled"; -+ }; -+ m4_i2c1: i2c@40012000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40012000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <21 1>; -+ clocks = <&rcc I2C1_K>; -+ status = "disabled"; -+ }; -+ m4_i2c2: i2c@40013000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40013000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <22 1>; -+ clocks = <&rcc I2C2_K>; -+ status = "disabled"; -+ }; -+ m4_i2c3: i2c@40014000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40014000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <23 1>; -+ clocks = <&rcc I2C3_K>; -+ status = "disabled"; -+ }; -+ m4_i2c5: i2c@40015000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40015000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <25 1>; -+ clocks = <&rcc I2C5_K>; -+ status = "disabled"; -+ }; -+ m4_cec: cec@40016000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40016000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <69 1>; -+ clocks = <&rcc CEC_K>, <&scmi0_clk CK_SCMI0_LSE>; -+ clock-names = "cec", "hdmi-cec"; -+ status = "disabled"; -+ }; -+ m4_dac: dac@40017000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40017000 0x400>; -+ clocks = <&rcc DAC12>; -+ clock-names = "pclk"; -+ status = "disabled"; -+ }; -+ m4_uart7: serial@40018000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40018000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <32 1>; -+ clocks = <&rcc UART7_K>; -+ status = "disabled"; -+ }; -+ m4_uart8: serial@40019000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x40019000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <33 1>; -+ clocks = <&rcc UART8_K>; -+ status = "disabled"; -+ }; -+ m4_timers1: timer@44000000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44000000 0x400>; -+ clocks = <&rcc TIM1_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers8: timer@44001000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44001000 0x400>; -+ clocks = <&rcc TIM8_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_usart6: serial@44003000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44003000 0x400>; -+ interrupt-parent = <&exti>; -+ interrupts = <29 1>; -+ clocks = <&rcc USART6_K>; -+ status = "disabled"; -+ }; -+ m4_spi1: spi@44004000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44004000 0x400>; -+ clocks = <&rcc SPI1_K>; -+ status = "disabled"; -+ }; -+ m4_i2s1: audio-controller@44004000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44004000 0x400>; -+ status = "disabled"; -+ }; -+ m4_spi4: spi@44005000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44005000 0x400>; -+ clocks = <&rcc SPI4_K>; -+ status = "disabled"; -+ }; -+ m4_timers15: timer@44006000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44006000 0x400>; -+ clocks = <&rcc TIM15_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers16: timer@44007000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44007000 0x400>; -+ clocks = <&rcc TIM16_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_timers17: timer@44008000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44008000 0x400>; -+ clocks = <&rcc TIM17_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ m4_spi5: spi@44009000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x44009000 0x400>; -+ clocks = <&rcc SPI5_K>; -+ status = "disabled"; -+ }; -+ m4_sai1: sai@4400a000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4400a000 0x4>; -+ clocks = <&rcc SAI1_K>; -+ clock-names = "sai_ck"; -+ status = "disabled"; -+ }; -+ m4_sai2: sai@4400b000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4400b000 0x4>; -+ clocks = <&rcc SAI2_K>; -+ clock-names = "sai_ck"; -+ status = "disabled"; -+ }; -+ m4_sai3: sai@4400c000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4400c000 0x4>; -+ clocks = <&rcc SAI3_K>; -+ clock-names = "sai_ck"; -+ status = "disabled"; -+ }; -+ m4_dfsdm: dfsdm@4400d000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4400d000 0x800>; -+ clocks = <&rcc DFSDM_K>, <&rcc ADFSDM_K>; -+ clock-names = "dfsdm", "audio"; -+ status = "disabled"; -+ }; -+ m4_m_can1: can@4400e000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4400e000 0x400>, <0x44011000 0x2800>; -+ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; -+ clock-names = "hclk", "cclk"; -+ status = "disabled"; -+ }; -+ m4_m_can2: can@4400f000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4400f000 0x400>, <0x44011000 0x2800>; -+ clocks = <&scmi0_clk CK_SCMI0_HSE>, <&rcc FDCAN_K>; -+ clock-names = "hclk", "cclk"; -+ status = "disabled"; -+ }; -+ m4_dma1: dma@48000000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x48000000 0x400>; -+ clocks = <&rcc DMA1>; -+ status = "disabled"; -+ }; -+ m4_dma2: dma@48001000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x48001000 0x400>; -+ clocks = <&rcc DMA2>; -+ status = "disabled"; -+ }; -+ m4_dmamux1: dma-router@48002000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x48002000 0x1c>; -+ clocks = <&rcc DMAMUX>; -+ status = "disabled"; -+ }; -+ m4_adc: adc@48003000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x48003000 0x400>; -+ clocks = <&rcc ADC12>, <&rcc ADC12_K>; -+ clock-names = "bus", "adc"; -+ status = "disabled"; -+ }; -+ m4_sdmmc3: sdmmc@48004000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x48004000 0x400>, <0x48005000 0x400>; -+ clocks = <&rcc SDMMC3_K>; -+ status = "disabled"; -+ }; -+ m4_usbotg_hs: usb-otg@49000000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x49000000 0x10000>; -+ clocks = <&rcc USBO_K>; -+ clock-names = "otg"; -+ status = "disabled"; -+ }; -+ m4_hash2: hash@4c002000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4c002000 0x400>; -+ clocks = <&rcc HASH2>; -+ status = "disabled"; -+ }; -+ m4_rng2: rng@4c003000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4c003000 0x400>; -+ clocks = <&rcc RNG2_K>; -+ status = "disabled"; -+ }; -+ m4_crc2: crc@4c004000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4c004000 0x400>; -+ clocks = <&rcc CRC2>; -+ status = "disabled"; -+ }; -+ m4_cryp2: cryp@4c005000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4c005000 0x400>; -+ clocks = <&rcc CRYP2>; -+ status = "disabled"; -+ }; -+ m4_dcmi: dcmi@4c006000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x4c006000 0x400>; -+ clocks = <&rcc DCMI>; -+ clock-names = "mclk"; -+ status = "disabled"; -+ }; -+ m4_lptimer2: timer@50021000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x50021000 0x400>; -+ clocks = <&rcc LPTIM2_K>; -+ clock-names = "mux"; -+ status = "disabled"; -+ }; -+ m4_lptimer3: timer@50022000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x50022000 0x400>; -+ clocks = <&rcc LPTIM3_K>; -+ clock-names = "mux"; -+ status = "disabled"; -+ }; -+ m4_lptimer4: timer@50023000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x50023000 0x400>; -+ clocks = <&rcc LPTIM4_K>; -+ clock-names = "mux"; -+ status = "disabled"; -+ }; -+ m4_lptimer5: timer@50024000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x50024000 0x400>; -+ clocks = <&rcc LPTIM5_K>; -+ clock-names = "mux"; -+ status = "disabled"; -+ }; -+ m4_sai4: sai@50027000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x50027000 0x4>; -+ clocks = <&rcc SAI4_K>; -+ clock-names = "sai_ck"; -+ status = "disabled"; -+ }; -+ m4_qspi: qspi@58003000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; -+ clocks = <&rcc QSPI_K>; -+ status = "disabled"; -+ }; -+ m4_ethernet0: ethernet@5800a000 { -+ compatible = "rproc-srm-dev"; -+ reg = <0x5800a000 0x2000>; -+ clock-names = "stmmaceth", -+ "mac-clk-tx", -+ "mac-clk-rx", -+ "ethstp", -+ "syscfg-clk"; -+ clocks = <&rcc ETHMAC>, -+ <&rcc ETHTX>, -+ <&rcc ETHRX>, -+ <&rcc ETHSTP>, -+ <&rcc SYSCFG>; -+ status = "disabled"; -+ }; -+ }; -+}; -+ -diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi -deleted file mode 100644 -index 0a3a7d66737b6..0000000000000 ---- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi -+++ /dev/null -@@ -1,925 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -- * Author: Ludovic Barre for STMicroelectronics. -- */ --#include -- --/ { -- soc { -- pinctrl: pin-controller@50002000 { -- #address-cells = <1>; -- #size-cells = <1>; -- compatible = "st,stm32mp157-pinctrl"; -- ranges = <0 0x50002000 0xa400>; -- interrupt-parent = <&exti>; -- st,syscfg = <&exti 0x60 0xff>; -- pins-are-numbered; -- -- gpioa: gpio@50002000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x0 0x400>; -- clocks = <&rcc GPIOA>; -- st,bank-name = "GPIOA"; -- status = "disabled"; -- }; -- -- gpiob: gpio@50003000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x1000 0x400>; -- clocks = <&rcc GPIOB>; -- st,bank-name = "GPIOB"; -- status = "disabled"; -- }; -- -- gpioc: gpio@50004000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x2000 0x400>; -- clocks = <&rcc GPIOC>; -- st,bank-name = "GPIOC"; -- status = "disabled"; -- }; -- -- gpiod: gpio@50005000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x3000 0x400>; -- clocks = <&rcc GPIOD>; -- st,bank-name = "GPIOD"; -- status = "disabled"; -- }; -- -- gpioe: gpio@50006000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x4000 0x400>; -- clocks = <&rcc GPIOE>; -- st,bank-name = "GPIOE"; -- status = "disabled"; -- }; -- -- gpiof: gpio@50007000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x5000 0x400>; -- clocks = <&rcc GPIOF>; -- st,bank-name = "GPIOF"; -- status = "disabled"; -- }; -- -- gpiog: gpio@50008000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x6000 0x400>; -- clocks = <&rcc GPIOG>; -- st,bank-name = "GPIOG"; -- status = "disabled"; -- }; -- -- gpioh: gpio@50009000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x7000 0x400>; -- clocks = <&rcc GPIOH>; -- st,bank-name = "GPIOH"; -- status = "disabled"; -- }; -- -- gpioi: gpio@5000a000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x8000 0x400>; -- clocks = <&rcc GPIOI>; -- st,bank-name = "GPIOI"; -- status = "disabled"; -- }; -- -- gpioj: gpio@5000b000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x9000 0x400>; -- clocks = <&rcc GPIOJ>; -- st,bank-name = "GPIOJ"; -- status = "disabled"; -- }; -- -- gpiok: gpio@5000c000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0xa000 0x400>; -- clocks = <&rcc GPIOK>; -- st,bank-name = "GPIOK"; -- status = "disabled"; -- }; -- -- cec_pins_a: cec-0 { -- pins { -- pinmux = ; -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- cec_pins_sleep_a: cec-sleep-0 { -- pins { -- pinmux = ; /* HDMI_CEC */ -- }; -- }; -- -- cec_pins_b: cec-1 { -- pins { -- pinmux = ; -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- cec_pins_sleep_b: cec-sleep-1 { -- pins { -- pinmux = ; /* HDMI_CEC */ -- }; -- }; -- -- dcmi_pins_a: dcmi-0 { -- pins { -- pinmux = ,/* DCMI_HSYNC */ -- ,/* DCMI_VSYNC */ -- ,/* DCMI_PIXCLK */ -- ,/* DCMI_D0 */ -- ,/* DCMI_D1 */ -- ,/* DCMI_D2 */ -- ,/* DCMI_D3 */ -- ,/* DCMI_D4 */ -- ,/* DCMI_D5 */ -- ,/* DCMI_D6 */ -- ,/* DCMI_D7 */ -- ,/* DCMI_D8 */ -- ,/* DCMI_D9 */ -- ,/* DCMI_D10 */ -- ;/* DCMI_D11 */ -- bias-disable; -- }; -- }; -- -- dcmi_sleep_pins_a: dcmi-sleep-0 { -- pins { -- pinmux = ,/* DCMI_HSYNC */ -- ,/* DCMI_VSYNC */ -- ,/* DCMI_PIXCLK */ -- ,/* DCMI_D0 */ -- ,/* DCMI_D1 */ -- ,/* DCMI_D2 */ -- ,/* DCMI_D3 */ -- ,/* DCMI_D4 */ -- ,/* DCMI_D5 */ -- ,/* DCMI_D6 */ -- ,/* DCMI_D7 */ -- ,/* DCMI_D8 */ -- ,/* DCMI_D9 */ -- ,/* DCMI_D10 */ -- ;/* DCMI_D11 */ -- }; -- }; -- -- ethernet0_rgmii_pins_a: rgmii-0 { -- pins1 { -- pinmux = , /* ETH_RGMII_CLK125 */ -- , /* ETH_RGMII_GTX_CLK */ -- , /* ETH_RGMII_TXD0 */ -- , /* ETH_RGMII_TXD1 */ -- , /* ETH_RGMII_TXD2 */ -- , /* ETH_RGMII_TXD3 */ -- , /* ETH_RGMII_TX_CTL */ -- , /* ETH_MDIO */ -- ; /* ETH_MDC */ -- bias-disable; -- drive-push-pull; -- slew-rate = <3>; -- }; -- pins2 { -- pinmux = , /* ETH_RGMII_RXD0 */ -- , /* ETH_RGMII_RXD1 */ -- , /* ETH_RGMII_RXD2 */ -- , /* ETH_RGMII_RXD3 */ -- , /* ETH_RGMII_RX_CLK */ -- ; /* ETH_RGMII_RX_CTL */ -- bias-disable; -- }; -- }; -- -- ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 { -- pins1 { -- pinmux = , /* ETH_RGMII_CLK125 */ -- , /* ETH_RGMII_GTX_CLK */ -- , /* ETH_RGMII_TXD0 */ -- , /* ETH_RGMII_TXD1 */ -- , /* ETH_RGMII_TXD2 */ -- , /* ETH_RGMII_TXD3 */ -- , /* ETH_RGMII_TX_CTL */ -- , /* ETH_MDIO */ -- , /* ETH_MDC */ -- , /* ETH_RGMII_RXD0 */ -- , /* ETH_RGMII_RXD1 */ -- , /* ETH_RGMII_RXD2 */ -- , /* ETH_RGMII_RXD3 */ -- , /* ETH_RGMII_RX_CLK */ -- ; /* ETH_RGMII_RX_CTL */ -- }; -- }; -- -- fmc_pins_a: fmc-0 { -- pins1 { -- pinmux = , /* FMC_NOE */ -- , /* FMC_NWE */ -- , /* FMC_A16_FMC_CLE */ -- , /* FMC_A17_FMC_ALE */ -- , /* FMC_D0 */ -- , /* FMC_D1 */ -- , /* FMC_D2 */ -- , /* FMC_D3 */ -- , /* FMC_D4 */ -- , /* FMC_D5 */ -- , /* FMC_D6 */ -- , /* FMC_D7 */ -- ; /* FMC_NE2_FMC_NCE */ -- bias-disable; -- drive-push-pull; -- slew-rate = <1>; -- }; -- pins2 { -- pinmux = ; /* FMC_NWAIT */ -- bias-pull-up; -- }; -- }; -- -- fmc_sleep_pins_a: fmc-sleep-0 { -- pins { -- pinmux = , /* FMC_NOE */ -- , /* FMC_NWE */ -- , /* FMC_A16_FMC_CLE */ -- , /* FMC_A17_FMC_ALE */ -- , /* FMC_D0 */ -- , /* FMC_D1 */ -- , /* FMC_D2 */ -- , /* FMC_D3 */ -- , /* FMC_D4 */ -- , /* FMC_D5 */ -- , /* FMC_D6 */ -- , /* FMC_D7 */ -- , /* FMC_NWAIT */ -- ; /* FMC_NE2_FMC_NCE */ -- }; -- }; -- -- i2c1_pins_a: i2c1-0 { -- pins { -- pinmux = , /* I2C1_SCL */ -- ; /* I2C1_SDA */ -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- i2c1_pins_sleep_a: i2c1-1 { -- pins { -- pinmux = , /* I2C1_SCL */ -- ; /* I2C1_SDA */ -- }; -- }; -- -- i2c1_pins_b: i2c1-2 { -- pins { -- pinmux = , /* I2C1_SCL */ -- ; /* I2C1_SDA */ -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- i2c1_pins_sleep_b: i2c1-3 { -- pins { -- pinmux = , /* I2C1_SCL */ -- ; /* I2C1_SDA */ -- }; -- }; -- -- i2c2_pins_a: i2c2-0 { -- pins { -- pinmux = , /* I2C2_SCL */ -- ; /* I2C2_SDA */ -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- i2c2_pins_sleep_a: i2c2-1 { -- pins { -- pinmux = , /* I2C2_SCL */ -- ; /* I2C2_SDA */ -- }; -- }; -- -- i2c2_pins_b1: i2c2-2 { -- pins { -- pinmux = ; /* I2C2_SDA */ -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- i2c2_pins_sleep_b1: i2c2-3 { -- pins { -- pinmux = ; /* I2C2_SDA */ -- }; -- }; -- -- i2c5_pins_a: i2c5-0 { -- pins { -- pinmux = , /* I2C5_SCL */ -- ; /* I2C5_SDA */ -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- i2c5_pins_sleep_a: i2c5-1 { -- pins { -- pinmux = , /* I2C5_SCL */ -- ; /* I2C5_SDA */ -- -- }; -- }; -- -- i2s2_pins_a: i2s2-0 { -- pins { -- pinmux = , /* I2S2_SDO */ -- , /* I2S2_WS */ -- ; /* I2S2_CK */ -- slew-rate = <1>; -- drive-push-pull; -- bias-disable; -- }; -- }; -- -- i2s2_pins_sleep_a: i2s2-1 { -- pins { -- pinmux = , /* I2S2_SDO */ -- , /* I2S2_WS */ -- ; /* I2S2_CK */ -- }; -- }; -- -- ltdc_pins_a: ltdc-a-0 { -- pins { -- pinmux = , /* LCD_CLK */ -- , /* LCD_HSYNC */ -- , /* LCD_VSYNC */ -- , /* LCD_DE */ -- , /* LCD_R0 */ -- , /* LCD_R1 */ -- , /* LCD_R2 */ -- , /* LCD_R3 */ -- , /* LCD_R4 */ -- , /* LCD_R5 */ -- , /* LCD_R6 */ -- , /* LCD_R7 */ -- , /* LCD_G0 */ -- , /* LCD_G1 */ -- , /* LCD_G2 */ -- , /* LCD_G3 */ -- , /* LCD_G4 */ -- , /* LCD_G5 */ -- , /* LCD_G6 */ -- , /* LCD_G7 */ -- , /* LCD_B0 */ -- , /* LCD_B1 */ -- , /* LCD_B2 */ -- , /* LCD_B3 */ -- , /* LCD_B4 */ -- , /* LCD_B5 */ -- , /* LCD_B6 */ -- ; /* LCD_B7 */ -- bias-disable; -- drive-push-pull; -- slew-rate = <1>; -- }; -- }; -- -- ltdc_pins_sleep_a: ltdc-a-1 { -- pins { -- pinmux = , /* LCD_CLK */ -- , /* LCD_HSYNC */ -- , /* LCD_VSYNC */ -- , /* LCD_DE */ -- , /* LCD_R0 */ -- , /* LCD_R1 */ -- , /* LCD_R2 */ -- , /* LCD_R3 */ -- , /* LCD_R4 */ -- , /* LCD_R5 */ -- , /* LCD_R6 */ -- , /* LCD_R7 */ -- , /* LCD_G0 */ -- , /* LCD_G1 */ -- , /* LCD_G2 */ -- , /* LCD_G3 */ -- , /* LCD_G4 */ -- , /* LCD_G5 */ -- , /* LCD_G6 */ -- , /* LCD_G7 */ -- , /* LCD_B0 */ -- , /* LCD_B1 */ -- , /* LCD_B2 */ -- , /* LCD_B3 */ -- , /* LCD_B4 */ -- , /* LCD_B5 */ -- , /* LCD_B6 */ -- ; /* LCD_B7 */ -- }; -- }; -- -- ltdc_pins_b: ltdc-b-0 { -- pins { -- pinmux = , /* LCD_CLK */ -- , /* LCD_HSYNC */ -- , /* LCD_VSYNC */ -- , /* LCD_DE */ -- , /* LCD_R0 */ -- , /* LCD_R1 */ -- , /* LCD_R2 */ -- , /* LCD_R3 */ -- , /* LCD_R4 */ -- , /* LCD_R5 */ -- , /* LCD_R6 */ -- , /* LCD_R7 */ -- , /* LCD_G0 */ -- , /* LCD_G1 */ -- , /* LCD_G2 */ -- , /* LCD_G3 */ -- , /* LCD_G4 */ -- , /* LCD_G5 */ -- , /* LCD_G6 */ -- , /* LCD_G7 */ -- , /* LCD_B0 */ -- , /* LCD_B1 */ -- , /* LCD_B2 */ -- , /* LCD_B3 */ -- , /* LCD_B4 */ -- , /* LCD_B5 */ -- , /* LCD_B6 */ -- ; /* LCD_B7 */ -- bias-disable; -- drive-push-pull; -- slew-rate = <1>; -- }; -- }; -- -- ltdc_pins_sleep_b: ltdc-b-1 { -- pins { -- pinmux = , /* LCD_CLK */ -- , /* LCD_HSYNC */ -- , /* LCD_VSYNC */ -- , /* LCD_DE */ -- , /* LCD_R0 */ -- , /* LCD_R1 */ -- , /* LCD_R2 */ -- , /* LCD_R3 */ -- , /* LCD_R4 */ -- , /* LCD_R5 */ -- , /* LCD_R6 */ -- , /* LCD_R7 */ -- , /* LCD_G0 */ -- , /* LCD_G1 */ -- , /* LCD_G2 */ -- , /* LCD_G3 */ -- , /* LCD_G4 */ -- , /* LCD_G5 */ -- , /* LCD_G6 */ -- , /* LCD_G7 */ -- , /* LCD_B0 */ -- , /* LCD_B1 */ -- , /* LCD_B2 */ -- , /* LCD_B3 */ -- , /* LCD_B4 */ -- , /* LCD_B5 */ -- , /* LCD_B6 */ -- ; /* LCD_B7 */ -- }; -- }; -- -- m_can1_pins_a: m-can1-0 { -- pins1 { -- pinmux = ; /* CAN1_TX */ -- slew-rate = <1>; -- drive-push-pull; -- bias-disable; -- }; -- pins2 { -- pinmux = ; /* CAN1_RX */ -- bias-disable; -- }; -- }; -- -- m_can1_sleep_pins_a: m_can1-sleep-0 { -- pins { -- pinmux = , /* CAN1_TX */ -- ; /* CAN1_RX */ -- }; -- }; -- -- pwm2_pins_a: pwm2-0 { -- pins { -- pinmux = ; /* TIM2_CH4 */ -- bias-pull-down; -- drive-push-pull; -- slew-rate = <0>; -- }; -- }; -- -- pwm8_pins_a: pwm8-0 { -- pins { -- pinmux = ; /* TIM8_CH4 */ -- bias-pull-down; -- drive-push-pull; -- slew-rate = <0>; -- }; -- }; -- -- pwm12_pins_a: pwm12-0 { -- pins { -- pinmux = ; /* TIM12_CH1 */ -- bias-pull-down; -- drive-push-pull; -- slew-rate = <0>; -- }; -- }; -- -- qspi_clk_pins_a: qspi-clk-0 { -- pins { -- pinmux = ; /* QSPI_CLK */ -- bias-disable; -- drive-push-pull; -- slew-rate = <3>; -- }; -- }; -- -- qspi_clk_sleep_pins_a: qspi-clk-sleep-0 { -- pins { -- pinmux = ; /* QSPI_CLK */ -- }; -- }; -- -- qspi_bk1_pins_a: qspi-bk1-0 { -- pins1 { -- pinmux = , /* QSPI_BK1_IO0 */ -- , /* QSPI_BK1_IO1 */ -- , /* QSPI_BK1_IO2 */ -- ; /* QSPI_BK1_IO3 */ -- bias-disable; -- drive-push-pull; -- slew-rate = <1>; -- }; -- pins2 { -- pinmux = ; /* QSPI_BK1_NCS */ -- bias-pull-up; -- drive-push-pull; -- slew-rate = <1>; -- }; -- }; -- -- qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 { -- pins { -- pinmux = , /* QSPI_BK1_IO0 */ -- , /* QSPI_BK1_IO1 */ -- , /* QSPI_BK1_IO2 */ -- , /* QSPI_BK1_IO3 */ -- ; /* QSPI_BK1_NCS */ -- }; -- }; -- -- qspi_bk2_pins_a: qspi-bk2-0 { -- pins1 { -- pinmux = , /* QSPI_BK2_IO0 */ -- , /* QSPI_BK2_IO1 */ -- , /* QSPI_BK2_IO2 */ -- ; /* QSPI_BK2_IO3 */ -- bias-disable; -- drive-push-pull; -- slew-rate = <1>; -- }; -- pins2 { -- pinmux = ; /* QSPI_BK2_NCS */ -- bias-pull-up; -- drive-push-pull; -- slew-rate = <1>; -- }; -- }; -- -- qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 { -- pins { -- pinmux = , /* QSPI_BK2_IO0 */ -- , /* QSPI_BK2_IO1 */ -- , /* QSPI_BK2_IO2 */ -- , /* QSPI_BK2_IO3 */ -- ; /* QSPI_BK2_NCS */ -- }; -- }; -- -- sai2a_pins_a: sai2a-0 { -- pins { -- pinmux = , /* SAI2_SCK_A */ -- , /* SAI2_SD_A */ -- , /* SAI2_FS_A */ -- ; /* SAI2_MCLK_A */ -- slew-rate = <0>; -- drive-push-pull; -- bias-disable; -- }; -- }; -- -- sai2a_sleep_pins_a: sai2a-1 { -- pins { -- pinmux = , /* SAI2_SCK_A */ -- , /* SAI2_SD_A */ -- , /* SAI2_FS_A */ -- ; /* SAI2_MCLK_A */ -- }; -- }; -- -- sai2b_pins_a: sai2b-0 { -- pins1 { -- pinmux = , /* SAI2_SCK_B */ -- , /* SAI2_FS_B */ -- ; /* SAI2_MCLK_B */ -- slew-rate = <0>; -- drive-push-pull; -- bias-disable; -- }; -- pins2 { -- pinmux = ; /* SAI2_SD_B */ -- bias-disable; -- }; -- }; -- -- sai2b_sleep_pins_a: sai2b-1 { -- pins { -- pinmux = , /* SAI2_SD_B */ -- , /* SAI2_SCK_B */ -- , /* SAI2_FS_B */ -- ; /* SAI2_MCLK_B */ -- }; -- }; -- -- sai2b_pins_b: sai2b-2 { -- pins { -- pinmux = ; /* SAI2_SD_B */ -- bias-disable; -- }; -- }; -- -- sai2b_sleep_pins_b: sai2b-3 { -- pins { -- pinmux = ; /* SAI2_SD_B */ -- }; -- }; -- -- sai4a_pins_a: sai4a-0 { -- pins { -- pinmux = ; /* SAI4_SD_A */ -- slew-rate = <0>; -- drive-push-pull; -- bias-disable; -- }; -- }; -- -- sai4a_sleep_pins_a: sai4a-1 { -- pins { -- pinmux = ; /* SAI4_SD_A */ -- }; -- }; -- -- sdmmc1_b4_pins_a: sdmmc1-b4-0 { -- pins { -- pinmux = , /* SDMMC1_D0 */ -- , /* SDMMC1_D1 */ -- , /* SDMMC1_D2 */ -- , /* SDMMC1_D3 */ -- , /* SDMMC1_CK */ -- ; /* SDMMC1_CMD */ -- slew-rate = <3>; -- drive-push-pull; -- bias-disable; -- }; -- }; -- -- sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 { -- pins1 { -- pinmux = , /* SDMMC1_D0 */ -- , /* SDMMC1_D1 */ -- , /* SDMMC1_D2 */ -- , /* SDMMC1_D3 */ -- ; /* SDMMC1_CK */ -- slew-rate = <3>; -- drive-push-pull; -- bias-disable; -- }; -- pins2{ -- pinmux = ; /* SDMMC1_CMD */ -- slew-rate = <3>; -- drive-open-drain; -- bias-disable; -- }; -- }; -- -- sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 { -- pins { -- pinmux = , /* SDMMC1_D0 */ -- , /* SDMMC1_D1 */ -- , /* SDMMC1_D2 */ -- , /* SDMMC1_D3 */ -- , /* SDMMC1_CK */ -- ; /* SDMMC1_CMD */ -- }; -- }; -- -- sdmmc1_dir_pins_a: sdmmc1-dir-0 { -- pins1 { -- pinmux = , /* SDMMC1_D0DIR */ -- , /* SDMMC1_D123DIR */ -- ; /* SDMMC1_CDIR */ -- slew-rate = <3>; -- drive-push-pull; -- bias-pull-up; -- }; -- pins2{ -- pinmux = ; /* SDMMC1_CKIN */ -- bias-pull-up; -- }; -- }; -- -- sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 { -- pins { -- pinmux = , /* SDMMC1_D0DIR */ -- , /* SDMMC1_D123DIR */ -- , /* SDMMC1_CDIR */ -- ; /* SDMMC1_CKIN */ -- }; -- }; -- -- spdifrx_pins_a: spdifrx-0 { -- pins { -- pinmux = ; /* SPDIF_IN1 */ -- bias-disable; -- }; -- }; -- -- spdifrx_sleep_pins_a: spdifrx-1 { -- pins { -- pinmux = ; /* SPDIF_IN1 */ -- }; -- }; -- -- uart4_pins_a: uart4-0 { -- pins1 { -- pinmux = ; /* UART4_TX */ -- bias-disable; -- drive-push-pull; -- slew-rate = <0>; -- }; -- pins2 { -- pinmux = ; /* UART4_RX */ -- bias-disable; -- }; -- }; -- -- uart4_pins_b: uart4-1 { -- pins1 { -- pinmux = ; /* UART4_TX */ -- bias-disable; -- drive-push-pull; -- slew-rate = <0>; -- }; -- pins2 { -- pinmux = ; /* UART4_RX */ -- bias-disable; -- }; -- }; -- -- uart7_pins_a: uart7-0 { -- pins1 { -- pinmux = ; /* UART4_TX */ -- bias-disable; -- drive-push-pull; -- slew-rate = <0>; -- }; -- pins2 { -- pinmux = , /* UART4_RX */ -- , /* UART4_CTS */ -- ; /* UART4_RTS */ -- bias-disable; -- }; -- }; -- }; -- -- pinctrl_z: pin-controller-z@54004000 { -- #address-cells = <1>; -- #size-cells = <1>; -- compatible = "st,stm32mp157-z-pinctrl"; -- ranges = <0 0x54004000 0x400>; -- pins-are-numbered; -- interrupt-parent = <&exti>; -- st,syscfg = <&exti 0x60 0xff>; -- -- gpioz: gpio@54004000 { -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0 0x400>; -- clocks = <&rcc GPIOZ>; -- st,bank-name = "GPIOZ"; -- st,bank-ioport = <11>; -- status = "disabled"; -- }; -- -- i2c2_pins_b2: i2c2-0 { -- pins { -- pinmux = ; /* I2C2_SCL */ -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- i2c2_pins_sleep_b2: i2c2-1 { -- pins { -- pinmux = ; /* I2C2_SCL */ -- }; -- }; -- -- i2c4_pins_a: i2c4-0 { -- pins { -- pinmux = , /* I2C4_SCL */ -- ; /* I2C4_SDA */ -- bias-disable; -- drive-open-drain; -- slew-rate = <0>; -- }; -- }; -- -- i2c4_pins_sleep_a: i2c4-1 { -- pins { -- pinmux = , /* I2C4_SCL */ -- ; /* I2C4_SDA */ -- }; -- }; -- -- spi1_pins_a: spi1-0 { -- pins1 { -- pinmux = , /* SPI1_SCK */ -- ; /* SPI1_MOSI */ -- bias-disable; -- drive-push-pull; -- slew-rate = <1>; -- }; -- -- pins2 { -- pinmux = ; /* SPI1_MISO */ -- bias-disable; -- }; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/stm32mp157.dtsi b/arch/arm/boot/dts/stm32mp157.dtsi -new file mode 100644 -index 0000000000000..ce1d83aa7b29e ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157.dtsi -@@ -0,0 +1,32 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+#include "stm32mp153.dtsi" -+ -+/ { -+ soc { -+ gpu: gpu@59000000 { -+ compatible = "vivante,gc"; -+ reg = <0x59000000 0x800>; -+ interrupts = ; -+ clocks = <&rcc GPU>, <&rcc GPU_K>; -+ clock-names = "bus" ,"core"; -+ resets = <&rcc GPU_R>; -+ status = "disabled"; -+ }; -+ -+ dsi: dsi@5a000000 { -+ compatible = "st,stm32-dsi"; -+ reg = <0x5a000000 0x800>; -+ phy-dsi-supply = <®18>; -+ clocks = <&rcc DSI_K>, <&scmi0_clk CK_SCMI0_HSE>, <&rcc DSI_PX>; -+ clock-names = "pclk", "ref", "px_clk"; -+ resets = <&rcc DSI_R>; -+ reset-names = "apb"; -+ status = "disabled"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157a-avenger96.dts b/arch/arm/boot/dts/stm32mp157a-avenger96.dts -index 7b8c3f25861c9..4479b06a94cf5 100644 ---- a/arch/arm/boot/dts/stm32mp157a-avenger96.dts -+++ b/arch/arm/boot/dts/stm32mp157a-avenger96.dts -@@ -6,9 +6,10 @@ - - /dts-v1/; - --#include "stm32mp157c.dtsi" --#include "stm32mp157xac-pinctrl.dtsi" --#include -+#include "stm32mp157.dtsi" -+#include "stm32mp15xa.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxac-pinctrl.dtsi" - #include - - / { -@@ -255,14 +256,13 @@ - regulator-name = "vbus_otg"; - interrupts = ; - interrupt-parent = <&pmic>; -- regulator-active-discharge; - }; - - vbus_sw: pwr_sw2 { - regulator-name = "vbus_sw"; - interrupts = ; - interrupt-parent = <&pmic>; -- regulator-active-discharge; -+ regulator-active-discharge = <1>; - }; - }; - -@@ -285,6 +285,11 @@ - status = "okay"; - }; - -+&pwr_regulators { -+ vdd-supply = <&vdd>; -+ vdd_3v3_usbfs-supply = <&vdd_usb>; -+}; -+ - &rng1 { - status = "okay"; - }; -@@ -298,7 +303,7 @@ - pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; - pinctrl-1 = <&sdmmc1_b4_od_pins_a>; - pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>; -- broken-cd; -+ cd-gpios = <&gpioi 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,sig-dir; - st,neg-edge; - st,use-ckin; -diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts -index 0615d1c8a6fcf..1f265fed2c5d6 100644 ---- a/arch/arm/boot/dts/stm32mp157a-dk1.dts -+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts -@@ -6,11 +6,11 @@ - - /dts-v1/; - --#include "stm32mp157c.dtsi" --#include "stm32mp157xac-pinctrl.dtsi" --#include --#include -- -+#include "stm32mp157.dtsi" -+#include "stm32mp15xa.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxac-pinctrl.dtsi" -+#include "stm32mp15xx-dkx.dtsi" - / { - model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; - compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; -@@ -18,434 +18,18 @@ - aliases { - ethernet0 = ðernet0; - serial0 = &uart4; -+ serial1 = &usart3; -+ serial2 = &uart7; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - -- memory@c0000000 { -- reg = <0xc0000000 0x20000000>; -- }; -- - reserved-memory { -- #address-cells = <1>; -- #size-cells = <1>; -- ranges; -- -- mcuram2: mcuram2@10000000 { -- compatible = "shared-dma-pool"; -- reg = <0x10000000 0x40000>; -- no-map; -- }; -- -- vdev0vring0: vdev0vring0@10040000 { -- compatible = "shared-dma-pool"; -- reg = <0x10040000 0x1000>; -- no-map; -- }; -- -- vdev0vring1: vdev0vring1@10041000 { -- compatible = "shared-dma-pool"; -- reg = <0x10041000 0x1000>; -- no-map; -- }; -- -- vdev0buffer: vdev0buffer@10042000 { -- compatible = "shared-dma-pool"; -- reg = <0x10042000 0x4000>; -+ gpu_reserved: gpu@da000000 { -+ reg = <0xda000000 0x4000000>; - no-map; - }; -- -- mcuram: mcuram@30000000 { -- compatible = "shared-dma-pool"; -- reg = <0x30000000 0x40000>; -- no-map; -- }; -- -- retram: retram@38000000 { -- compatible = "shared-dma-pool"; -- reg = <0x38000000 0x10000>; -- no-map; -- }; -- -- gpu_reserved: gpu@d4000000 { -- reg = <0xd4000000 0x4000000>; -- no-map; -- }; -- }; -- -- led { -- compatible = "gpio-leds"; -- blue { -- label = "heartbeat"; -- gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; -- linux,default-trigger = "heartbeat"; -- default-state = "off"; -- }; -- }; -- -- sound { -- compatible = "audio-graph-card"; -- label = "STM32MP1-DK"; -- routing = -- "Playback" , "MCLK", -- "Capture" , "MCLK", -- "MICL" , "Mic Bias"; -- dais = <&sai2a_port &sai2b_port>; -- status = "okay"; -- }; --}; -- --&cec { -- pinctrl-names = "default", "sleep"; -- pinctrl-0 = <&cec_pins_b>; -- pinctrl-1 = <&cec_pins_sleep_b>; -- status = "okay"; --}; -- --ðernet0 { -- status = "okay"; -- pinctrl-0 = <ðernet0_rgmii_pins_a>; -- pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; -- pinctrl-names = "default", "sleep"; -- phy-mode = "rgmii-id"; -- max-speed = <1000>; -- phy-handle = <&phy0>; -- -- mdio0 { -- #address-cells = <1>; -- #size-cells = <0>; -- compatible = "snps,dwmac-mdio"; -- phy0: ethernet-phy@0 { -- reg = <0>; -- }; -- }; --}; -- --&gpu { -- contiguous-area = <&gpu_reserved>; -- status = "okay"; --}; -- --&i2c1 { -- pinctrl-names = "default", "sleep"; -- pinctrl-0 = <&i2c1_pins_a>; -- pinctrl-1 = <&i2c1_pins_sleep_a>; -- i2c-scl-rising-time-ns = <100>; -- i2c-scl-falling-time-ns = <7>; -- status = "okay"; -- /delete-property/dmas; -- /delete-property/dma-names; -- -- hdmi-transmitter@39 { -- compatible = "sil,sii9022"; -- reg = <0x39>; -- iovcc-supply = <&v3v3_hdmi>; -- cvcc12-supply = <&v1v2_hdmi>; -- reset-gpios = <&gpioa 10 GPIO_ACTIVE_LOW>; -- interrupts = <1 IRQ_TYPE_EDGE_FALLING>; -- interrupt-parent = <&gpiog>; -- pinctrl-names = "default", "sleep"; -- pinctrl-0 = <<dc_pins_a>; -- pinctrl-1 = <<dc_pins_sleep_a>; -- status = "okay"; -- -- ports { -- #address-cells = <1>; -- #size-cells = <0>; -- -- port@0 { -- reg = <0>; -- sii9022_in: endpoint { -- remote-endpoint = <<dc_ep0_out>; -- }; -- }; -- }; - }; -- -- cs42l51: cs42l51@4a { -- compatible = "cirrus,cs42l51"; -- reg = <0x4a>; -- #sound-dai-cells = <0>; -- VL-supply = <&v3v3>; -- VD-supply = <&v1v8_audio>; -- VA-supply = <&v1v8_audio>; -- VAHP-supply = <&v1v8_audio>; -- reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; -- clocks = <&sai2a>; -- clock-names = "MCLK"; -- status = "okay"; -- -- cs42l51_port: port { -- #address-cells = <1>; -- #size-cells = <0>; -- -- cs42l51_tx_endpoint: endpoint@0 { -- reg = <0>; -- remote-endpoint = <&sai2a_endpoint>; -- frame-master; -- bitclock-master; -- }; -- -- cs42l51_rx_endpoint: endpoint@1 { -- reg = <1>; -- remote-endpoint = <&sai2b_endpoint>; -- frame-master; -- bitclock-master; -- }; -- }; -- }; --}; -- --&i2c4 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c4_pins_a>; -- i2c-scl-rising-time-ns = <185>; -- i2c-scl-falling-time-ns = <20>; -- status = "okay"; -- /* spare dmas for other usage */ -- /delete-property/dmas; -- /delete-property/dma-names; -- -- pmic: stpmic@33 { -- compatible = "st,stpmic1"; -- reg = <0x33>; -- interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; -- interrupt-controller; -- #interrupt-cells = <2>; -- status = "okay"; -- -- regulators { -- compatible = "st,stpmic1-regulators"; -- ldo1-supply = <&v3v3>; -- ldo3-supply = <&vdd_ddr>; -- ldo6-supply = <&v3v3>; -- pwr_sw1-supply = <&bst_out>; -- pwr_sw2-supply = <&bst_out>; -- -- vddcore: buck1 { -- regulator-name = "vddcore"; -- regulator-min-microvolt = <800000>; -- regulator-max-microvolt = <1350000>; -- regulator-always-on; -- regulator-initial-mode = <0>; -- regulator-over-current-protection; -- }; -- -- vdd_ddr: buck2 { -- regulator-name = "vdd_ddr"; -- regulator-min-microvolt = <1350000>; -- regulator-max-microvolt = <1350000>; -- regulator-always-on; -- regulator-initial-mode = <0>; -- regulator-over-current-protection; -- }; -- -- vdd: buck3 { -- regulator-name = "vdd"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- st,mask-reset; -- regulator-initial-mode = <0>; -- regulator-over-current-protection; -- }; -- -- v3v3: buck4 { -- regulator-name = "v3v3"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- regulator-over-current-protection; -- regulator-initial-mode = <0>; -- }; -- -- v1v8_audio: ldo1 { -- regulator-name = "v1v8_audio"; -- regulator-min-microvolt = <1800000>; -- regulator-max-microvolt = <1800000>; -- regulator-always-on; -- interrupts = ; -- }; -- -- v3v3_hdmi: ldo2 { -- regulator-name = "v3v3_hdmi"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- interrupts = ; -- }; -- -- vtt_ddr: ldo3 { -- regulator-name = "vtt_ddr"; -- regulator-min-microvolt = <500000>; -- regulator-max-microvolt = <750000>; -- regulator-always-on; -- regulator-over-current-protection; -- }; -- -- vdd_usb: ldo4 { -- regulator-name = "vdd_usb"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- interrupts = ; -- }; -- -- vdda: ldo5 { -- regulator-name = "vdda"; -- regulator-min-microvolt = <2900000>; -- regulator-max-microvolt = <2900000>; -- interrupts = ; -- regulator-boot-on; -- }; -- -- v1v2_hdmi: ldo6 { -- regulator-name = "v1v2_hdmi"; -- regulator-min-microvolt = <1200000>; -- regulator-max-microvolt = <1200000>; -- regulator-always-on; -- interrupts = ; -- }; -- -- vref_ddr: vref_ddr { -- regulator-name = "vref_ddr"; -- regulator-always-on; -- regulator-over-current-protection; -- }; -- -- bst_out: boost { -- regulator-name = "bst_out"; -- interrupts = ; -- }; -- -- vbus_otg: pwr_sw1 { -- regulator-name = "vbus_otg"; -- interrupts = ; -- }; -- -- vbus_sw: pwr_sw2 { -- regulator-name = "vbus_sw"; -- interrupts = ; -- regulator-active-discharge; -- }; -- }; -- -- onkey { -- compatible = "st,stpmic1-onkey"; -- interrupts = , ; -- interrupt-names = "onkey-falling", "onkey-rising"; -- power-off-time-sec = <10>; -- status = "okay"; -- }; -- -- watchdog { -- compatible = "st,stpmic1-wdt"; -- status = "disabled"; -- }; -- }; --}; -- --&ipcc { -- status = "okay"; --}; -- --&iwdg2 { -- timeout-sec = <32>; -- status = "okay"; --}; -- --<dc { -- status = "okay"; -- -- port { -- #address-cells = <1>; -- #size-cells = <0>; -- -- ltdc_ep0_out: endpoint@0 { -- reg = <0>; -- remote-endpoint = <&sii9022_in>; -- }; -- }; --}; -- --&m4_rproc { -- memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, -- <&vdev0vring1>, <&vdev0buffer>; -- mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; -- mbox-names = "vq0", "vq1", "shutdown"; -- interrupt-parent = <&exti>; -- interrupts = <68 1>; -- status = "okay"; --}; -- --&rng1 { -- status = "okay"; --}; -- --&rtc { -- status = "okay"; --}; -- --&sai2 { -- clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; -- clock-names = "pclk", "x8k", "x11k"; -- pinctrl-names = "default", "sleep"; -- pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>; -- pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>; -- status = "okay"; -- -- sai2a: audio-controller@4400b004 { -- #clock-cells = <0>; -- dma-names = "tx"; -- clocks = <&rcc SAI2_K>; -- clock-names = "sai_ck"; -- status = "okay"; -- -- sai2a_port: port { -- sai2a_endpoint: endpoint { -- remote-endpoint = <&cs42l51_tx_endpoint>; -- format = "i2s"; -- mclk-fs = <256>; -- dai-tdm-slot-num = <2>; -- dai-tdm-slot-width = <32>; -- }; -- }; -- }; -- -- sai2b: audio-controller@4400b024 { -- dma-names = "rx"; -- st,sync = <&sai2a 2>; -- clocks = <&rcc SAI2_K>, <&sai2a>; -- clock-names = "sai_ck", "MCLK"; -- status = "okay"; -- -- sai2b_port: port { -- sai2b_endpoint: endpoint { -- remote-endpoint = <&cs42l51_rx_endpoint>; -- format = "i2s"; -- mclk-fs = <256>; -- dai-tdm-slot-num = <2>; -- dai-tdm-slot-width = <32>; -- }; -- }; -- }; --}; -- --&sdmmc1 { -- pinctrl-names = "default", "opendrain", "sleep"; -- pinctrl-0 = <&sdmmc1_b4_pins_a>; -- pinctrl-1 = <&sdmmc1_b4_od_pins_a>; -- pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>; -- broken-cd; -- st,neg-edge; -- bus-width = <4>; -- vmmc-supply = <&v3v3>; -- status = "okay"; --}; -- --&uart4 { -- pinctrl-names = "default"; -- pinctrl-0 = <&uart4_pins_a>; -- status = "okay"; - }; -diff --git a/arch/arm/boot/dts/stm32mp157a-ed1.dts b/arch/arm/boot/dts/stm32mp157a-ed1.dts -new file mode 100644 -index 0000000000000..e7fad7d39476b ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157a-ed1.dts -@@ -0,0 +1,43 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157.dtsi" -+#include "stm32mp15xa.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxaa-pinctrl.dtsi" -+#include "stm32mp157-m4-srm.dtsi" -+#include "stm32mp157-m4-srm-pinctrl.dtsi" -+#include "stm32mp15xx-edx.dtsi" -+ -+/ { -+ model = "STMicroelectronics STM32MP157A eval daughter"; -+ compatible = "st,stm32mp157a-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial0 = &uart4; -+ }; -+ -+ reserved-memory { -+ gpu_reserved: gpu@f6000000 { -+ reg = <0xf6000000 0x8000000>; -+ no-map; -+ }; -+ }; -+}; -+ -+&cpu1{ -+ cpu-supply = <&vddcore>; -+}; -+ -+&gpu { -+ contiguous-area = <&gpu_reserved>; -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157a-ev1.dts b/arch/arm/boot/dts/stm32mp157a-ev1.dts -new file mode 100644 -index 0000000000000..29ecd15c32161 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157a-ev1.dts -@@ -0,0 +1,86 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157a-ed1.dts" -+#include "stm32mp15xx-evx.dtsi" -+#include -+#include -+ -+/ { -+ model = "STMicroelectronics STM32MP157A eval daughter on eval mother"; -+ compatible = "st,stm32mp157a-ev1", "st,stm32mp157a-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial1 = &usart3; -+ ethernet0 = ðernet0; -+ }; -+}; -+ -+&dsi { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ dsi_in: endpoint { -+ remote-endpoint = <<dc_ep0_out>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ dsi_out: endpoint { -+ remote-endpoint = <&dsi_panel_in>; -+ }; -+ }; -+ }; -+ -+ panel_dsi: panel-dsi@0 { -+ compatible = "raydium,rm68200"; -+ reg = <0>; -+ reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; -+ backlight = <&panel_backlight>; -+ power-supply = <&v3v3>; -+ status = "okay"; -+ -+ port { -+ dsi_panel_in: endpoint { -+ remote-endpoint = <&dsi_out>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c2 { -+ gt9147: goodix_ts@5d { -+ compatible = "goodix,gt9147"; -+ reg = <0x5d>; -+ panel = <&panel_dsi>; -+ pinctrl-0 = <&goodix_pins>; -+ pinctrl-names = "default"; -+ status = "okay"; -+ -+ interrupts = <14 IRQ_TYPE_EDGE_RISING>; -+ interrupt-parent = <&stmfx_pinctrl>; -+ }; -+}; -+ -+&m_can1 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&m_can1_pins_a>; -+ pinctrl-1 = <&m_can1_sleep_pins_a>; -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts b/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts -new file mode 100644 -index 0000000000000..372ceb2c71283 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts -@@ -0,0 +1,60 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157c-dk2.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157C-DK2 configured to run Linux A7 examples"; -+ compatible = "st,stm32mp157c-dk2-a7-examples", "st,stm32mp157c-dk2", "st,stm32mp157"; -+}; -+ -+&adc { -+ status = "okay"; -+ -+ adc2: adc@100 { -+ /* Set IRQ mode as example. DMA is the preferred mode, yet. */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ }; -+}; -+ -+&i2c5 { -+ status = "okay"; -+}; -+ -+&timers1 { -+ status = "okay"; -+}; -+ -+&timers3 { -+ status = "okay"; -+}; -+ -+&timers4 { -+ status = "okay"; -+}; -+ -+&timers5 { -+ status = "okay"; -+}; -+ -+&timers6 { -+ status = "okay"; -+}; -+ -+&timers12 { -+ status = "okay"; -+}; -+ -+&uart7 { -+ status = "okay"; -+}; -+ -+&usart3 { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts b/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts -new file mode 100644 -index 0000000000000..14eac740d4e31 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts -@@ -0,0 +1,129 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157c-dk2.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157C-DK2 configured to run M4 examples"; -+ compatible = "st,stm32mp157c-dk2-m4-examples", "st,stm32mp157c-dk2", "st,stm32mp157"; -+}; -+ -+&adc { -+ status = "disabled"; -+}; -+ -+&dac { -+ status = "disabled"; -+}; -+ -+&dma2 { -+ status = "disabled"; -+}; -+ -+&dmamux1 { -+ dma-masters = <&dma1>; -+ dma-channels = <8>; -+}; -+ -+&m4_adc { -+ vref-supply = <&vrefbuf>; -+ status = "okay"; -+}; -+ -+&m4_dac { -+ vref-supply = <&vrefbuf>; -+ status = "okay"; -+}; -+ -+&m4_dma2 { -+ status = "okay"; -+}; -+ -+&m4_crc2 { -+ status = "okay"; -+}; -+ -+&m4_cryp2 { -+ status = "okay"; -+}; -+ -+&m4_hash2 { -+ status = "okay"; -+}; -+ -+&m4_i2c5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_i2c5_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_rng2 { -+ status = "okay"; -+}; -+ -+&m4_rproc { -+ m4_system_resources { -+ status = "okay"; -+ -+ button { -+ compatible = "rproc-srm-dev"; -+ interrupt-parent = <&gpioa>; -+ interrupts = <14 2>; -+ interrupt-names = "irq"; -+ status = "okay"; -+ }; -+ -+ m4_led: m4_led { -+ compatible = "rproc-srm-dev"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_leds_orange_pins>; -+ status = "okay"; -+ }; -+ }; -+}; -+ -+&m4_spi4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_spi4_pins_a>; -+ status = "okay"; -+}; -+ -+ -+&m4_timers2 { -+ status = "okay"; -+}; -+ -+&m4_timers1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_pwm1_pins_a_ch1>; -+ status = "okay"; -+}; -+ -+&m4_uart7 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_uart7_pins_a>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ m4_leds_orange_pins: m4-leds-orange-0 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_pwm1_pins_a_ch1: m4-pwm1-0-ch1 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+}; -+ -+&timers1 { -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts -index 20ea601a546dd..ba1d15de2f2c6 100644 ---- a/arch/arm/boot/dts/stm32mp157c-dk2.dts -+++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts -@@ -6,26 +6,50 @@ - - /dts-v1/; - --#include "stm32mp157a-dk1.dts" -+#include "stm32mp157.dtsi" -+#include "stm32mp15xc.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxac-pinctrl.dtsi" -+#include "stm32mp15xx-dkx.dtsi" -+#include - - / { - model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; - compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; - -- reg18: reg18 { -- compatible = "regulator-fixed"; -- regulator-name = "reg18"; -- regulator-min-microvolt = <1800000>; -- regulator-max-microvolt = <1800000>; -- regulator-always-on; -+ aliases { -+ ethernet0 = ðernet0; -+ serial0 = &uart4; -+ serial1 = &usart3; -+ serial2 = &uart7; -+ serial3 = &usart2; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ reserved-memory { -+ gpu_reserved: gpu@da000000 { -+ reg = <0xda000000 0x4000000>; -+ no-map; -+ }; -+ }; -+ -+ wifi_pwrseq: wifi-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ reset-gpios = <&gpioh 4 GPIO_ACTIVE_LOW>; - }; - }; - -+&cryp1 { -+ status="okay"; -+}; -+ - &dsi { - #address-cells = <1>; - #size-cells = <0>; - status = "okay"; -- phy-dsi-supply = <®18>; - - ports { - #address-cells = <1>; -@@ -46,7 +70,7 @@ - }; - }; - -- panel@0 { -+ panel_otm8009a: panel-otm8009a@0 { - compatible = "orisetech,otm8009a"; - reg = <0>; - reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; -@@ -61,6 +85,31 @@ - }; - }; - -+&i2c1 { -+ touchscreen@2a { -+ compatible = "focaltech,ft6236"; -+ reg = <0x2a>; -+ interrupts = <2 2>; -+ interrupt-parent = <&gpiof>; -+ interrupt-controller; -+ touchscreen-size-x = <480>; -+ touchscreen-size-y = <800>; -+ panel = <&panel_otm8009a>; -+ status = "okay"; -+ }; -+ touchscreen@38 { -+ compatible = "focaltech,ft6236"; -+ reg = <0x38>; -+ interrupts = <2 2>; -+ interrupt-parent = <&gpiof>; -+ interrupt-controller; -+ touchscreen-size-x = <480>; -+ touchscreen-size-y = <800>; -+ panel = <&panel_otm8009a>; -+ status = "okay"; -+ }; -+}; -+ - <dc { - status = "okay"; - -@@ -74,3 +123,49 @@ - }; - }; - }; -+ -+&rtc { -+ st,lsco = ; -+ pinctrl-0 = <&rtc_out2_rmp_pins_a>; -+ pinctrl-names = "default"; -+}; -+ -+/* Wifi */ -+&sdmmc2 { -+ arm,primecell-periphid = <0x10153180>; -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc2_b4_pins_a>; -+ pinctrl-1 = <&sdmmc2_b4_od_pins_a>; -+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>; -+ non-removable; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&v3v3>; -+ mmc-pwrseq = <&wifi_pwrseq>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ brcmf: bcrmf@1 { -+ reg = <1>; -+ compatible = "brcm,bcm4329-fmac"; -+ }; -+}; -+ -+/* Bluetooth */ -+&usart2 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&usart2_pins_a>; -+ pinctrl-1 = <&usart2_sleep_pins_a>; -+ pinctrl-2 = <&usart2_idle_pins_a>; -+ uart-has-rtscts; -+ status = "okay"; -+ -+ bluetooth { -+ shutdown-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>; -+ compatible = "brcm,bcm43438-bt"; -+ max-speed = <3000000>; -+ vbat-supply = <&v3v3>; -+ vddio-supply = <&v3v3>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts -index 1d426ea8bdafa..16ddc0e9f832e 100644 ---- a/arch/arm/boot/dts/stm32mp157c-ed1.dts -+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts -@@ -1,14 +1,17 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* -- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -- * Author: Ludovic Barre for STMicroelectronics. -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. - */ - /dts-v1/; - --#include "stm32mp157c.dtsi" --#include "stm32mp157xaa-pinctrl.dtsi" --#include --#include -+#include "stm32mp157.dtsi" -+#include "stm32mp15xc.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxaa-pinctrl.dtsi" -+#include "stm32mp157-m4-srm.dtsi" -+#include "stm32mp157-m4-srm-pinctrl.dtsi" -+#include "stm32mp15xx-edx.dtsi" - - / { - model = "STMicroelectronics STM32MP157C eval daughter"; -@@ -18,314 +21,27 @@ - stdout-path = "serial0:115200n8"; - }; - -- memory@c0000000 { -- device_type = "memory"; -- reg = <0xC0000000 0x40000000>; -+ aliases { -+ serial0 = &uart4; - }; - - reserved-memory { -- #address-cells = <1>; -- #size-cells = <1>; -- ranges; -- -- mcuram2: mcuram2@10000000 { -- compatible = "shared-dma-pool"; -- reg = <0x10000000 0x40000>; -- no-map; -- }; -- -- vdev0vring0: vdev0vring0@10040000 { -- compatible = "shared-dma-pool"; -- reg = <0x10040000 0x1000>; -- no-map; -- }; -- -- vdev0vring1: vdev0vring1@10041000 { -- compatible = "shared-dma-pool"; -- reg = <0x10041000 0x1000>; -- no-map; -- }; -- -- vdev0buffer: vdev0buffer@10042000 { -- compatible = "shared-dma-pool"; -- reg = <0x10042000 0x4000>; -- no-map; -- }; -- -- mcuram: mcuram@30000000 { -- compatible = "shared-dma-pool"; -- reg = <0x30000000 0x40000>; -+ gpu_reserved: gpu@f6000000 { -+ reg = <0xf6000000 0x8000000>; - no-map; - }; -- -- retram: retram@38000000 { -- compatible = "shared-dma-pool"; -- reg = <0x38000000 0x10000>; -- no-map; -- }; -- -- gpu_reserved: gpu@e8000000 { -- reg = <0xe8000000 0x8000000>; -- no-map; -- }; -- }; -- -- aliases { -- serial0 = &uart4; - }; -+}; - -- reg11: reg11 { -- compatible = "regulator-fixed"; -- regulator-name = "reg11"; -- regulator-min-microvolt = <1100000>; -- regulator-max-microvolt = <1100000>; -- regulator-always-on; -- }; -- -- reg18: reg18 { -- compatible = "regulator-fixed"; -- regulator-name = "reg18"; -- regulator-min-microvolt = <1800000>; -- regulator-max-microvolt = <1800000>; -- regulator-always-on; -- }; -- -- sd_switch: regulator-sd_switch { -- compatible = "regulator-gpio"; -- regulator-name = "sd_switch"; -- regulator-min-microvolt = <1800000>; -- regulator-max-microvolt = <2900000>; -- regulator-type = "voltage"; -- regulator-always-on; -- -- gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; -- gpios-states = <0>; -- states = <1800000 0x1 2900000 0x0>; -- }; -+&cpu1{ -+ cpu-supply = <&vddcore>; - }; - --&dts { -- status = "okay"; -+&cryp1 { -+ status="okay"; - }; - - &gpu { - contiguous-area = <&gpu_reserved>; - status = "okay"; - }; -- --&i2c4 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c4_pins_a>; -- i2c-scl-rising-time-ns = <185>; -- i2c-scl-falling-time-ns = <20>; -- status = "okay"; -- /* spare dmas for other usage */ -- /delete-property/dmas; -- /delete-property/dma-names; -- -- pmic: stpmic@33 { -- compatible = "st,stpmic1"; -- reg = <0x33>; -- interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; -- interrupt-controller; -- #interrupt-cells = <2>; -- status = "okay"; -- -- regulators { -- compatible = "st,stpmic1-regulators"; -- ldo1-supply = <&v3v3>; -- ldo2-supply = <&v3v3>; -- ldo3-supply = <&vdd_ddr>; -- ldo5-supply = <&v3v3>; -- ldo6-supply = <&v3v3>; -- pwr_sw1-supply = <&bst_out>; -- pwr_sw2-supply = <&bst_out>; -- -- vddcore: buck1 { -- regulator-name = "vddcore"; -- regulator-min-microvolt = <800000>; -- regulator-max-microvolt = <1350000>; -- regulator-always-on; -- regulator-initial-mode = <0>; -- regulator-over-current-protection; -- }; -- -- vdd_ddr: buck2 { -- regulator-name = "vdd_ddr"; -- regulator-min-microvolt = <1350000>; -- regulator-max-microvolt = <1350000>; -- regulator-always-on; -- regulator-initial-mode = <0>; -- regulator-over-current-protection; -- }; -- -- vdd: buck3 { -- regulator-name = "vdd"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- st,mask-reset; -- regulator-initial-mode = <0>; -- regulator-over-current-protection; -- }; -- -- v3v3: buck4 { -- regulator-name = "v3v3"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- regulator-over-current-protection; -- regulator-initial-mode = <0>; -- }; -- -- vdda: ldo1 { -- regulator-name = "vdda"; -- regulator-min-microvolt = <2900000>; -- regulator-max-microvolt = <2900000>; -- interrupts = ; -- }; -- -- v2v8: ldo2 { -- regulator-name = "v2v8"; -- regulator-min-microvolt = <2800000>; -- regulator-max-microvolt = <2800000>; -- interrupts = ; -- }; -- -- vtt_ddr: ldo3 { -- regulator-name = "vtt_ddr"; -- regulator-min-microvolt = <500000>; -- regulator-max-microvolt = <750000>; -- regulator-always-on; -- regulator-over-current-protection; -- }; -- -- vdd_usb: ldo4 { -- regulator-name = "vdd_usb"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- interrupts = ; -- }; -- -- vdd_sd: ldo5 { -- regulator-name = "vdd_sd"; -- regulator-min-microvolt = <2900000>; -- regulator-max-microvolt = <2900000>; -- interrupts = ; -- regulator-boot-on; -- }; -- -- v1v8: ldo6 { -- regulator-name = "v1v8"; -- regulator-min-microvolt = <1800000>; -- regulator-max-microvolt = <1800000>; -- interrupts = ; -- }; -- -- vref_ddr: vref_ddr { -- regulator-name = "vref_ddr"; -- regulator-always-on; -- regulator-over-current-protection; -- }; -- -- bst_out: boost { -- regulator-name = "bst_out"; -- interrupts = ; -- }; -- -- vbus_otg: pwr_sw1 { -- regulator-name = "vbus_otg"; -- interrupts = ; -- }; -- -- vbus_sw: pwr_sw2 { -- regulator-name = "vbus_sw"; -- interrupts = ; -- regulator-active-discharge; -- }; -- }; -- -- onkey { -- compatible = "st,stpmic1-onkey"; -- interrupts = , ; -- interrupt-names = "onkey-falling", "onkey-rising"; -- power-off-time-sec = <10>; -- status = "okay"; -- }; -- -- watchdog { -- compatible = "st,stpmic1-wdt"; -- status = "disabled"; -- }; -- }; --}; -- --&ipcc { -- status = "okay"; --}; -- --&iwdg2 { -- timeout-sec = <32>; -- status = "okay"; --}; -- --&m4_rproc { -- memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, -- <&vdev0vring1>, <&vdev0buffer>; -- mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; -- mbox-names = "vq0", "vq1", "shutdown"; -- interrupt-parent = <&exti>; -- interrupts = <68 1>; -- status = "okay"; --}; -- --&rng1 { -- status = "okay"; --}; -- --&rtc { -- status = "okay"; --}; -- --&sdmmc1 { -- pinctrl-names = "default", "opendrain", "sleep"; -- pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; -- pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; -- pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; -- broken-cd; -- st,sig-dir; -- st,neg-edge; -- st,use-ckin; -- bus-width = <4>; -- vmmc-supply = <&vdd_sd>; -- vqmmc-supply = <&sd_switch>; -- status = "okay"; --}; -- --&timers6 { -- status = "okay"; -- /* spare dmas for other usage */ -- /delete-property/dmas; -- /delete-property/dma-names; -- timer@5 { -- status = "okay"; -- }; --}; -- --&uart4 { -- pinctrl-names = "default"; -- pinctrl-0 = <&uart4_pins_a>; -- status = "okay"; --}; -- --&usbphyc_port0 { -- phy-supply = <&vdd_usb>; -- vdda1v1-supply = <®11>; -- vdda1v8-supply = <®18>; --}; -- --&usbphyc_port1 { -- phy-supply = <&vdd_usb>; -- vdda1v1-supply = <®11>; -- vdda1v8-supply = <®18>; --}; -diff --git a/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts -new file mode 100644 -index 0000000000000..8a4eda70d4521 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157c-ev1.dts" -+#include -+ -+/ { -+ model = "STMicroelectronics STM32MP157C-EV1 configured to run Linux A7 examples"; -+ compatible = "st,stm32mp157c-ev1-a7-examples", "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; -+ -+ test_keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ autorepeat; -+ status = "okay"; -+ /* gpio needs vdd core in retention for wakeup */ -+ power-domains = <&pd_core_ret>; -+ -+ button@1 { -+ label = "PA13"; -+ linux,code = ; -+ interrupts-extended = <&gpioa 13 IRQ_TYPE_EDGE_FALLING>; -+ status = "okay"; -+ wakeup-source; -+ }; -+ }; -+}; -+ -+&adc { -+ status = "okay"; -+}; -+ -+&dac { -+ status = "okay"; -+}; -+ -+&timers2 { -+ status = "okay"; -+}; -+ -+&timers8 { -+ status = "okay"; -+}; -+ -+&timers12 { -+ status = "okay"; -+}; -+ -+&usart3 { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts -new file mode 100644 -index 0000000000000..b1bb38efbfa80 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts -@@ -0,0 +1,146 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157c-ev1.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157C-EV1 configured to run M4 examples"; -+ compatible = "st,stm32mp157c-ev1-m4-examples", "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; -+}; -+ -+&adc { -+ status = "disabled"; -+}; -+ -+&dac { -+ status = "disabled"; -+}; -+ -+&dcmi { -+ status = "disabled"; -+}; -+ -+&dma2 { -+ status = "disabled"; -+}; -+ -+&dmamux1 { -+ dma-masters = <&dma1>; -+ dma-channels = <8>; -+}; -+ -+&fmc { -+ status = "disabled"; -+}; -+ -+&i2c5 { -+ status = "disabled"; -+}; -+ -+&m4_adc { -+ vref-supply = <&vdda>; -+ status = "okay"; -+}; -+ -+&m4_crc2 { -+ status = "okay"; -+}; -+ -+&m4_cryp2 { -+ status = "okay"; -+}; -+ -+&m4_dac { -+ vref-supply = <&vdda>; -+ status = "okay"; -+}; -+ -+&m4_dma2 { -+ status = "okay"; -+}; -+ -+&m4_hash2 { -+ status = "okay"; -+}; -+ -+&m4_i2c5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_i2c5_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_qspi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_qspi_clk_pins_a &m4_qspi_bk1_pins_a -+ &m4_qspi_bk2_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_rproc { -+ m4_system_resources { -+ status = "okay"; -+ -+ /* button { -+ compatible = "rproc-srm-dev"; -+ interrupt-parent = <&gpioa>; -+ interrupts = <14 2>; -+ interrupt-names = "irq"; -+ status = "okay"; -+ };*/ -+ -+ m4_led: m4_led { -+ compatible = "rproc-srm-dev"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_leds_orange_pins>; -+ status = "okay"; -+ }; -+ }; -+}; -+ -+&m4_rng2 { -+ status = "okay"; -+}; -+ -+&m4_spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_spi1_pins_a>; -+ status = "okay"; -+}; -+ -+ -+&m4_timers2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_pwm2_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_usart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_usart3_pins_a>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ m4_leds_orange_pins: m4-leds-orange-0 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "disabled"; -+}; -+ -+&sai2b { -+ status = "disabled"; -+}; -+ -+&timers2 { -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts -index 91fc0a315c491..c60727d9b1ae0 100644 ---- a/arch/arm/boot/dts/stm32mp157c-ev1.dts -+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts -@@ -1,13 +1,14 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* -- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -- * Author: Ludovic Barre for STMicroelectronics. -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. - */ - /dts-v1/; - - #include "stm32mp157c-ed1.dts" --#include -+#include "stm32mp15xx-evx.dtsi" - #include -+#include - - / { - model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; -@@ -18,90 +19,14 @@ - }; - - aliases { -- serial0 = &uart4; -+ serial1 = &usart3; - ethernet0 = ðernet0; - }; -- -- clocks { -- clk_ext_camera: clk-ext-camera { -- #clock-cells = <0>; -- compatible = "fixed-clock"; -- clock-frequency = <24000000>; -- }; -- }; -- -- joystick { -- compatible = "gpio-keys"; -- #size-cells = <0>; -- pinctrl-0 = <&joystick_pins>; -- pinctrl-names = "default"; -- button-0 { -- label = "JoySel"; -- linux,code = ; -- interrupt-parent = <&stmfx_pinctrl>; -- interrupts = <0 IRQ_TYPE_EDGE_RISING>; -- }; -- button-1 { -- label = "JoyDown"; -- linux,code = ; -- interrupt-parent = <&stmfx_pinctrl>; -- interrupts = <1 IRQ_TYPE_EDGE_RISING>; -- }; -- button-2 { -- label = "JoyLeft"; -- linux,code = ; -- interrupt-parent = <&stmfx_pinctrl>; -- interrupts = <2 IRQ_TYPE_EDGE_RISING>; -- }; -- button-3 { -- label = "JoyRight"; -- linux,code = ; -- interrupt-parent = <&stmfx_pinctrl>; -- interrupts = <3 IRQ_TYPE_EDGE_RISING>; -- }; -- button-4 { -- label = "JoyUp"; -- linux,code = ; -- interrupt-parent = <&stmfx_pinctrl>; -- interrupts = <4 IRQ_TYPE_EDGE_RISING>; -- }; -- }; -- -- panel_backlight: panel-backlight { -- compatible = "gpio-backlight"; -- gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; -- default-on; -- status = "okay"; -- }; --}; -- --&cec { -- pinctrl-names = "default"; -- pinctrl-0 = <&cec_pins_a>; -- status = "okay"; --}; -- --&dcmi { -- status = "okay"; -- pinctrl-names = "default", "sleep"; -- pinctrl-0 = <&dcmi_pins_a>; -- pinctrl-1 = <&dcmi_sleep_pins_a>; -- -- port { -- dcmi_0: endpoint { -- remote-endpoint = <&ov5640_0>; -- bus-width = <8>; -- hsync-active = <0>; -- vsync-active = <0>; -- pclk-sample = <1>; -- }; -- }; - }; - - &dsi { - #address-cells = <1>; - #size-cells = <0>; -- phy-dsi-supply = <®18>; - status = "okay"; - - ports { -@@ -123,7 +48,7 @@ - }; - }; - -- panel-dsi@0 { -+ panel_dsi: panel-dsi@0 { - compatible = "raydium,rm68200"; - reg = <0>; - reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; -@@ -139,113 +64,17 @@ - }; - }; - --ðernet0 { -- status = "okay"; -- pinctrl-0 = <ðernet0_rgmii_pins_a>; -- pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; -- pinctrl-names = "default", "sleep"; -- phy-mode = "rgmii-id"; -- max-speed = <1000>; -- phy-handle = <&phy0>; -- -- mdio0 { -- #address-cells = <1>; -- #size-cells = <0>; -- compatible = "snps,dwmac-mdio"; -- phy0: ethernet-phy@0 { -- reg = <0>; -- }; -- }; --}; -- --&fmc { -- pinctrl-names = "default", "sleep"; -- pinctrl-0 = <&fmc_pins_a>; -- pinctrl-1 = <&fmc_sleep_pins_a>; -- status = "okay"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- nand@0 { -- reg = <0>; -- nand-on-flash-bbt; -- #address-cells = <1>; -- #size-cells = <1>; -- }; --}; -- - &i2c2 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c2_pins_a>; -- i2c-scl-rising-time-ns = <185>; -- i2c-scl-falling-time-ns = <20>; -- status = "okay"; -- -- ov5640: camera@3c { -- compatible = "ovti,ov5640"; -- reg = <0x3c>; -- clocks = <&clk_ext_camera>; -- clock-names = "xclk"; -- DOVDD-supply = <&v2v8>; -- powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; -- reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; -- rotation = <180>; -+ gt9147: goodix_ts@5d { -+ compatible = "goodix,gt9147"; -+ reg = <0x5d>; -+ panel = <&panel_dsi>; -+ pinctrl-0 = <&goodix_pins>; -+ pinctrl-names = "default"; - status = "okay"; - -- port { -- ov5640_0: endpoint { -- remote-endpoint = <&dcmi_0>; -- bus-width = <8>; -- data-shift = <2>; /* lines 9:2 are used */ -- hsync-active = <0>; -- vsync-active = <0>; -- pclk-sample = <1>; -- }; -- }; -- }; -- -- stmfx: stmfx@42 { -- compatible = "st,stmfx-0300"; -- reg = <0x42>; -- interrupts = <8 IRQ_TYPE_EDGE_RISING>; -- interrupt-parent = <&gpioi>; -- vdd-supply = <&v3v3>; -- -- stmfx_pinctrl: stmfx-pin-controller { -- compatible = "st,stmfx-0300-pinctrl"; -- gpio-controller; -- #gpio-cells = <2>; -- interrupt-controller; -- #interrupt-cells = <2>; -- gpio-ranges = <&stmfx_pinctrl 0 0 24>; -- -- joystick_pins: joystick { -- pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; -- bias-pull-down; -- }; -- }; -- }; --}; -- --&i2c5 { -- pinctrl-names = "default"; -- pinctrl-0 = <&i2c5_pins_a>; -- i2c-scl-rising-time-ns = <185>; -- i2c-scl-falling-time-ns = <20>; -- status = "okay"; --}; -- --<dc { -- status = "okay"; -- -- port { -- #address-cells = <1>; -- #size-cells = <0>; -- -- ltdc_ep0_out: endpoint@0 { -- reg = <0>; -- remote-endpoint = <&dsi_in>; -- }; -+ interrupts = <14 IRQ_TYPE_EDGE_RISING>; -+ interrupt-parent = <&stmfx_pinctrl>; - }; - }; - -@@ -255,97 +84,3 @@ - pinctrl-1 = <&m_can1_sleep_pins_a>; - status = "okay"; - }; -- --&qspi { -- pinctrl-names = "default", "sleep"; -- pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; -- pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; -- reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- flash0: mx66l51235l@0 { -- compatible = "jedec,spi-nor"; -- reg = <0>; -- spi-rx-bus-width = <4>; -- spi-max-frequency = <108000000>; -- #address-cells = <1>; -- #size-cells = <1>; -- }; -- -- flash1: mx66l51235l@1 { -- compatible = "jedec,spi-nor"; -- reg = <1>; -- spi-rx-bus-width = <4>; -- spi-max-frequency = <108000000>; -- #address-cells = <1>; -- #size-cells = <1>; -- }; --}; -- --&spi1 { -- pinctrl-names = "default"; -- pinctrl-0 = <&spi1_pins_a>; -- status = "disabled"; --}; -- --&timers2 { -- /* spare dmas for other usage (un-delete to enable pwm capture) */ -- /delete-property/dmas; -- /delete-property/dma-names; -- status = "disabled"; -- pwm { -- pinctrl-0 = <&pwm2_pins_a>; -- pinctrl-names = "default"; -- status = "okay"; -- }; -- timer@1 { -- status = "okay"; -- }; --}; -- --&timers8 { -- /delete-property/dmas; -- /delete-property/dma-names; -- status = "disabled"; -- pwm { -- pinctrl-0 = <&pwm8_pins_a>; -- pinctrl-names = "default"; -- status = "okay"; -- }; -- timer@7 { -- status = "okay"; -- }; --}; -- --&timers12 { -- /delete-property/dmas; -- /delete-property/dma-names; -- status = "disabled"; -- pwm { -- pinctrl-0 = <&pwm12_pins_a>; -- pinctrl-names = "default"; -- status = "okay"; -- }; -- timer@11 { -- status = "okay"; -- }; --}; -- --&usbh_ehci { -- phys = <&usbphyc_port0>; -- phy-names = "usb"; -- status = "okay"; --}; -- --&usbotg_hs { -- dr_mode = "peripheral"; -- phys = <&usbphyc_port1 0>; -- phy-names = "usb2-phy"; -- status = "okay"; --}; -- --&usbphyc { -- status = "okay"; --}; -diff --git a/arch/arm/boot/dts/stm32mp157d-dk1.dts b/arch/arm/boot/dts/stm32mp157d-dk1.dts -new file mode 100644 -index 0000000000000..aa98012fd32d8 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157d-dk1.dts -@@ -0,0 +1,35 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157.dtsi" -+#include "stm32mp15xd.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxac-pinctrl.dtsi" -+#include "stm32mp15xx-dkx.dtsi" -+/ { -+ model = "STMicroelectronics STM32MP157D-DK1 Discovery Board"; -+ compatible = "st,stm32mp157d-dk1", "st,stm32mp157"; -+ -+ aliases { -+ ethernet0 = ðernet0; -+ serial0 = &uart4; -+ serial1 = &usart3; -+ serial2 = &uart7; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ reserved-memory { -+ gpu_reserved: gpu@da000000 { -+ reg = <0xda000000 0x4000000>; -+ no-map; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157d-ed1.dts b/arch/arm/boot/dts/stm32mp157d-ed1.dts -new file mode 100644 -index 0000000000000..aaf9adf51c55c ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157d-ed1.dts -@@ -0,0 +1,43 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157.dtsi" -+#include "stm32mp15xd.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxaa-pinctrl.dtsi" -+#include "stm32mp157-m4-srm.dtsi" -+#include "stm32mp157-m4-srm-pinctrl.dtsi" -+#include "stm32mp15xx-edx.dtsi" -+ -+/ { -+ model = "STMicroelectronics STM32MP157D eval daughter"; -+ compatible = "st,stm32mp157d-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial0 = &uart4; -+ }; -+ -+ reserved-memory { -+ gpu_reserved: gpu@f6000000 { -+ reg = <0xf6000000 0x8000000>; -+ no-map; -+ }; -+ }; -+}; -+ -+&cpu1{ -+ cpu-supply = <&vddcore>; -+}; -+ -+&gpu { -+ contiguous-area = <&gpu_reserved>; -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157d-ev1.dts b/arch/arm/boot/dts/stm32mp157d-ev1.dts -new file mode 100644 -index 0000000000000..a4752c100ef93 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157d-ev1.dts -@@ -0,0 +1,86 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157d-ed1.dts" -+#include "stm32mp15xx-evx.dtsi" -+#include -+#include -+ -+/ { -+ model = "STMicroelectronics STM32MP157D eval daughter on eval mother"; -+ compatible = "st,stm32mp157d-ev1", "st,stm32mp157d-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial1 = &usart3; -+ ethernet0 = ðernet0; -+ }; -+}; -+ -+&dsi { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ dsi_in: endpoint { -+ remote-endpoint = <<dc_ep0_out>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ dsi_out: endpoint { -+ remote-endpoint = <&dsi_panel_in>; -+ }; -+ }; -+ }; -+ -+ panel_dsi: panel-dsi@0 { -+ compatible = "raydium,rm68200"; -+ reg = <0>; -+ reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; -+ backlight = <&panel_backlight>; -+ power-supply = <&v3v3>; -+ status = "okay"; -+ -+ port { -+ dsi_panel_in: endpoint { -+ remote-endpoint = <&dsi_out>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c2 { -+ gt9147: goodix_ts@5d { -+ compatible = "goodix,gt9147"; -+ reg = <0x5d>; -+ panel = <&panel_dsi>; -+ pinctrl-0 = <&goodix_pins>; -+ pinctrl-names = "default"; -+ status = "okay"; -+ -+ interrupts = <14 IRQ_TYPE_EDGE_RISING>; -+ interrupt-parent = <&stmfx_pinctrl>; -+ }; -+}; -+ -+&m_can1 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&m_can1_pins_a>; -+ pinctrl-1 = <&m_can1_sleep_pins_a>; -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts b/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts -new file mode 100644 -index 0000000000000..339e24b91616b ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts -@@ -0,0 +1,52 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157f-dk2.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157F-DK2 configured to run Linux A7 examples"; -+ compatible = "st,stm32mp157f-dk2-a7-examples", "st,stm32mp157f-dk2", "st,stm32mp157"; -+}; -+ -+&adc { -+ status = "okay"; -+ -+ adc2: adc@100 { -+ /* Set IRQ mode as example. DMA is the preferred mode, yet. */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ }; -+}; -+ -+&i2c5 { -+ status = "okay"; -+}; -+ -+&timers1 { -+ status = "okay"; -+}; -+ -+&timers3 { -+ status = "okay"; -+}; -+ -+&timers4 { -+ status = "okay"; -+}; -+ -+&timers5 { -+ status = "okay"; -+}; -+ -+&timers6 { -+ status = "okay"; -+}; -+ -+&timers12 { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts b/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts -new file mode 100644 -index 0000000000000..72652299743b9 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts -@@ -0,0 +1,129 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157f-dk2.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157F-DK2 configured to run M4 examples"; -+ compatible = "st,stm32mp157f-dk2-m4-examples", "st,stm32mp157f-dk2", "st,stm32mp157"; -+}; -+ -+&adc { -+ status = "disabled"; -+}; -+ -+&dac { -+ status = "disabled"; -+}; -+ -+&dma2 { -+ status = "disabled"; -+}; -+ -+&dmamux1 { -+ dma-masters = <&dma1>; -+ dma-channels = <8>; -+}; -+ -+&m4_adc { -+ vref-supply = <&vrefbuf>; -+ status = "okay"; -+}; -+ -+&m4_dac { -+ vref-supply = <&vrefbuf>; -+ status = "okay"; -+}; -+ -+&m4_dma2 { -+ status = "okay"; -+}; -+ -+&m4_crc2 { -+ status = "okay"; -+}; -+ -+&m4_cryp2 { -+ status = "okay"; -+}; -+ -+&m4_hash2 { -+ status = "okay"; -+}; -+ -+&m4_i2c5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_i2c5_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_rng2 { -+ status = "okay"; -+}; -+ -+&m4_rproc { -+ m4_system_resources { -+ status = "okay"; -+ -+ button { -+ compatible = "rproc-srm-dev"; -+ interrupt-parent = <&gpioa>; -+ interrupts = <14 2>; -+ interrupt-names = "irq"; -+ status = "okay"; -+ }; -+ -+ m4_led: m4_led { -+ compatible = "rproc-srm-dev"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_leds_orange_pins>; -+ status = "okay"; -+ }; -+ }; -+}; -+ -+&m4_spi4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_spi4_pins_a>; -+ status = "okay"; -+}; -+ -+ -+&m4_timers2 { -+ status = "okay"; -+}; -+ -+&m4_timers1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_pwm1_pins_a_ch1>; -+ status = "okay"; -+}; -+ -+&m4_uart7 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_uart7_pins_a>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ m4_leds_orange_pins: m4-leds-orange-0 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+ -+ m4_pwm1_pins_a_ch1: m4-pwm1-0-ch1 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+}; -+ -+&timers1 { -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157f-dk2.dts b/arch/arm/boot/dts/stm32mp157f-dk2.dts -new file mode 100644 -index 0000000000000..1123d0f3ed4a5 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157f-dk2.dts -@@ -0,0 +1,171 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157.dtsi" -+#include "stm32mp15xf.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxac-pinctrl.dtsi" -+#include "stm32mp15xx-dkx.dtsi" -+#include -+ -+/ { -+ model = "STMicroelectronics STM32MP157F-DK2 Discovery Board"; -+ compatible = "st,stm32mp157f-dk2", "st,stm32mp157"; -+ -+ aliases { -+ ethernet0 = ðernet0; -+ serial0 = &uart4; -+ serial1 = &usart3; -+ serial2 = &uart7; -+ serial3 = &usart2; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ reserved-memory { -+ gpu_reserved: gpu@da000000 { -+ reg = <0xda000000 0x4000000>; -+ no-map; -+ }; -+ }; -+ -+ wifi_pwrseq: wifi-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ reset-gpios = <&gpioh 4 GPIO_ACTIVE_LOW>; -+ }; -+}; -+ -+&cryp1 { -+ status="okay"; -+}; -+ -+&dsi { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ dsi_in: endpoint { -+ remote-endpoint = <<dc_ep1_out>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ dsi_out: endpoint { -+ remote-endpoint = <&panel_in>; -+ }; -+ }; -+ }; -+ -+ panel_otm8009a: panel-otm8009a@0 { -+ compatible = "orisetech,otm8009a"; -+ reg = <0>; -+ reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; -+ power-supply = <&v3v3>; -+ status = "okay"; -+ -+ port { -+ panel_in: endpoint { -+ remote-endpoint = <&dsi_out>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c1 { -+ touchscreen@2a { -+ compatible = "focaltech,ft6236"; -+ reg = <0x2a>; -+ interrupts = <2 2>; -+ interrupt-parent = <&gpiof>; -+ interrupt-controller; -+ touchscreen-size-x = <480>; -+ touchscreen-size-y = <800>; -+ panel = <&panel_otm8009a>; -+ status = "okay"; -+ }; -+ touchscreen@38 { -+ compatible = "focaltech,ft6236"; -+ reg = <0x38>; -+ interrupts = <2 2>; -+ interrupt-parent = <&gpiof>; -+ interrupt-controller; -+ touchscreen-size-x = <480>; -+ touchscreen-size-y = <800>; -+ panel = <&panel_otm8009a>; -+ status = "okay"; -+ }; -+}; -+ -+<dc { -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ltdc_ep1_out: endpoint@1 { -+ reg = <1>; -+ remote-endpoint = <&dsi_in>; -+ }; -+ }; -+}; -+ -+&rtc { -+ st,lsco = ; -+ pinctrl-0 = <&rtc_out2_rmp_pins_a>; -+ pinctrl-names = "default"; -+}; -+ -+/* Wifi */ -+&sdmmc2 { -+ arm,primecell-periphid = <0x10153180>; -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc2_b4_pins_a>; -+ pinctrl-1 = <&sdmmc2_b4_od_pins_a>; -+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>; -+ non-removable; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&v3v3>; -+ mmc-pwrseq = <&wifi_pwrseq>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ brcmf: bcrmf@1 { -+ reg = <1>; -+ compatible = "brcm,bcm4329-fmac"; -+ }; -+}; -+ -+/* Bluetooth */ -+&usart2 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&usart2_pins_a>; -+ pinctrl-1 = <&usart2_sleep_pins_a>; -+ pinctrl-2 = <&usart2_idle_pins_a>; -+ uart-has-rtscts; -+ status = "okay"; -+ -+ bluetooth { -+ shutdown-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>; -+ compatible = "brcm,bcm43438-bt"; -+ max-speed = <3000000>; -+ vbat-supply = <&v3v3>; -+ vddio-supply = <&v3v3>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157f-ed1.dts b/arch/arm/boot/dts/stm32mp157f-ed1.dts -new file mode 100644 -index 0000000000000..7ddb96a0ef5d9 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157f-ed1.dts -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157.dtsi" -+#include "stm32mp15xf.dtsi" -+#include "stm32mp15-pinctrl.dtsi" -+#include "stm32mp15xxaa-pinctrl.dtsi" -+#include "stm32mp157-m4-srm.dtsi" -+#include "stm32mp157-m4-srm-pinctrl.dtsi" -+#include "stm32mp15xx-edx.dtsi" -+ -+/ { -+ model = "STMicroelectronics STM32MP157F eval daughter"; -+ compatible = "st,stm32mp157f-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial0 = &uart4; -+ }; -+ -+ reserved-memory { -+ gpu_reserved: gpu@f6000000 { -+ reg = <0xf6000000 0x8000000>; -+ no-map; -+ }; -+ }; -+}; -+ -+&cpu1{ -+ cpu-supply = <&vddcore>; -+}; -+ -+&cryp1 { -+ status="okay"; -+}; -+ -+&gpu { -+ contiguous-area = <&gpu_reserved>; -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts -new file mode 100644 -index 0000000000000..17d92b7bebdb1 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts -@@ -0,0 +1,53 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157f-ev1.dts" -+#include -+ -+/ { -+ model = "STMicroelectronics STM32MP157F-EV1 configured to run Linux A7 examples"; -+ compatible = "st,stm32mp157f-ev1-a7-examples", "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; -+ -+ test_keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ autorepeat; -+ status = "okay"; -+ /* gpio needs vdd core in retention for wakeup */ -+ power-domains = <&pd_core_ret>; -+ -+ button@1 { -+ label = "PA13"; -+ linux,code = ; -+ interrupts-extended = <&gpioa 13 IRQ_TYPE_EDGE_FALLING>; -+ status = "okay"; -+ wakeup-source; -+ }; -+ }; -+}; -+ -+&adc { -+ status = "okay"; -+}; -+ -+&dac { -+ status = "okay"; -+}; -+ -+&timers2 { -+ status = "okay"; -+}; -+ -+&timers8 { -+ status = "okay"; -+}; -+ -+&timers12 { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts -new file mode 100644 -index 0000000000000..d508be27666a5 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts -@@ -0,0 +1,146 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157f-ev1.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157F-EV1 configured to run M4 examples"; -+ compatible = "st,stm32mp157f-ev1-m4-examples", "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; -+}; -+ -+&adc { -+ status = "disabled"; -+}; -+ -+&dac { -+ status = "disabled"; -+}; -+ -+&dcmi { -+ status = "disabled"; -+}; -+ -+&dma2 { -+ status = "disabled"; -+}; -+ -+&dmamux1 { -+ dma-masters = <&dma1>; -+ dma-channels = <8>; -+}; -+ -+&fmc { -+ status = "disabled"; -+}; -+ -+&i2c5 { -+ status = "disabled"; -+}; -+ -+&m4_adc { -+ vref-supply = <&vdda>; -+ status = "okay"; -+}; -+ -+&m4_crc2 { -+ status = "okay"; -+}; -+ -+&m4_cryp2 { -+ status = "okay"; -+}; -+ -+&m4_dac { -+ vref-supply = <&vdda>; -+ status = "okay"; -+}; -+ -+&m4_dma2 { -+ status = "okay"; -+}; -+ -+&m4_hash2 { -+ status = "okay"; -+}; -+ -+&m4_i2c5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_i2c5_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_qspi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_qspi_clk_pins_a &m4_qspi_bk1_pins_a -+ &m4_qspi_bk2_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_rproc { -+ m4_system_resources { -+ status = "okay"; -+ -+ /* button { -+ compatible = "rproc-srm-dev"; -+ interrupt-parent = <&gpioa>; -+ interrupts = <14 2>; -+ interrupt-names = "irq"; -+ status = "okay"; -+ };*/ -+ -+ m4_led: m4_led { -+ compatible = "rproc-srm-dev"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_leds_orange_pins>; -+ status = "okay"; -+ }; -+ }; -+}; -+ -+&m4_rng2 { -+ status = "okay"; -+}; -+ -+&m4_spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_spi1_pins_a>; -+ status = "okay"; -+}; -+ -+ -+&m4_timers2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_pwm2_pins_a>; -+ status = "okay"; -+}; -+ -+&m4_usart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&m4_usart3_pins_a>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ m4_leds_orange_pins: m4-leds-orange-0 { -+ pins { -+ pinmux = ; -+ }; -+ }; -+}; -+ -+&qspi { -+ status = "disabled"; -+}; -+ -+&sai2b { -+ status = "disabled"; -+}; -+ -+&timers2 { -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157f-ev1.dts b/arch/arm/boot/dts/stm32mp157f-ev1.dts -new file mode 100644 -index 0000000000000..0c18333c07cf3 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp157f-ev1.dts -@@ -0,0 +1,86 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157f-ed1.dts" -+#include "stm32mp15xx-evx.dtsi" -+#include -+#include -+ -+/ { -+ model = "STMicroelectronics STM32MP157F eval daughter on eval mother"; -+ compatible = "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial1 = &usart3; -+ ethernet0 = ðernet0; -+ }; -+}; -+ -+&dsi { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ dsi_in: endpoint { -+ remote-endpoint = <<dc_ep0_out>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ dsi_out: endpoint { -+ remote-endpoint = <&dsi_panel_in>; -+ }; -+ }; -+ }; -+ -+ panel_dsi: panel-dsi@0 { -+ compatible = "raydium,rm68200"; -+ reg = <0>; -+ reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; -+ backlight = <&panel_backlight>; -+ power-supply = <&v3v3>; -+ status = "okay"; -+ -+ port { -+ dsi_panel_in: endpoint { -+ remote-endpoint = <&dsi_out>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c2 { -+ gt9147: goodix_ts@5d { -+ compatible = "goodix,gt9147"; -+ reg = <0x5d>; -+ panel = <&panel_dsi>; -+ pinctrl-0 = <&goodix_pins>; -+ pinctrl-names = "default"; -+ status = "okay"; -+ -+ interrupts = <14 IRQ_TYPE_EDGE_RISING>; -+ interrupt-parent = <&stmfx_pinctrl>; -+ }; -+}; -+ -+&m_can1 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&m_can1_pins_a>; -+ pinctrl-1 = <&m_can1_sleep_pins_a>; -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp157xaa-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157xaa-pinctrl.dtsi -deleted file mode 100644 -index 875adf5e1e303..0000000000000 ---- a/arch/arm/boot/dts/stm32mp157xaa-pinctrl.dtsi -+++ /dev/null -@@ -1,90 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -- */ -- --#include "stm32mp157-pinctrl.dtsi" --/ { -- soc { -- pinctrl: pin-controller@50002000 { -- st,package = ; -- -- gpioa: gpio@50002000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 0 16>; -- }; -- -- gpiob: gpio@50003000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 16 16>; -- }; -- -- gpioc: gpio@50004000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 32 16>; -- }; -- -- gpiod: gpio@50005000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 48 16>; -- }; -- -- gpioe: gpio@50006000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 64 16>; -- }; -- -- gpiof: gpio@50007000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 80 16>; -- }; -- -- gpiog: gpio@50008000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 96 16>; -- }; -- -- gpioh: gpio@50009000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 112 16>; -- }; -- -- gpioi: gpio@5000a000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 128 16>; -- }; -- -- gpioj: gpio@5000b000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 144 16>; -- }; -- -- gpiok: gpio@5000c000 { -- status = "okay"; -- ngpios = <8>; -- gpio-ranges = <&pinctrl 0 160 8>; -- }; -- }; -- -- pinctrl_z: pin-controller-z@54004000 { -- st,package = ; -- -- gpioz: gpio@54004000 { -- status = "okay"; -- ngpios = <8>; -- gpio-ranges = <&pinctrl_z 0 400 8>; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/stm32mp157xab-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157xab-pinctrl.dtsi -deleted file mode 100644 -index 961fa12a59c31..0000000000000 ---- a/arch/arm/boot/dts/stm32mp157xab-pinctrl.dtsi -+++ /dev/null -@@ -1,62 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -- */ -- --#include "stm32mp157-pinctrl.dtsi" --/ { -- soc { -- pinctrl: pin-controller@50002000 { -- st,package = ; -- -- gpioa: gpio@50002000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 0 16>; -- }; -- -- gpiob: gpio@50003000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 16 16>; -- }; -- -- gpioc: gpio@50004000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 32 16>; -- }; -- -- gpiod: gpio@50005000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 48 16>; -- }; -- -- gpioe: gpio@50006000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 64 16>; -- }; -- -- gpiof: gpio@50007000 { -- status = "okay"; -- ngpios = <6>; -- gpio-ranges = <&pinctrl 6 86 6>; -- }; -- -- gpiog: gpio@50008000 { -- status = "okay"; -- ngpios = <10>; -- gpio-ranges = <&pinctrl 6 102 10>; -- }; -- -- gpioh: gpio@50009000 { -- status = "okay"; -- ngpios = <2>; -- gpio-ranges = <&pinctrl 0 112 2>; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/stm32mp157xac-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157xac-pinctrl.dtsi -deleted file mode 100644 -index 26600f188d251..0000000000000 ---- a/arch/arm/boot/dts/stm32mp157xac-pinctrl.dtsi -+++ /dev/null -@@ -1,78 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -- */ -- --#include "stm32mp157-pinctrl.dtsi" --/ { -- soc { -- pinctrl: pin-controller@50002000 { -- st,package = ; -- -- gpioa: gpio@50002000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 0 16>; -- }; -- -- gpiob: gpio@50003000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 16 16>; -- }; -- -- gpioc: gpio@50004000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 32 16>; -- }; -- -- gpiod: gpio@50005000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 48 16>; -- }; -- -- gpioe: gpio@50006000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 64 16>; -- }; -- -- gpiof: gpio@50007000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 80 16>; -- }; -- -- gpiog: gpio@50008000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 96 16>; -- }; -- -- gpioh: gpio@50009000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 112 16>; -- }; -- -- gpioi: gpio@5000a000 { -- status = "okay"; -- ngpios = <12>; -- gpio-ranges = <&pinctrl 0 128 12>; -- }; -- }; -- -- pinctrl_z: pin-controller-z@54004000 { -- st,package = ; -- -- gpioz: gpio@54004000 { -- status = "okay"; -- ngpios = <8>; -- gpio-ranges = <&pinctrl_z 0 400 8>; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/stm32mp157xad-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157xad-pinctrl.dtsi -deleted file mode 100644 -index 910113f3e69ae..0000000000000 ---- a/arch/arm/boot/dts/stm32mp157xad-pinctrl.dtsi -+++ /dev/null -@@ -1,62 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -- */ -- --#include "stm32mp157-pinctrl.dtsi" --/ { -- soc { -- pinctrl: pin-controller@50002000 { -- st,package = ; -- -- gpioa: gpio@50002000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 0 16>; -- }; -- -- gpiob: gpio@50003000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 16 16>; -- }; -- -- gpioc: gpio@50004000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 32 16>; -- }; -- -- gpiod: gpio@50005000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 48 16>; -- }; -- -- gpioe: gpio@50006000 { -- status = "okay"; -- ngpios = <16>; -- gpio-ranges = <&pinctrl 0 64 16>; -- }; -- -- gpiof: gpio@50007000 { -- status = "okay"; -- ngpios = <6>; -- gpio-ranges = <&pinctrl 6 86 6>; -- }; -- -- gpiog: gpio@50008000 { -- status = "okay"; -- ngpios = <10>; -- gpio-ranges = <&pinctrl 6 102 10>; -- }; -- -- gpioh: gpio@50009000 { -- status = "okay"; -- ngpios = <2>; -- gpio-ranges = <&pinctrl 0 112 2>; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/stm32mp15xa.dtsi b/arch/arm/boot/dts/stm32mp15xa.dtsi -new file mode 100644 -index 0000000000000..5ed7e594f4cd9 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xa.dtsi -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+&cpu0_opp_table { -+ opp-650000000 { -+ opp-hz = /bits/ 64 <650000000>; -+ opp-microvolt = <1200000>; -+ opp-supported-hw = <0x1>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xc.dtsi b/arch/arm/boot/dts/stm32mp15xc.dtsi -new file mode 100644 -index 0000000000000..adc1568a72850 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xc.dtsi -@@ -0,0 +1,20 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+#include "stm32mp15xa.dtsi" -+ -+/ { -+ soc { -+ cryp1: cryp@54001000 { -+ compatible = "st,stm32mp1-cryp"; -+ reg = <0x54001000 0x400>; -+ interrupts = ; -+ clocks = <&scmi0_clk CK_SCMI0_CRYP1>; -+ resets = <&scmi0_reset RST_SCMI0_CRYP1>; -+ status = "disabled"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xd.dtsi b/arch/arm/boot/dts/stm32mp15xd.dtsi -new file mode 100644 -index 0000000000000..e2f8b1297c33d ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xd.dtsi -@@ -0,0 +1,42 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+&cpu0_opp_table { -+ opp-800000000 { -+ opp-hz = /bits/ 64 <800000000>; -+ opp-microvolt = <1350000>; -+ opp-supported-hw = <0x2>; -+ }; -+ opp-400000000 { -+ opp-hz = /bits/ 64 <400000000>; -+ opp-microvolt = <1200000>; -+ opp-supported-hw = <0x2>; -+ opp-suspend; -+ }; -+}; -+ -+&cpu_thermal { -+ trips { -+ cpu-crit { -+ temperature = <105000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ -+ cpu_alert: cpu-alert { -+ temperature = <95000>; -+ hysteresis = <10000>; -+ type = "passive"; -+ }; -+ }; -+ -+ cooling-maps { -+ map0 { -+ trip = <&cpu_alert>; -+ cooling-device = <&cpu0 1 1>; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xf.dtsi b/arch/arm/boot/dts/stm32mp15xf.dtsi -new file mode 100644 -index 0000000000000..77f50b9bda64e ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xf.dtsi -@@ -0,0 +1,20 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+#include "stm32mp15xd.dtsi" -+ -+/ { -+ soc { -+ cryp1: cryp@54001000 { -+ compatible = "st,stm32mp1-cryp"; -+ reg = <0x54001000 0x400>; -+ interrupts = ; -+ clocks = <&scmi0_clk CK_SCMI0_CRYP1>; -+ resets = <&scmi0_reset RST_SCMI0_CRYP1>; -+ status = "disabled"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi -new file mode 100644 -index 0000000000000..685a82161cc8e ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi -@@ -0,0 +1,770 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+#include "stm32mp157-m4-srm.dtsi" -+#include "stm32mp157-m4-srm-pinctrl.dtsi" -+#include -+ -+/ { -+ memory@c0000000 { -+ device_type = "memory"; -+ reg = <0xc0000000 0x20000000>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ mcuram2: mcuram2@10000000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10000000 0x40000>; -+ no-map; -+ }; -+ -+ vdev0vring0: vdev0vring0@10040000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10040000 0x1000>; -+ no-map; -+ }; -+ -+ vdev0vring1: vdev0vring1@10041000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10041000 0x1000>; -+ no-map; -+ }; -+ -+ vdev0buffer: vdev0buffer@10042000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10042000 0x4000>; -+ no-map; -+ }; -+ -+ mcuram: mcuram@30000000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x30000000 0x40000>; -+ no-map; -+ }; -+ -+ retram: retram@38000000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x38000000 0x10000>; -+ no-map; -+ }; -+ }; -+ -+ led { -+ compatible = "gpio-leds"; -+ blue { -+ label = "heartbeat"; -+ gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ default-state = "off"; -+ }; -+ }; -+ -+ sound { -+ compatible = "audio-graph-card"; -+ label = "STM32MP1-DK"; -+ routing = -+ "Playback" , "MCLK", -+ "Capture" , "MCLK", -+ "MICL" , "Mic Bias"; -+ dais = <&sai2a_port &sai2b_port &i2s2_port>; -+ status = "okay"; -+ }; -+ -+ usb_phy_tuning: usb-phy-tuning { -+ st,hs-dc-level = <2>; -+ st,fs-rftime-tuning; -+ st,hs-rftime-reduction; -+ st,hs-current-trim = <15>; -+ st,hs-impedance-trim = <1>; -+ st,squelch-level = <3>; -+ st,hs-rx-offset = <2>; -+ st,no-lsfs-sc; -+ }; -+ -+ vin: vin { -+ compatible = "regulator-fixed"; -+ regulator-name = "vin"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+}; -+ -+&adc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; -+ vdd-supply = <&vdd>; -+ vdda-supply = <&vdd>; -+ vref-supply = <&vrefbuf>; -+ status = "disabled"; -+ adc1: adc@0 { -+ /* -+ * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19. -+ * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: -+ * 5 * (56 + 47kOhms) * 5pF => 2.5us. -+ * Use arbitrary margin here (e.g. 5us). -+ */ -+ st,min-sample-time-nsecs = <5000>; -+ /* AIN connector, USB Type-C CC1 & CC2 */ -+ st,adc-channels = <0 1 6 13 18 19>; -+ status = "okay"; -+ }; -+ adc2: adc@100 { -+ /* AIN connector, USB Type-C CC1 & CC2 */ -+ st,adc-channels = <0 1 2 6 18 19>; -+ st,min-sample-time-nsecs = <5000>; -+ status = "okay"; -+ }; -+}; -+ -+&cec { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&cec_pins_b>; -+ pinctrl-1 = <&cec_pins_sleep_b>; -+ status = "okay"; -+}; -+ -+&cpu0{ -+ cpu-supply = <&vddcore>; -+}; -+ -+&cpu1{ -+ cpu-supply = <&vddcore>; -+}; -+ -+&crc1 { -+ status = "okay"; -+}; -+ -+&dma1 { -+ sram = <&dma_pool>; -+}; -+ -+&dma2 { -+ sram = <&dma_pool>; -+}; -+ -+&dts { -+ status = "okay"; -+}; -+ -+ðernet0 { -+ status = "okay"; -+ pinctrl-0 = <ðernet0_rgmii_pins_a>; -+ pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; -+ pinctrl-names = "default", "sleep"; -+ phy-mode = "rgmii-id"; -+ max-speed = <1000>; -+ phy-handle = <&phy0>; -+ nvmem-cells = <ðernet_mac_address>; -+ nvmem-cell-names = "mac-address"; -+ -+ mdio0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "snps,dwmac-mdio"; -+ phy0: ethernet-phy@0 { -+ reg = <0>; -+ }; -+ }; -+}; -+ -+&gpu { -+ contiguous-area = <&gpu_reserved>; -+ status = "okay"; -+}; -+ -+&hash1 { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c1_pins_a>; -+ pinctrl-1 = <&i2c1_pins_sleep_a>; -+ i2c-scl-rising-time-ns = <100>; -+ i2c-scl-falling-time-ns = <7>; -+ status = "okay"; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ -+ hdmi-transmitter@39 { -+ compatible = "sil,sii9022"; -+ reg = <0x39>; -+ iovcc-supply = <&v3v3_hdmi>; -+ cvcc12-supply = <&v1v2_hdmi>; -+ reset-gpios = <&gpioa 10 GPIO_ACTIVE_LOW>; -+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-parent = <&gpiog>; -+ #sound-dai-cells = <0>; -+ status = "okay"; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ sii9022_in: endpoint { -+ remote-endpoint = <<dc_ep0_out>; -+ }; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ sii9022_tx_endpoint: endpoint { -+ remote-endpoint = <&i2s2_endpoint>; -+ }; -+ }; -+ }; -+ }; -+ -+ cs42l51: cs42l51@4a { -+ compatible = "cirrus,cs42l51"; -+ reg = <0x4a>; -+ #sound-dai-cells = <0>; -+ VL-supply = <&v3v3>; -+ VD-supply = <&v1v8_audio>; -+ VA-supply = <&v1v8_audio>; -+ VAHP-supply = <&v1v8_audio>; -+ reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; -+ clocks = <&sai2a>; -+ clock-names = "MCLK"; -+ status = "okay"; -+ -+ cs42l51_port: port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cs42l51_tx_endpoint: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&sai2a_endpoint>; -+ frame-master; -+ bitclock-master; -+ }; -+ -+ cs42l51_rx_endpoint: endpoint@1 { -+ reg = <1>; -+ remote-endpoint = <&sai2b_endpoint>; -+ frame-master; -+ bitclock-master; -+ }; -+ }; -+ }; -+}; -+ -+&i2c4 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c4_pins_a>; -+ pinctrl-1 = <&i2c4_pins_sleep_a>; -+ i2c-scl-rising-time-ns = <185>; -+ i2c-scl-falling-time-ns = <20>; -+ clock-frequency = <400000>; -+ status = "okay"; -+ /* spare dmas for other usage */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ -+ stusb1600@28 { -+ compatible = "st,stusb1600"; -+ reg = <0x28>; -+ interrupts = <11 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-parent = <&gpioi>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&stusb1600_pins_a>; -+ status = "okay"; -+ vdd-supply = <&vin>; -+ -+ connector { -+ compatible = "usb-c-connector"; -+ label = "USB-C"; -+ power-role = "dual"; -+ power-opmode = "default"; -+ -+ port { -+ con_usbotg_hs_ep: endpoint { -+ remote-endpoint = <&usbotg_hs_ep>; -+ }; -+ }; -+ }; -+ }; -+ -+ pmic: stpmic@33 { -+ compatible = "st,stpmic1"; -+ reg = <0x33>; -+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ status = "okay"; -+ -+ regulators { -+ compatible = "st,stpmic1-regulators"; -+ buck1-supply = <&vin>; -+ buck2-supply = <&vin>; -+ buck3-supply = <&vin>; -+ buck4-supply = <&vin>; -+ ldo1-supply = <&v3v3>; -+ ldo2-supply = <&vin>; -+ ldo3-supply = <&vdd_ddr>; -+ ldo4-supply = <&vin>; -+ ldo5-supply = <&vin>; -+ ldo6-supply = <&v3v3>; -+ vref_ddr-supply = <&vin>; -+ boost-supply = <&vin>; -+ pwr_sw1-supply = <&bst_out>; -+ pwr_sw2-supply = <&bst_out>; -+ -+ vddcore: buck1 { -+ regulator-name = "vddcore"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_ddr: buck2 { -+ regulator-name = "vdd_ddr"; -+ regulator-min-microvolt = <1350000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd: buck3 { -+ regulator-name = "vdd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ st,mask-reset; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ v3v3: buck4 { -+ regulator-name = "v3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ regulator-initial-mode = <0>; -+ }; -+ -+ v1v8_audio: ldo1 { -+ regulator-name = "v1v8_audio"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ interrupts = ; -+ }; -+ -+ v3v3_hdmi: ldo2 { -+ regulator-name = "v3v3_hdmi"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ interrupts = ; -+ }; -+ -+ vtt_ddr: ldo3 { -+ regulator-name = "vtt_ddr"; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <750000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_usb: ldo4 { -+ regulator-name = "vdd_usb"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ interrupts = ; -+ regulator-always-on; -+ }; -+ -+ vdda: ldo5 { -+ regulator-name = "vdda"; -+ regulator-min-microvolt = <2900000>; -+ regulator-max-microvolt = <2900000>; -+ interrupts = ; -+ regulator-boot-on; -+ }; -+ -+ v1v2_hdmi: ldo6 { -+ regulator-name = "v1v2_hdmi"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ regulator-always-on; -+ interrupts = ; -+ }; -+ -+ vref_ddr: vref_ddr { -+ regulator-name = "vref_ddr"; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ -+ bst_out: boost { -+ regulator-name = "bst_out"; -+ interrupts = ; -+ }; -+ -+ vbus_otg: pwr_sw1 { -+ regulator-name = "vbus_otg"; -+ interrupts = ; -+ }; -+ -+ vbus_sw: pwr_sw2 { -+ regulator-name = "vbus_sw"; -+ interrupts = ; -+ regulator-active-discharge = <1>; -+ }; -+ }; -+ -+ onkey { -+ compatible = "st,stpmic1-onkey"; -+ interrupts = , ; -+ interrupt-names = "onkey-falling", "onkey-rising"; -+ power-off-time-sec = <10>; -+ status = "okay"; -+ }; -+ -+ watchdog { -+ compatible = "st,stpmic1-wdt"; -+ status = "disabled"; -+ }; -+ }; -+}; -+ -+&i2c5 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c5_pins_a>; -+ pinctrl-1 = <&i2c5_pins_sleep_a>; -+ i2c-scl-rising-time-ns = <185>; -+ i2c-scl-falling-time-ns = <20>; -+ clock-frequency = <400000>; -+ /* spare dmas for other usage */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+}; -+ -+&i2s2 { -+ clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>; -+ clock-names = "pclk", "i2sclk", "x8k", "x11k"; -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2s2_pins_a>; -+ pinctrl-1 = <&i2s2_pins_sleep_a>; -+ status = "okay"; -+ -+ i2s2_port: port { -+ i2s2_endpoint: endpoint { -+ remote-endpoint = <&sii9022_tx_endpoint>; -+ format = "i2s"; -+ mclk-fs = <256>; -+ }; -+ }; -+}; -+ -+&ipcc { -+ status = "okay"; -+}; -+ -+&iwdg2 { -+ timeout-sec = <32>; -+ status = "okay"; -+}; -+ -+<dc { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <<dc_pins_a>; -+ pinctrl-1 = <<dc_pins_sleep_a>; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ltdc_ep0_out: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&sii9022_in>; -+ }; -+ }; -+}; -+ -+&m4_rproc { -+ memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, -+ <&vdev0vring1>, <&vdev0buffer>; -+ mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; -+ mbox-names = "vq0", "vq1", "shutdown"; -+ interrupt-parent = <&exti>; -+ interrupts = <68 1>; -+ wakeup-source; -+ status = "okay"; -+}; -+ -+&pwr_regulators { -+ vdd-supply = <&vdd>; -+ vdd_3v3_usbfs-supply = <&vdd_usb>; -+}; -+ -+&rng1 { -+ status = "okay"; -+}; -+ -+&rtc { -+ status = "okay"; -+}; -+ -+&sai2 { -+ clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; -+ clock-names = "pclk", "x8k", "x11k"; -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>; -+ pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>; -+ status = "okay"; -+ -+ sai2a: audio-controller@4400b004 { -+ #clock-cells = <0>; -+ dma-names = "tx"; -+ clocks = <&rcc SAI2_K>; -+ clock-names = "sai_ck"; -+ status = "okay"; -+ -+ sai2a_port: port { -+ sai2a_endpoint: endpoint { -+ remote-endpoint = <&cs42l51_tx_endpoint>; -+ format = "i2s"; -+ mclk-fs = <256>; -+ dai-tdm-slot-num = <2>; -+ dai-tdm-slot-width = <32>; -+ }; -+ }; -+ }; -+ -+ sai2b: audio-controller@4400b024 { -+ dma-names = "rx"; -+ st,sync = <&sai2a 2>; -+ clocks = <&rcc SAI2_K>, <&sai2a>; -+ clock-names = "sai_ck", "MCLK"; -+ status = "okay"; -+ -+ sai2b_port: port { -+ sai2b_endpoint: endpoint { -+ remote-endpoint = <&cs42l51_rx_endpoint>; -+ format = "i2s"; -+ mclk-fs = <256>; -+ dai-tdm-slot-num = <2>; -+ dai-tdm-slot-width = <32>; -+ }; -+ }; -+ }; -+}; -+ -+&sdmmc1 { -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc1_b4_pins_a>; -+ pinctrl-1 = <&sdmmc1_b4_od_pins_a>; -+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>; -+ cd-gpios = <&gpiob 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; -+ disable-wp; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&v3v3>; -+ status = "okay"; -+}; -+ -+&sdmmc3 { -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc3_b4_pins_a>; -+ pinctrl-1 = <&sdmmc3_b4_od_pins_a>; -+ pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; -+ broken-cd; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&v3v3>; -+ status = "disabled"; -+}; -+ -+&spi4 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&spi4_pins_a>; -+ pinctrl-1 = <&spi4_sleep_pins_a>; -+ status = "disabled"; -+}; -+ -+&spi5 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&spi5_pins_a>; -+ pinctrl-1 = <&spi5_sleep_pins_a>; -+ status = "disabled"; -+}; -+ -+&sram { -+ dma_pool: dma_pool@0 { -+ reg = <0x50000 0x10000>; -+ pool; -+ }; -+}; -+ -+&timers1 { -+ /* spare dmas for other usage */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm1_pins_a>; -+ pinctrl-1 = <&pwm1_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@0 { -+ status = "okay"; -+ }; -+}; -+ -+&timers3 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm3_pins_a>; -+ pinctrl-1 = <&pwm3_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@2 { -+ status = "okay"; -+ }; -+}; -+ -+&timers4 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm4_pins_a &pwm4_pins_b>; -+ pinctrl-1 = <&pwm4_sleep_pins_a &pwm4_sleep_pins_b>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@3 { -+ status = "okay"; -+ }; -+}; -+ -+&timers5 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm5_pins_a>; -+ pinctrl-1 = <&pwm5_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@4 { -+ status = "okay"; -+ }; -+}; -+ -+&timers6 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ timer@5 { -+ status = "okay"; -+ }; -+}; -+ -+&timers12 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm12_pins_a>; -+ pinctrl-1 = <&pwm12_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@11 { -+ status = "okay"; -+ }; -+}; -+ -+&uart4 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&uart4_pins_a>; -+ pinctrl-1 = <&uart4_sleep_pins_a>; -+ pinctrl-2 = <&uart4_idle_pins_a>; -+ pinctrl-3 = <&uart4_pins_a>; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "okay"; -+}; -+ -+&uart7 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&uart7_pins_b>; -+ pinctrl-1 = <&uart7_sleep_pins_b>; -+ pinctrl-2 = <&uart7_idle_pins_b>; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+}; -+ -+&usart3 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&usart3_pins_b>; -+ pinctrl-1 = <&usart3_sleep_pins_b>; -+ pinctrl-2 = <&usart3_idle_pins_b>; -+ uart-has-rtscts; -+ status = "disabled"; -+}; -+ -+&usbh_ehci { -+ phys = <&usbphyc_port0>; -+ status = "okay"; -+}; -+ -+&usbotg_hs { -+ phys = <&usbphyc_port1 0>; -+ phy-names = "usb2-phy"; -+ usb-role-switch; -+ status = "okay"; -+ -+ port { -+ usbotg_hs_ep: endpoint { -+ remote-endpoint = <&con_usbotg_hs_ep>; -+ }; -+ }; -+}; -+ -+&usbphyc { -+ status = "okay"; -+}; -+ -+&usbphyc_port0 { -+ phy-supply = <&vdd_usb>; -+ st,phy-tuning = <&usb_phy_tuning>; -+}; -+ -+&usbphyc_port1 { -+ phy-supply = <&vdd_usb>; -+ st,phy-tuning = <&usb_phy_tuning>; -+}; -+ -+&vrefbuf { -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ vdda-supply = <&vdd>; -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xx-edx.dtsi b/arch/arm/boot/dts/stm32mp15xx-edx.dtsi -new file mode 100644 -index 0000000000000..c67d57cc02373 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xx-edx.dtsi -@@ -0,0 +1,407 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Ludovic Barre for STMicroelectronics. -+ */ -+ -+#include -+#include -+ -+/ { -+ memory@c0000000 { -+ device_type = "memory"; -+ reg = <0xC0000000 0x40000000>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ mcuram2: mcuram2@10000000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10000000 0x40000>; -+ no-map; -+ }; -+ -+ vdev0vring0: vdev0vring0@10040000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10040000 0x1000>; -+ no-map; -+ }; -+ -+ vdev0vring1: vdev0vring1@10041000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10041000 0x1000>; -+ no-map; -+ }; -+ -+ vdev0buffer: vdev0buffer@10042000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x10042000 0x4000>; -+ no-map; -+ }; -+ -+ mcuram: mcuram@30000000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x30000000 0x40000>; -+ no-map; -+ }; -+ -+ retram: retram@38000000 { -+ compatible = "shared-dma-pool"; -+ reg = <0x38000000 0x10000>; -+ no-map; -+ }; -+ }; -+ -+ led { -+ compatible = "gpio-leds"; -+ blue { -+ label = "heartbeat"; -+ gpios = <&gpiod 9 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ default-state = "off"; -+ }; -+ }; -+ -+ sd_switch: regulator-sd_switch { -+ compatible = "regulator-gpio"; -+ regulator-name = "sd_switch"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <2900000>; -+ regulator-type = "voltage"; -+ regulator-always-on; -+ -+ gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; -+ gpios-states = <0>; -+ states = <1800000 0x1 2900000 0x0>; -+ }; -+ -+ vin: vin { -+ compatible = "regulator-fixed"; -+ regulator-name = "vin"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+}; -+ -+&adc { -+ /* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */ -+ pinctrl-0 = <&adc1_in6_pins_a>; -+ pinctrl-names = "default"; -+ vdd-supply = <&vdd>; -+ vdda-supply = <&vdda>; -+ vref-supply = <&vdda>; -+ status = "disabled"; -+ adc1: adc@0 { -+ st,adc-channels = <0 1 6>; -+ /* 16.5 ck_cycles sampling time */ -+ st,min-sample-time-nsecs = <400>; -+ status = "okay"; -+ }; -+}; -+ -+&cpu0{ -+ cpu-supply = <&vddcore>; -+}; -+ -+&crc1 { -+ status = "okay"; -+}; -+ -+&dac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; -+ vref-supply = <&vdda>; -+ status = "disabled"; -+ dac1: dac@1 { -+ status = "okay"; -+ }; -+ dac2: dac@2 { -+ status = "okay"; -+ }; -+}; -+ -+&dma1 { -+ sram = <&dma_pool>; -+}; -+ -+&dma2 { -+ sram = <&dma_pool>; -+}; -+ -+&dts { -+ status = "okay"; -+}; -+ -+&hash1 { -+ status = "okay"; -+}; -+ -+&i2c4 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c4_pins_a>; -+ pinctrl-1 = <&i2c4_pins_sleep_a>; -+ i2c-scl-rising-time-ns = <185>; -+ i2c-scl-falling-time-ns = <20>; -+ clock-frequency = <400000>; -+ status = "okay"; -+ /* spare dmas for other usage */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ -+ pmic: stpmic@33 { -+ compatible = "st,stpmic1"; -+ reg = <0x33>; -+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ status = "okay"; -+ -+ regulators { -+ compatible = "st,stpmic1-regulators"; -+ buck1-supply = <&vin>; -+ buck2-supply = <&vin>; -+ buck3-supply = <&vin>; -+ buck4-supply = <&vin>; -+ ldo1-supply = <&v3v3>; -+ ldo2-supply = <&v3v3>; -+ ldo3-supply = <&vdd_ddr>; -+ ldo4-supply = <&vin>; -+ ldo5-supply = <&v3v3>; -+ ldo6-supply = <&v3v3>; -+ vref_ddr-supply = <&vin>; -+ boost-supply = <&vin>; -+ pwr_sw1-supply = <&bst_out>; -+ pwr_sw2-supply = <&bst_out>; -+ -+ vddcore: buck1 { -+ regulator-name = "vddcore"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_ddr: buck2 { -+ regulator-name = "vdd_ddr"; -+ regulator-min-microvolt = <1350000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd: buck3 { -+ regulator-name = "vdd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ st,mask-reset; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ v3v3: buck4 { -+ regulator-name = "v3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ regulator-initial-mode = <0>; -+ }; -+ -+ vdda: ldo1 { -+ regulator-name = "vdda"; -+ regulator-min-microvolt = <2900000>; -+ regulator-max-microvolt = <2900000>; -+ interrupts = ; -+ }; -+ -+ v2v8: ldo2 { -+ regulator-name = "v2v8"; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; -+ interrupts = ; -+ }; -+ -+ vtt_ddr: ldo3 { -+ regulator-name = "vtt_ddr"; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <750000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_usb: ldo4 { -+ regulator-name = "vdd_usb"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ interrupts = ; -+ regulator-always-on; -+ }; -+ -+ vdd_sd: ldo5 { -+ regulator-name = "vdd_sd"; -+ regulator-min-microvolt = <2900000>; -+ regulator-max-microvolt = <2900000>; -+ interrupts = ; -+ regulator-boot-on; -+ }; -+ -+ v1v8: ldo6 { -+ regulator-name = "v1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ interrupts = ; -+ }; -+ -+ vref_ddr: vref_ddr { -+ regulator-name = "vref_ddr"; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ -+ bst_out: boost { -+ regulator-name = "bst_out"; -+ interrupts = ; -+ }; -+ -+ vbus_otg: pwr_sw1 { -+ regulator-name = "vbus_otg"; -+ interrupts = ; -+ }; -+ -+ vbus_sw: pwr_sw2 { -+ regulator-name = "vbus_sw"; -+ interrupts = ; -+ regulator-active-discharge = <1>; -+ }; -+ }; -+ -+ onkey { -+ compatible = "st,stpmic1-onkey"; -+ interrupts = , ; -+ interrupt-names = "onkey-falling", "onkey-rising"; -+ power-off-time-sec = <10>; -+ status = "okay"; -+ }; -+ -+ watchdog { -+ compatible = "st,stpmic1-wdt"; -+ status = "disabled"; -+ }; -+ }; -+}; -+ -+&ipcc { -+ status = "okay"; -+}; -+ -+&iwdg2 { -+ timeout-sec = <32>; -+ status = "okay"; -+}; -+ -+&m4_rproc { -+ memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, -+ <&vdev0vring1>, <&vdev0buffer>; -+ mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; -+ mbox-names = "vq0", "vq1", "shutdown"; -+ interrupt-parent = <&exti>; -+ interrupts = <68 1>; -+ wakeup-source; -+ status = "okay"; -+}; -+ -+&pwr_regulators { -+ vdd-supply = <&vdd>; -+ vdd_3v3_usbfs-supply = <&vdd_usb>; -+}; -+ -+&rng1 { -+ status = "okay"; -+}; -+ -+&rtc { -+ status = "okay"; -+}; -+ -+&sdmmc1 { -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; -+ pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; -+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; -+ cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; -+ disable-wp; -+ st,sig-dir; -+ st,neg-edge; -+ st,use-ckin; -+ bus-width = <4>; -+ vmmc-supply = <&vdd_sd>; -+ vqmmc-supply = <&sd_switch>; -+ sd-uhs-sdr12; -+ sd-uhs-sdr25; -+ sd-uhs-sdr50; -+ sd-uhs-ddr50; -+ sd-uhs-sdr104; -+ status = "okay"; -+}; -+ -+&sdmmc2 { -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; -+ pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; -+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; -+ non-removable; -+ no-sd; -+ no-sdio; -+ st,neg-edge; -+ bus-width = <8>; -+ vmmc-supply = <&v3v3>; -+ vqmmc-supply = <&vdd>; -+ mmc-ddr-3_3v; -+ status = "okay"; -+}; -+ -+&sram { -+ dma_pool: dma_pool@0 { -+ reg = <0x50000 0x10000>; -+ pool; -+ }; -+}; -+ -+&timers6 { -+ status = "okay"; -+ /* spare dmas for other usage */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ timer@5 { -+ status = "okay"; -+ }; -+}; -+ -+&uart4 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&uart4_pins_a>; -+ pinctrl-1 = <&uart4_sleep_pins_a>; -+ pinctrl-2 = <&uart4_idle_pins_a>; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "okay"; -+}; -+ -+&usbotg_hs { -+ vbus-supply = <&vbus_otg>; -+}; -+ -+&usbphyc_port0 { -+ phy-supply = <&vdd_usb>; -+}; -+ -+&usbphyc_port1 { -+ phy-supply = <&vdd_usb>; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xx-evx.dtsi b/arch/arm/boot/dts/stm32mp15xx-evx.dtsi -new file mode 100644 -index 0000000000000..1a2b49cadac25 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xx-evx.dtsi -@@ -0,0 +1,687 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Ludovic Barre for STMicroelectronics. -+ */ -+ -+#include -+#include -+ -+/ { -+ clocks { -+ clk_ext_camera: clk-ext-camera { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <24000000>; -+ }; -+ }; -+ -+ joystick { -+ compatible = "gpio-keys"; -+ #size-cells = <0>; -+ pinctrl-0 = <&joystick_pins>; -+ pinctrl-names = "default"; -+ button-0 { -+ label = "JoySel"; -+ linux,code = ; -+ interrupt-parent = <&stmfx_pinctrl>; -+ interrupts = <0 IRQ_TYPE_EDGE_RISING>; -+ }; -+ button-1 { -+ label = "JoyDown"; -+ linux,code = ; -+ interrupt-parent = <&stmfx_pinctrl>; -+ interrupts = <1 IRQ_TYPE_EDGE_RISING>; -+ }; -+ button-2 { -+ label = "JoyLeft"; -+ linux,code = ; -+ interrupt-parent = <&stmfx_pinctrl>; -+ interrupts = <2 IRQ_TYPE_EDGE_RISING>; -+ }; -+ button-3 { -+ label = "JoyRight"; -+ linux,code = ; -+ interrupt-parent = <&stmfx_pinctrl>; -+ interrupts = <3 IRQ_TYPE_EDGE_RISING>; -+ }; -+ button-4 { -+ label = "JoyUp"; -+ linux,code = ; -+ interrupt-parent = <&stmfx_pinctrl>; -+ interrupts = <4 IRQ_TYPE_EDGE_RISING>; -+ }; -+ }; -+ -+ panel_backlight: panel-backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; -+ default-on; -+ status = "okay"; -+ }; -+ -+ spdif_out: spdif-out { -+ #sound-dai-cells = <0>; -+ compatible = "linux,spdif-dit"; -+ status = "okay"; -+ -+ spdif_out_port: port { -+ spdif_out_endpoint: endpoint { -+ remote-endpoint = <&sai4a_endpoint>; -+ }; -+ }; -+ }; -+ -+ spdif_in: spdif-in { -+ #sound-dai-cells = <0>; -+ compatible = "linux,spdif-dir"; -+ status = "okay"; -+ -+ spdif_in_port: port { -+ spdif_in_endpoint: endpoint { -+ remote-endpoint = <&spdifrx_endpoint>; -+ }; -+ }; -+ }; -+ -+ sound { -+ compatible = "audio-graph-card"; -+ label = "STM32MP1-EV"; -+ routing = -+ "AIF1CLK" , "MCLK1", -+ "AIF2CLK" , "MCLK1", -+ "IN1LN" , "MICBIAS2", -+ "DMIC2DAT" , "MICBIAS1", -+ "DMIC1DAT" , "MICBIAS1"; -+ dais = <&sai2a_port &sai2b_port &sai4a_port &spdifrx_port -+ &dfsdm0_port &dfsdm1_port &dfsdm2_port &dfsdm3_port>; -+ status = "okay"; -+ }; -+ -+ dmic0: dmic-0 { -+ compatible = "dmic-codec"; -+ #sound-dai-cells = <1>; -+ sound-name-prefix = "dmic0"; -+ status = "okay"; -+ -+ port { -+ dmic0_endpoint: endpoint { -+ remote-endpoint = <&dfsdm_endpoint0>; -+ }; -+ }; -+ }; -+ -+ dmic1: dmic-1 { -+ compatible = "dmic-codec"; -+ #sound-dai-cells = <1>; -+ sound-name-prefix = "dmic1"; -+ status = "okay"; -+ -+ port { -+ dmic1_endpoint: endpoint { -+ remote-endpoint = <&dfsdm_endpoint1>; -+ }; -+ }; -+ }; -+ -+ dmic2: dmic-2 { -+ compatible = "dmic-codec"; -+ #sound-dai-cells = <1>; -+ sound-name-prefix = "dmic2"; -+ status = "okay"; -+ -+ port { -+ dmic2_endpoint: endpoint { -+ remote-endpoint = <&dfsdm_endpoint2>; -+ }; -+ }; -+ }; -+ -+ dmic3: dmic-3 { -+ compatible = "dmic-codec"; -+ #sound-dai-cells = <1>; -+ sound-name-prefix = "dmic3"; -+ status = "okay"; -+ -+ port { -+ dmic3_endpoint: endpoint { -+ remote-endpoint = <&dfsdm_endpoint3>; -+ }; -+ }; -+ }; -+ -+ usb_phy_tuning: usb-phy-tuning { -+ st,hs-dc-level = <2>; -+ st,fs-rftime-tuning; -+ st,hs-rftime-reduction; -+ st,hs-current-trim = <15>; -+ st,hs-impedance-trim = <1>; -+ st,squelch-level = <3>; -+ st,hs-rx-offset = <2>; -+ st,no-lsfs-sc; -+ }; -+}; -+ -+&cec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&cec_pins_a>; -+ status = "okay"; -+}; -+ -+&dcmi { -+ status = "okay"; -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&dcmi_pins_a>; -+ pinctrl-1 = <&dcmi_sleep_pins_a>; -+ -+ port { -+ dcmi_0: endpoint { -+ remote-endpoint = <&ov5640_0>; -+ bus-width = <8>; -+ hsync-active = <0>; -+ vsync-active = <0>; -+ pclk-sample = <1>; -+ pclk-max-frequency = <77000000>; -+ }; -+ }; -+}; -+ -+&dfsdm { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&dfsdm_clkout_pins_a -+ &dfsdm_data1_pins_a &dfsdm_data3_pins_a>; -+ pinctrl-1 = <&dfsdm_clkout_sleep_pins_a -+ &dfsdm_data1_sleep_pins_a &dfsdm_data3_sleep_pins_a>; -+ spi-max-frequency = <2048000>; -+ -+ clocks = <&rcc DFSDM_K>, <&rcc ADFSDM_K>; -+ clock-names = "dfsdm", "audio"; -+ status = "okay"; -+ -+ dfsdm0: filter@0 { -+ compatible = "st,stm32-dfsdm-dmic"; -+ st,adc-channels = <3>; -+ st,adc-channel-names = "dmic_u1"; -+ st,adc-channel-types = "SPI_R"; -+ st,adc-channel-clk-src = "CLKOUT"; -+ st,filter-order = <3>; -+ status = "okay"; -+ -+ asoc_pdm0: dfsdm-dai { -+ compatible = "st,stm32h7-dfsdm-dai"; -+ #sound-dai-cells = <0>; -+ io-channels = <&dfsdm0 0>; -+ status = "okay"; -+ -+ dfsdm0_port: port { -+ dfsdm_endpoint0: endpoint { -+ remote-endpoint = <&dmic0_endpoint>; -+ }; -+ }; -+ }; -+ }; -+ -+ dfsdm1: filter@1 { -+ compatible = "st,stm32-dfsdm-dmic"; -+ st,adc-channels = <0>; -+ st,adc-channel-names = "dmic_u2"; -+ st,adc-channel-types = "SPI_F"; -+ st,adc-channel-clk-src = "CLKOUT"; -+ st,filter-order = <3>; -+ st,adc-alt-channel = <1>; -+ status = "okay"; -+ -+ asoc_pdm1: dfsdm-dai { -+ compatible = "st,stm32h7-dfsdm-dai"; -+ #sound-dai-cells = <0>; -+ io-channels = <&dfsdm1 0>; -+ status = "okay"; -+ -+ dfsdm1_port: port { -+ dfsdm_endpoint1: endpoint { -+ remote-endpoint = <&dmic1_endpoint>; -+ }; -+ }; -+ }; -+ }; -+ -+ dfsdm2: filter@2 { -+ compatible = "st,stm32-dfsdm-dmic"; -+ st,adc-channels = <2>; -+ st,adc-channel-names = "dmic_u3"; -+ st,adc-channel-types = "SPI_F"; -+ st,adc-channel-clk-src = "CLKOUT"; -+ st,adc-alt-channel = <1>; -+ st,filter-order = <3>; -+ status = "okay"; -+ -+ asoc_pdm2: dfsdm-dai { -+ compatible = "st,stm32h7-dfsdm-dai"; -+ #sound-dai-cells = <0>; -+ io-channels = <&dfsdm2 0>; -+ status = "okay"; -+ -+ dfsdm2_port: port { -+ dfsdm_endpoint2: endpoint { -+ remote-endpoint = <&dmic2_endpoint>; -+ }; -+ }; -+ }; -+ }; -+ -+ dfsdm3: filter@3 { -+ compatible = "st,stm32-dfsdm-dmic"; -+ st,adc-channels = <1>; -+ st,adc-channel-names = "dmic_u4"; -+ st,adc-channel-types = "SPI_R"; -+ st,adc-channel-clk-src = "CLKOUT"; -+ st,filter-order = <3>; -+ status = "okay"; -+ -+ asoc_pdm3: dfsdm-dai { -+ compatible = "st,stm32h7-dfsdm-dai"; -+ #sound-dai-cells = <0>; -+ io-channels = <&dfsdm3 0>; -+ status = "okay"; -+ -+ dfsdm3_port: port { -+ dfsdm_endpoint3: endpoint { -+ remote-endpoint = <&dmic3_endpoint>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+ðernet0 { -+ status = "okay"; -+ pinctrl-0 = <ðernet0_rgmii_pins_a>; -+ pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; -+ pinctrl-names = "default", "sleep"; -+ phy-mode = "rgmii-id"; -+ max-speed = <1000>; -+ phy-handle = <&phy0>; -+ nvmem-cells = <ðernet_mac_address>; -+ nvmem-cell-names = "mac-address"; -+ -+ mdio0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "snps,dwmac-mdio"; -+ phy0: ethernet-phy@0 { -+ reg = <0>; -+ }; -+ }; -+}; -+ -+&fmc { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&fmc_pins_a>; -+ pinctrl-1 = <&fmc_sleep_pins_a>; -+ status = "okay"; -+ -+ nand-controller@4,0 { -+ status = "okay"; -+ -+ nand@0 { -+ reg = <0>; -+ nand-on-flash-bbt; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+ }; -+}; -+ -+&hdp { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&hdp0_pins_a &hdp6_pins_a &hdp7_pins_a>; -+ pinctrl-1 = <&hdp0_pins_sleep_a &hdp6_pins_sleep_a &hdp7_pins_sleep_a>; -+ status = "disabled"; -+ -+ muxing-hdp = <(STM32_HDP(0, HDP0_GPOVAL_0) | -+ STM32_HDP(6, HDP6_GPOVAL_6) | -+ STM32_HDP(7, HDP7_GPOVAL_7))>; -+}; -+ -+&i2c2 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c2_pins_a>; -+ pinctrl-1 = <&i2c2_pins_sleep_a>; -+ i2c-scl-rising-time-ns = <185>; -+ i2c-scl-falling-time-ns = <20>; -+ status = "okay"; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ -+ wm8994: wm8994@1b { -+ compatible = "wlf,wm8994"; -+ #sound-dai-cells = <0>; -+ reg = <0x1b>; -+ status = "okay"; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ DBVDD-supply = <&vdd>; -+ SPKVDD1-supply = <&vdd>; -+ SPKVDD2-supply = <&vdd>; -+ AVDD2-supply = <&v1v8>; -+ CPVDD-supply = <&v1v8>; -+ -+ wlf,ldoena-always-driven; -+ -+ clocks = <&sai2a>; -+ clock-names = "MCLK1"; -+ -+ wlf,gpio-cfg = <0x8101 0xa100 0xa100 0xa100 0xa101 0xa101 0xa100 0xa101 0xa101 0xa101 0xa101>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ wm8994_tx_port: port@0 { -+ reg = <0>; -+ wm8994_tx_endpoint: endpoint { -+ remote-endpoint = <&sai2a_endpoint>; -+ }; -+ }; -+ -+ wm8994_rx_port: port@1 { -+ reg = <1>; -+ wm8994_rx_endpoint: endpoint { -+ remote-endpoint = <&sai2b_endpoint>; -+ }; -+ }; -+ }; -+ }; -+ -+ ov5640: camera@3c { -+ compatible = "ovti,ov5640"; -+ reg = <0x3c>; -+ clocks = <&clk_ext_camera>; -+ clock-names = "xclk"; -+ DOVDD-supply = <&v2v8>; -+ powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; -+ reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; -+ rotation = <180>; -+ status = "okay"; -+ -+ port { -+ ov5640_0: endpoint { -+ remote-endpoint = <&dcmi_0>; -+ bus-width = <8>; -+ data-shift = <2>; /* lines 9:2 are used */ -+ hsync-active = <0>; -+ vsync-active = <0>; -+ pclk-sample = <1>; -+ pclk-max-frequency = <77000000>; -+ }; -+ }; -+ }; -+ -+ stmfx: stmfx@42 { -+ compatible = "st,stmfx-0300"; -+ reg = <0x42>; -+ interrupts = <8 IRQ_TYPE_EDGE_RISING>; -+ interrupt-parent = <&gpioi>; -+ vdd-supply = <&v3v3>; -+ -+ stmfx_pinctrl: stmfx-pin-controller { -+ compatible = "st,stmfx-0300-pinctrl"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ gpio-ranges = <&stmfx_pinctrl 0 0 24>; -+ -+ goodix_pins: goodix { -+ pins = "gpio14"; -+ bias-pull-down; -+ }; -+ -+ joystick_pins: joystick { -+ pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; -+ bias-pull-down; -+ }; -+ }; -+ }; -+}; -+ -+&i2c4 { -+ pmic: stpmic@33 { -+ regulators { -+ v1v8: ldo6 { -+ regulator-enable-ramp-delay = <300000>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c5 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c5_pins_a>; -+ pinctrl-1 = <&i2c5_pins_sleep_a>; -+ i2c-scl-rising-time-ns = <185>; -+ i2c-scl-falling-time-ns = <20>; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "okay"; -+}; -+ -+<dc { -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ltdc_ep0_out: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&dsi_in>; -+ }; -+ }; -+}; -+ -+&qspi { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; -+ pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; -+ reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ flash0: mx66l51235l@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-rx-bus-width = <4>; -+ spi-max-frequency = <108000000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+ -+ flash1: mx66l51235l@1 { -+ compatible = "jedec,spi-nor"; -+ reg = <1>; -+ spi-rx-bus-width = <4>; -+ spi-max-frequency = <108000000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+}; -+ -+&sai2 { -+ clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_a>; -+ pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_a>; -+ clock-names = "pclk", "x8k", "x11k"; -+ status = "okay"; -+ -+ sai2a: audio-controller@4400b004 { -+ #clock-cells = <0>; -+ dma-names = "tx"; -+ clocks = <&rcc SAI2_K>; -+ clock-names = "sai_ck"; -+ status = "okay"; -+ -+ sai2a_port: port { -+ sai2a_endpoint: endpoint { -+ remote-endpoint = <&wm8994_tx_endpoint>; -+ format = "i2s"; -+ mclk-fs = <256>; -+ }; -+ }; -+ }; -+ -+ sai2b: audio-controller@4400b024 { -+ dma-names = "rx"; -+ clocks = <&rcc SAI2_K>, <&sai2a>; -+ clock-names = "sai_ck", "MCLK"; -+ status = "okay"; -+ -+ sai2b_port: port { -+ sai2b_endpoint: endpoint { -+ remote-endpoint = <&wm8994_rx_endpoint>; -+ format = "i2s"; -+ mclk-fs = <256>; -+ }; -+ }; -+ }; -+}; -+ -+&sai4 { -+ clocks = <&rcc SAI4>, <&rcc PLL3_Q>, <&rcc PLL3_R>; -+ clock-names = "pclk", "x8k", "x11k"; -+ status = "okay"; -+ -+ sai4a: audio-controller@50027004 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&sai4a_pins_a>; -+ pinctrl-1 = <&sai4a_sleep_pins_a>; -+ dma-names = "tx"; -+ clocks = <&rcc SAI4_K>; -+ clock-names = "sai_ck"; -+ st,iec60958; -+ status = "okay"; -+ -+ sai4a_port: port { -+ sai4a_endpoint: endpoint { -+ remote-endpoint = <&spdif_out_endpoint>; -+ }; -+ }; -+ }; -+}; -+ -+&sdmmc3 { -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc3_b4_pins_a>; -+ pinctrl-1 = <&sdmmc3_b4_od_pins_a>; -+ pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; -+ vmmc-supply = <&v3v3>; -+ broken-cd; -+ st,neg-edge; -+ bus-width = <4>; -+ status = "disabled"; -+}; -+ -+&spdifrx { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&spdifrx_pins_a>; -+ pinctrl-1 = <&spdifrx_sleep_pins_a>; -+ status = "okay"; -+ -+ spdifrx_port: port { -+ spdifrx_endpoint: endpoint { -+ remote-endpoint = <&spdif_in_endpoint>; -+ }; -+ }; -+}; -+ -+&spi1 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&spi1_pins_a>; -+ pinctrl-1 = <&spi1_sleep_pins_a>; -+ status = "disabled"; -+}; -+ -+&timers2 { -+ /* spare dmas for other usage (un-delete to enable pwm capture) */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm2_pins_a>; -+ pinctrl-1 = <&pwm2_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@1 { -+ status = "okay"; -+ }; -+}; -+ -+&timers8 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm8_pins_a>; -+ pinctrl-1 = <&pwm8_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@7 { -+ status = "okay"; -+ }; -+}; -+ -+&timers12 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm12_pins_a>; -+ pinctrl-1 = <&pwm12_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@11 { -+ status = "okay"; -+ }; -+}; -+ -+&usart3 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&usart3_pins_a>; -+ pinctrl-1 = <&usart3_sleep_pins_a>; -+ pinctrl-2 = <&usart3_idle_pins_a>; -+ uart-has-rtscts; -+ status = "disabled"; -+}; -+ -+&usbh_ehci { -+ phys = <&usbphyc_port0>; -+ status = "okay"; -+}; -+ -+&usbotg_hs { -+ pinctrl-0 = <&usbotg_hs_pins_a>; -+ pinctrl-names = "default"; -+ phys = <&usbphyc_port1 0>; -+ phy-names = "usb2-phy"; -+ status = "okay"; -+}; -+ -+&usbphyc { -+ status = "okay"; -+}; -+ -+&usbphyc_port0 { -+ st,phy-tuning = <&usb_phy_tuning>; -+ vbus-supply = <&vbus_sw>; -+}; -+ -+&usbphyc_port1 { -+ st,phy-tuning = <&usb_phy_tuning>; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xxaa-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15xxaa-pinctrl.dtsi -new file mode 100644 -index 0000000000000..64e566bf82f50 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xxaa-pinctrl.dtsi -@@ -0,0 +1,85 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+&pinctrl { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 80 16>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 96 16>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 112 16>; -+ }; -+ -+ gpioi: gpio@5000a000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 128 16>; -+ }; -+ -+ gpioj: gpio@5000b000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 144 16>; -+ }; -+ -+ gpiok: gpio@5000c000 { -+ status = "okay"; -+ ngpios = <8>; -+ gpio-ranges = <&pinctrl 0 160 8>; -+ }; -+}; -+ -+&pinctrl_z { -+ st,package = ; -+ -+ gpioz: gpio@54004000 { -+ status = "okay"; -+ ngpios = <8>; -+ gpio-ranges = <&pinctrl_z 0 400 8>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xxab-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15xxab-pinctrl.dtsi -new file mode 100644 -index 0000000000000..d29af8986f2de ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xxab-pinctrl.dtsi -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+&pinctrl { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <6>; -+ gpio-ranges = <&pinctrl 6 86 6>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <10>; -+ gpio-ranges = <&pinctrl 6 102 10>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <2>; -+ gpio-ranges = <&pinctrl 0 112 2>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xxac-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15xxac-pinctrl.dtsi -new file mode 100644 -index 0000000000000..5d8199fd19c4b ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xxac-pinctrl.dtsi -@@ -0,0 +1,73 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+&pinctrl { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 80 16>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 96 16>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 112 16>; -+ }; -+ -+ gpioi: gpio@5000a000 { -+ status = "okay"; -+ ngpios = <12>; -+ gpio-ranges = <&pinctrl 0 128 12>; -+ }; -+}; -+ -+&pinctrl_z { -+ st,package = ; -+ -+ gpioz: gpio@54004000 { -+ status = "okay"; -+ ngpios = <8>; -+ gpio-ranges = <&pinctrl_z 0 400 8>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/stm32mp15xxad-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15xxad-pinctrl.dtsi -new file mode 100644 -index 0000000000000..023f5404c4687 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp15xxad-pinctrl.dtsi -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+&pinctrl { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <6>; -+ gpio-ranges = <&pinctrl 6 86 6>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <10>; -+ gpio-ranges = <&pinctrl 6 102 10>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <2>; -+ gpio-ranges = <&pinctrl 0 112 2>; -+ }; -+}; --- -2.17.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.4/fragment-04-optee.config b/recipes-kernel/linux/linux-stm32mp/5.4/fragment-04-optee.config deleted file mode 100644 index 07554cf..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.4/fragment-04-optee.config +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_TEE=y -CONFIG_OPTEE=y diff --git a/recipes-kernel/linux/linux-stm32mp_5.4.bb b/recipes-kernel/linux/linux-stm32mp_5.10.bb similarity index 62% rename from recipes-kernel/linux/linux-stm32mp_5.4.bb rename to recipes-kernel/linux/linux-stm32mp_5.10.bb index 63dbe05..45b3808 100644 --- a/recipes-kernel/linux/linux-stm32mp_5.4.bb +++ b/recipes-kernel/linux/linux-stm32mp_5.10.bb @@ -1,43 +1,48 @@ SUMMARY = "Linux STM32MP Kernel" SECTION = "kernel" LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814" +#LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814" +LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46" include linux-stm32mp.inc -LINUX_VERSION = "5.4" -LINUX_SUBVERSION = "56" +LINUX_VERSION = "5.10" +LINUX_SUBVERSION = "10" SRC_URI = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}.tar.xz;name=kernel" -SRC_URI[kernel.sha256sum] = "318390b98480ec5663ed8403fca764b07924c5d2d6411de62c4241b4d9c57cad" +#SRC_URI = "https://git.kernel.org/torvalds/t/linux-${LINUX_VERSION}-${LINUX_SUBVERSION}.tar.gz;name=kernel" + +SRC_URI[kernel.sha256sum] = "60ed866fa951522a5255ea37ec3ac2006d3f3427d4783a13ef478464f37cdb19" SRC_URI += " \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-ARM-stm32mp1-r2-MACHINE.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0002-ARM-stm32mp1-r2-CPUFREQ.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0003-ARM-stm32mp1-r2-CRYPTO.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0004-ARM-stm32mp1-r2-RNG-DEBUG-NVMEM.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0005-ARM-stm32mp1-r2-CLOCK.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0006-ARM-stm32mp1-r2-DMA.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0007-ARM-stm32mp1-r2-DRM.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0008-ARM-stm32mp1-r2-HWSPINLOCK.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0009-ARM-stm32mp1-r2-I2C-IIO-IRQCHIP.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0010-ARM-stm32mp1-r2-MAILBOX-REMOTEPROC-RPMSG.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0011-ARM-stm32mp1-r2-RESET-RTC-WATCHDOG.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0012-ARM-stm32mp1-r2-MEDIA-SOC-THERMAL.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0013-ARM-stm32mp1-r2-MFD.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0014-ARM-stm32mp1-r2-MMC-NAND.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0015-ARM-stm32mp1-r2-NET-TTY.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0016-ARM-stm32mp1-r2-PHY-USB.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0017-ARM-stm32mp1-r2-PINCTRL-REGULATOR-SPI-PWM.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0018-ARM-stm32mp1-r2-SOUND.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0019-ARM-stm32mp1-r2-MISC-CPUIDLE-MM.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0020-ARM-stm32mp1-r2-DEVICETREE.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0021-ARM-stm32mp1-r2-CONFIG.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-ARM-stm32mp1-r2-PERF.patch \ -" + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-ARM-5.10.10-stm32mp1-r1-MACHINE.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0002-ARM-5.10.10-stm32mp1-r1-CLOCK.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0003-ARM-5.10.10-stm32mp1-r1-CPUFREQ.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0004-ARM-5.10.10-stm32mp1-r1-CRYPTO.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0005-ARM-5.10.10-stm32mp1-r1-DMA.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0006-ARM-5.10.10-stm32mp1-r1-DRM.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0007-ARM-5.10.10-stm32mp1-r1-HWSPINLOCK.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0008-ARM-5.10.10-stm32mp1-r1-I2C-IIO-IRQCHIP.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0009-ARM-5.10.10-stm32mp1-r1-MAILBOX-REMOTEPROC-RPMSG.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0010-ARM-5.10.10-stm32mp1-r1-MEDIA-SOC-THERMAL.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0011-ARM-5.10.10-stm32mp1-r1-MFD.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0012-ARM-5.10.10-stm32mp1-r1-MMC.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0013-ARM-5.10.10-stm32mp1-r1-NET-TTY.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0014-ARM-5.10.10-stm32mp1-r1-PERF.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0015-ARM-5.10.10-stm32mp1-r1-PHY-USB.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0016-ARM-5.10.10-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0017-ARM-5.10.10-stm32mp1-r1-RESET-RTC-WATCHDOG.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0018-ARM-5.10.10-stm32mp1-r1-SCMI.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0019-ARM-5.10.10-stm32mp1-r1-SOUND.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0020-ARM-5.10.10-stm32mp1-r1-MISC-CPUIDLE-POWER.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0021-ARM-5.10.10-stm32mp1-r1-DEVICETREE.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-ARM-5.10.10-stm32mp1-r1-CONFIG.patch \ + " PV = "${LINUX_VERSION}.${LINUX_SUBVERSION}" S = "${WORKDIR}/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}" +#S = "${WORKDIR}/linux-${LINUX_VERSION}-${LINUX_SUBVERSION}" +#S = "${WORKDIR}/linux-${LINUX_VERSION}" # --------------------------------- # Configure devupstream class usage @@ -45,7 +50,7 @@ S = "${WORKDIR}/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}" BBCLASSEXTEND = "devupstream:target" SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/linux.git;protocol=https;branch=v${LINUX_VERSION}-stm32mp" -SRCREV_class-devupstream = "a56628a8ab25734a771086664cc80c215a198438" +SRCREV_class-devupstream = "ce6891abb1c895d4849e6f784615687341b3dbde" # --------------------------------- # Configure default preference to manage dynamic selection between tarball and github @@ -65,21 +70,18 @@ include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'linux-stm32mp KERNEL_DEFCONFIG = "defconfig" KERNEL_CONFIG_FRAGMENTS = "${@bb.utils.contains('KERNEL_DEFCONFIG', 'defconfig', '${S}/arch/arm/configs/fragment-01-multiv7_cleanup.config', '', d)}" KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('KERNEL_DEFCONFIG', 'defconfig', '${S}/arch/arm/configs/fragment-02-multiv7_addons.config', '', d)}" -KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${WORKDIR}/fragments/5.4/fragment-03-systemd.config', '', d)} " -KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('COMBINED_FEATURES', 'optee', '${WORKDIR}/fragments/5.4/fragment-04-optee.config', '', d)}" -KERNEL_CONFIG_FRAGMENTS += "${WORKDIR}/fragments/5.4/fragment-05-modules.config" -KERNEL_CONFIG_FRAGMENTS += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', '${WORKDIR}/fragments/5.4/fragment-06-signature.config','')} " +KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${WORKDIR}/fragments/${LINUX_VERSION}/fragment-03-systemd.config', '', d)} " +KERNEL_CONFIG_FRAGMENTS += "${WORKDIR}/fragments/${LINUX_VERSION}/fragment-04-modules.config" +KERNEL_CONFIG_FRAGMENTS += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', '${WORKDIR}/fragments/${LINUX_VERSION}/fragment-05-signature.config','')} " SRC_URI += "file://${LINUX_VERSION}/fragment-03-systemd.config;subdir=fragments" -SRC_URI += "file://${LINUX_VERSION}/fragment-04-optee.config;subdir=fragments" -SRC_URI += "file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments" -SRC_URI += "file://${LINUX_VERSION}/fragment-06-signature.config;subdir=fragments" +SRC_URI += "file://${LINUX_VERSION}/fragment-04-modules.config;subdir=fragments" +SRC_URI += "file://${LINUX_VERSION}/fragment-05-signature.config;subdir=fragments" # Don't forget to add/del for devupstream SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-03-systemd.config;subdir=fragments" -SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-04-optee.config;subdir=fragments" -SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments" -SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-06-signature.config;subdir=fragments" +SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-04-modules.config;subdir=fragments" +SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-05-signature.config;subdir=fragments" # ------------------------------------------------------------- # Kernel Args