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
FILESEXTRAPATHS_prepend := "${THISDIR}:"
# -------------------------------------------------------------
# Do not deploy kernel module with specfic tarball
MODULE_TARBALL_DEPLOY = "0"
do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel"
#---------------------------------------------------------------
@ -22,13 +19,16 @@ do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/kernel"
KERNEL_SIGN_ENABLE ?= "0"
EXTRA_OEMAKE += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', 'INSTALL_MOD_STRIP=1','')}"
# YoctoProject bugzilla : 140044
# There's a race between do_symlink_kernsrc and do_populate_lic, since the latter is ordered "after do_patch";
#
# Force task order for link creation
#
# Below a STMicroelectonics' hacks waiting for official Yocto patch:
# commit already exists in gathesgarth :
#a2b50b74d609ce079ab36b82d4c7c3539fb56485 kernel.bbclass: ensure symlink_kernsrc task gets run even with externalsrc
python () {
d.appendVarFlag("do_unpack", "postfuncs", " do_symlink_kernsrc")
bb.build.deltask('do_symlink_kernsrc', d)
bb.build.addtask('do_symlink_kernsrc', 'do_patch do_configure', 'do_unpack', d)
}
do_symlink_kernsrc[noexec] = "1"
# ---------------------------------------------------------------------
@ -77,6 +77,15 @@ do_configure_prepend() {
#oe_runmake -C ${S} O=${B} savedefconfig && cp ${B}/defconfig ${WORKDIR}/defconfig.saved
}
# ---------------------------------------------------------------------
do_compile_kernelmodules_append() {
if (grep -q -i -e '^CONFIG_MODULES=y$' ${B}/.config); then
# 5.10+ kernels have module.lds that we need to copy for external module builds
if [ -e "${B}/scripts/module.lds" ]; then
install -Dm 0644 ${B}/scripts/module.lds ${STAGING_KERNEL_BUILDDIR}/scripts/module.lds
fi
fi
}
# ---------------------------------------------------------------------
do_install_append() {
# Install KERNEL_IMAGETYPE for kernel-imagebootfs package
@ -86,8 +95,19 @@ do_install_append() {
# when ACCEPT_EULA are filled
echo "blacklist etnaviv" > ${D}/${sysconfdir}/modprobe.d/blacklist.conf
fi
#snd dependencies
install -d ${D}/${sysconfdir}/modprobe.d/
echo "softdep snd-soc-cs42l51 pre: snd-soc-cs42l51-i2c" > ${D}/${sysconfdir}/modprobe.d/stm32mp1-snd.conf
}
# ---------------------------------------------------------------------
do_deploy_append() {
if [ ${MODULE_TARBALL_DEPLOY} = "1" ] && (grep -q -i -e '^CONFIG_MODULES=y$' .config); then
mkdir -p ${D}${root_prefix}/lib
tar -cvzf $deployDir/modules-stripped-${MODULE_TARBALL_NAME}.tgz -C ${WORKDIR}/package/${root_prefix} lib
ln -sf modules-stripped-${MODULE_TARBALL_NAME}.tgz $deployDir/modules-stripped-${MODULE_TARBALL_LINK_NAME}.tgz
fi
}
do_deploy[depends] += " virtual/kernel:do_package "
# ---------------------------------------------------------------------
# Support checking the kernel load address parameter: expecting proper value for ST kernel.
#

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

View File

@ -1,244 +1,18 @@
From 0f32661351778c6c282c9509defdcec61abf7fab 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 03/22] ARM-stm32mp1-r2-rc8-CRYPTO
From 56442e69cbaf31555a9bb4f3311a0593a0c172cc Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Tue, 16 Mar 2021 08:56:48 +0100
Subject: [PATCH 04/22] ARM 5.10.10-stm32mp1-r1 CRYPTO
---
drivers/crypto/stm32/Kconfig | 2 +
drivers/crypto/stm32/stm32-crc32.c | 99 +++++++++-
drivers/crypto/stm32/stm32-cryp.c | 300 +++++++++++++++++++++--------
drivers/crypto/stm32/stm32-hash.c | 57 ++++--
4 files changed, 348 insertions(+), 110 deletions(-)
drivers/crypto/stm32/stm32-cryp.c | 300 +++++++++++++++++++++---------
drivers/crypto/stm32/stm32-hash.c | 19 +-
2 files changed, 228 insertions(+), 91 deletions(-)
diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig
index 1aba9372cd232..425c68d42a5fe 100644
--- a/drivers/crypto/stm32/Kconfig
+++ b/drivers/crypto/stm32/Kconfig
@@ -3,6 +3,8 @@ config CRYPTO_DEV_STM32_CRC
tristate "Support for STM32 crc accelerators"
depends on ARCH_STM32
select CRYPTO_HASH
+ select CRYPTO_CRC32
+ select CRYPTO_CRC32C
help
This enables support for the CRC32 hw accelerator which can be found
on STMicroelectronics STM32 SOC.
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c
index e68b856d03b6e..22b301c684f09 100644
--- a/drivers/crypto/stm32/stm32-crc32.c
+++ b/drivers/crypto/stm32/stm32-crc32.c
@@ -6,6 +6,7 @@
#include <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
index ba5ea6434f9ca..fbf522dc3d63f 100644
index 2670c30332fa..503428bf15cb 100644
--- a/drivers/crypto/stm32/stm32-cryp.c
+++ b/drivers/crypto/stm32/stm32-cryp.c
@@ -143,10 +143,10 @@ struct stm32_cryp {
@@ -144,10 +144,10 @@ struct stm32_cryp {
size_t authsize;
size_t hw_blocksize;
@ -251,7 +25,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
struct scatterlist *in_sg;
struct scatterlist *out_sg;
@@ -156,9 +156,6 @@ struct stm32_cryp {
@@ -157,9 +157,6 @@ struct stm32_cryp {
struct scatterlist out_sgl;
bool sgs_copied;
@ -261,7 +35,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
struct scatter_walk in_walk;
struct scatter_walk out_walk;
@@ -321,28 +318,46 @@ static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp)
@@ -322,28 +319,46 @@ static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp)
ret = stm32_cryp_check_aligned(cryp->out_sg, cryp->total_out,
cryp->hw_blocksize);
@ -311,7 +85,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
if (!stm32_cryp_check_io_aligned(cryp)) {
cryp->sgs_copied = 0;
@@ -350,29 +365,37 @@ static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp)
@@ -351,29 +366,37 @@ static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp)
}
total_in = ALIGN(cryp->total_in, cryp->hw_blocksize);
@ -356,7 +130,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
cryp->sgs_copied = 1;
@@ -649,14 +672,14 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err)
@@ -654,14 +677,14 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err)
buf_in = sg_virt(&cryp->in_sgl);
buf_out = sg_virt(&cryp->out_sgl);
@ -375,7 +149,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
pages = len ? get_order(len) : 1;
free_pages((unsigned long)buf_out, pages);
}
@@ -796,7 +819,20 @@ static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key,
@@ -801,7 +824,20 @@ static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key,
static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm,
unsigned int authsize)
{
@ -397,69 +171,69 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
}
static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
@@ -820,31 +856,61 @@ static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
@@ -825,31 +861,61 @@ static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
static int stm32_cryp_aes_ecb_encrypt(struct ablkcipher_request *req)
static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req)
{
+ if (req->nbytes % AES_BLOCK_SIZE)
+ if (req->cryptlen % AES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT);
}
static int stm32_cryp_aes_ecb_decrypt(struct ablkcipher_request *req)
static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req)
{
+ if (req->nbytes % AES_BLOCK_SIZE)
+ if (req->cryptlen % AES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_AES | FLG_ECB);
}
static int stm32_cryp_aes_cbc_encrypt(struct ablkcipher_request *req)
static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req)
{
+ if (req->nbytes % AES_BLOCK_SIZE)
+ if (req->cryptlen % AES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT);
}
static int stm32_cryp_aes_cbc_decrypt(struct ablkcipher_request *req)
static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req)
{
+ if (req->nbytes % AES_BLOCK_SIZE)
+ if (req->cryptlen % AES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_AES | FLG_CBC);
}
static int stm32_cryp_aes_ctr_encrypt(struct ablkcipher_request *req)
static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req)
{
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT);
}
static int stm32_cryp_aes_ctr_decrypt(struct ablkcipher_request *req)
static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req)
{
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_AES | FLG_CTR);
}
@@ -858,53 +924,122 @@ static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req)
@@ -863,53 +929,122 @@ static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req)
return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM);
}
@ -494,95 +268,95 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM);
}
static int stm32_cryp_des_ecb_encrypt(struct ablkcipher_request *req)
static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT);
}
static int stm32_cryp_des_ecb_decrypt(struct ablkcipher_request *req)
static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_DES | FLG_ECB);
}
static int stm32_cryp_des_cbc_encrypt(struct ablkcipher_request *req)
static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT);
}
static int stm32_cryp_des_cbc_decrypt(struct ablkcipher_request *req)
static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_DES | FLG_CBC);
}
static int stm32_cryp_tdes_ecb_encrypt(struct ablkcipher_request *req)
static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT);
}
static int stm32_cryp_tdes_ecb_decrypt(struct ablkcipher_request *req)
static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB);
}
static int stm32_cryp_tdes_cbc_encrypt(struct ablkcipher_request *req)
static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT);
}
static int stm32_cryp_tdes_cbc_decrypt(struct ablkcipher_request *req)
static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req)
{
+ if (req->nbytes % DES_BLOCK_SIZE)
+ if (req->cryptlen % DES_BLOCK_SIZE)
+ return -EINVAL;
+
+ if (req->nbytes == 0)
+ if (req->cryptlen == 0)
+ return 0;
+
return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC);
}
@@ -966,36 +1101,25 @@ static int stm32_cryp_prepare_req(struct ablkcipher_request *req,
@@ -971,36 +1106,25 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req,
cryp->areq = areq;
cryp->req = NULL;
cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq));
@ -627,7 +401,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
ret = stm32_cryp_copy_sgs(cryp);
if (ret)
return ret;
@@ -1006,7 +1130,7 @@ static int stm32_cryp_prepare_req(struct ablkcipher_request *req,
@@ -1011,7 +1135,7 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req,
if (is_gcm(cryp) || is_ccm(cryp)) {
/* In output, jump after assoc data */
scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen);
@ -636,7 +410,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
}
ret = stm32_cryp_hw_init(cryp);
@@ -1125,7 +1249,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
@@ -1130,7 +1254,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
stm32_cryp_write(cryp, CRYP_DIN, size_bit);
size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen :
@ -644,8 +418,8 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
+ cryp->areq->cryptlen - cryp->authsize;
size_bit *= 8;
if (cryp->caps->swap_final)
size_bit = cpu_to_be32(size_bit);
@@ -1159,14 +1283,14 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
size_bit = (__force u32)cpu_to_be32(size_bit);
@@ -1169,14 +1293,14 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
dst = sg_virt(cryp->out_sg) + _walked_out;
for (i = 0; i < AES_BLOCK_32; i++) {
@ -663,7 +437,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* Empty fifo out (data from input padding) */
stm32_cryp_read(cryp, CRYP_DOUT);
} else {
@@ -1174,11 +1298,11 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
@@ -1184,11 +1308,11 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
d32 = stm32_cryp_read(cryp, CRYP_DOUT);
d8 = (u8 *)&d32;
@ -677,7 +451,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
}
}
} else {
@@ -1186,7 +1310,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
@@ -1196,7 +1320,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32];
scatterwalk_map_and_copy(in_tag, cryp->in_sg,
@ -686,7 +460,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
cryp->authsize, 0);
for (i = 0; i < AES_BLOCK_32; i++)
@@ -1246,13 +1370,13 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
@@ -1256,13 +1380,13 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
dst = sg_virt(cryp->out_sg) + _walked_out;
for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) {
@ -703,7 +477,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* Empty fifo out (data from input padding) */
d32 = stm32_cryp_read(cryp, CRYP_DOUT);
} else {
@@ -1260,15 +1384,15 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
@@ -1270,15 +1394,15 @@ static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
d32 = stm32_cryp_read(cryp, CRYP_DOUT);
d8 = (u8 *)&d32;
@ -722,7 +496,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
}
static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
@@ -1287,25 +1411,25 @@ static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
@@ -1297,25 +1421,25 @@ static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
src = sg_virt(cryp->in_sg) + _walked_in;
for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) {
@ -753,7 +527,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
}
}
}
@@ -1314,7 +1438,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
@@ -1324,7 +1448,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
{
int err;
u32 cfg, tmp[AES_BLOCK_32];
@ -762,7 +536,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
struct scatterlist *out_sg_ori = cryp->out_sg;
unsigned int i;
@@ -1340,7 +1464,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
@@ -1350,7 +1474,7 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
/* b) pad and write the last block */
stm32_cryp_irq_write_block(cryp);
@ -771,7 +545,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
err = stm32_cryp_wait_output(cryp);
if (err) {
dev_err(cryp->dev, "Timeout (write gcm header)\n");
@@ -1350,8 +1474,8 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
@@ -1360,8 +1484,8 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
/* c) get and store encrypted data */
stm32_cryp_irq_read_data(cryp);
scatterwalk_map_and_copy(tmp, out_sg_ori,
@ -782,7 +556,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* d) change mode back to AES GCM */
cfg &= ~CR_ALGO_MASK;
@@ -1365,12 +1489,12 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
@@ -1375,12 +1499,12 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
/* f) write padded data */
for (i = 0; i < AES_BLOCK_32; i++) {
@ -797,7 +571,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
}
/* g) Empty fifo out */
@@ -1396,8 +1520,8 @@ static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp)
@@ -1406,8 +1530,8 @@ static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp)
cfg &= ~CR_CRYPEN;
stm32_cryp_write(cryp, CRYP_CR, cfg);
@ -808,7 +582,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
cfg |= (cryp->hw_blocksize - payload_bytes) << CR_NBPBL_SHIFT;
cfg |= CR_CRYPEN;
stm32_cryp_write(cryp, CRYP_CR, cfg);
@@ -1408,7 +1532,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
@@ -1418,7 +1542,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
int err = 0;
u32 cfg, iv1tmp;
u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32], tmp[AES_BLOCK_32];
@ -817,7 +591,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
struct scatterlist *out_sg_ori = cryp->out_sg;
unsigned int i;
@@ -1443,7 +1567,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
@@ -1453,7 +1577,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
/* b) pad and write the last block */
stm32_cryp_irq_write_block(cryp);
@ -826,7 +600,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
err = stm32_cryp_wait_output(cryp);
if (err) {
dev_err(cryp->dev, "Timeout (wite ccm padded data)\n");
@@ -1451,13 +1575,13 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
@@ -1461,13 +1585,13 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
}
/* c) get and store decrypted data */
@ -843,7 +617,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* d) Load again CRYP_CSGCMCCMxR */
for (i = 0; i < ARRAY_SIZE(cstmp2); i++)
@@ -1491,12 +1615,12 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
@@ -1501,12 +1625,12 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
{
@ -858,7 +632,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
(stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) &&
is_encrypt(cryp))) {
/* Padding for AES GCM encryption */
@@ -1508,7 +1632,7 @@ static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
@@ -1518,7 +1642,7 @@ static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
stm32_cryp_irq_set_npblb(cryp);
}
@ -867,7 +641,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
(stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) &&
is_decrypt(cryp))) {
/* Padding for AES CCM decryption */
@@ -1538,10 +1662,10 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp)
@@ -1548,10 +1672,10 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp)
stm32_cryp_write(cryp, CRYP_DIN, *src);
src = stm32_cryp_next_in(cryp, src, sizeof(u32));
@ -880,7 +654,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
cryp->areq->assoclen) {
/* Write padding if needed */
for (j = i + 1; j < AES_BLOCK_32; j++)
@@ -1573,7 +1697,7 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp)
@@ -1583,7 +1707,7 @@ static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp)
break;
}
@ -889,7 +663,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
break;
}
}
@@ -1601,7 +1725,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
@@ -1611,7 +1735,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
i++;
@ -898,7 +672,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
} else {
/* Build the two first u32 of B1 */
d8[0] = 0xFF;
@@ -1622,7 +1746,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
@@ -1632,7 +1756,7 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
i++;
@ -907,7 +681,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
}
}
@@ -1634,14 +1758,14 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
@@ -1644,14 +1768,14 @@ static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
d8[k] = *((u8 *)src);
src = stm32_cryp_next_in(cryp, src, 1);
@ -925,7 +699,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
/* Write padding if needed */
for (j = i + 1; j < AES_BLOCK_32; j++)
stm32_cryp_write(cryp, CRYP_DIN, 0);
@@ -1966,7 +2090,9 @@ static int stm32_cryp_probe(struct platform_device *pdev)
@@ -1955,7 +2079,9 @@ static int stm32_cryp_probe(struct platform_device *pdev)
cryp->clk = devm_clk_get(dev, NULL);
if (IS_ERR(cryp->clk)) {
@ -936,7 +710,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
return PTR_ERR(cryp->clk);
}
@@ -1984,7 +2110,11 @@ static int stm32_cryp_probe(struct platform_device *pdev)
@@ -1973,7 +2099,11 @@ static int stm32_cryp_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
rst = devm_reset_control_get(dev, NULL);
@ -949,7 +723,7 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
reset_control_assert(rst);
udelay(2);
reset_control_deassert(rst);
@@ -2035,7 +2165,7 @@ static int stm32_cryp_probe(struct platform_device *pdev)
@@ -2024,7 +2154,7 @@ static int stm32_cryp_probe(struct platform_device *pdev)
spin_lock(&cryp_list.lock);
list_del(&cryp->list);
spin_unlock(&cryp_list.lock);
@ -959,35 +733,10 @@ index ba5ea6434f9ca..fbf522dc3d63f 100644
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index cfc8e0e37beec..f8b0e1b28971e 100644
index e3e25278a970..da9c3e913e55 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -507,6 +507,7 @@ static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev)
static int stm32_hash_dma_init(struct stm32_hash_dev *hdev)
{
struct dma_slave_config dma_conf;
+ struct dma_chan *chan;
int err;
memset(&dma_conf, 0, sizeof(dma_conf));
@@ -518,11 +519,11 @@ static int stm32_hash_dma_init(struct stm32_hash_dev *hdev)
dma_conf.dst_maxburst = hdev->dma_maxburst;
dma_conf.device_fc = false;
- hdev->dma_lch = dma_request_slave_channel(hdev->dev, "in");
- if (!hdev->dma_lch) {
- dev_err(hdev->dev, "Couldn't acquire a slave DMA channel.\n");
- return -EBUSY;
- }
+ chan = dma_request_chan(hdev->dev, "in");
+ if (IS_ERR(chan))
+ return PTR_ERR(chan);
+
+ hdev->dma_lch = chan;
err = dmaengine_slave_config(hdev->dma_lch, &dma_conf);
if (err) {
@@ -923,15 +924,10 @@ static int stm32_hash_final(struct ahash_request *req)
@@ -925,15 +925,10 @@ static int stm32_hash_final(struct ahash_request *req)
static int stm32_hash_finup(struct ahash_request *req)
{
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
@ -1003,7 +752,7 @@ index cfc8e0e37beec..f8b0e1b28971e 100644
err1 = stm32_hash_update(req);
if (err1 == -EINPROGRESS || err1 == -EBUSY)
@@ -948,7 +944,19 @@ static int stm32_hash_finup(struct ahash_request *req)
@@ -950,7 +945,19 @@ static int stm32_hash_finup(struct ahash_request *req)
static int stm32_hash_digest(struct ahash_request *req)
{
@ -1024,64 +773,6 @@ index cfc8e0e37beec..f8b0e1b28971e 100644
}
static int stm32_hash_export(struct ahash_request *req, void *out)
@@ -1463,8 +1471,11 @@ static int stm32_hash_probe(struct platform_device *pdev)
hdev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(hdev->clk)) {
- dev_err(dev, "failed to get clock for hash (%lu)\n",
- PTR_ERR(hdev->clk));
+ if (PTR_ERR(hdev->clk) != -EPROBE_DEFER) {
+ dev_err(dev, "failed to get clock for hash (%lu)\n",
+ PTR_ERR(hdev->clk));
+ }
+
return PTR_ERR(hdev->clk);
}
@@ -1482,7 +1493,12 @@ static int stm32_hash_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
hdev->rst = devm_reset_control_get(&pdev->dev, NULL);
- if (!IS_ERR(hdev->rst)) {
+ if (IS_ERR(hdev->rst)) {
+ if (PTR_ERR(hdev->rst) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_reset;
+ }
+ } else {
reset_control_assert(hdev->rst);
udelay(2);
reset_control_deassert(hdev->rst);
@@ -1493,8 +1509,15 @@ static int stm32_hash_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hdev);
ret = stm32_hash_dma_init(hdev);
- if (ret)
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOENT:
dev_dbg(dev, "DMA mode not available\n");
+ break;
+ default:
+ goto err_dma;
+ }
spin_lock(&stm32_hash.lock);
list_add_tail(&hdev->list, &stm32_hash.dev_list);
@@ -1532,10 +1555,10 @@ static int stm32_hash_probe(struct platform_device *pdev)
spin_lock(&stm32_hash.lock);
list_del(&hdev->list);
spin_unlock(&stm32_hash.lock);
-
+err_dma:
if (hdev->dma_lch)
dma_release_channel(hdev->dma_lch);
-
+err_reset:
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
--
2.17.1

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

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: Lionel VITTE <lionel.vitte@st.com>
Date: Mon, 5 Oct 2020 13:19:56 +0200
Subject: [PATCH 22/22] ARM-stm32mp1-r2-rc8-PERF
From f9e34d8836c280d291e1779bf50f895f55a1e8fc Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Tue, 16 Mar 2021 09:16:53 +0100
Subject: [PATCH 14/22] ARM 5.10.10-stm32mp1-r1 PERF
---
Documentation/perf/stm32-ddr-pmu.txt | 41 +++
drivers/perf/Kconfig | 6 +
drivers/perf/Makefile | 1 +
drivers/perf/stm32_ddr_pmu.c | 505 +++++++++++++++++++++++++++
4 files changed, 553 insertions(+)
create mode 100644 Documentation/perf/stm32-ddr-pmu.txt
Documentation/admin-guide/perf/index.rst | 1 +
.../admin-guide/perf/stm32-ddr-pmu.rst | 44 ++
drivers/perf/Kconfig | 7 +
drivers/perf/Makefile | 1 +
drivers/perf/stm32_ddr_pmu.c | 428 ++++++++++++++++++
5 files changed, 481 insertions(+)
create mode 100644 Documentation/admin-guide/perf/stm32-ddr-pmu.rst
create mode 100644 drivers/perf/stm32_ddr_pmu.c
diff --git a/Documentation/perf/stm32-ddr-pmu.txt b/Documentation/perf/stm32-ddr-pmu.txt
diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst
index 5a8f2529a033..9f68f68be161 100644
--- a/Documentation/admin-guide/perf/index.rst
+++ b/Documentation/admin-guide/perf/index.rst
@@ -11,6 +11,7 @@ Performance monitor support
imx-ddr
qcom_l2_pmu
qcom_l3_pmu
+ stm32-ddr-pmu
arm-ccn
arm-cmn
xgene-pmu
diff --git a/Documentation/admin-guide/perf/stm32-ddr-pmu.rst b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst
new file mode 100644
index 0000000000000..d5b35b3261bdb
index 000000000000..db647fc1acad
--- /dev/null
+++ b/Documentation/perf/stm32-ddr-pmu.txt
@@ -0,0 +1,41 @@
+++ b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst
@@ -0,0 +1,44 @@
+========================================
+STM32 DDR Performance Monitor (DDRPERFM)
+========================================
+
+The DDRPERFM is the DDR Performance Monitor embedded in STM32MP1 SOC.
+See STM32MP157 reference manual RM0436 to get a description of this peripheral.
+See Documentation/arm/stm32/stm32mp157-overview.rst to get access to
+STM32MP157 reference manual RM0436 where DDRPERFM is described.
+
+
+The five following counters are supported by stm32-ddr-pmu driver:
@ -34,6 +49,9 @@ index 0000000000000..d5b35b3261bdb
+
+The stm32-ddr-pmu driver relies on the perf PMU framework to expose the
+counters via sysfs:
+
+ .. code-block:: bash
+
+ $ ls /sys/bus/event_source/devices/ddrperfm/events
+ activate_cnt idle_cnt read_cnt time_cnt write_cnt
+
@ -46,7 +64,10 @@ index 0000000000000..d5b35b3261bdb
+option is mandatory!
+
+Example:
+ $ perf stat -e ddrperfm/read_cnt/,ddrperfm/time_cnt/ -a sleep 20
+
+ .. code-block:: bash
+
+ $ perf stat -e ddrperfm/read_cnt/,ddrperfm/time_cnt/ -a sleep 20
+ Performance counter stats for 'system wide':
+
+ 342541560 ddrperfm/read_cnt/
@ -54,33 +75,29 @@ index 0000000000000..d5b35b3261bdb
+
+ 20.021068551 seconds time elapsed
+
+
+The driver also exposes a 'bandwidth' attribute that can be used to display
+the read/write/total bandwidth achieved during the last 'perf stat' execution.
+ $ cat /sys/bus/event_source/devices/ddrperfm/bandwidth
+ Read = 403, Write = 239, Read & Write = 642 (MB/s)
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 09ae8a970880f..2c50413145ab1 100644
index 130327ff0b0e..a62a26fc516a 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -105,6 +105,12 @@ config QCOM_L3_PMU
@@ -106,6 +106,13 @@ config QCOM_L3_PMU
Adds the L3 cache PMU into the perf events subsystem for
monitoring L3 cache events.
+config STM32_DDR_PMU
+ bool "STM32 DDR PMU"
+ depends on MACH_STM32MP157
+ help
+ Support for STM32 DDR performance monitor (DDRPERFM).
+ tristate "STM32 DDR PMU"
+ depends on MACH_STM32MP157
+ default m
+ help
+ Support for STM32 DDR performance monitor (DDRPERFM).
+
config THUNDERX2_PMU
tristate "Cavium ThunderX2 SoC PMU UNCORE"
depends on ARCH_THUNDER2 && ARM64 && ACPI && NUMA
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index 2ebb4de178151..fd3368c1b4549 100644
index 5365fd56f88f..7f2b7c5f9216 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o
@@ -10,6 +10,7 @@ obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o
obj-$(CONFIG_HISI_PMU) += hisilicon/
obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o
obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o
@ -90,51 +107,52 @@ index 2ebb4de178151..fd3368c1b4549 100644
obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o
diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c
new file mode 100644
index 0000000000000..4f30f6f8be964
index 000000000000..ee7a33083e02
--- /dev/null
+++ b/drivers/perf/stm32_ddr_pmu.c
@@ -0,0 +1,505 @@
@@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file is the STM32 DDR performance monitor (DDRPERFM) driver
+ *
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ * Author: Gerald Baeza <gerald.baeza@st.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/perf_event.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define POLL_MS 4000 /* The counter roll over after ~8s @533MHz */
+#define WORD_LENGTH 4 /* Bytes */
+#define BURST_LENGTH 8 /* Words */
+/*
+ * The PMU is able to freeze all counters and generate an interrupt when there
+ * is a counter overflow. But, relying on this means that we lose all the
+ * events that occur between the freeze and the interrupt handler execution.
+ * So we use a polling mechanism to avoid this lose of information.
+ * The fastest counter can overflow in ~8s @533MHz (that is the maximum DDR
+ * frequency supported on STM32MP157), so we poll in 4s intervals to ensure
+ * we don't reach this limit.
+ */
+#define POLL_MS 4000
+
+#define DDRPERFM_CTL 0x000
+#define DDRPERFM_CFG 0x004
+#define DDRPERFM_STATUS 0x008
+#define DDRPERFM_CCR 0x00C
+#define DDRPERFM_IER 0x010
+#define DDRPERFM_ISR 0x014
+#define DDRPERFM_ICR 0x018
+#define DDRPERFM_TCNT 0x020
+#define DDRPERFM_CNT(X) (0x030 + 8 * (X))
+#define DDRPERFM_HWCFG 0x3F0
+#define DDRPERFM_VER 0x3F4
+#define DDRPERFM_ID 0x3F8
+#define DDRPERFM_SID 0x3FC
+
+#define CTL_START 0x00000001
+#define CTL_STOP 0x00000002
+#define CCR_CLEAR_ALL 0x8000000F
+#define SID_MAGIC_ID 0xA3C5DD01
+
+#define STRING "Read = %llu, Write = %llu, Read & Write = %llu (MB/s)\n"
+
+enum {
+ READ_CNT,
@ -148,12 +166,11 @@ index 0000000000000..4f30f6f8be964
+struct stm32_ddr_pmu {
+ struct pmu pmu;
+ void __iomem *membase;
+ struct device *dev;
+ struct clk *clk;
+ struct clk *clk_ddr;
+ unsigned long clk_ddr_rate;
+ struct hrtimer hrtimer;
+ cpumask_t pmu_cpu;
+ ktime_t poll_period;
+ spinlock_t lock; /* for shared registers access */
+ struct perf_event *events[PMU_NR_COUNTERS];
+ u64 events_cnt[PMU_NR_COUNTERS];
+};
@ -168,98 +185,41 @@ index 0000000000000..4f30f6f8be964
+ return container_of(h, struct stm32_ddr_pmu, hrtimer);
+}
+
+static u64 stm32_ddr_pmu_compute_bw(struct stm32_ddr_pmu *stm32_ddr_pmu,
+ int counter)
+{
+ u64 bw = stm32_ddr_pmu->events_cnt[counter], tmp;
+ u64 div = stm32_ddr_pmu->events_cnt[TIME_CNT];
+ u32 prediv = 1, premul = 1;
+
+ if (bw && div) {
+ /* Maximize the dividend into 64 bits */
+ while ((bw < 0x8000000000000000ULL) &&
+ (premul < 0x40000000UL)) {
+ bw = bw << 1;
+ premul *= 2;
+ }
+ /* Minimize the dividor to fit in 32 bits */
+ while ((div > 0xffffffffUL) && (prediv < 0x40000000UL)) {
+ div = div >> 1;
+ prediv *= 2;
+ }
+ /* Divide counter per time and multiply per DDR settings */
+ do_div(bw, div);
+ tmp = bw * BURST_LENGTH * WORD_LENGTH;
+ tmp *= stm32_ddr_pmu->clk_ddr_rate;
+ if (tmp < bw)
+ goto error;
+ bw = tmp;
+ /* Cancel the prediv and premul factors */
+ while (prediv > 1) {
+ bw = bw >> 1;
+ prediv /= 2;
+ }
+ while (premul > 1) {
+ bw = bw >> 1;
+ premul /= 2;
+ }
+ /* Convert MHz to Hz and B to MB, to finally get MB/s */
+ tmp = bw * 1000000;
+ if (tmp < bw)
+ goto error;
+ bw = tmp;
+ premul = 1024 * 1024;
+ while (premul > 1) {
+ bw = bw >> 1;
+ premul /= 2;
+ }
+ }
+ return bw;
+
+error:
+ pr_warn("stm32-ddr-pmu: overflow detected\n");
+ return 0;
+}
+
+static void stm32_ddr_pmu_event_configure(struct perf_event *event)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ unsigned long lock_flags, config_base = event->hw.config_base;
+ unsigned long config_base = event->hw.config_base;
+ u32 val;
+
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
+
+ if (config_base < TIME_CNT) {
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG);
+ val |= (1 << config_base);
+ val |= BIT(config_base);
+ writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG);
+ }
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags);
+}
+
+static void stm32_ddr_pmu_event_read(struct perf_event *event)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ unsigned long flags, config_base = event->hw.config_base;
+ unsigned long config_base = event->hw.config_base;
+ struct hw_perf_event *hw = &event->hw;
+ u64 prev_count, new_count, mask;
+ u32 val, offset, bit;
+
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, flags);
+
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
+
+ if (config_base == TIME_CNT) {
+ offset = DDRPERFM_TCNT;
+ bit = 1 << 31;
+ bit = BIT(31);
+ } else {
+ offset = DDRPERFM_CNT(config_base);
+ bit = 1 << config_base;
+ bit = BIT(config_base);
+ }
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_STATUS);
+ if (val & bit)
+ pr_warn("stm32_ddr_pmu hardware overflow\n");
+ dev_warn(stm32_ddr_pmu->dev, "hardware counter overflow\n");
+ val = readl_relaxed(stm32_ddr_pmu->membase + offset);
+ writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR);
+ writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL);
@ -271,18 +231,12 @@ index 0000000000000..4f30f6f8be964
+
+ mask = GENMASK_ULL(31, 0);
+ local64_add(val & mask, &event->count);
+
+ if (new_count < prev_count)
+ pr_warn("STM32 DDR PMU counter saturated\n");
+
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, flags);
+}
+
+static void stm32_ddr_pmu_event_start(struct perf_event *event, int flags)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ unsigned long lock_flags;
+
+ if (WARN_ON_ONCE(!(hw->state & PERF_HES_STOPPED)))
+ return;
@ -293,37 +247,33 @@ index 0000000000000..4f30f6f8be964
+ stm32_ddr_pmu_event_configure(event);
+
+ /* Clear all counters to synchronize them, then start */
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
+ writel_relaxed(CCR_CLEAR_ALL, stm32_ddr_pmu->membase + DDRPERFM_CCR);
+ writel_relaxed(CTL_START, stm32_ddr_pmu->membase + DDRPERFM_CTL);
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags);
+
+ local64_set(&hw->prev_count, 0);
+ hw->state = 0;
+}
+
+static void stm32_ddr_pmu_event_stop(struct perf_event *event, int flags)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ unsigned long lock_flags, config_base = event->hw.config_base;
+ unsigned long config_base = event->hw.config_base;
+ struct hw_perf_event *hw = &event->hw;
+ u32 val, bit;
+
+ if (WARN_ON_ONCE(hw->state & PERF_HES_STOPPED))
+ return;
+
+ spin_lock_irqsave(&stm32_ddr_pmu->lock, lock_flags);
+ writel_relaxed(CTL_STOP, stm32_ddr_pmu->membase + DDRPERFM_CTL);
+ if (config_base == TIME_CNT)
+ bit = 1 << 31;
+ bit = BIT(31);
+ else
+ bit = 1 << config_base;
+ bit = BIT(config_base);
+ writel_relaxed(bit, stm32_ddr_pmu->membase + DDRPERFM_CCR);
+ if (config_base < TIME_CNT) {
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_CFG);
+ val &= ~bit;
+ writel_relaxed(val, stm32_ddr_pmu->membase + DDRPERFM_CFG);
+ }
+ spin_unlock_irqrestore(&stm32_ddr_pmu->lock, lock_flags);
+
+ hw->state |= PERF_HES_STOPPED;
+
@ -343,8 +293,13 @@ index 0000000000000..4f30f6f8be964
+ stm32_ddr_pmu->events[config_base] = event;
+
+ clk_enable(stm32_ddr_pmu->clk);
+ /*
+ * Pin the timer, so that the overflows are handled by the chosen
+ * event->cpu (this is the same one as presented in "cpumask"
+ * attribute).
+ */
+ hrtimer_start(&stm32_ddr_pmu->hrtimer, stm32_ddr_pmu->poll_period,
+ HRTIMER_MODE_REL);
+ HRTIMER_MODE_REL_PINNED);
+
+ stm32_ddr_pmu_event_configure(event);
+
@ -360,7 +315,6 @@ index 0000000000000..4f30f6f8be964
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ unsigned long config_base = event->hw.config_base;
+ bool stop = true;
+ int i;
+
+ stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE);
@ -370,8 +324,9 @@ index 0000000000000..4f30f6f8be964
+
+ for (i = 0; i < PMU_NR_COUNTERS; i++)
+ if (stm32_ddr_pmu->events[i])
+ stop = false;
+ if (stop)
+ break;
+
+ if (i == PMU_NR_COUNTERS)
+ hrtimer_cancel(&stm32_ddr_pmu->hrtimer);
+
+ clk_disable(stm32_ddr_pmu->clk);
@ -379,11 +334,15 @@ index 0000000000000..4f30f6f8be964
+
+static int stm32_ddr_pmu_event_init(struct perf_event *event)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = pmu_to_stm32_ddr_pmu(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (event->attr.config >= PMU_NR_COUNTERS)
+ return -ENOENT;
+
+ if (is_sampling_event(event))
+ return -EINVAL;
+
@ -402,6 +361,7 @@ index 0000000000000..4f30f6f8be964
+ return -EINVAL;
+
+ hw->config_base = event->attr.config;
+ event->cpu = cpumask_first(&stm32_ddr_pmu->pmu_cpu);
+
+ return 0;
+}
@ -431,27 +391,6 @@ index 0000000000000..4f30f6f8be964
+ return sprintf(buf, "config=0x%lx\n", (unsigned long)eattr->var);
+}
+
+static ssize_t bandwidth_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = dev_get_drvdata(dev);
+ u64 r_bw, w_bw;
+ int ret;
+
+ if (stm32_ddr_pmu->events_cnt[TIME_CNT]) {
+ r_bw = stm32_ddr_pmu_compute_bw(stm32_ddr_pmu, READ_CNT);
+ w_bw = stm32_ddr_pmu_compute_bw(stm32_ddr_pmu, WRITE_CNT);
+
+ ret = snprintf(buf, PAGE_SIZE, STRING,
+ r_bw, w_bw, (r_bw + w_bw));
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "No data available\n");
+ }
+
+ return ret;
+}
+
+#define STM32_DDR_PMU_ATTR(_name, _func, _config) \
+ (&((struct dev_ext_attribute[]) { \
+ { __ATTR(_name, 0444, _func, NULL), (void *)_config } \
@ -470,82 +409,66 @@ index 0000000000000..4f30f6f8be964
+ NULL
+};
+
+static DEVICE_ATTR_RO(bandwidth);
+static struct attribute *stm32_ddr_pmu_bandwidth_attrs[] = {
+ &dev_attr_bandwidth.attr,
+ NULL,
+};
+
+static struct attribute_group stm32_ddr_pmu_event_attrs_group = {
+ .name = "events",
+ .attrs = stm32_ddr_pmu_event_attrs,
+};
+
+static struct attribute_group stm32_ddr_pmu_bandwidth_attrs_group = {
+ .attrs = stm32_ddr_pmu_bandwidth_attrs,
+};
+
+static const struct attribute_group *stm32_ddr_pmu_attr_groups[] = {
+ &stm32_ddr_pmu_event_attrs_group,
+ &stm32_ddr_pmu_bandwidth_attrs_group,
+ NULL,
+};
+
+static int stm32_ddr_pmu_device_probe(struct platform_device *pdev)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu;
+ struct reset_control *rst;
+ struct resource *res;
+ int i, ret;
+ u32 val;
+
+ stm32_ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(struct stm32_ddr_pmu),
+ GFP_KERNEL);
+ if (!stm32_ddr_pmu)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, stm32_ddr_pmu);
+ stm32_ddr_pmu->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ stm32_ddr_pmu->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(stm32_ddr_pmu->membase)) {
+ pr_warn("Unable to get STM32 DDR PMU membase\n");
+ dev_err(&pdev->dev, "Unable to get membase\n");
+ return PTR_ERR(stm32_ddr_pmu->membase);
+ }
+
+ stm32_ddr_pmu->clk = devm_clk_get(&pdev->dev, "bus");
+ stm32_ddr_pmu->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(stm32_ddr_pmu->clk)) {
+ pr_warn("Unable to get STM32 DDR PMU clock\n");
+ dev_err(&pdev->dev, "unable to get the clock\n");
+ return PTR_ERR(stm32_ddr_pmu->clk);
+ }
+
+ ret = clk_prepare_enable(stm32_ddr_pmu->clk);
+ if (ret) {
+ pr_warn("Unable to prepare STM32 DDR PMU clock\n");
+ dev_err(&pdev->dev, "unable to prepare the clock\n");
+ return ret;
+ }
+
+ stm32_ddr_pmu->clk_ddr = devm_clk_get(&pdev->dev, "ddr");
+ if (IS_ERR(stm32_ddr_pmu->clk_ddr)) {
+ pr_warn("Unable to get STM32 DDR clock\n");
+ return PTR_ERR(stm32_ddr_pmu->clk_ddr);
+ }
+ stm32_ddr_pmu->clk_ddr_rate = clk_get_rate(stm32_ddr_pmu->clk_ddr);
+ stm32_ddr_pmu->clk_ddr_rate /= 1000000;
+
+ stm32_ddr_pmu->poll_period = ms_to_ktime(POLL_MS);
+ hrtimer_init(&stm32_ddr_pmu->hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ stm32_ddr_pmu->hrtimer.function = stm32_ddr_pmu_poll;
+ spin_lock_init(&stm32_ddr_pmu->lock);
+
+ /*
+ * The PMU is assigned to the cpu0 and there is no need to manage cpu
+ * hot plug migration because cpu0 is always the first/last active cpu
+ * during low power transitions.
+ */
+ cpumask_set_cpu(0, &stm32_ddr_pmu->pmu_cpu);
+
+ for (i = 0; i < PMU_NR_COUNTERS; i++) {
+ stm32_ddr_pmu->events[i] = NULL;
+ stm32_ddr_pmu->events_cnt[i] = 0;
+ }
+
+ val = readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_SID);
+ if (val != SID_MAGIC_ID)
+ return -EINVAL;
+
+ stm32_ddr_pmu->pmu = (struct pmu) {
+ .task_ctx_nr = perf_invalid_context,
+ .start = stm32_ddr_pmu_event_start,
@ -555,20 +478,35 @@ index 0000000000000..4f30f6f8be964
+ .event_init = stm32_ddr_pmu_event_init,
+ .attr_groups = stm32_ddr_pmu_attr_groups,
+ };
+ ret = perf_pmu_register(&stm32_ddr_pmu->pmu, "ddrperfm", -1);
+ ret = perf_pmu_register(&stm32_ddr_pmu->pmu, "stm32_ddr_pmu", -1);
+ if (ret) {
+ pr_warn("Unable to register STM32 DDR PMU\n");
+ return ret;
+ dev_err(&pdev->dev, "unable to register the pmu\n");
+ goto err_pmu_register;
+ }
+
+ pr_info("stm32-ddr-pmu: probed (ID=0x%08x VER=0x%08x), DDR@%luMHz\n",
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_ID),
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_VER),
+ stm32_ddr_pmu->clk_ddr_rate);
+ rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(rst)) {
+ dev_err(&pdev->dev, "unable to get the reset\n");
+ ret = -ENOENT;
+ goto err_get_reset;
+ }
+ reset_control_assert(rst);
+ udelay(2);
+ reset_control_deassert(rst);
+
+ dev_info(&pdev->dev, "probed (DDRPERFM ID=0x%08x VER=0x%08x)\n",
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_ID),
+ readl_relaxed(stm32_ddr_pmu->membase + DDRPERFM_VER));
+
+ clk_disable(stm32_ddr_pmu->clk);
+
+ return 0;
+
+err_get_reset:
+ perf_pmu_unregister(&stm32_ddr_pmu->pmu);
+err_pmu_register:
+ clk_disable_unprepare(stm32_ddr_pmu->clk);
+ return ret;
+}
+
+static int stm32_ddr_pmu_device_remove(struct platform_device *pdev)
@ -577,6 +515,8 @@ index 0000000000000..4f30f6f8be964
+
+ perf_pmu_unregister(&stm32_ddr_pmu->pmu);
+
+ clk_unprepare(stm32_ddr_pmu->clk);
+
+ return 0;
+}
+

View File

@ -1,139 +1,163 @@
From 60ca74ac3c89a476b38d4f41c3bea3745779587e Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Mon, 5 Oct 2020 13:19:46 +0200
Subject: [PATCH 11/22] ARM-stm32mp1-r2-rc8-RESET-RTC-WATCHDOG
From c40d4d83b3de542be7d64b88f0c842ebecc9a6b2 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Tue, 16 Mar 2021 09:09:52 +0100
Subject: [PATCH 17/22] ARM 5.10.10-stm32mp1-r1 RESET-RTC-WATCHDOG
Signed-off-by: Romuald JEANNE <romuald.jeanne@st.com>
---
.../devicetree/bindings/rtc/st,stm32-rtc.txt | 10 +-
drivers/reset/reset-stm32mp1.c | 83 +++++---
drivers/rtc/Kconfig | 1 +
drivers/rtc/rtc-stm32.c | 180 +++++++++++++++---
drivers/watchdog/stm32_iwdg.c | 6 +-
include/dt-bindings/reset/stm32mp1-resets.h | 15 ++
include/dt-bindings/rtc/rtc-stm32.h | 13 ++
7 files changed, 246 insertions(+), 62 deletions(-)
drivers/reset/Kconfig | 6 -
drivers/reset/Makefile | 1 -
drivers/reset/reset-stm32mp1.c | 115 -------------
drivers/rtc/Kconfig | 1 +
drivers/rtc/rtc-stm32.c | 180 ++++++++++++++++----
drivers/watchdog/stm32_iwdg.c | 13 +-
include/dt-bindings/reset/stm32mp1-resets.h | 15 ++
include/dt-bindings/rtc/rtc-stm32.h | 13 ++
8 files changed, 183 insertions(+), 161 deletions(-)
delete mode 100644 drivers/reset/reset-stm32mp1.c
create mode 100644 include/dt-bindings/rtc/rtc-stm32.h
diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
index 130ca5b982538..bab0df81af2cc 100644
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
@@ -21,9 +21,14 @@ Required properties:
domain (RTC registers) write protection.
It is required on stm32(f4/f7/h7).
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 07d162b179fc..c3186d80c33e 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -180,12 +180,6 @@ config RESET_SIMPLE
- Allwinner SoCs
- ZTE's zx2967 family
-Optional properties (to override default rtc_ck parent clock on stm32(f4/f7/h7):
+Optional properties:
+* to override default rtc_ck parent clock on stm32(f4/f7/h7):
- assigned-clocks: reference to the rtc_ck clock entry.
- assigned-clock-parents: phandle of the new parent clock of rtc_ck.
+* to select and enable RTC Low Speed Clock Output on stm32mp1:
+- st,lsco: defines the RTC output on which RTC Low-Speed Clock is Output. The
+ valid output values are defined in <dt-bindings/rtc/rtc-stm32.h>.
+- pinctrl state named "default" may be defined to reserve pin for RTC output.
Example:
@@ -58,4 +63,7 @@ Example:
clock-names = "pclk", "rtc_ck";
interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_NONE>,
<&exti 19 1>;
+ st,lsco = <RTC_OUT2_RMP>;
+ pinctrl-0 = <&rtc_out2_rmp_pins_a>;
+ pinctrl-names = "default";
};
-config RESET_STM32MP157
- bool "STM32MP157 Reset Driver" if COMPILE_TEST
- default MACH_STM32MP157
- help
- This enables the RCC reset controller driver for STM32 MPUs.
-
config RESET_SOCFPGA
bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA
default ARCH_SOCFPGA
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 16947610cc3b..b2c9eff41d3b 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -24,7 +24,6 @@ obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
-obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
diff --git a/drivers/reset/reset-stm32mp1.c b/drivers/reset/reset-stm32mp1.c
index b221a28041fa0..daf0e26b27a8d 100644
deleted file mode 100644
index b221a28041fa..000000000000
--- a/drivers/reset/reset-stm32mp1.c
+++ b/drivers/reset/reset-stm32mp1.c
@@ -4,14 +4,21 @@
* Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
*/
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <linux/arm-smccc.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
+#include <linux/slab.h>
+++ /dev/null
@@ -1,115 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
- * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/reset-controller.h>
-
-#define CLR_OFFSET 0x4
+#define STM32MP1_RESET_ID_MASK GENMASK(15, 0)
+
+#define CLR_OFFSET 0x4
struct stm32_reset_data {
struct reset_controller_dev rcdev;
@@ -79,37 +86,57 @@ static const struct of_device_id stm32_reset_dt_ids[] = {
{ /* sentinel */ },
};
-
-struct stm32_reset_data {
- struct reset_controller_dev rcdev;
- void __iomem *membase;
-};
-
-static inline struct stm32_reset_data *
-to_stm32_reset_data(struct reset_controller_dev *rcdev)
-{
- return container_of(rcdev, struct stm32_reset_data, rcdev);
-}
-
-static int stm32_reset_update(struct reset_controller_dev *rcdev,
- unsigned long id, bool assert)
-{
- struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
- int reg_width = sizeof(u32);
- int bank = id / (reg_width * BITS_PER_BYTE);
- int offset = id % (reg_width * BITS_PER_BYTE);
- void __iomem *addr;
-
- addr = data->membase + (bank * reg_width);
- if (!assert)
- addr += CLR_OFFSET;
-
- writel(BIT(offset), addr);
-
- return 0;
-}
-
-static int stm32_reset_assert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- return stm32_reset_update(rcdev, id, true);
-}
-
-static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- return stm32_reset_update(rcdev, id, false);
-}
-
-static int stm32_reset_status(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
- int reg_width = sizeof(u32);
- int bank = id / (reg_width * BITS_PER_BYTE);
- int offset = id % (reg_width * BITS_PER_BYTE);
- u32 reg;
-
- reg = readl(data->membase + (bank * reg_width));
-
- return !!(reg & BIT(offset));
-}
-
-static const struct reset_control_ops stm32_reset_ops = {
- .assert = stm32_reset_assert,
- .deassert = stm32_reset_deassert,
- .status = stm32_reset_status,
-};
-
-static const struct of_device_id stm32_reset_dt_ids[] = {
- { .compatible = "st,stm32mp1-rcc"},
- { /* sentinel */ },
-};
-
-static int stm32_reset_probe(struct platform_device *pdev)
+static void __init stm32mp1_reset_init(struct device_node *np)
{
-{
- struct device *dev = &pdev->dev;
- struct stm32_reset_data *data;
- void __iomem *membase;
- struct resource *res;
-
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ void __iomem *base;
+ const struct of_device_id *match;
+ struct stm32_reset_data *data = NULL;
+ int ret;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%pOFn: unable to map resource", np);
+ of_node_put(np);
+ return;
+ }
+
+ match = of_match_node(stm32_reset_dt_ids, np);
+ if (!match) {
+ pr_err("%s: match data not found\n", __func__);
+ goto err;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
- if (!data)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- membase = devm_ioremap_resource(dev, res);
- if (IS_ERR(membase))
- return PTR_ERR(membase);
+ goto err;
-
- data->membase = membase;
+ data->membase = base;
data->rcdev.owner = THIS_MODULE;
- data->rcdev.owner = THIS_MODULE;
- data->rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE;
data->rcdev.ops = &stm32_reset_ops;
- data->rcdev.ops = &stm32_reset_ops;
- data->rcdev.of_node = dev->of_node;
-
- return devm_reset_controller_register(dev, &data->rcdev);
+ data->rcdev.of_node = np;
+ data->rcdev.nr_resets = STM32MP1_RESET_ID_MASK;
+
+ ret = reset_controller_register(&data->rcdev);
+ if (!ret)
+ return;
+
+err:
+ pr_err("stm32mp1 reset failed to initialize\n");
+ if (data)
+ kfree(data);
+ if (base)
+ iounmap(base);
+ of_node_put(np);
}
-}
-
-static struct platform_driver stm32_reset_driver = {
- .probe = stm32_reset_probe,
- .driver = {
@ -143,22 +167,11 @@ index b221a28041fa0..daf0e26b27a8d 100644
-};
-
-builtin_platform_driver(stm32_reset_driver);
+/*
+ * RCC reset and clock drivers bind to the same RCC node.
+ * Register RCC reset driver at init through clock of table,
+ * clock driver for RCC will register at probe time.
+ */
+static void __init stm32mp1_reset_of_init_drv(struct device_node *np)
+{
+ of_node_clear_flag(np, OF_POPULATED);
+ stm32mp1_reset_init(np);
+}
+OF_DECLARE_1(clk, stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_reset_of_init_drv);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index c5b9804140860..d590b420525ce 100644
index 65ad9d0b47ab..f2a4d7c633c8 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1862,6 +1862,7 @@ config RTC_DRV_R7301
@@ -1884,6 +1884,7 @@ config RTC_DRV_R7301
config RTC_DRV_STM32
tristate "STM32 RTC"
select REGMAP_MMIO
@ -167,7 +180,7 @@ index c5b9804140860..d590b420525ce 100644
help
If you say yes here you get support for the STM32 On-Chip
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 2999e33a7e376..3cf51497681a4 100644
index d774aa18f57a..7fd6347691bb 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -6,6 +6,8 @@
@ -399,7 +412,7 @@ index 2999e33a7e376..3cf51497681a4 100644
}
/*
@@ -738,13 +848,15 @@ static int stm32_rtc_probe(struct platform_device *pdev)
@@ -736,13 +846,15 @@ static int stm32_rtc_probe(struct platform_device *pdev)
} else {
rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(rtc->pclk)) {
@ -417,7 +430,7 @@ index 2999e33a7e376..3cf51497681a4 100644
return PTR_ERR(rtc->rtc_ck);
}
@@ -781,19 +893,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
@@ -779,19 +891,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
}
ret = device_init_wakeup(&pdev->dev, true);
@ -442,7 +455,7 @@ index 2999e33a7e376..3cf51497681a4 100644
platform_set_drvdata(pdev, rtc);
@@ -816,6 +921,21 @@ static int stm32_rtc_probe(struct platform_device *pdev)
@@ -814,6 +919,21 @@ static int stm32_rtc_probe(struct platform_device *pdev)
goto err;
}
@ -464,7 +477,7 @@ index 2999e33a7e376..3cf51497681a4 100644
/*
* If INITS flag is reset (calendar year field set to 0x00), calendar
* must be initialized
@@ -852,6 +972,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
@@ -850,6 +970,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int cr;
@ -474,7 +487,7 @@ index 2999e33a7e376..3cf51497681a4 100644
/* Disable interrupts */
stm32_rtc_wpr_unlock(rtc);
cr = readl_relaxed(rtc->base + regs->cr);
@@ -881,9 +1004,6 @@ static int stm32_rtc_suspend(struct device *dev)
@@ -879,9 +1002,6 @@ static int stm32_rtc_suspend(struct device *dev)
if (rtc->data->has_pclk)
clk_disable_unprepare(rtc->pclk);
@ -484,9 +497,9 @@ index 2999e33a7e376..3cf51497681a4 100644
return 0;
}
@@ -902,15 +1022,13 @@ static int stm32_rtc_resume(struct device *dev)
if (ret < 0)
@@ -903,15 +1023,13 @@ static int stm32_rtc_resume(struct device *dev)
return ret;
}
- if (device_may_wakeup(dev))
- return disable_irq_wake(rtc->irq_alarm);
@ -504,31 +517,35 @@ index 2999e33a7e376..3cf51497681a4 100644
static struct platform_driver stm32_rtc_driver = {
.probe = stm32_rtc_probe,
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index 25188d6bbe152..1b71c205cee0e 100644
index 25188d6bbe15..a3436c296c97 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -163,7 +163,8 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
@@ -162,18 +162,15 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
u32 ret;
wdt->clk_lsi = devm_clk_get(dev, "lsi");
if (IS_ERR(wdt->clk_lsi)) {
- if (IS_ERR(wdt->clk_lsi)) {
- dev_err(dev, "Unable to get lsi clock\n");
+ if (PTR_ERR(wdt->clk_lsi) != -EPROBE_DEFER)
+ dev_err(dev, "Unable to get lsi clock\n");
return PTR_ERR(wdt->clk_lsi);
}
- return PTR_ERR(wdt->clk_lsi);
- }
+ if (IS_ERR(wdt->clk_lsi))
+ return dev_err_probe(dev, PTR_ERR(wdt->clk_lsi), "Unable to get lsi clock\n");
@@ -171,7 +172,8 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
/* optional peripheral clock */
if (wdt->data->has_pclk) {
wdt->clk_pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(wdt->clk_pclk)) {
- if (IS_ERR(wdt->clk_pclk)) {
- dev_err(dev, "Unable to get pclk clock\n");
+ if (PTR_ERR(wdt->clk_pclk) != -EPROBE_DEFER)
+ dev_err(dev, "Unable to get pclk clock\n");
return PTR_ERR(wdt->clk_pclk);
}
- return PTR_ERR(wdt->clk_pclk);
- }
+ if (IS_ERR(wdt->clk_pclk))
+ return dev_err_probe(dev, PTR_ERR(wdt->clk_pclk),
+ "Unable to get pclk clock\n");
ret = clk_prepare_enable(wdt->clk_pclk);
if (ret) {
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
index f0c3aaef67a0a..f3a0ed3178356 100644
index f0c3aaef67a0..f3a0ed317835 100644
--- a/include/dt-bindings/reset/stm32mp1-resets.h
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -7,6 +7,7 @@
@ -560,7 +577,7 @@ index f0c3aaef67a0a..f3a0ed3178356 100644
#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h
new file mode 100644
index 0000000000000..4373c4dea5879
index 000000000000..4373c4dea587
--- /dev/null
+++ b/include/dt-bindings/rtc/rtc-stm32.h
@@ -0,0 +1,13 @@

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: Lionel VITTE <lionel.vitte@st.com>
Date: Mon, 5 Oct 2020 13:19:55 +0200
Subject: [PATCH 21/22] ARM-stm32mp1-r2-rc8-CONFIG
From 106f488712b412ed24f600c82febf95901c45054 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Tue, 16 Mar 2021 09:03:42 +0100
Subject: [PATCH 22/22] ARM 5.10.10-stm32mp1-r1 CONFIG
Signed-off-by: Romuald JEANNE <romuald.jeanne@st.com>
---
.../fragment-01-multiv7_cleanup.config | 148 ++++++
.../configs/fragment-02-multiv7_addons.config | 434 ++++++++++++++++++
arch/arm/configs/multi_v7_defconfig | 1 +
3 files changed, 583 insertions(+)
.../fragment-01-multiv7_cleanup.config | 374 ++++++++++++++++
.../configs/fragment-02-multiv7_addons.config | 398 ++++++++++++++++++
arch/arm/configs/multi_v7_defconfig | 5 +
3 files changed, 777 insertions(+)
create mode 100644 arch/arm/configs/fragment-01-multiv7_cleanup.config
create mode 100644 arch/arm/configs/fragment-02-multiv7_addons.config
diff --git a/arch/arm/configs/fragment-01-multiv7_cleanup.config b/arch/arm/configs/fragment-01-multiv7_cleanup.config
new file mode 100644
index 0000000000000..3c43593d5665f
index 000000000000..0c5667237e27
--- /dev/null
+++ b/arch/arm/configs/fragment-01-multiv7_cleanup.config
@@ -0,0 +1,148 @@
@@ -0,0 +1,374 @@
+#
+# CPU Core family selection
+#
@ -76,7 +77,6 @@ index 0000000000000..3c43593d5665f
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
@ -165,12 +165,239 @@ index 0000000000000..3c43593d5665f
+# Debug Lockups and Hangs
+#
+# CONFIG_SCHED_DEBUG is not set
+
+# SPI NOR device support
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+
+#
+# Media core support
+#
+# CONFIG_DVB_CORE is not set
+# CONFIG_MEDIA_TUNER is not set
+# CONFIG_MEDIA_CONTROLLER_REQUEST_API is not set
+
+# Digital TV options
+#
+# CONFIG_DVB_NET is not set
+# CONFIG_DVB_MAX_ADAPTERS is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+# end of Digital TV options
+
+#
+# Media SPI Adapters
+#
+# CONFIG_CXD2880_SPI_DRV is not set
+# end of Media SPI Adapters
+
+#
+# Customize TV tuners
+#
+# CONFIG_MEDIA_TUNER_SIMPLE is not set
+# CONFIG_MEDIA_TUNER_TDA18250 is not set
+# CONFIG_MEDIA_TUNER_TDA8290 is not set
+# CONFIG_MEDIA_TUNER_TDA827X is not set
+# CONFIG_MEDIA_TUNER_TDA18271 is not set
+# CONFIG_MEDIA_TUNER_TDA9887 is not set
+# CONFIG_MEDIA_TUNER_TEA5761 is not set
+# CONFIG_MEDIA_TUNER_TEA5767 is not set
+# CONFIG_MEDIA_TUNER_MSI001 is not set
+# CONFIG_MEDIA_TUNER_MT20XX is not set
+# CONFIG_MEDIA_TUNER_MT2060 is not set
+# CONFIG_MEDIA_TUNER_MT2063 is not set
+# CONFIG_MEDIA_TUNER_MT2266 is not set
+# CONFIG_MEDIA_TUNER_MT2131 is not set
+# CONFIG_MEDIA_TUNER_QT1010 is not set
+# CONFIG_MEDIA_TUNER_XC2028 is not set
+# CONFIG_MEDIA_TUNER_XC5000 is not set
+# CONFIG_MEDIA_TUNER_XC4000 is not set
+# CONFIG_MEDIA_TUNER_MXL5005S is not set
+# CONFIG_MEDIA_TUNER_MXL5007T is not set
+# CONFIG_MEDIA_TUNER_MC44S803 is not set
+# CONFIG_MEDIA_TUNER_MAX2165 is not set
+# CONFIG_MEDIA_TUNER_TDA18218 is not set
+# CONFIG_MEDIA_TUNER_FC0011 is not set
+# CONFIG_MEDIA_TUNER_FC0012 is not set
+# CONFIG_MEDIA_TUNER_FC0013 is not set
+# CONFIG_MEDIA_TUNER_TDA18212 is not set
+# CONFIG_MEDIA_TUNER_E4000 is not set
+# CONFIG_MEDIA_TUNER_FC2580 is not set
+# CONFIG_MEDIA_TUNER_M88RS6000T is not set
+# CONFIG_MEDIA_TUNER_TUA9001 is not set
+# CONFIG_MEDIA_TUNER_SI2157 is not set
+# CONFIG_MEDIA_TUNER_IT913X is not set
+# CONFIG_MEDIA_TUNER_R820T is not set
+# CONFIG_MEDIA_TUNER_MXL301RF is not set
+# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set
+# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set
+# end of Customize TV tuners
+#
+# Customise DVB Frontends
+#
+
+#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+# CONFIG_DVB_STV090x is not set
+# CONFIG_DVB_STV0910 is not set
+# CONFIG_DVB_STV6110x is not set
+# CONFIG_DVB_STV6111 is not set
+# CONFIG_DVB_MXL5XX is not set
+# CONFIG_DVB_M88DS3103 is not set
+
+#
+# Multistandard (cable + terrestrial) frontends
+#
+# CONFIG_DVB_DRXK is not set
+# CONFIG_DVB_TDA18271C2DD is not set
+# CONFIG_DVB_SI2165 is not set
+# CONFIG_DVB_MN88472 is not set
+# CONFIG_DVB_MN88473 is not set
+
+#
+# DVB-S (satellite) frontends
+#
+# CONFIG_DVB_CX24110 is not set
+# CONFIG_DVB_CX24123 is not set
+# CONFIG_DVB_MT312 is not set
+# CONFIG_DVB_ZL10036 is not set
+# CONFIG_DVB_ZL10039 is not set
+# CONFIG_DVB_S5H1420 is not set
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STB6000 is not set
+# CONFIG_DVB_STV0299 is not set
+# CONFIG_DVB_STV6110 is not set
+# CONFIG_DVB_STV0900 is not set
+# CONFIG_DVB_TDA8083 is not set
+# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
+# CONFIG_DVB_VES1X93 is not set
+# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
+# CONFIG_DVB_TDA826X is not set
+# CONFIG_DVB_TUA6100 is not set
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_CX24117 is not set
+# CONFIG_DVB_CX24120 is not set
+# CONFIG_DVB_SI21XX is not set
+# CONFIG_DVB_TS2020 is not set
+# CONFIG_DVB_DS3000 is not set
+# CONFIG_DVB_MB86A16 is not set
+# CONFIG_DVB_TDA10071 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+# CONFIG_DVB_SP8870 is not set
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_CX22700 is not set
+# CONFIG_DVB_CX22702 is not set
+# CONFIG_DVB_S5H1432 is not set
+# CONFIG_DVB_DRXD is not set
+# CONFIG_DVB_L64781 is not set
+# CONFIG_DVB_TDA1004X is not set
+# CONFIG_DVB_NXT6000 is not set
+# CONFIG_DVB_MT352 is not set
+# CONFIG_DVB_ZL10353 is not set
+# CONFIG_DVB_DIB3000MB is not set
+# CONFIG_DVB_DIB3000MC is not set
+# CONFIG_DVB_DIB7000M is not set
+# CONFIG_DVB_DIB7000P is not set
+# CONFIG_DVB_DIB9000 is not set
+# CONFIG_DVB_TDA10048 is not set
+# CONFIG_DVB_AF9013 is not set
+# CONFIG_DVB_EC100 is not set
+# CONFIG_DVB_STV0367 is not set
+# CONFIG_DVB_CXD2820R is not set
+# CONFIG_DVB_CXD2841ER is not set
+# CONFIG_DVB_RTL2830 is not set
+# CONFIG_DVB_RTL2832 is not set
+# CONFIG_DVB_RTL2832_SDR is not set
+# CONFIG_DVB_SI2168 is not set
+# CONFIG_DVB_ZD1301_DEMOD is not set
+# CONFIG_DVB_CXD2880 is not set
+
+#
+# DVB-C (cable) frontends
+#
+# CONFIG_DVB_VES1820 is not set
+# CONFIG_DVB_TDA10021 is not set
+# CONFIG_DVB_TDA10023 is not set
+# CONFIG_DVB_STV0297 is not set
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3305 is not set
+# CONFIG_DVB_LGDT3306A is not set
+# CONFIG_DVB_LG2160 is not set
+# CONFIG_DVB_S5H1409 is not set
+# CONFIG_DVB_AU8522 is not set
+# CONFIG_DVB_AU8522_DTV is not set
+# CONFIG_DVB_AU8522_V4L is not set
+# CONFIG_DVB_S5H1411 is not set
+
+#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+# CONFIG_DVB_DIB8000 is not set
+# CONFIG_DVB_MB86A20S is not set
+
+#
+# ISDB-S (satellite) & ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_TC90522 is not set
+# CONFIG_DVB_MN88443X is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+# CONFIG_DVB_PLL is not set
+# CONFIG_DVB_TUNER_DIB0070 is not set
+# CONFIG_DVB_TUNER_DIB0090 is not set
+
+#
+# SEC control devices for DVB-S
+#
+# CONFIG_DVB_DRX39XYJ is not set
+# CONFIG_DVB_LNBH25 is not set
+# CONFIG_DVB_LNBH29 is not set
+# CONFIG_DVB_LNBP21 is not set
+# CONFIG_DVB_LNBP22 is not set
+# CONFIG_DVB_ISL6405 is not set
+# CONFIG_DVB_ISL6421 is not set
+# CONFIG_DVB_ISL6423 is not set
+# CONFIG_DVB_A8293 is not set
+# CONFIG_DVB_LGS8GL5 is not set
+# CONFIG_DVB_LGS8GXX is not set
+# CONFIG_DVB_ATBM8830 is not set
+# CONFIG_DVB_TDA665x is not set
+# CONFIG_DVB_IX2505V is not set
+# CONFIG_DVB_M88RS2000 is not set
+# CONFIG_DVB_AF9033 is not set
+# CONFIG_DVB_HORUS3A is not set
+# CONFIG_DVB_ASCOT2E is not set
+# CONFIG_DVB_HELENE is not set
+
+#
+# Common Interface (EN50221) controller drivers
+#
+# CONFIG_DVB_CXD2099 is not set
+# CONFIG_DVB_SP2 is not set
+# end of Customise DVB Frontends
diff --git a/arch/arm/configs/fragment-02-multiv7_addons.config b/arch/arm/configs/fragment-02-multiv7_addons.config
new file mode 100644
index 0000000000000..5fd995006583f
index 000000000000..d6c1a48d5702
--- /dev/null
+++ b/arch/arm/configs/fragment-02-multiv7_addons.config
@@ -0,0 +1,434 @@
@@ -0,0 +1,398 @@
+#
+# General setup
+#
@ -259,7 +486,6 @@ index 0000000000000..5fd995006583f
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
@ -311,6 +537,7 @@ index 0000000000000..5fd995006583f
+#
+
+CONFIG_MTD_SPI_NAND=y
+CONFIG_MTD_MCHP23K256=m
+
+#
+# USB GPIO expanders
@ -344,18 +571,13 @@ index 0000000000000..5fd995006583f
+CONFIG_PROTECTION_CONSUMER=y
+
+#
+# Regulator drivers
+#
+CONFIG_REGULATOR_STM32_PWR=y
+
+#
+# Multimedia core support
+#
+
+#
+# USB HDMI CEC adapters
+#
+CONFIG_VIDEO_STM32_HDMI_CEC=m
+CONFIG_CEC_STM32=m
+
+#
+# Camera sensor devices
@ -402,29 +624,19 @@ index 0000000000000..5fd995006583f
+CONFIG_BACKLIGHT_GPIO=y
+
+#
+# HD-Audio
+# STMicroelectronics STM32 SOC audio support
+#
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_STM32_SAI=y
+CONFIG_SND_SOC_STM32_I2S=y
+CONFIG_SND_SOC_STM32_SPDIFRX=y
+CONFIG_SND_SOC_STM32_DFSDM=y
+CONFIG_SND_AUDIO_GRAPH_CARD=y
+CONFIG_SND_SOC_STM32_SPDIFRX=m
+CONFIG_SND_SOC_STM32_DFSDM=m
+
+#
+# CODEC drivers
+#
+CONFIG_MFD_WM8994=y
+CONFIG_SND_SOC_WM8994=y
+CONFIG_SND_SOC_DMIC=y
+CONFIG_SND_SOC_CS42L42=y
+CONFIG_SND_SOC_CS42L51_I2C=y
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=y
+CONFIG_USB_ACM=m
+
+#
+# also be needed; see USB_STORAGE Help for more info
@ -433,13 +645,10 @@ index 0000000000000..5fd995006583f
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+CONFIG_USB_CONFIGFS=y
+
+#
+# USB Physical Layer drivers
+#
+CONFIG_TYPEC=y
+CONFIG_TYPEC_STUSB=y
+
+#
+# Platform Support
@ -454,8 +663,23 @@ index 0000000000000..5fd995006583f
+#
+
+#
+# Regulators
+#
+CONFIG_REGULATOR_STM32_VREFBUF=y
+
+#
+# Remoteproc drivers
+#
+CONFIG_REMOTEPROC=y
+CONFIG_STM32_RPROC=y
+CONFIG_REMOTEPROC_SRM_CORE=y
+CONFIG_REMOTEPROC_SRM_DEV=y
+
+#
+# Rpmsg drivers
+#
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_RPMSG_TTY=m
+
+#
+# File systems
@ -497,10 +721,6 @@ index 0000000000000..5fd995006583f
+#
+CONFIG_KEYS=y
+
+CONFIG_CRYPTO_DEV_STM32_CRC=y
+CONFIG_CRYPTO_DEV_STM32_HASH=y
+CONFIG_CRYPTO_DEV_STM32_CRYP=y
+
+#
+# Library routines
+#
@ -510,12 +730,6 @@ index 0000000000000..5fd995006583f
+# STM32 DFSDM
+#
+CONFIG_SD_ADC_MODULATOR=y
+CONFIG_STM32_DFSDM_ADC=y
+
+#
+# STM32 BSEC NVMEM
+#
+CONFIG_NVMEM_STM32_ROMEM=y
+
+#
+# STM32 HSEM
@ -529,59 +743,6 @@ index 0000000000000..5fd995006583f
+CONFIG_STM32_IPCC=y
+
+#
+# STM32 RPROC
+#
+CONFIG_REMOTEPROC=y
+CONFIG_STM32_RPROC=y
+CONFIG_RPMSG_VIRTIO=y
+
+#
+# RPMSG_TTY
+#
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_RPMSG_TTY=y
+
+#
+# RPMSG client sample
+#
+CONFIG_SAMPLES=y
+CONFIG_SAMPLE_RPMSG_CLIENT=m
+
+#
+# STM32 TIMER
+#
+CONFIG_MFD_STM32_TIMERS=y
+CONFIG_IIO_STM32_TIMER_TRIGGER=y
+CONFIG_PWM_STM32=y
+CONFIG_COUNTER=y
+CONFIG_STM32_TIMER_CNT=y
+
+#
+# STM32 LPTIMER
+#
+CONFIG_MFD_STM32_LPTIMER=y
+CONFIG_PWM_STM32_LP=y
+CONFIG_IIO_STM32_LPTIMER_TRIGGER=y
+CONFIG_STM32_LPTIMER_CNT=y
+CONFIG_CLKSRC_STM32_LP=y
+
+#
+# STM32 ADC
+#
+CONFIG_STM32_ADC_CORE=y
+CONFIG_STM32_ADC=y
+
+#
+# STM32 DAC
+#
+CONFIG_STM32_DAC=y
+
+#
+# STM32 VREFBUF
+#
+CONFIG_REGULATOR_STM32_VREFBUF=y
+
+#
+# SCMI
+#
+CONFIG_ARM_SCMI_PROTOCOL=y
@ -594,10 +755,21 @@ index 0000000000000..5fd995006583f
+CONFIG_LEGACY_PTY_COUNT=8
+
+#
+# FMC EBI
+# STM32 BSEC NVMEM
+#
+CONFIG_MEMORY=y
+CONFIG_STM32_FMC2_EBI=y
+CONFIG_NVMEM_STM32_ROMEM=y
+
+#
+# RPMSG client sample
+#
+CONFIG_SAMPLES=y
+CONFIG_SAMPLE_RPMSG_CLIENT=m
+
+#
+# REBOOT
+#
+CONFIG_REBOOT_MODE=y
+CONFIG_SYSCON_REBOOT_MODE=y
+
+#
+# STM32 CPUIDLE
@ -605,18 +777,48 @@ index 0000000000000..5fd995006583f
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_STM32_CPUIDLE=y
+CONFIG_ARM_CPUIDLE=n
+
+#
+# STM32 TIMER
+#
+CONFIG_COUNTER=m
+CONFIG_STM32_TIMER_CNT=m
+
+#
+# STM32 LPTIMER
+#
+CONFIG_MFD_STM32_LPTIMER=y
+CONFIG_STM32_LPTIMER_CNT=m
+CONFIG_CLKSRC_STM32_LP=y
+
+#
+# TEE drivers
+#
+CONFIG_TEE=y
+CONFIG_OPTEE=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index e4c8def9a0a57..4231ad37ea3bc 100644
index a611b0c1e540..abf1b17cb03a 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1038,6 +1038,7 @@ CONFIG_TI_PIPE3=y
CONFIG_TWL4030_USB=m
CONFIG_MESON_MX_EFUSE=m
CONFIG_ROCKCHIP_EFUSE=m
+CONFIG_STM32_DDR_PMU=y
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_NVMEM_VF610_OCOTP=y
@@ -829,6 +829,8 @@ CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_CONFIGFS_F_PRINTER=y
CONFIG_USB_ETH=m
+CONFIG_TYPEC=m
+CONFIG_TYPEC_STUSB160X=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16
CONFIG_MMC_ARMMMCI=y
@@ -1133,6 +1135,9 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=m
CONFIG_CRYPTO_DEV_ATMEL_TDES=m
CONFIG_CRYPTO_DEV_ATMEL_SHA=m
CONFIG_CRYPTO_DEV_ROCKCHIP=m
+CONFIG_CRYPTO_DEV_STM32_CRC=m
+CONFIG_CRYPTO_DEV_STM32_HASH=m
+CONFIG_CRYPTO_DEV_STM32_CRYP=m
CONFIG_CMA_SIZE_MBYTES=64
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
--
2.17.1

View File

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

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"
SECTION = "kernel"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
#LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
include linux-stm32mp.inc
LINUX_VERSION = "5.4"
LINUX_SUBVERSION = "56"
LINUX_VERSION = "5.10"
LINUX_SUBVERSION = "10"
SRC_URI = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}.tar.xz;name=kernel"
SRC_URI[kernel.sha256sum] = "318390b98480ec5663ed8403fca764b07924c5d2d6411de62c4241b4d9c57cad"
#SRC_URI = "https://git.kernel.org/torvalds/t/linux-${LINUX_VERSION}-${LINUX_SUBVERSION}.tar.gz;name=kernel"
SRC_URI[kernel.sha256sum] = "60ed866fa951522a5255ea37ec3ac2006d3f3427d4783a13ef478464f37cdb19"
SRC_URI += " \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-ARM-stm32mp1-r2-MACHINE.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0002-ARM-stm32mp1-r2-CPUFREQ.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0003-ARM-stm32mp1-r2-CRYPTO.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0004-ARM-stm32mp1-r2-RNG-DEBUG-NVMEM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0005-ARM-stm32mp1-r2-CLOCK.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0006-ARM-stm32mp1-r2-DMA.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0007-ARM-stm32mp1-r2-DRM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0008-ARM-stm32mp1-r2-HWSPINLOCK.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0009-ARM-stm32mp1-r2-I2C-IIO-IRQCHIP.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0010-ARM-stm32mp1-r2-MAILBOX-REMOTEPROC-RPMSG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0011-ARM-stm32mp1-r2-RESET-RTC-WATCHDOG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0012-ARM-stm32mp1-r2-MEDIA-SOC-THERMAL.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0013-ARM-stm32mp1-r2-MFD.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0014-ARM-stm32mp1-r2-MMC-NAND.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0015-ARM-stm32mp1-r2-NET-TTY.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0016-ARM-stm32mp1-r2-PHY-USB.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0017-ARM-stm32mp1-r2-PINCTRL-REGULATOR-SPI-PWM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0018-ARM-stm32mp1-r2-SOUND.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0019-ARM-stm32mp1-r2-MISC-CPUIDLE-MM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0020-ARM-stm32mp1-r2-DEVICETREE.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0021-ARM-stm32mp1-r2-CONFIG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-ARM-stm32mp1-r2-PERF.patch \
"
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-ARM-5.10.10-stm32mp1-r1-MACHINE.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0002-ARM-5.10.10-stm32mp1-r1-CLOCK.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0003-ARM-5.10.10-stm32mp1-r1-CPUFREQ.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0004-ARM-5.10.10-stm32mp1-r1-CRYPTO.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0005-ARM-5.10.10-stm32mp1-r1-DMA.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0006-ARM-5.10.10-stm32mp1-r1-DRM.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0007-ARM-5.10.10-stm32mp1-r1-HWSPINLOCK.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0008-ARM-5.10.10-stm32mp1-r1-I2C-IIO-IRQCHIP.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0009-ARM-5.10.10-stm32mp1-r1-MAILBOX-REMOTEPROC-RPMSG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0010-ARM-5.10.10-stm32mp1-r1-MEDIA-SOC-THERMAL.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0011-ARM-5.10.10-stm32mp1-r1-MFD.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0012-ARM-5.10.10-stm32mp1-r1-MMC.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0013-ARM-5.10.10-stm32mp1-r1-NET-TTY.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0014-ARM-5.10.10-stm32mp1-r1-PERF.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0015-ARM-5.10.10-stm32mp1-r1-PHY-USB.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0016-ARM-5.10.10-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0017-ARM-5.10.10-stm32mp1-r1-RESET-RTC-WATCHDOG.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0018-ARM-5.10.10-stm32mp1-r1-SCMI.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0019-ARM-5.10.10-stm32mp1-r1-SOUND.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0020-ARM-5.10.10-stm32mp1-r1-MISC-CPUIDLE-POWER.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0021-ARM-5.10.10-stm32mp1-r1-DEVICETREE.patch \
file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-ARM-5.10.10-stm32mp1-r1-CONFIG.patch \
"
PV = "${LINUX_VERSION}.${LINUX_SUBVERSION}"
S = "${WORKDIR}/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}"
#S = "${WORKDIR}/linux-${LINUX_VERSION}-${LINUX_SUBVERSION}"
#S = "${WORKDIR}/linux-${LINUX_VERSION}"
# ---------------------------------
# Configure devupstream class usage
@ -45,7 +50,7 @@ S = "${WORKDIR}/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}"
BBCLASSEXTEND = "devupstream:target"
SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/linux.git;protocol=https;branch=v${LINUX_VERSION}-stm32mp"
SRCREV_class-devupstream = "a56628a8ab25734a771086664cc80c215a198438"
SRCREV_class-devupstream = "ce6891abb1c895d4849e6f784615687341b3dbde"
# ---------------------------------
# Configure default preference to manage dynamic selection between tarball and github
@ -65,21 +70,18 @@ include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'linux-stm32mp
KERNEL_DEFCONFIG = "defconfig"
KERNEL_CONFIG_FRAGMENTS = "${@bb.utils.contains('KERNEL_DEFCONFIG', 'defconfig', '${S}/arch/arm/configs/fragment-01-multiv7_cleanup.config', '', d)}"
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('KERNEL_DEFCONFIG', 'defconfig', '${S}/arch/arm/configs/fragment-02-multiv7_addons.config', '', d)}"
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${WORKDIR}/fragments/5.4/fragment-03-systemd.config', '', d)} "
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('COMBINED_FEATURES', 'optee', '${WORKDIR}/fragments/5.4/fragment-04-optee.config', '', d)}"
KERNEL_CONFIG_FRAGMENTS += "${WORKDIR}/fragments/5.4/fragment-05-modules.config"
KERNEL_CONFIG_FRAGMENTS += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', '${WORKDIR}/fragments/5.4/fragment-06-signature.config','')} "
KERNEL_CONFIG_FRAGMENTS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${WORKDIR}/fragments/${LINUX_VERSION}/fragment-03-systemd.config', '', d)} "
KERNEL_CONFIG_FRAGMENTS += "${WORKDIR}/fragments/${LINUX_VERSION}/fragment-04-modules.config"
KERNEL_CONFIG_FRAGMENTS += "${@oe.utils.ifelse(d.getVar('KERNEL_SIGN_ENABLE') == '1', '${WORKDIR}/fragments/${LINUX_VERSION}/fragment-05-signature.config','')} "
SRC_URI += "file://${LINUX_VERSION}/fragment-03-systemd.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-04-optee.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-06-signature.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-04-modules.config;subdir=fragments"
SRC_URI += "file://${LINUX_VERSION}/fragment-05-signature.config;subdir=fragments"
# Don't forget to add/del for devupstream
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-03-systemd.config;subdir=fragments"
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-04-optee.config;subdir=fragments"
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-05-modules.config;subdir=fragments"
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-06-signature.config;subdir=fragments"
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-04-modules.config;subdir=fragments"
SRC_URI_class-devupstream += "file://${LINUX_VERSION}/fragment-05-signature.config;subdir=fragments"
# -------------------------------------------------------------
# Kernel Args