LINUX-STM32MP: update to v5.10-stm32mp-r1

Change-Id: I83bff180c4b5b8717d3735da1d0c51427f1a5908
This commit is contained in:
Romuald JEANNE 2021-03-15 16:11:47 +01:00
parent 57ece9a998
commit 302d750d20
39 changed files with 17882 additions and 34738 deletions

View File

@ -12,9 +12,6 @@ EXTERNALSRC_BUILD_pn-${PN} = "${WORKDIR}/build"
# To share config fragments between layers # To share config fragments between layers
FILESEXTRAPATHS_prepend := "${THISDIR}:" FILESEXTRAPATHS_prepend := "${THISDIR}:"
# -------------------------------------------------------------
# Do not deploy kernel module with specfic tarball
MODULE_TARBALL_DEPLOY = "0"
do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel" do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel"
#--------------------------------------------------------------- #---------------------------------------------------------------
@ -22,13 +19,16 @@ do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel"
KERNEL_SIGN_ENABLE ?= "0" KERNEL_SIGN_ENABLE ?= "0"
EXTRA_OEMAKE += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', 'INSTALL_MOD_STRIP=1','')}" 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 () { 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 #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() { do_install_append() {
# Install KERNEL_IMAGETYPE for kernel-imagebootfs package # Install KERNEL_IMAGETYPE for kernel-imagebootfs package
@ -86,8 +95,19 @@ do_install_append() {
# when ACCEPT_EULA are filled # when ACCEPT_EULA are filled
echo "blacklist etnaviv" > ${D}/${sysconfdir}/modprobe.d/blacklist.conf echo "blacklist etnaviv" > ${D}/${sysconfdir}/modprobe.d/blacklist.conf
fi 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. # Support checking the kernel load address parameter: expecting proper value for ST kernel.
# #

View File

@ -0,0 +1,40 @@
From ac8315bbe1279affc860703a9062143e9eab9fa0 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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 <romuald.jeanne@st.com>
---
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

View File

@ -1,22 +1,21 @@
From 458e623d9cf01cde1dc2404da5377064b3136389 Mon Sep 17 00:00:00 2001 From 147c507542ee7feb5bd85212669eeaec2c0420b1 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com> From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Mon, 5 Oct 2020 13:19:41 +0200 Date: Tue, 16 Mar 2021 08:56:21 +0100
Subject: [PATCH 02/22] ARM-stm32mp1-r2-rc8-CPUFREQ Subject: [PATCH 03/22] ARM 5.10.10-stm32mp1-r1 CPUFREQ
--- ---
drivers/cpufreq/Kconfig.arm | 7 ++ drivers/cpufreq/Kconfig.arm | 7 ++
drivers/cpufreq/Makefile | 1 + 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/cpufreq/stm32-cpufreq.c | 101 +++++++++++++++++++++++++++
drivers/opp/core.c | 12 +++- 4 files changed, 112 insertions(+)
5 files changed, 121 insertions(+), 1 deletion(-)
create mode 100644 drivers/cpufreq/stm32-cpufreq.c create mode 100644 drivers/cpufreq/stm32-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm 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 --- a/drivers/cpufreq/Kconfig.arm
+++ b/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 this config option if you wish to add CPUFreq support for STi based
SoCs. SoCs.
@ -31,10 +30,10 @@ index a905796f7f856..b2beb170840be 100644
bool bool
depends on CPUFREQ_DT && ARCH_TANGO depends on CPUFREQ_DT && ARCH_TANGO
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 9a9f5ccd13d98..6139d2aebea40 100644 index f1b7e3dd6e5d..b373f97f26a2 100644
--- a/drivers/cpufreq/Makefile --- a/drivers/cpufreq/Makefile
+++ b/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_SCPI_CPUFREQ) += scpi-cpufreq.o
obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-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_TANGO_CPUFREQ) += tango-cpufreq.o
obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-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 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 --- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/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,stih407", },
{ .compatible = "st,stih410", }, { .compatible = "st,stih410", },
{ .compatible = "st,stih418", },
+ { .compatible = "st,stm32mp151", },
+ { .compatible = "st,stm32mp153", },
+ { .compatible = "st,stm32mp157", }, + { .compatible = "st,stm32mp157", },
{ .compatible = "sigma,tango4", }, { .compatible = "sigma,tango4", },
diff --git a/drivers/cpufreq/stm32-cpufreq.c b/drivers/cpufreq/stm32-cpufreq.c diff --git a/drivers/cpufreq/stm32-cpufreq.c b/drivers/cpufreq/stm32-cpufreq.c
new file mode 100644 new file mode 100644
index 0000000000000..35fb3520d48df index 000000000000..35fb3520d48d
--- /dev/null --- /dev/null
+++ b/drivers/cpufreq/stm32-cpufreq.c +++ b/drivers/cpufreq/stm32-cpufreq.c
@@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
@ -161,38 +162,6 @@ index 0000000000000..35fb3520d48df
+MODULE_DESCRIPTION("STM32 CPU freq driver"); +MODULE_DESCRIPTION("STM32 CPU freq driver");
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>"); +MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_LICENSE("GPL v2"); +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 2.17.1

View File

@ -1,244 +1,18 @@
From 0f32661351778c6c282c9509defdcec61abf7fab Mon Sep 17 00:00:00 2001 From 56442e69cbaf31555a9bb4f3311a0593a0c172cc Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com> From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Mon, 5 Oct 2020 13:19:41 +0200 Date: Tue, 16 Mar 2021 08:56:48 +0100
Subject: [PATCH 03/22] ARM-stm32mp1-r2-rc8-CRYPTO Subject: [PATCH 04/22] ARM 5.10.10-stm32mp1-r1 CRYPTO
--- ---
drivers/crypto/stm32/Kconfig | 2 + drivers/crypto/stm32/stm32-cryp.c | 300 +++++++++++++++++++++---------
drivers/crypto/stm32/stm32-crc32.c | 99 +++++++++- drivers/crypto/stm32/stm32-hash.c | 19 +-
drivers/crypto/stm32/stm32-cryp.c | 300 +++++++++++++++++++++-------- 2 files changed, 228 insertions(+), 91 deletions(-)
drivers/crypto/stm32/stm32-hash.c | 57 ++++--
4 files changed, 348 insertions(+), 110 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 <linux/bitrev.h>
#include <linux/clk.h>
+#include <linux/crc32.h>
#include <linux/crc32poly.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
@@ -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 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 --- a/drivers/crypto/stm32/stm32-cryp.c
+++ b/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 authsize;
size_t hw_blocksize; size_t hw_blocksize;
@ -251,7 +25,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
struct scatterlist *in_sg; struct scatterlist *in_sg;
struct scatterlist *out_sg; struct scatterlist *out_sg;
@@ -156,9 +156,6 @@ struct stm32_cryp { @@ -157,9 +157,6 @@ struct stm32_cryp {
struct scatterlist out_sgl; struct scatterlist out_sgl;
bool sgs_copied; bool sgs_copied;
@ -261,7 +35,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
struct scatter_walk in_walk; struct scatter_walk in_walk;
struct scatter_walk out_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, ret = stm32_cryp_check_aligned(cryp->out_sg, cryp->total_out,
cryp->hw_blocksize); cryp->hw_blocksize);
@ -311,7 +85,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
if (!stm32_cryp_check_io_aligned(cryp)) { if (!stm32_cryp_check_io_aligned(cryp)) {
cryp->sgs_copied = 0; 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); total_in = ALIGN(cryp->total_in, cryp->hw_blocksize);
@ -356,7 +130,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
cryp->sgs_copied = 1; 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_in = sg_virt(&cryp->in_sgl);
buf_out = sg_virt(&cryp->out_sgl); buf_out = sg_virt(&cryp->out_sgl);
@ -375,7 +149,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
pages = len ? get_order(len) : 1; pages = len ? get_order(len) : 1;
free_pages((unsigned long)buf_out, pages); 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, static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm,
unsigned int authsize) unsigned int authsize)
{ {
@ -397,69 +171,69 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
} }
static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm, 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_AES | FLG_ECB); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_AES | FLG_CBC); 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 0;
+ +
return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT); 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 0;
+ +
return stm32_cryp_crypt(req, FLG_AES | FLG_CTR); 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); 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); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_DES | FLG_ECB); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_DES | FLG_CBC); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT); 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; + return -EINVAL;
+ +
+ if (req->nbytes == 0) + if (req->cryptlen == 0)
+ return 0; + return 0;
+ +
return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC); 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->areq = areq;
cryp->req = NULL; cryp->req = NULL;
cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq)); cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq));
@ -627,7 +401,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
ret = stm32_cryp_copy_sgs(cryp); ret = stm32_cryp_copy_sgs(cryp);
if (ret) if (ret)
return 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)) { if (is_gcm(cryp) || is_ccm(cryp)) {
/* In output, jump after assoc data */ /* In output, jump after assoc data */
scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen); scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen);
@ -636,7 +410,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
} }
ret = stm32_cryp_hw_init(cryp); 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); stm32_cryp_write(cryp, CRYP_DIN, size_bit);
size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen : size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen :
@ -644,8 +418,8 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
+ cryp->areq->cryptlen - cryp->authsize; + cryp->areq->cryptlen - cryp->authsize;
size_bit *= 8; size_bit *= 8;
if (cryp->caps->swap_final) if (cryp->caps->swap_final)
size_bit = cpu_to_be32(size_bit); size_bit = (__force u32)cpu_to_be32(size_bit);
@@ -1159,14 +1283,14 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) @@ -1169,14 +1293,14 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
dst = sg_virt(cryp->out_sg) + _walked_out; dst = sg_virt(cryp->out_sg) + _walked_out;
for (i = 0; i < AES_BLOCK_32; i++) { for (i = 0; i < AES_BLOCK_32; i++) {
@ -663,7 +437,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* Empty fifo out (data from input padding) */ /* Empty fifo out (data from input padding) */
stm32_cryp_read(cryp, CRYP_DOUT); stm32_cryp_read(cryp, CRYP_DOUT);
} else { } 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); d32 = stm32_cryp_read(cryp, CRYP_DOUT);
d8 = (u8 *)&d32; d8 = (u8 *)&d32;
@ -677,7 +451,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
} }
} }
} else { } 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]; u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32];
scatterwalk_map_and_copy(in_tag, cryp->in_sg, scatterwalk_map_and_copy(in_tag, cryp->in_sg,
@ -686,7 +460,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
cryp->authsize, 0); cryp->authsize, 0);
for (i = 0; i < AES_BLOCK_32; i++) 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; dst = sg_virt(cryp->out_sg) + _walked_out;
for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { 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) */ /* Empty fifo out (data from input padding) */
d32 = stm32_cryp_read(cryp, CRYP_DOUT); d32 = stm32_cryp_read(cryp, CRYP_DOUT);
} else { } 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); d32 = stm32_cryp_read(cryp, CRYP_DOUT);
d8 = (u8 *)&d32; d8 = (u8 *)&d32;
@ -722,7 +496,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
} }
static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp) 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; src = sg_virt(cryp->in_sg) + _walked_in;
for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { 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; int err;
u32 cfg, tmp[AES_BLOCK_32]; u32 cfg, tmp[AES_BLOCK_32];
@ -762,7 +536,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
struct scatterlist *out_sg_ori = cryp->out_sg; struct scatterlist *out_sg_ori = cryp->out_sg;
unsigned int i; 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 */ /* b) pad and write the last block */
stm32_cryp_irq_write_block(cryp); stm32_cryp_irq_write_block(cryp);
@ -771,7 +545,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
err = stm32_cryp_wait_output(cryp); err = stm32_cryp_wait_output(cryp);
if (err) { if (err) {
dev_err(cryp->dev, "Timeout (write gcm header)\n"); 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 */ /* c) get and store encrypted data */
stm32_cryp_irq_read_data(cryp); stm32_cryp_irq_read_data(cryp);
scatterwalk_map_and_copy(tmp, out_sg_ori, scatterwalk_map_and_copy(tmp, out_sg_ori,
@ -782,7 +556,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* d) change mode back to AES GCM */ /* d) change mode back to AES GCM */
cfg &= ~CR_ALGO_MASK; 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 */ /* f) write padded data */
for (i = 0; i < AES_BLOCK_32; i++) { for (i = 0; i < AES_BLOCK_32; i++) {
@ -797,7 +571,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
} }
/* g) Empty fifo out */ /* 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; cfg &= ~CR_CRYPEN;
stm32_cryp_write(cryp, CRYP_CR, cfg); 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 |= (cryp->hw_blocksize - payload_bytes) << CR_NBPBL_SHIFT;
cfg |= CR_CRYPEN; cfg |= CR_CRYPEN;
stm32_cryp_write(cryp, CRYP_CR, cfg); 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; int err = 0;
u32 cfg, iv1tmp; u32 cfg, iv1tmp;
u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32], tmp[AES_BLOCK_32]; 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; struct scatterlist *out_sg_ori = cryp->out_sg;
unsigned int i; 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 */ /* b) pad and write the last block */
stm32_cryp_irq_write_block(cryp); stm32_cryp_irq_write_block(cryp);
@ -826,7 +600,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
err = stm32_cryp_wait_output(cryp); err = stm32_cryp_wait_output(cryp);
if (err) { if (err) {
dev_err(cryp->dev, "Timeout (wite ccm padded data)\n"); 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 */ /* c) get and store decrypted data */
@ -843,7 +617,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* d) Load again CRYP_CSGCMCCMxR */ /* d) Load again CRYP_CSGCMCCMxR */
for (i = 0; i < ARRAY_SIZE(cstmp2); i++) 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) 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) && (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) &&
is_encrypt(cryp))) { is_encrypt(cryp))) {
/* Padding for AES GCM encryption */ /* 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); stm32_cryp_irq_set_npblb(cryp);
} }
@ -867,7 +641,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
(stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) && (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) &&
is_decrypt(cryp))) { is_decrypt(cryp))) {
/* Padding for AES CCM decryption */ /* 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); stm32_cryp_write(cryp, CRYP_DIN, *src);
src = stm32_cryp_next_in(cryp, src, sizeof(u32)); src = stm32_cryp_next_in(cryp, src, sizeof(u32));
@ -880,7 +654,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
cryp->areq->assoclen) { cryp->areq->assoclen) {
/* Write padding if needed */ /* Write padding if needed */
for (j = i + 1; j < AES_BLOCK_32; j++) 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; break;
} }
@ -889,7 +663,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
break; 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); stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
i++; i++;
@ -898,7 +672,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
} else { } else {
/* Build the two first u32 of B1 */ /* Build the two first u32 of B1 */
d8[0] = 0xFF; 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); stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
i++; 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); d8[k] = *((u8 *)src);
src = stm32_cryp_next_in(cryp, src, 1); src = stm32_cryp_next_in(cryp, src, 1);
@ -925,7 +699,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* Write padding if needed */ /* Write padding if needed */
for (j = i + 1; j < AES_BLOCK_32; j++) for (j = i + 1; j < AES_BLOCK_32; j++)
stm32_cryp_write(cryp, CRYP_DIN, 0); 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); cryp->clk = devm_clk_get(dev, NULL);
if (IS_ERR(cryp->clk)) { if (IS_ERR(cryp->clk)) {
@ -936,7 +710,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
return PTR_ERR(cryp->clk); 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); pm_runtime_enable(dev);
rst = devm_reset_control_get(dev, NULL); rst = devm_reset_control_get(dev, NULL);
@ -949,7 +723,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
reset_control_assert(rst); reset_control_assert(rst);
udelay(2); udelay(2);
reset_control_deassert(rst); 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); spin_lock(&cryp_list.lock);
list_del(&cryp->list); list_del(&cryp->list);
spin_unlock(&cryp_list.lock); spin_unlock(&cryp_list.lock);
@ -959,35 +733,10 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
pm_runtime_put_noidle(dev); pm_runtime_put_noidle(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c 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 --- a/drivers/crypto/stm32/stm32-hash.c
+++ b/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) @@ -925,15 +925,10 @@ static int stm32_hash_final(struct ahash_request *req)
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)
static int stm32_hash_finup(struct ahash_request *req) static int stm32_hash_finup(struct ahash_request *req)
{ {
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
@ -1003,7 +752,7 @@ index cfc8e0e37beec..f8b0e1b28971e 100644
err1 = stm32_hash_update(req); err1 = stm32_hash_update(req);
if (err1 == -EINPROGRESS || err1 == -EBUSY) 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) 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) 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 2.17.1

View File

@ -0,0 +1,881 @@
From fe6c762c8d16cddae0a0fd5673f7ab8c6b06f4e5 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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 <linux/i2c-mux.h>
#include <linux/i2c.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
@@ -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 <linux/uaccess.h>
#include <asm/unaligned.h>
+#include <linux/of_device.h>
+#include <drm/drm_mipi_dsi.h>
#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 <linux/input/touchscreen.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <drm/drm_mipi_dsi.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
@@ -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

View File

@ -1,19 +1,20 @@
From 10e0333454dbd6ccecb67ad303eae3aef707ce0b Mon Sep 17 00:00:00 2001 From 5c27ce1dc05fd740cc8f0f1d8072361ccab51a9f Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com> From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Mon, 5 Oct 2020 13:19:43 +0200 Date: Tue, 16 Mar 2021 09:02:36 +0100
Subject: [PATCH 08/22] ARM-stm32mp1-r2-rc8-HWSPINLOCK Subject: [PATCH 07/22] ARM 5.10.10-stm32mp1-r1 HWSPINLOCK
Signed-off-by: Romuald JEANNE <romuald.jeanne@st.com>
--- ---
Documentation/hwspinlock.txt | 10 ++- Documentation/locking/hwspinlock.rst | 10 ++-
drivers/hwspinlock/hwspinlock_core.c | 82 ++++++++++++++++++------ drivers/hwspinlock/hwspinlock_core.c | 80 +++++++++++++++++++-----
drivers/hwspinlock/hwspinlock_internal.h | 2 + drivers/hwspinlock/hwspinlock_internal.h | 2 +
drivers/hwspinlock/stm32_hwspinlock.c | 62 +++++++++++------- drivers/hwspinlock/stm32_hwspinlock.c | 60 +++++++++++-------
4 files changed, 112 insertions(+), 44 deletions(-) 4 files changed, 110 insertions(+), 42 deletions(-)
diff --git a/Documentation/hwspinlock.txt b/Documentation/hwspinlock.txt diff --git a/Documentation/locking/hwspinlock.rst b/Documentation/locking/hwspinlock.rst
index 6f03713b70039..605bd2dc8a03e 100644 index 6f03713b7003..605bd2dc8a03 100644
--- a/Documentation/hwspinlock.txt --- a/Documentation/locking/hwspinlock.rst
+++ b/Documentation/hwspinlock.txt +++ b/Documentation/locking/hwspinlock.rst
@@ -54,9 +54,11 @@ Should be called from a process context (might sleep). @@ -54,9 +54,11 @@ Should be called from a process context (might sleep).
struct hwspinlock *hwspin_lock_request_specific(unsigned int id); 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 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 --- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -29,6 +29,8 @@ @@ -29,6 +29,8 @@
@ -144,9 +145,9 @@ index 8862445aa8580..ac76631c7059b 100644
/* prevent underlying implementation from being removed */ /* prevent underlying implementation from being removed */
if (!try_module_get(dev->driver->owner)) { if (!try_module_get(dev->driver->owner)) {
@@ -664,13 +700,18 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock) @@ -666,13 +702,18 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock)
return ret;
} ret = 0;
+ /* update shareable refcount */ + /* update shareable refcount */
+ id = hwlock_to_id(hwlock); + id = hwlock_to_id(hwlock);
@ -166,7 +167,7 @@ index 8862445aa8580..ac76631c7059b 100644
return ret; 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) */ /* sanity check (this shouldn't happen) */
WARN_ON(hwlock_to_id(hwlock) != id); 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); pr_warn("hwspinlock %u is already in use\n", id);
hwlock = NULL; hwlock = NULL;
goto out; 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 device *dev;
struct hwspinlock *tmp; struct hwspinlock *tmp;
@ -188,7 +189,7 @@ index 8862445aa8580..ac76631c7059b 100644
if (!hwlock) { if (!hwlock) {
pr_err("invalid hwlock\n"); 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); mutex_lock(&hwspinlock_tree_lock);
/* make sure the hwspinlock is used */ /* make sure the hwspinlock is used */
@ -205,16 +206,13 @@ index 8862445aa8580..ac76631c7059b 100644
} }
/* notify the underlying device that power is not needed */ /* notify the underlying device that power is not needed */
ret = pm_runtime_put(dev); pm_runtime_put(dev);
if (ret < 0)
- goto out;
+ goto unlock;
+
+ /* update shareable refcount */ + /* update shareable refcount */
+ if (radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_SHARED) && + if (radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_SHARED) &&
+ --hwlock->refcount) + --hwlock->refcount)
+ goto put; + goto put;
+
/* mark this hwspinlock as available */ /* mark this hwspinlock as available */
- tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock), - tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock),
- HWSPINLOCK_UNUSED); - HWSPINLOCK_UNUSED);
@ -232,7 +230,7 @@ index 8862445aa8580..ac76631c7059b 100644
return ret; return ret;
} }
diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h 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 --- a/drivers/hwspinlock/hwspinlock_internal.h
+++ b/drivers/hwspinlock/hwspinlock_internal.h +++ b/drivers/hwspinlock/hwspinlock_internal.h
@@ -35,11 +35,13 @@ struct hwspinlock_ops { @@ -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 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 --- a/drivers/hwspinlock/stm32_hwspinlock.c
+++ b/drivers/hwspinlock/stm32_hwspinlock.c +++ b/drivers/hwspinlock/stm32_hwspinlock.c
@@ -54,8 +54,23 @@ static const struct hwspinlock_ops stm32_hwspinlock_ops = { @@ -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 device *dev = &pdev->dev;
struct stm32_hwspinlock *hw; struct stm32_hwspinlock *hw;
void __iomem *io_base; void __iomem *io_base;
struct resource *res; size_t array_size;
@@ -63,46 +78,48 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev) @@ -66,41 +81,43 @@ 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))
return PTR_ERR(io_base); return PTR_ERR(io_base);
array_size = STM32_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock); 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) 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 = { static struct platform_driver stm32_hwspinlock_driver = {
.probe = stm32_hwspinlock_probe, .probe = stm32_hwspinlock_probe,

View File

@ -0,0 +1,532 @@
From 55dcc42c73d9d2c733972cd89bbbbb6d75b7d942 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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 <romuald.jeanne@st.com>
---
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 <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/gpio.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <asm/exception.h>
+
+#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

View File

@ -0,0 +1,62 @@
From 83c3a690670bb23a4a1fb645cf980056b4f85f4d Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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

View File

@ -1,28 +1,43 @@
From 38993f1a9ca823da25a15d8c8b1bc839a0165c0a Mon Sep 17 00:00:00 2001 From f9e34d8836c280d291e1779bf50f895f55a1e8fc Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com> From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Mon, 5 Oct 2020 13:19:56 +0200 Date: Tue, 16 Mar 2021 09:16:53 +0100
Subject: [PATCH 22/22] ARM-stm32mp1-r2-rc8-PERF Subject: [PATCH 14/22] ARM 5.10.10-stm32mp1-r1 PERF
--- ---
Documentation/perf/stm32-ddr-pmu.txt | 41 +++ Documentation/admin-guide/perf/index.rst | 1 +
drivers/perf/Kconfig | 6 + .../admin-guide/perf/stm32-ddr-pmu.rst | 44 ++
drivers/perf/Makefile | 1 + drivers/perf/Kconfig | 7 +
drivers/perf/stm32_ddr_pmu.c | 505 +++++++++++++++++++++++++++ drivers/perf/Makefile | 1 +
4 files changed, 553 insertions(+) drivers/perf/stm32_ddr_pmu.c | 428 ++++++++++++++++++
create mode 100644 Documentation/perf/stm32-ddr-pmu.txt 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 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 new file mode 100644
index 0000000000000..d5b35b3261bdb index 000000000000..db647fc1acad
--- /dev/null --- /dev/null
+++ b/Documentation/perf/stm32-ddr-pmu.txt +++ b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst
@@ -0,0 +1,41 @@ @@ -0,0 +1,44 @@
+========================================
+STM32 DDR Performance Monitor (DDRPERFM) +STM32 DDR Performance Monitor (DDRPERFM)
+======================================== +========================================
+ +
+The DDRPERFM is the DDR Performance Monitor embedded in STM32MP1 SOC. +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: +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 +The stm32-ddr-pmu driver relies on the perf PMU framework to expose the
+counters via sysfs: +counters via sysfs:
+
+ .. code-block:: bash
+
+ $ ls /sys/bus/event_source/devices/ddrperfm/events + $ ls /sys/bus/event_source/devices/ddrperfm/events
+ activate_cnt idle_cnt read_cnt time_cnt write_cnt + activate_cnt idle_cnt read_cnt time_cnt write_cnt
+ +
@ -46,7 +64,10 @@ index 0000000000000..d5b35b3261bdb
+option is mandatory! +option is mandatory!
+ +
+Example: +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': + Performance counter stats for 'system wide':
+ +
+ 342541560 ddrperfm/read_cnt/ + 342541560 ddrperfm/read_cnt/
@ -54,33 +75,29 @@ index 0000000000000..d5b35b3261bdb
+ +
+ 20.021068551 seconds time elapsed + 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 diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 09ae8a970880f..2c50413145ab1 100644 index 130327ff0b0e..a62a26fc516a 100644
--- a/drivers/perf/Kconfig --- a/drivers/perf/Kconfig
+++ b/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 Adds the L3 cache PMU into the perf events subsystem for
monitoring L3 cache events. monitoring L3 cache events.
+config STM32_DDR_PMU +config STM32_DDR_PMU
+ bool "STM32 DDR PMU" + tristate "STM32 DDR PMU"
+ depends on MACH_STM32MP157 + depends on MACH_STM32MP157
+ help + default m
+ Support for STM32 DDR performance monitor (DDRPERFM). + help
+ Support for STM32 DDR performance monitor (DDRPERFM).
+ +
config THUNDERX2_PMU config THUNDERX2_PMU
tristate "Cavium ThunderX2 SoC PMU UNCORE" tristate "Cavium ThunderX2 SoC PMU UNCORE"
depends on ARCH_THUNDER2 && ARM64 && ACPI && NUMA depends on ARCH_THUNDER2 && ARM64 && ACPI && NUMA
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index 2ebb4de178151..fd3368c1b4549 100644 index 5365fd56f88f..7f2b7c5f9216 100644
--- a/drivers/perf/Makefile --- a/drivers/perf/Makefile
+++ b/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_HISI_PMU) += hisilicon/
obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o
obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_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 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 diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c
new file mode 100644 new file mode 100644
index 0000000000000..4f30f6f8be964 index 000000000000..ee7a33083e02
--- /dev/null --- /dev/null
+++ b/drivers/perf/stm32_ddr_pmu.c +++ b/drivers/perf/stm32_ddr_pmu.c
@@ -0,0 +1,505 @@ @@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0
+/* +/*
+ * This file is the STM32 DDR performance monitor (DDRPERFM) driver + * 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 <gerald.baeza@st.com> + * Author: Gerald Baeza <gerald.baeza@st.com>
+ */ + */
+ +
+#include <linux/clk.h> +#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h> +#include <linux/hrtimer.h>
+#include <linux/io.h> +#include <linux/io.h>
+#include <linux/module.h> +#include <linux/module.h>
+#include <linux/of_platform.h> +#include <linux/of_platform.h>
+#include <linux/perf_event.h> +#include <linux/perf_event.h>
+#include <linux/reset.h>
+#include <linux/slab.h> +#include <linux/slab.h>
+#include <linux/types.h> +#include <linux/types.h>
+ +
+#define POLL_MS 4000 /* The counter roll over after ~8s @533MHz */ +/*
+#define WORD_LENGTH 4 /* Bytes */ + * The PMU is able to freeze all counters and generate an interrupt when there
+#define BURST_LENGTH 8 /* Words */ + * 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_CTL 0x000
+#define DDRPERFM_CFG 0x004 +#define DDRPERFM_CFG 0x004
+#define DDRPERFM_STATUS 0x008 +#define DDRPERFM_STATUS 0x008
+#define DDRPERFM_CCR 0x00C +#define DDRPERFM_CCR 0x00C
+#define DDRPERFM_IER 0x010
+#define DDRPERFM_ISR 0x014
+#define DDRPERFM_ICR 0x018
+#define DDRPERFM_TCNT 0x020 +#define DDRPERFM_TCNT 0x020
+#define DDRPERFM_CNT(X) (0x030 + 8 * (X)) +#define DDRPERFM_CNT(X) (0x030 + 8 * (X))
+#define DDRPERFM_HWCFG 0x3F0
+#define DDRPERFM_VER 0x3F4 +#define DDRPERFM_VER 0x3F4
+#define DDRPERFM_ID 0x3F8 +#define DDRPERFM_ID 0x3F8
+#define DDRPERFM_SID 0x3FC
+ +
+#define CTL_START 0x00000001 +#define CTL_START 0x00000001
+#define CTL_STOP 0x00000002 +#define CTL_STOP 0x00000002
+#define CCR_CLEAR_ALL 0x8000000F +#define CCR_CLEAR_ALL 0x8000000F
+#define SID_MAGIC_ID 0xA3C5DD01
+
+#define STRING "Read = %llu, Write = %llu, Read & Write = %llu (MB/s)\n"
+ +
+enum { +enum {
+ READ_CNT, + READ_CNT,
@ -148,12 +166,11 @@ index 0000000000000..4f30f6f8be964
+struct stm32_ddr_pmu { +struct stm32_ddr_pmu {
+ struct pmu pmu; + struct pmu pmu;
+ void __iomem *membase; + void __iomem *membase;
+ struct device *dev;
+ struct clk *clk; + struct clk *clk;
+ struct clk *clk_ddr;
+ unsigned long clk_ddr_rate;
+ struct hrtimer hrtimer; + struct hrtimer hrtimer;
+ cpumask_t pmu_cpu;
+ ktime_t poll_period; + ktime_t poll_period;
+ spinlock_t lock; /* for shared registers access */
+ struct perf_event *events[PMU_NR_COUNTERS]; + struct perf_event *events[PMU_NR_COUNTERS];
+ u64 events_cnt[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); + 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) +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); + 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; + u32 val;
+ +
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL); + writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
+ +
+ if (config_base < TIME_CNT) { + if (config_base < TIME_CNT) {
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG); + 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); + 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) +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); + 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; + struct hw_perf_event *hw = &event->hw;
+ u64 prev_count, new_count, mask; + u64 prev_count, new_count, mask;
+ u32 val, offset, bit; + u32 val, offset, bit;
+ +
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, flags);
+
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL); + writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
+ +
+ if (config_base == TIME_CNT) { + if (config_base == TIME_CNT) {
+ offset = DDRPERFM_TCNT; + offset = DDRPERFM_TCNT;
+ bit = 1 << 31; + bit = BIT(31);
+ } else { + } else {
+ offset = DDRPERFM_CNT(config_base); + offset = DDRPERFM_CNT(config_base);
+ bit = 1 << config_base; + bit = BIT(config_base);
+ } + }
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_STATUS); + val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_STATUS);
+ if (val & bit) + 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); + val = readl_relaxed(stm32_ddr_pmu->membase + offset);
+ writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR); + writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR);
+ writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL); + writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL);
@ -271,18 +231,12 @@ index 0000000000000..4f30f6f8be964
+ +
+ mask = GENMASK_ULL(31, 0); + mask = GENMASK_ULL(31, 0);
+ local64_add(val & mask, &event->count); + 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) +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 stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ struct hw_perf_event *hw = &event->hw; + struct hw_perf_event *hw = &event->hw;
+ unsigned long lock_flags;
+ +
+ if (WARN_ON_ONCE(!(hw->state & PERF_HES_STOPPED))) + if (WARN_ON_ONCE(!(hw->state & PERF_HES_STOPPED)))
+ return; + return;
@ -293,37 +247,33 @@ index 0000000000000..4f30f6f8be964
+ stm32_ddr_pmu_event_configure(event); + stm32_ddr_pmu_event_configure(event);
+ +
+ /* Clear all counters to synchronize them, then start */ + /* 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(CCR_CLEAR_ALL, stm32_ddr_pmu->membase + DDRPERFM_CCR);
+ writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL); + 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; + hw->state = 0;
+} +}
+ +
+static void stm32_ddr_pmu_event_stop(struct perf_event *event, int flags) +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); + 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; + struct hw_perf_event *hw = &event->hw;
+ u32 val, bit; + u32 val, bit;
+ +
+ if (WARN_ON_ONCE(hw->state & PERF_HES_STOPPED)) + if (WARN_ON_ONCE(hw->state & PERF_HES_STOPPED))
+ return; + return;
+ +
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL); + writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
+ if (config_base == TIME_CNT) + if (config_base == TIME_CNT)
+ bit = 1 << 31; + bit = BIT(31);
+ else + else
+ bit = 1 << config_base; + bit = BIT(config_base);
+ writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR); + writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR);
+ if (config_base < TIME_CNT) { + if (config_base < TIME_CNT) {
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG); + val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG);
+ val &= ~bit; + val &= ~bit;
+ writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG); + writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG);
+ } + }
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags);
+ +
+ hw->state |= PERF_HES_STOPPED; + hw->state |= PERF_HES_STOPPED;
+ +
@ -343,8 +293,13 @@ index 0000000000000..4f30f6f8be964
+ stm32_ddr_pmu->events[config_base] = event; + stm32_ddr_pmu->events[config_base] = event;
+ +
+ clk_enable(stm32_ddr_pmu->clk); + 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_start(&stm32_ddr_pmu->hrtimer, stm32_ddr_pmu->poll_period,
+ HRTIMER_MODE_REL); + HRTIMER_MODE_REL_PINNED);
+ +
+ stm32_ddr_pmu_event_configure(event); + 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); + struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ unsigned long config_base = event->hw.config_base; + unsigned long config_base = event->hw.config_base;
+ bool stop = true;
+ int i; + int i;
+ +
+ stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE); + stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE);
@ -370,8 +324,9 @@ index 0000000000000..4f30f6f8be964
+ +
+ for (i = 0; i < PMU_NR_COUNTERS; i++) + for (i = 0; i < PMU_NR_COUNTERS; i++)
+ if (stm32_ddr_pmu->events[i]) + if (stm32_ddr_pmu->events[i])
+ stop = false; + break;
+ if (stop) +
+ if (i == PMU_NR_COUNTERS)
+ hrtimer_cancel(&stm32_ddr_pmu->hrtimer); + hrtimer_cancel(&stm32_ddr_pmu->hrtimer);
+ +
+ clk_disable(stm32_ddr_pmu->clk); + clk_disable(stm32_ddr_pmu->clk);
@ -379,11 +334,15 @@ index 0000000000000..4f30f6f8be964
+ +
+static int stm32_ddr_pmu_event_init(struct perf_event *event) +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; + struct hw_perf_event *hw = &event->hw;
+ +
+ if (event->attr.type != event->pmu->type) + if (event->attr.type != event->pmu->type)
+ return -ENOENT; + return -ENOENT;
+ +
+ if (event->attr.config >= PMU_NR_COUNTERS)
+ return -ENOENT;
+
+ if (is_sampling_event(event)) + if (is_sampling_event(event))
+ return -EINVAL; + return -EINVAL;
+ +
@ -402,6 +361,7 @@ index 0000000000000..4f30f6f8be964
+ return -EINVAL; + return -EINVAL;
+ +
+ hw->config_base = event->attr.config; + hw->config_base = event->attr.config;
+ event->cpu = cpumask_first(&stm32_ddr_pmu->pmu_cpu);
+ +
+ return 0; + return 0;
+} +}
@ -431,27 +391,6 @@ index 0000000000000..4f30f6f8be964
+ return sprintf(buf, "config=0x%lx\n", (unsigned long)eattr->var); + 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) \ +#define STM32_DDR_PMU_ATTR(_name, _func, _config) \
+ (&((struct dev_ext_attribute[]) { \ + (&((struct dev_ext_attribute[]) { \
+ { __ATTR(_name, 0444, _func, NULL), (void *)_config } \ + { __ATTR(_name, 0444, _func, NULL), (void *)_config } \
@ -470,82 +409,66 @@ index 0000000000000..4f30f6f8be964
+ NULL + 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 = { +static struct attribute_group stm32_ddr_pmu_event_attrs_group = {
+ .name = "events", + .name = "events",
+ .attrs = stm32_ddr_pmu_event_attrs, + .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[] = { +static const struct attribute_group *stm32_ddr_pmu_attr_groups[] = {
+ &stm32_ddr_pmu_event_attrs_group, + &stm32_ddr_pmu_event_attrs_group,
+ &stm32_ddr_pmu_bandwidth_attrs_group,
+ NULL, + NULL,
+}; +};
+ +
+static int stm32_ddr_pmu_device_probe(struct platform_device *pdev) +static int stm32_ddr_pmu_device_probe(struct platform_device *pdev)
+{ +{
+ struct stm32_ddr_pmu *stm32_ddr_pmu; + struct stm32_ddr_pmu *stm32_ddr_pmu;
+ struct reset_control *rst;
+ struct resource *res; + struct resource *res;
+ int i, ret; + int i, ret;
+ u32 val;
+ +
+ stm32_ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(struct stm32_ddr_pmu), + stm32_ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(struct stm32_ddr_pmu),
+ GFP_KERNEL); + GFP_KERNEL);
+ if (!stm32_ddr_pmu) + if (!stm32_ddr_pmu)
+ return -ENOMEM; + return -ENOMEM;
+ platform_set_drvdata(pdev, stm32_ddr_pmu); + platform_set_drvdata(pdev, stm32_ddr_pmu);
+ stm32_ddr_pmu->dev = &pdev->dev;
+ +
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ stm32_ddr_pmu->membase = devm_ioremap_resource(&pdev->dev, res); + stm32_ddr_pmu->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(stm32_ddr_pmu->membase)) { + 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); + 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)) { + 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); + return PTR_ERR(stm32_ddr_pmu->clk);
+ } + }
+ +
+ ret = clk_prepare_enable(stm32_ddr_pmu->clk); + ret = clk_prepare_enable(stm32_ddr_pmu->clk);
+ if (ret) { + if (ret) {
+ pr_warn("Unable to prepare STM32 DDR PMU clock\n"); + dev_err(&pdev->dev, "unable to prepare the clock\n");
+ return ret; + 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); + stm32_ddr_pmu->poll_period = ms_to_ktime(POLL_MS);
+ hrtimer_init(&stm32_ddr_pmu->hrtimer, CLOCK_MONOTONIC, + hrtimer_init(&stm32_ddr_pmu->hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL); + HRTIMER_MODE_REL);
+ stm32_ddr_pmu->hrtimer.function = stm32_ddr_pmu_poll; + 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++) { + for (i = 0; i < PMU_NR_COUNTERS; i++) {
+ stm32_ddr_pmu->events[i] = NULL; + stm32_ddr_pmu->events[i] = NULL;
+ stm32_ddr_pmu->events_cnt[i] = 0; + 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) { + stm32_ddr_pmu->pmu = (struct pmu) {
+ .task_ctx_nr = perf_invalid_context, + .task_ctx_nr = perf_invalid_context,
+ .start = stm32_ddr_pmu_event_start, + .start = stm32_ddr_pmu_event_start,
@ -555,20 +478,35 @@ index 0000000000000..4f30f6f8be964
+ .event_init = stm32_ddr_pmu_event_init, + .event_init = stm32_ddr_pmu_event_init,
+ .attr_groups = stm32_ddr_pmu_attr_groups, + .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) { + if (ret) {
+ pr_warn("Unable to register STM32 DDR PMU\n"); + dev_err(&pdev->dev, "unable to register the pmu\n");
+ return ret; + goto err_pmu_register;
+ } + }
+ +
+ pr_info("stm32-ddr-pmu: probed (ID=0x%08x VER=0x%08x), DDR@%luMHz\n", + rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_ID), + if (IS_ERR(rst)) {
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_VER), + dev_err(&pdev->dev, "unable to get the reset\n");
+ stm32_ddr_pmu->clk_ddr_rate); + 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); + clk_disable(stm32_ddr_pmu->clk);
+ +
+ return 0; + 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) +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); + perf_pmu_unregister(&stm32_ddr_pmu->pmu);
+ +
+ clk_unprepare(stm32_ddr_pmu->clk);
+
+ return 0; + return 0;
+} +}
+ +

View File

@ -1,139 +1,163 @@
From 60ca74ac3c89a476b38d4f41c3bea3745779587e Mon Sep 17 00:00:00 2001 From c40d4d83b3de542be7d64b88f0c842ebecc9a6b2 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com> From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Mon, 5 Oct 2020 13:19:46 +0200 Date: Tue, 16 Mar 2021 09:09:52 +0100
Subject: [PATCH 11/22] ARM-stm32mp1-r2-rc8-RESET-RTC-WATCHDOG Subject: [PATCH 17/22] ARM 5.10.10-stm32mp1-r1 RESET-RTC-WATCHDOG
Signed-off-by: Romuald JEANNE <romuald.jeanne@st.com>
--- ---
.../devicetree/bindings/rtc/st,stm32-rtc.txt | 10 +- drivers/reset/Kconfig | 6 -
drivers/reset/reset-stm32mp1.c | 83 +++++--- drivers/reset/Makefile | 1 -
drivers/rtc/Kconfig | 1 + drivers/reset/reset-stm32mp1.c | 115 -------------
drivers/rtc/rtc-stm32.c | 180 +++++++++++++++--- drivers/rtc/Kconfig | 1 +
drivers/watchdog/stm32_iwdg.c | 6 +- drivers/rtc/rtc-stm32.c | 180 ++++++++++++++++----
include/dt-bindings/reset/stm32mp1-resets.h | 15 ++ drivers/watchdog/stm32_iwdg.c | 13 +-
include/dt-bindings/rtc/rtc-stm32.h | 13 ++ include/dt-bindings/reset/stm32mp1-resets.h | 15 ++
7 files changed, 246 insertions(+), 62 deletions(-) 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 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 diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 130ca5b982538..bab0df81af2cc 100644 index 07d162b179fc..c3186d80c33e 100644
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt --- a/drivers/reset/Kconfig
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt +++ b/drivers/reset/Kconfig
@@ -21,9 +21,14 @@ Required properties: @@ -180,12 +180,6 @@ config RESET_SIMPLE
domain (RTC registers) write protection. - Allwinner SoCs
It is required on stm32(f4/f7/h7). - ZTE's zx2967 family
-Optional properties (to override default rtc_ck parent clock on stm32(f4/f7/h7): -config RESET_STM32MP157
+Optional properties: - bool "STM32MP157 Reset Driver" if COMPILE_TEST
+* to override default rtc_ck parent clock on stm32(f4/f7/h7): - default MACH_STM32MP157
- assigned-clocks: reference to the rtc_ck clock entry. - help
- assigned-clock-parents: phandle of the new parent clock of rtc_ck. - This enables the RCC reset controller driver for STM32 MPUs.
+* 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 config RESET_SOCFPGA
+ valid output values are defined in <dt-bindings/rtc/rtc-stm32.h>. bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA
+- pinctrl state named "default" may be defined to reserve pin for RTC output. default ARCH_SOCFPGA
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
Example: index 16947610cc3b..b2c9eff41d3b 100644
--- a/drivers/reset/Makefile
@@ -58,4 +63,7 @@ Example: +++ b/drivers/reset/Makefile
clock-names = "pclk", "rtc_ck"; @@ -24,7 +24,6 @@ obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_NONE>, obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
<&exti 19 1>; obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
+ st,lsco = <RTC_OUT2_RMP>; obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
+ pinctrl-0 = <&rtc_out2_rmp_pins_a>; -obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
+ pinctrl-names = "default"; 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 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 --- a/drivers/reset/reset-stm32mp1.c
+++ b/drivers/reset/reset-stm32mp1.c +++ /dev/null
@@ -4,14 +4,21 @@ @@ -1,115 +0,0 @@
* Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics. -// SPDX-License-Identifier: GPL-2.0
*/ -/*
- * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+#include <dt-bindings/reset/stm32mp1-resets.h> - * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
+#include <linux/arm-smccc.h> - */
#include <linux/device.h> -
#include <linux/err.h> -#include <linux/device.h>
#include <linux/io.h> -#include <linux/err.h>
+#include <linux/module.h> -#include <linux/io.h>
#include <linux/of.h> -#include <linux/of.h>
+#include <linux/of_address.h> -#include <linux/platform_device.h>
#include <linux/platform_device.h> -#include <linux/reset-controller.h>
#include <linux/reset-controller.h> -
+#include <linux/slab.h>
-#define CLR_OFFSET 0x4 -#define CLR_OFFSET 0x4
+#define STM32MP1_RESET_ID_MASK GENMASK(15, 0) -
+ -struct stm32_reset_data {
+#define CLR_OFFSET 0x4 - struct reset_controller_dev rcdev;
- void __iomem *membase;
struct stm32_reset_data { -};
struct reset_controller_dev rcdev; -
@@ -79,37 +86,57 @@ static const struct of_device_id stm32_reset_dt_ids[] = { -static inline struct stm32_reset_data *
{ /* sentinel */ }, -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 int stm32_reset_probe(struct platform_device *pdev)
+static void __init stm32mp1_reset_init(struct device_node *np) -{
{
- struct device *dev = &pdev->dev; - struct device *dev = &pdev->dev;
- struct stm32_reset_data *data; - struct stm32_reset_data *data;
- void __iomem *membase; - void __iomem *membase;
- struct resource *res; - struct resource *res;
- -
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ void __iomem *base; - if (!data)
+ 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)
- return -ENOMEM; - return -ENOMEM;
- -
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- membase = devm_ioremap_resource(dev, res); - membase = devm_ioremap_resource(dev, res);
- if (IS_ERR(membase)) - if (IS_ERR(membase))
- return PTR_ERR(membase); - return PTR_ERR(membase);
+ goto err; -
- data->membase = membase; - 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.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; - data->rcdev.of_node = dev->of_node;
- -
- return devm_reset_controller_register(dev, &data->rcdev); - 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 = { -static struct platform_driver stm32_reset_driver = {
- .probe = stm32_reset_probe, - .probe = stm32_reset_probe,
- .driver = { - .driver = {
@ -143,22 +167,11 @@ index b221a28041fa0..daf0e26b27a8d 100644
-}; -};
- -
-builtin_platform_driver(stm32_reset_driver); -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 diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index c5b9804140860..d590b420525ce 100644 index 65ad9d0b47ab..f2a4d7c633c8 100644
--- a/drivers/rtc/Kconfig --- a/drivers/rtc/Kconfig
+++ b/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 config RTC_DRV_STM32
tristate "STM32 RTC" tristate "STM32 RTC"
select REGMAP_MMIO select REGMAP_MMIO
@ -167,7 +180,7 @@ index c5b9804140860..d590b420525ce 100644
help help
If you say yes here you get support for the STM32 On-Chip 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 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 --- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c
@@ -6,6 +6,8 @@ @@ -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 { } else {
rtc->pclk = devm_clk_get(&pdev->dev, "pclk"); rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(rtc->pclk)) { if (IS_ERR(rtc->pclk)) {
@ -417,7 +430,7 @@ index 2999e33a7e376..3cf51497681a4 100644
return PTR_ERR(rtc->rtc_ck); 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); ret = device_init_wakeup(&pdev->dev, true);
@ -442,7 +455,7 @@ index 2999e33a7e376..3cf51497681a4 100644
platform_set_drvdata(pdev, rtc); 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; goto err;
} }
@ -464,7 +477,7 @@ index 2999e33a7e376..3cf51497681a4 100644
/* /*
* If INITS flag is reset (calendar year field set to 0x00), calendar * If INITS flag is reset (calendar year field set to 0x00), calendar
* must be initialized * 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; const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int cr; unsigned int cr;
@ -474,7 +487,7 @@ index 2999e33a7e376..3cf51497681a4 100644
/* Disable interrupts */ /* Disable interrupts */
stm32_rtc_wpr_unlock(rtc); stm32_rtc_wpr_unlock(rtc);
cr = readl_relaxed(rtc->base + regs->cr); 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) if (rtc->data->has_pclk)
clk_disable_unprepare(rtc->pclk); clk_disable_unprepare(rtc->pclk);
@ -484,9 +497,9 @@ index 2999e33a7e376..3cf51497681a4 100644
return 0; return 0;
} }
@@ -902,15 +1022,13 @@ static int stm32_rtc_resume(struct device *dev) @@ -903,15 +1023,13 @@ static int stm32_rtc_resume(struct device *dev)
if (ret < 0)
return ret; return ret;
}
- if (device_may_wakeup(dev)) - if (device_may_wakeup(dev))
- return disable_irq_wake(rtc->irq_alarm); - return disable_irq_wake(rtc->irq_alarm);
@ -504,31 +517,35 @@ index 2999e33a7e376..3cf51497681a4 100644
static struct platform_driver stm32_rtc_driver = { static struct platform_driver stm32_rtc_driver = {
.probe = stm32_rtc_probe, .probe = stm32_rtc_probe,
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c 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 --- a/drivers/watchdog/stm32_iwdg.c
+++ b/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"); 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"); - dev_err(dev, "Unable to get lsi clock\n");
+ if (PTR_ERR(wdt->clk_lsi) != -EPROBE_DEFER) - return PTR_ERR(wdt->clk_lsi);
+ dev_err(dev, "Unable to get lsi clock\n"); - }
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) { if (wdt->data->has_pclk) {
wdt->clk_pclk = devm_clk_get(dev, "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"); - dev_err(dev, "Unable to get pclk clock\n");
+ if (PTR_ERR(wdt->clk_pclk) != -EPROBE_DEFER) - return PTR_ERR(wdt->clk_pclk);
+ dev_err(dev, "Unable to get pclk clock\n"); - }
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 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 --- a/include/dt-bindings/reset/stm32mp1-resets.h
+++ b/include/dt-bindings/reset/stm32mp1-resets.h +++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
@ -560,7 +577,7 @@ index f0c3aaef67a0a..f3a0ed3178356 100644
#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h
new file mode 100644 new file mode 100644
index 0000000000000..4373c4dea5879 index 000000000000..4373c4dea587
--- /dev/null --- /dev/null
+++ b/include/dt-bindings/rtc/rtc-stm32.h +++ b/include/dt-bindings/rtc/rtc-stm32.h
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@

View File

@ -0,0 +1,131 @@
From 51f0826032cee1b8cb0a1597c0a8d60b0042109d Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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

View File

@ -0,0 +1,626 @@
From f934df539b8cdfa58cb512b439749dba32a42932 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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 <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -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 <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_irq.h>
@@ -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

View File

@ -0,0 +1,437 @@
From 996898e1ae8bd13f5bb6986c52bd9777b68e80fa Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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 <romuald.jeanne@st.com>
---
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 <linux/arm-smccc.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/tick.h>
+
+#include <asm/cpuidle.h>
+
+#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

View File

@ -1,22 +1,23 @@
From 850ec78d02a21c585da6ede580eaff5fbe3db61b Mon Sep 17 00:00:00 2001 From 106f488712b412ed24f600c82febf95901c45054 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com> From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Mon, 5 Oct 2020 13:19:55 +0200 Date: Tue, 16 Mar 2021 09:03:42 +0100
Subject: [PATCH 21/22] ARM-stm32mp1-r2-rc8-CONFIG Subject: [PATCH 22/22] ARM 5.10.10-stm32mp1-r1 CONFIG
Signed-off-by: Romuald JEANNE <romuald.jeanne@st.com>
--- ---
.../fragment-01-multiv7_cleanup.config | 148 ++++++ .../fragment-01-multiv7_cleanup.config | 374 ++++++++++++++++
.../configs/fragment-02-multiv7_addons.config | 434 ++++++++++++++++++ .../configs/fragment-02-multiv7_addons.config | 398 ++++++++++++++++++
arch/arm/configs/multi_v7_defconfig | 1 + arch/arm/configs/multi_v7_defconfig | 5 +
3 files changed, 583 insertions(+) 3 files changed, 777 insertions(+)
create mode 100644 arch/arm/configs/fragment-01-multiv7_cleanup.config create mode 100644 arch/arm/configs/fragment-01-multiv7_cleanup.config
create mode 100644 arch/arm/configs/fragment-02-multiv7_addons.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 diff --git a/arch/arm/configs/fragment-01-multiv7_cleanup.config b/arch/arm/configs/fragment-01-multiv7_cleanup.config
new file mode 100644 new file mode 100644
index 0000000000000..3c43593d5665f index 000000000000..0c5667237e27
--- /dev/null --- /dev/null
+++ b/arch/arm/configs/fragment-01-multiv7_cleanup.config +++ b/arch/arm/configs/fragment-01-multiv7_cleanup.config
@@ -0,0 +1,148 @@ @@ -0,0 +1,374 @@
+# +#
+# CPU Core family selection +# CPU Core family selection
+# +#
@ -76,7 +77,6 @@ index 0000000000000..3c43593d5665f
+# CONFIG_SOC_TI is not set +# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set +# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set +# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
@ -165,12 +165,239 @@ index 0000000000000..3c43593d5665f
+# Debug Lockups and Hangs +# Debug Lockups and Hangs
+# +#
+# CONFIG_SCHED_DEBUG is not set +# 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 diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
new file mode 100644 new file mode 100644
index 0000000000000..5fd995006583f index 000000000000..d6c1a48d5702
--- /dev/null --- /dev/null
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config +++ b/arch/arm/configs/fragment-02-multiv7_addons.config
@@ -0,0 +1,434 @@ @@ -0,0 +1,398 @@
+# +#
+# General setup +# General setup
+# +#
@ -259,7 +486,6 @@ index 0000000000000..5fd995006583f
+# +#
+# Disk-On-Chip Device Drivers +# Disk-On-Chip Device Drivers
+# +#
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+ +
+# +#
+# LPDDR & LPDDR2 PCM memory drivers +# LPDDR & LPDDR2 PCM memory drivers
@ -311,6 +537,7 @@ index 0000000000000..5fd995006583f
+# +#
+ +
+CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NAND=y
+CONFIG_MTD_MCHP23K256=m
+ +
+# +#
+# USB GPIO expanders +# USB GPIO expanders
@ -344,18 +571,13 @@ index 0000000000000..5fd995006583f
+CONFIG_PROTECTION_CONSUMER=y +CONFIG_PROTECTION_CONSUMER=y
+ +
+# +#
+# Regulator drivers
+#
+CONFIG_REGULATOR_STM32_PWR=y
+
+#
+# Multimedia core support +# Multimedia core support
+# +#
+ +
+# +#
+# USB HDMI CEC adapters +# USB HDMI CEC adapters
+# +#
+CONFIG_VIDEO_STM32_HDMI_CEC=m +CONFIG_CEC_STM32=m
+ +
+# +#
+# Camera sensor devices +# Camera sensor devices
@ -402,29 +624,19 @@ index 0000000000000..5fd995006583f
+CONFIG_BACKLIGHT_GPIO=y +CONFIG_BACKLIGHT_GPIO=y
+ +
+# +#
+# HD-Audio +# STMicroelectronics STM32 SOC audio support
+# +#
+CONFIG_SOUND=y +CONFIG_SND_SOC_STM32_SPDIFRX=m
+CONFIG_SND=y +CONFIG_SND_SOC_STM32_DFSDM=m
+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
+ +
+# +#
+# CODEC drivers +# 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 +# USB Device Class drivers
+# +#
+CONFIG_USB_ACM=y +CONFIG_USB_ACM=m
+ +
+# +#
+# also be needed; see USB_STORAGE Help for more info +# 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 +# Gadget/Dual-role mode requires USB Gadget support to be enabled
+# +#
+CONFIG_USB_CONFIGFS=y
+ +
+# +#
+# USB Physical Layer drivers +# USB Physical Layer drivers
+# +#
+CONFIG_TYPEC=y
+CONFIG_TYPEC_STUSB=y
+ +
+# +#
+# Platform Support +# 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 +# Rpmsg drivers
+# +#
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_RPMSG_TTY=m
+ +
+# +#
+# File systems +# File systems
@ -497,10 +721,6 @@ index 0000000000000..5fd995006583f
+# +#
+CONFIG_KEYS=y +CONFIG_KEYS=y
+ +
+CONFIG_CRYPTO_DEV_STM32_CRC=y
+CONFIG_CRYPTO_DEV_STM32_HASH=y
+CONFIG_CRYPTO_DEV_STM32_CRYP=y
+
+# +#
+# Library routines +# Library routines
+# +#
@ -510,12 +730,6 @@ index 0000000000000..5fd995006583f
+# STM32 DFSDM +# STM32 DFSDM
+# +#
+CONFIG_SD_ADC_MODULATOR=y +CONFIG_SD_ADC_MODULATOR=y
+CONFIG_STM32_DFSDM_ADC=y
+
+#
+# STM32 BSEC NVMEM
+#
+CONFIG_NVMEM_STM32_ROMEM=y
+ +
+# +#
+# STM32 HSEM +# STM32 HSEM
@ -529,59 +743,6 @@ index 0000000000000..5fd995006583f
+CONFIG_STM32_IPCC=y +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 +# SCMI
+# +#
+CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ARM_SCMI_PROTOCOL=y
@ -594,10 +755,21 @@ index 0000000000000..5fd995006583f
+CONFIG_LEGACY_PTY_COUNT=8 +CONFIG_LEGACY_PTY_COUNT=8
+ +
+# +#
+# FMC EBI +# STM32 BSEC NVMEM
+# +#
+CONFIG_MEMORY=y +CONFIG_NVMEM_STM32_ROMEM=y
+CONFIG_STM32_FMC2_EBI=y +
+#
+# RPMSG client sample
+#
+CONFIG_SAMPLES=y
+CONFIG_SAMPLE_RPMSG_CLIENT=m
+
+#
+# REBOOT
+#
+CONFIG_REBOOT_MODE=y
+CONFIG_SYSCON_REBOOT_MODE=y
+ +
+# +#
+# STM32 CPUIDLE +# STM32 CPUIDLE
@ -605,18 +777,48 @@ index 0000000000000..5fd995006583f
+CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE=y
+CONFIG_ARM_STM32_CPUIDLE=y +CONFIG_ARM_STM32_CPUIDLE=y
+CONFIG_ARM_CPUIDLE=n +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 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 --- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig
@@ -1038,6 +1038,7 @@ CONFIG_TI_PIPE3=y @@ -829,6 +829,8 @@ CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_TWL4030_USB=m CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_MESON_MX_EFUSE=m CONFIG_USB_CONFIGFS_F_PRINTER=y
CONFIG_ROCKCHIP_EFUSE=m CONFIG_USB_ETH=m
+CONFIG_STM32_DDR_PMU=y +CONFIG_TYPEC=m
CONFIG_NVMEM_IMX_OCOTP=y +CONFIG_TYPEC_STUSB160X=m
CONFIG_NVMEM_SUNXI_SID=y CONFIG_MMC=y
CONFIG_NVMEM_VF610_OCOTP=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 2.17.1

View File

@ -1,3 +1,5 @@
# CONFIG_GCC_PLUGINS is not set
# Allow to load kernel modules built with different kernel version # Allow to load kernel modules built with different kernel version
CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODVERSIONS=y CONFIG_MODVERSIONS=y
@ -18,4 +20,3 @@ CONFIG_INPUT_UINPUT=m
CONFIG_USBIP_CORE=m CONFIG_USBIP_CORE=m
CONFIG_USBIP_HOST=m CONFIG_USBIP_HOST=m
# CONFIG_USBIP_DEBUG is not set # CONFIG_USBIP_DEBUG is not set

View File

@ -1,58 +0,0 @@
From 4556074b66971918536ed27d52f5f4f6337f0646 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
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 <linux/clk-provider.h>
+#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/errno.h>
#include <linux/export.h>
@@ -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

View File

@ -1,231 +0,0 @@
From bfe89db1821d391733d9410f1102f456de687474 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
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 <gerald.baeza@st.com> 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

View File

@ -1,929 +0,0 @@
From c37d67ecd03c14eabef9d8cde67913bdfe497ae8 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
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 = <GIC_SPI 149 IRQ_TYPE_NONE>;
+ 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 = <BTN_4>;
+ 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 <christophe.kerello@st.com>
+
+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 <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/stm32mp1-clks.h>
+ #include <dt-bindings/reset/stm32mp1-resets.h>
+ nand-controller@58002000 {
+ compatible = "st,stm32mp15-fmc2";
+ reg = <0x58002000 0x1000>,
+ <0x80000000 0x1000>,
+ <0x88010000 0x1000>,
+ <0x88020000 0x1000>,
+ <0x81000000 0x1000>,
+ <0x89010000 0x1000>,
+ <0x89020000 0x1000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ 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 <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/gpio.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <asm/exception.h>
+
+#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 <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -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

View File

@ -1,2 +0,0 @@
CONFIG_TEE=y
CONFIG_OPTEE=y

View File

@ -1,43 +1,48 @@
SUMMARY = "Linux STM32MP Kernel" SUMMARY = "Linux STM32MP Kernel"
SECTION = "kernel" SECTION = "kernel"
LICENSE = "GPLv2" 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 include linux-stm32mp.inc
LINUX_VERSION = "5.4" LINUX_VERSION = "5.10"
LINUX_SUBVERSION = "56" 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 = "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 += " \ SRC_URI += " \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-ARM-stm32mp1-r2-MACHINE.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-stm32mp1-r2-CPUFREQ.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-stm32mp1-r2-CRYPTO.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-stm32mp1-r2-RNG-DEBUG-NVMEM.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-stm32mp1-r2-CLOCK.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-stm32mp1-r2-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-stm32mp1-r2-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-stm32mp1-r2-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-stm32mp1-r2-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-stm32mp1-r2-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-stm32mp1-r2-RESET-RTC-WATCHDOG.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-stm32mp1-r2-MEDIA-SOC-THERMAL.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-stm32mp1-r2-MFD.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-stm32mp1-r2-MMC-NAND.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-stm32mp1-r2-NET-TTY.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-stm32mp1-r2-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-stm32mp1-r2-PINCTRL-REGULATOR-SPI-PWM.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-stm32mp1-r2-SOUND.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-stm32mp1-r2-MISC-CPUIDLE-MM.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-stm32mp1-r2-DEVICETREE.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-stm32mp1-r2-CONFIG.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-stm32mp1-r2-PERF.patch \ file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-ARM-5.10.10-stm32mp1-r1-CONFIG.patch \
" "
PV = "${LINUX_VERSION}.${LINUX_SUBVERSION}" PV = "${LINUX_VERSION}.${LINUX_SUBVERSION}"
S = "${WORKDIR}/linux-${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 # Configure devupstream class usage
@ -45,7 +50,7 @@ S = "${WORKDIR}/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}"
BBCLASSEXTEND = "devupstream:target" BBCLASSEXTEND = "devupstream:target"
SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/linux.git;protocol=https;branch=v${LINUX_VERSION}-stm32mp" 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 # 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_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-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('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('DISTRO_FEATURES', 'systemd', '${WORKDIR}/fragments/${LINUX_VERSION}/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/${LINUX_VERSION}/fragment-04-modules.config"
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/${LINUX_VERSION}/fragment-05-signature.config','')} "
KERNEL_CONFIG_FRAGMENTS += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', '${WORKDIR}/fragments/5.4/fragment-06-signature.config','')} "
SRC_URI += "file://${LINUX_VERSION}/fragment-03-systemd.config;subdir=fragments" 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-04-modules.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments" SRC_URI += "file://${LINUX_VERSION}/fragment-05-signature.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-06-signature.config;subdir=fragments"
# Don't forget to add/del for devupstream # 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-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-04-modules.config;subdir=fragments"
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments" SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-05-signature.config;subdir=fragments"
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-06-signature.config;subdir=fragments"
# ------------------------------------------------------------- # -------------------------------------------------------------
# Kernel Args # Kernel Args