From efe2f89975c08f94c7674f9f83a115a372ab97b1 Mon Sep 17 00:00:00 2001 From: Sebastien GANDON Date: Thu, 30 Jun 2022 11:09:27 +0200 Subject: [PATCH] LINUX-STM32MP: v5.15-stm32mp-r2 Signed-off-by: Romuald JEANNE Change-Id: I908051bb3c17f9c36e163f1459cdbdafac725d20 --- .../0004-ARM-5.15.24-stm32mp1-r1-CRYPTO.patch | 1539 --------- .../0012-ARM-5.15.24-stm32mp1-r1-MMC.patch | 114 - ...24-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch | 1703 ---------- .../0001-v5.15-stm32mp-r2-MACHINE.patch} | 22 +- .../0002-v5.15-stm32mp-r2-CLOCK.patch} | 2246 +++++++++++- .../0003-v5.15-stm32mp-r2-CPUFREQ.patch} | 99 +- ...0004-v5.15-stm32mp-r2-CPUIDLE-POWER.patch} | 99 +- .../0005-v5.15-stm32mp-r2-CRYPTO.patch | 2687 +++++++++++++++ .../0006-v5.15-stm32mp-r2-DMA.patch} | 116 +- .../0007-v5.15-stm32mp-r2-DRM.patch} | 840 +++-- .../0008-v5.15-stm32mp-r2-HWSPINLOCK.patch} | 24 +- ...09-v5.15-stm32mp-r2-I2C-IIO-IRQCHIP.patch} | 1562 +++++++-- ...0-v5.15-stm32mp-r2-REMOTEPROC-RPMSG.patch} | 1530 ++++++--- ...5-stm32mp-r2-MISC-MEDIA-SOC-THERMAL.patch} | 1292 ++++--- .../0012-v5.15-stm32mp-r2-MFD.patch} | 30 +- .../5.15.67/0013-v5.15-stm32mp-r2-MMC.patch | 341 ++ .../0014-v5.15-stm32mp-r2-NET-TTY.patch} | 714 +++- .../0015-v5.15-stm32mp-r2-PERF.patch} | 24 +- .../0016-v5.15-stm32mp-r2-PHY-USB.patch} | 208 +- ....15-stm32mp-r2-PINCTRL-REGULATOR-SPI.patch | 3016 +++++++++++++++++ .../0018-v5.15-stm32mp-r2-RESET-RTC.patch} | 24 +- .../0019-v5.15-stm32mp-r2-SCMI.patch} | 32 +- .../0020-v5.15-stm32mp-r2-SOUND.patch} | 68 +- .../0021-v5.15-stm32mp-r2-DEVICETREE.patch} | 2666 +++++++++------ .../0022-v5.15-stm32mp-r2-CONFIG.patch} | 31 +- .../5.15/fragment-04-modules.config | 1 - recipes-kernel/linux/linux-stm32mp_5.15.bb | 52 +- 27 files changed, 14680 insertions(+), 6400 deletions(-) delete mode 100644 recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0004-ARM-5.15.24-stm32mp1-r1-CRYPTO.patch delete mode 100644 recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0012-ARM-5.15.24-stm32mp1-r1-MMC.patch delete mode 100644 recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0016-ARM-5.15.24-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0001-ARM-5.15.24-stm32mp1-r1-MACHINE.patch => 5.15.67/0001-v5.15-stm32mp-r2-MACHINE.patch} (87%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0002-ARM-5.15.24-stm32mp1-r1-CLOCK.patch => 5.15.67/0002-v5.15-stm32mp-r2-CLOCK.patch} (72%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0003-ARM-5.15.24-stm32mp1-r1-CPUFREQ.patch => 5.15.67/0003-v5.15-stm32mp-r2-CPUFREQ.patch} (62%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0020-ARM-5.15.24-stm32mp1-r1-CPUIDLE-POWER.patch => 5.15.67/0004-v5.15-stm32mp-r2-CPUIDLE-POWER.patch} (75%) create mode 100644 recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0005-v5.15-stm32mp-r2-CRYPTO.patch rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0005-ARM-5.15.24-stm32mp1-r1-DMA.patch => 5.15.67/0006-v5.15-stm32mp-r2-DMA.patch} (95%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0006-ARM-5.15.24-stm32mp1-r1-DRM.patch => 5.15.67/0007-v5.15-stm32mp-r2-DRM.patch} (76%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0007-ARM-5.15.24-stm32mp1-r1-HWSPINLOCK.patch => 5.15.67/0008-v5.15-stm32mp-r2-HWSPINLOCK.patch} (96%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0008-ARM-5.15.24-stm32mp1-r1-I2C-IIO-IRQCHIP.patch => 5.15.67/0009-v5.15-stm32mp-r2-I2C-IIO-IRQCHIP.patch} (66%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0009-ARM-5.15.24-stm32mp1-r1-REMOTEPROC-RPMSG.patch => 5.15.67/0010-v5.15-stm32mp-r2-REMOTEPROC-RPMSG.patch} (82%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0010-ARM-5.15.24-stm32mp1-r1-MISC-MEDIA-SOC-THERMAL.patch => 5.15.67/0011-v5.15-stm32mp-r2-MISC-MEDIA-SOC-THERMAL.patch} (89%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0011-ARM-5.15.24-stm32mp1-r1-MFD.patch => 5.15.67/0012-v5.15-stm32mp-r2-MFD.patch} (96%) create mode 100644 recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0013-v5.15-stm32mp-r2-MMC.patch rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0013-ARM-5.15.24-stm32mp1-r1-NET-TTY.patch => 5.15.67/0014-v5.15-stm32mp-r2-NET-TTY.patch} (73%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0014-ARM-5.15.24-stm32mp1-r1-PERF.patch => 5.15.67/0015-v5.15-stm32mp-r2-PERF.patch} (97%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0015-ARM-5.15.24-stm32mp1-r1-PHY-USB.patch => 5.15.67/0016-v5.15-stm32mp-r2-PHY-USB.patch} (92%) create mode 100644 recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0017-v5.15-stm32mp-r2-PINCTRL-REGULATOR-SPI.patch rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0017-ARM-5.15.24-stm32mp1-r1-RESET-RTC.patch => 5.15.67/0018-v5.15-stm32mp-r2-RESET-RTC.patch} (98%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0018-ARM-5.15.24-stm32mp1-r1-SCMI.patch => 5.15.67/0019-v5.15-stm32mp-r2-SCMI.patch} (97%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0019-ARM-5.15.24-stm32mp1-r1-SOUND.patch => 5.15.67/0020-v5.15-stm32mp-r2-SOUND.patch} (82%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0021-ARM-5.15.24-stm32mp1-r1-DEVICETREE.patch => 5.15.67/0021-v5.15-stm32mp-r2-DEVICETREE.patch} (87%) rename recipes-kernel/linux/linux-stm32mp/5.15/{5.15.24/0022-ARM-5.15.24-stm32mp1-r1-CONFIG.patch => 5.15.67/0022-v5.15-stm32mp-r2-CONFIG.patch} (96%) diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0004-ARM-5.15.24-stm32mp1-r1-CRYPTO.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0004-ARM-5.15.24-stm32mp1-r1-CRYPTO.patch deleted file mode 100644 index 257f76e..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0004-ARM-5.15.24-stm32mp1-r1-CRYPTO.patch +++ /dev/null @@ -1,1539 +0,0 @@ -From a3e88eba0837217682d75a26b81498d6476d0cc2 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:51:37 +0200 -Subject: [PATCH 04/22] ARM-5.15.24-stm32mp1-r1-CRYPTO - -Signed-off-by: Christophe Priouzeau ---- - drivers/crypto/stm32/stm32-cryp.c | 50 +- - drivers/crypto/stm32/stm32-hash.c | 839 ++++++++++++++++++++++-------- - 2 files changed, 662 insertions(+), 227 deletions(-) - -diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c -index 81eb136b6..59ef54112 100644 ---- a/drivers/crypto/stm32/stm32-cryp.c -+++ b/drivers/crypto/stm32/stm32-cryp.c -@@ -232,6 +232,11 @@ static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp) - !(status & SR_BUSY), 10, 100000); - } - -+static inline void stm32_cryp_enable(struct stm32_cryp *cryp) -+{ -+ writel_relaxed(readl_relaxed(cryp->regs + CRYP_CR) | CR_CRYPEN, cryp->regs + CRYP_CR); -+} -+ - static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp) - { - u32 status; -@@ -535,9 +540,6 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) - /* Disable interrupt */ - stm32_cryp_write(cryp, CRYP_IMSCR, 0); - -- /* Set key */ -- stm32_cryp_hw_write_key(cryp); -- - /* Set configuration */ - cfg = CR_DATA8 | CR_FFLUSH; - -@@ -563,23 +565,36 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) - /* AES ECB/CBC decrypt: run key preparation first */ - if (is_decrypt(cryp) && - ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) { -- stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP | CR_CRYPEN); -+ /* Configure in key preparation mode */ -+ stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP); -+ -+ /* Set key only after full configuration done */ -+ stm32_cryp_hw_write_key(cryp); - -+ /* Start prepare key */ -+ stm32_cryp_enable(cryp); - /* Wait for end of processing */ - ret = stm32_cryp_wait_busy(cryp); - if (ret) { - dev_err(cryp->dev, "Timeout (key preparation)\n"); - return ret; - } -- } - -- cfg |= hw_mode; -+ cfg |= hw_mode | CR_DEC_NOT_ENC; - -- if (is_decrypt(cryp)) -- cfg |= CR_DEC_NOT_ENC; -+ /* Apply updated config (Decrypt + algo) and flush */ -+ stm32_cryp_write(cryp, CRYP_CR, cfg); -+ } else { -+ cfg |= hw_mode; -+ if (is_decrypt(cryp)) -+ cfg |= CR_DEC_NOT_ENC; - -- /* Apply config and flush (valid when CRYPEN = 0) */ -- stm32_cryp_write(cryp, CRYP_CR, cfg); -+ /* Apply config and flush */ -+ stm32_cryp_write(cryp, CRYP_CR, cfg); -+ -+ /* Set key only after configuration done */ -+ stm32_cryp_hw_write_key(cryp); -+ } - - switch (hw_mode) { - case CR_AES_GCM: -@@ -607,9 +622,7 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) - } - - /* Enable now */ -- cfg |= CR_CRYPEN; -- -- stm32_cryp_write(cryp, CRYP_CR, cfg); -+ stm32_cryp_enable(cryp); - - return 0; - } -@@ -1761,7 +1774,8 @@ static int stm32_cryp_probe(struct platform_device *pdev) - - cryp->clk = devm_clk_get(dev, NULL); - if (IS_ERR(cryp->clk)) { -- dev_err(dev, "Could not get clock\n"); -+ dev_err_probe(dev, PTR_ERR(cryp->clk), "Could not get clock\n"); -+ - return PTR_ERR(cryp->clk); - } - -@@ -1779,7 +1793,11 @@ static int stm32_cryp_probe(struct platform_device *pdev) - pm_runtime_enable(dev); - - rst = devm_reset_control_get(dev, NULL); -- if (!IS_ERR(rst)) { -+ if (IS_ERR(rst)) { -+ ret = PTR_ERR(rst); -+ if (ret == -EPROBE_DEFER) -+ goto err_rst; -+ } else { - reset_control_assert(rst); - udelay(2); - reset_control_deassert(rst); -@@ -1830,7 +1848,7 @@ static int stm32_cryp_probe(struct platform_device *pdev) - spin_lock(&cryp_list.lock); - list_del(&cryp->list); - spin_unlock(&cryp_list.lock); -- -+err_rst: - pm_runtime_disable(dev); - pm_runtime_put_noidle(dev); - -diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c -index d33006d43..383324f5f 100644 ---- a/drivers/crypto/stm32/stm32-hash.c -+++ b/drivers/crypto/stm32/stm32-hash.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - - #define HASH_CR 0x00 -@@ -49,11 +50,6 @@ - #define HASH_CR_DMAA BIT(14) - #define HASH_CR_LKEY BIT(16) - --#define HASH_CR_ALGO_SHA1 0x0 --#define HASH_CR_ALGO_MD5 0x80 --#define HASH_CR_ALGO_SHA224 0x40000 --#define HASH_CR_ALGO_SHA256 0x40080 -- - /* Interrupt */ - #define HASH_DINIE BIT(0) - #define HASH_DCIE BIT(1) -@@ -62,9 +58,6 @@ - #define HASH_MASK_CALC_COMPLETION BIT(0) - #define HASH_MASK_DATA_INPUT BIT(1) - --/* Context swap register */ --#define HASH_CSR_REGISTER_NUMBER 53 -- - /* Status Flags */ - #define HASH_SR_DATA_INPUT_READY BIT(0) - #define HASH_SR_OUTPUT_READY BIT(1) -@@ -75,6 +68,17 @@ - #define HASH_STR_NBLW_MASK GENMASK(4, 0) - #define HASH_STR_DCAL BIT(8) - -+/* HWCFGR Register */ -+#define HASH_HWCFG_DMA_MASK GENMASK(3, 0) -+ -+/* CSR register */ -+#define HASH_CSR_NB_SHA256_HMAC 54 -+#define HASH_CSR_NB_SHA256 22 -+#define HASH_CSR_NB_SHA512_HMAC 103 -+#define HASH_CSR_NB_SHA512 91 -+#define HASH_CSR_NB_SHA3_HMAC 88 -+#define HASH_CSR_NB_SHA3 72 -+ - #define HASH_FLAGS_INIT BIT(0) - #define HASH_FLAGS_OUTPUT_READY BIT(1) - #define HASH_FLAGS_CPU BIT(2) -@@ -83,20 +87,19 @@ - #define HASH_FLAGS_HMAC_INIT BIT(5) - #define HASH_FLAGS_HMAC_FINAL BIT(6) - #define HASH_FLAGS_HMAC_KEY BIT(7) -- -+#define HASH_FLAGS_SHA3_MODE BIT(8) - #define HASH_FLAGS_FINAL BIT(15) - #define HASH_FLAGS_FINUP BIT(16) --#define HASH_FLAGS_ALGO_MASK GENMASK(21, 18) --#define HASH_FLAGS_MD5 BIT(18) --#define HASH_FLAGS_SHA1 BIT(19) --#define HASH_FLAGS_SHA224 BIT(20) --#define HASH_FLAGS_SHA256 BIT(21) --#define HASH_FLAGS_ERRORS BIT(22) --#define HASH_FLAGS_HMAC BIT(23) -+#define HASH_FLAGS_ALGO_MASK GENMASK(20, 17) -+#define HASH_FLAGS_ALGO_SHIFT 17 -+#define HASH_FLAGS_ERRORS BIT(21) -+#define HASH_FLAGS_HMAC BIT(22) - - #define HASH_OP_UPDATE 1 - #define HASH_OP_FINAL 2 - -+#define HASH_BURST_LEVEL 4 -+ - enum stm32_hash_data_format { - HASH_DATA_32_BITS = 0x0, - HASH_DATA_16_BITS = 0x1, -@@ -104,17 +107,26 @@ enum stm32_hash_data_format { - HASH_DATA_1_BIT = 0x3 - }; - --#define HASH_BUFLEN 256 --#define HASH_LONG_KEY 64 --#define HASH_MAX_KEY_SIZE (SHA256_BLOCK_SIZE * 8) --#define HASH_QUEUE_LENGTH 16 --#define HASH_DMA_THRESHOLD 50 -+enum stm32_hash_algo { -+ HASH_SHA1 = 0, -+ HASH_MD5 = 1, -+ HASH_SHA224 = 2, -+ HASH_SHA256 = 3, -+ HASH_SHA3_224 = 4, -+ HASH_SHA3_256 = 5, -+ HASH_SHA3_384 = 6, -+ HASH_SHA3_512 = 7, -+ HASH_SHA384 = 12, -+ HASH_SHA512 = 15, -+}; - -+#define HASH_MAX_BUFLEN (SHA3_224_BLOCK_SIZE + 4) -+#define HASH_MAX_KEY_SIZE (SHA512_BLOCK_SIZE * 8) -+#define HASH_QUEUE_LENGTH 60 - #define HASH_AUTOSUSPEND_DELAY 50 - - struct stm32_hash_ctx { - struct crypto_engine_ctx enginectx; -- struct stm32_hash_dev *hdev; - unsigned long flags; - - u8 key[HASH_MAX_KEY_SIZE]; -@@ -126,8 +138,7 @@ struct stm32_hash_request_ctx { - unsigned long flags; - unsigned long op; - -- u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32)); -- size_t digcnt; -+ u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32)); - size_t bufcnt; - size_t buflen; - -@@ -143,7 +154,7 @@ struct stm32_hash_request_ctx { - - u8 data_type; - -- u8 buffer[HASH_BUFLEN] __aligned(sizeof(u32)); -+ u8 buffer[HASH_MAX_BUFLEN] __aligned(sizeof(u32)); - - /* Export Context */ - u32 *hw_context; -@@ -155,8 +166,9 @@ struct stm32_hash_algs_info { - }; - - struct stm32_hash_pdata { -- struct stm32_hash_algs_info *algs_info; -- size_t algs_info_size; -+ const int alg_shift; -+ const struct stm32_hash_algs_info *algs_info; -+ size_t algs_info_size; - }; - - struct stm32_hash_dev { -@@ -167,10 +179,10 @@ struct stm32_hash_dev { - void __iomem *io_base; - phys_addr_t phys_base; - u32 dma_mode; -- u32 dma_maxburst; - - struct ahash_request *req; - struct crypto_engine *engine; -+ struct crypto_queue queue; - - int err; - unsigned long flags; -@@ -212,11 +224,18 @@ static inline int stm32_hash_wait_busy(struct stm32_hash_dev *hdev) - !(status & HASH_SR_BUSY), 10, 10000); - } - -+static inline int stm32_hash_wait_dinis(struct stm32_hash_dev *hdev) -+{ -+ u32 status; -+ -+ return readl_relaxed_poll_timeout(hdev->io_base + HASH_SR, status, -+ (status & HASH_SR_DATA_INPUT_READY), 10, 10000); -+} -+ - static void stm32_hash_set_nblw(struct stm32_hash_dev *hdev, int length) - { -- u32 reg; -+ u32 reg = stm32_hash_read(hdev, HASH_STR); - -- reg = stm32_hash_read(hdev, HASH_STR); - reg &= ~(HASH_STR_NBLW_MASK); - reg |= (8U * ((length) % 4U)); - stm32_hash_write(hdev, HASH_STR, reg); -@@ -254,44 +273,32 @@ static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev) - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); - struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); -- -+ u32 alg = (rctx->flags & HASH_FLAGS_ALGO_MASK) >> HASH_FLAGS_ALGO_SHIFT; - u32 reg = HASH_CR_INIT; - -- if (!(hdev->flags & HASH_FLAGS_INIT)) { -- switch (rctx->flags & HASH_FLAGS_ALGO_MASK) { -- case HASH_FLAGS_MD5: -- reg |= HASH_CR_ALGO_MD5; -- break; -- case HASH_FLAGS_SHA1: -- reg |= HASH_CR_ALGO_SHA1; -- break; -- case HASH_FLAGS_SHA224: -- reg |= HASH_CR_ALGO_SHA224; -- break; -- case HASH_FLAGS_SHA256: -- reg |= HASH_CR_ALGO_SHA256; -- break; -- default: -- reg |= HASH_CR_ALGO_MD5; -- } -+ if (hdev->pdata->alg_shift == 7) -+ reg |= ((alg & BIT(1)) << 17) | ((alg & BIT(0)) << 7); -+ else -+ reg |= alg << hdev->pdata->alg_shift; - -- reg |= (rctx->data_type << HASH_CR_DATATYPE_POS); -+ reg |= (rctx->data_type << HASH_CR_DATATYPE_POS); - -- if (rctx->flags & HASH_FLAGS_HMAC) { -- hdev->flags |= HASH_FLAGS_HMAC; -- reg |= HASH_CR_MODE; -- if (ctx->keylen > HASH_LONG_KEY) -- reg |= HASH_CR_LKEY; -- } -+ if (rctx->flags & HASH_FLAGS_HMAC) { -+ hdev->flags |= HASH_FLAGS_HMAC; -+ reg |= HASH_CR_MODE; -+ if (ctx->keylen > (rctx->buflen - sizeof(uint32_t))) -+ reg |= HASH_CR_LKEY; -+ } - -- stm32_hash_write(hdev, HASH_IMR, HASH_DCIE); -+ stm32_hash_write(hdev, HASH_IMR, HASH_DCIE); -+ stm32_hash_write(hdev, HASH_CR, reg); -+ stm32_hash_read(hdev, HASH_SR); - -- stm32_hash_write(hdev, HASH_CR, reg); -+ hdev->flags |= HASH_FLAGS_INIT; - -- hdev->flags |= HASH_FLAGS_INIT; -+ dev_dbg(hdev->dev, "Write Control %x\n", reg); - -- dev_dbg(hdev->dev, "Write Control %x\n", reg); -- } -+ rctx->buflen = rctx->buflen - sizeof(uint32_t); - } - - static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) -@@ -328,11 +335,12 @@ static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) - } - } - --static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, -- const u8 *buf, size_t length, int final) -+static int stm32_hash_xmit_cpu(struct stm32_hash_request_ctx *rctx, -+ size_t length, int final) - { -+ const u32 *buffer = (const u32 *)rctx->buffer; -+ struct stm32_hash_dev *hdev = rctx->hdev; - unsigned int count, len32; -- const u32 *buffer = (const u32 *)buf; - u32 reg; - - if (final) -@@ -345,10 +353,8 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, - - hdev->flags |= HASH_FLAGS_CPU; - -- stm32_hash_write_ctrl(hdev); -- -- if (stm32_hash_wait_busy(hdev)) -- return -ETIMEDOUT; -+ if (!(hdev->flags & HASH_FLAGS_INIT)) -+ stm32_hash_write_ctrl(hdev); - - if ((hdev->flags & HASH_FLAGS_HMAC) && - (!(hdev->flags & HASH_FLAGS_HMAC_KEY))) { -@@ -371,6 +377,7 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, - return -ETIMEDOUT; - stm32_hash_write_key(hdev); - } -+ - return -EINPROGRESS; - } - -@@ -386,12 +393,12 @@ static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev) - - final = (rctx->flags & HASH_FLAGS_FINUP); - -- while ((rctx->total >= rctx->buflen) || -- (rctx->bufcnt + rctx->total >= rctx->buflen)) { -+ while ((rctx->total > rctx->buflen) || -+ (rctx->bufcnt + rctx->total > rctx->buflen)) { - stm32_hash_append_sg(rctx); - bufcnt = rctx->bufcnt; - rctx->bufcnt = 0; -- err = stm32_hash_xmit_cpu(hdev, rctx->buffer, bufcnt, 0); -+ err = stm32_hash_xmit_cpu(rctx, bufcnt, 0); - } - - stm32_hash_append_sg(rctx); -@@ -399,7 +406,7 @@ static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev) - if (final) { - bufcnt = rctx->bufcnt; - rctx->bufcnt = 0; -- err = stm32_hash_xmit_cpu(hdev, rctx->buffer, bufcnt, -+ err = stm32_hash_xmit_cpu(rctx, bufcnt, - (rctx->flags & HASH_FLAGS_FINUP)); - } - -@@ -482,7 +489,7 @@ static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev) - struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); - int err; - -- if (ctx->keylen < HASH_DMA_THRESHOLD || (hdev->dma_mode == 1)) { -+ if (ctx->keylen < rctx->buflen || (hdev->dma_mode == 1)) { - err = stm32_hash_write_key(hdev); - if (stm32_hash_wait_busy(hdev)) - return -ETIMEDOUT; -@@ -517,8 +524,8 @@ static int stm32_hash_dma_init(struct stm32_hash_dev *hdev) - dma_conf.direction = DMA_MEM_TO_DEV; - dma_conf.dst_addr = hdev->phys_base + HASH_DIN; - dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -- dma_conf.src_maxburst = hdev->dma_maxburst; -- dma_conf.dst_maxburst = hdev->dma_maxburst; -+ dma_conf.src_maxburst = HASH_BURST_LEVEL; -+ dma_conf.dst_maxburst = HASH_BURST_LEVEL; - dma_conf.device_fc = false; - - chan = dma_request_chan(hdev->dev, "in"); -@@ -552,11 +559,11 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) - rctx->total = hdev->req->nbytes; - - rctx->nents = sg_nents(rctx->sg); -- - if (rctx->nents < 0) - return -EINVAL; - -- stm32_hash_write_ctrl(hdev); -+ if (!(hdev->flags & HASH_FLAGS_INIT)) -+ stm32_hash_write_ctrl(hdev); - - if (hdev->flags & HASH_FLAGS_HMAC) { - err = stm32_hash_hmac_dma_send(hdev); -@@ -633,21 +640,17 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) - return err; - } - --static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx) -+static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_request_ctx *rctx) - { -- struct stm32_hash_dev *hdev = NULL, *tmp; -+ struct stm32_hash_dev *hdev = NULL; - -- spin_lock_bh(&stm32_hash.lock); -- if (!ctx->hdev) { -- list_for_each_entry(tmp, &stm32_hash.dev_list, list) { -- hdev = tmp; -- break; -- } -- ctx->hdev = hdev; -- } else { -- hdev = ctx->hdev; -- } -+ if (rctx->hdev) -+ return rctx->hdev; - -+ spin_lock_bh(&stm32_hash.lock); -+ hdev = list_first_entry(&stm32_hash.dev_list, struct stm32_hash_dev, list); -+ list_move_tail(&hdev->list, &stm32_hash.dev_list); -+ rctx->hdev = hdev; - spin_unlock_bh(&stm32_hash.lock); - - return hdev; -@@ -656,16 +659,17 @@ static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx) - static bool stm32_hash_dma_aligned_data(struct ahash_request *req) - { - struct scatterlist *sg; -- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); -- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); -+ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -+ struct stm32_hash_dev *hdev = rctx->hdev; - int i; - -- if (req->nbytes <= HASH_DMA_THRESHOLD) -+ if ((!hdev->dma_lch) || (req->nbytes <= rctx->buflen)) - return false; - - if (sg_nents(req->src) > 1) { - if (hdev->dma_mode == 1) - return false; -+ - for_each_sg(req->src, sg, sg_nents(req->src), i) { - if ((!IS_ALIGNED(sg->length, sizeof(u32))) && - (!sg_is_last(sg))) -@@ -684,37 +688,61 @@ static int stm32_hash_init(struct ahash_request *req) - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); -+ struct stm32_hash_dev *hdev; -+ bool sha3_mode = ctx->flags & HASH_FLAGS_SHA3_MODE; - -- rctx->hdev = hdev; -+ rctx->hdev = NULL; -+ hdev = stm32_hash_find_dev(rctx); -+ if (!hdev) -+ return -ENODEV; - - rctx->flags = HASH_FLAGS_CPU; - -- rctx->digcnt = crypto_ahash_digestsize(tfm); -- switch (rctx->digcnt) { -+ if (sha3_mode) -+ rctx->flags |= HASH_FLAGS_SHA3_MODE; -+ -+ switch (crypto_ahash_digestsize(tfm)) { - case MD5_DIGEST_SIZE: -- rctx->flags |= HASH_FLAGS_MD5; -+ rctx->flags |= HASH_MD5 << HASH_FLAGS_ALGO_SHIFT; - break; - case SHA1_DIGEST_SIZE: -- rctx->flags |= HASH_FLAGS_SHA1; -+ rctx->flags |= HASH_SHA1 << HASH_FLAGS_ALGO_SHIFT; - break; - case SHA224_DIGEST_SIZE: -- rctx->flags |= HASH_FLAGS_SHA224; -+ if (sha3_mode) -+ rctx->flags |= HASH_SHA3_224 << HASH_FLAGS_ALGO_SHIFT; -+ else -+ rctx->flags |= HASH_SHA224 << HASH_FLAGS_ALGO_SHIFT; - break; - case SHA256_DIGEST_SIZE: -- rctx->flags |= HASH_FLAGS_SHA256; -+ if (sha3_mode) -+ rctx->flags |= HASH_SHA3_256 << HASH_FLAGS_ALGO_SHIFT; -+ else -+ rctx->flags |= HASH_SHA256 << HASH_FLAGS_ALGO_SHIFT; -+ break; -+ case SHA384_DIGEST_SIZE: -+ if (sha3_mode) -+ rctx->flags |= HASH_SHA3_384 << HASH_FLAGS_ALGO_SHIFT; -+ else -+ rctx->flags |= HASH_SHA384 << HASH_FLAGS_ALGO_SHIFT; -+ break; -+ case SHA512_DIGEST_SIZE: -+ if (sha3_mode) -+ rctx->flags |= HASH_SHA3_512 << HASH_FLAGS_ALGO_SHIFT; -+ else -+ rctx->flags |= HASH_SHA512 << HASH_FLAGS_ALGO_SHIFT; - break; - default: - return -EINVAL; - } - -+ rctx->buflen = crypto_ahash_blocksize(tfm) + sizeof(uint32_t); - rctx->bufcnt = 0; -- rctx->buflen = HASH_BUFLEN; - rctx->total = 0; - rctx->offset = 0; - rctx->data_type = HASH_DATA_8_BITS; - -- memset(rctx->buffer, 0, HASH_BUFLEN); -+ memset(rctx->buffer, 0, rctx->buflen); - - if (ctx->flags & HASH_FLAGS_HMAC) - rctx->flags |= HASH_FLAGS_HMAC; -@@ -741,8 +769,7 @@ static int stm32_hash_final_req(struct stm32_hash_dev *hdev) - if (!(rctx->flags & HASH_FLAGS_CPU)) - err = stm32_hash_dma_send(hdev); - else -- err = stm32_hash_xmit_cpu(hdev, rctx->buffer, buflen, 1); -- -+ err = stm32_hash_xmit_cpu(rctx, buflen, 1); - - return err; - } -@@ -750,39 +777,31 @@ static int stm32_hash_final_req(struct stm32_hash_dev *hdev) - static void stm32_hash_copy_hash(struct ahash_request *req) - { - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ unsigned int hashsize = crypto_ahash_digestsize(tfm); - __be32 *hash = (void *)rctx->digest; -- unsigned int i, hashsize; -- -- switch (rctx->flags & HASH_FLAGS_ALGO_MASK) { -- case HASH_FLAGS_MD5: -- hashsize = MD5_DIGEST_SIZE; -- break; -- case HASH_FLAGS_SHA1: -- hashsize = SHA1_DIGEST_SIZE; -- break; -- case HASH_FLAGS_SHA224: -- hashsize = SHA224_DIGEST_SIZE; -- break; -- case HASH_FLAGS_SHA256: -- hashsize = SHA256_DIGEST_SIZE; -- break; -- default: -- return; -- } -+ unsigned int i; -+ u32 reg; - - for (i = 0; i < hashsize / sizeof(u32); i++) - hash[i] = cpu_to_be32(stm32_hash_read(rctx->hdev, - HASH_HREG(i))); -+ -+ reg = stm32_hash_read(rctx->hdev, HASH_SR); -+ reg &= ~HASH_SR_OUTPUT_READY; -+ stm32_hash_write(rctx->hdev, HASH_SR, reg); - } - - static int stm32_hash_finish(struct ahash_request *req) - { - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ unsigned int digsize = crypto_ahash_digestsize(tfm); - - if (!req->result) - return -EINVAL; - -- memcpy(req->result, rctx->digest, rctx->digcnt); -+ memcpy(req->result, rctx->digest, digsize); - - return 0; - } -@@ -799,7 +818,7 @@ static void stm32_hash_finish_req(struct ahash_request *req, int err) - HASH_FLAGS_INIT | HASH_FLAGS_DMA_READY | - HASH_FLAGS_OUTPUT_READY | HASH_FLAGS_HMAC | - HASH_FLAGS_HMAC_INIT | HASH_FLAGS_HMAC_FINAL | -- HASH_FLAGS_HMAC_KEY); -+ HASH_FLAGS_HMAC_KEY | HASH_FLAGS_SHA3_MODE); - } else { - rctx->flags |= HASH_FLAGS_ERRORS; - } -@@ -810,8 +829,7 @@ static void stm32_hash_finish_req(struct ahash_request *req, int err) - crypto_finalize_hash_request(hdev->engine, req, err); - } - --static int stm32_hash_hw_init(struct stm32_hash_dev *hdev, -- struct stm32_hash_request_ctx *rctx) -+static int stm32_hash_hw_init(struct stm32_hash_dev *hdev) - { - pm_runtime_get_sync(hdev->dev); - -@@ -839,38 +857,30 @@ static int stm32_hash_prepare_req(struct crypto_engine *engine, void *areq) - { - struct ahash_request *req = container_of(areq, struct ahash_request, - base); -- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); -- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); -- struct stm32_hash_request_ctx *rctx; -- -- if (!hdev) -- return -ENODEV; -+ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -+ struct stm32_hash_dev *hdev = rctx->hdev; - - hdev->req = req; - -- rctx = ahash_request_ctx(req); -- - dev_dbg(hdev->dev, "processing new req, op: %lu, nbytes %d\n", - rctx->op, req->nbytes); - -- return stm32_hash_hw_init(hdev, rctx); -+ return stm32_hash_hw_init(hdev); - } - - static int stm32_hash_one_request(struct crypto_engine *engine, void *areq) - { - struct ahash_request *req = container_of(areq, struct ahash_request, - base); -- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); -- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); -- struct stm32_hash_request_ctx *rctx; -+ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -+ struct stm32_hash_dev *hdev = rctx->hdev; - int err = 0; - -- if (!hdev) -- return -ENODEV; -- - hdev->req = req; - -- rctx = ahash_request_ctx(req); -+ err = stm32_hash_hw_init(hdev); -+ if (err) -+ return err; - - if (rctx->op == HASH_OP_UPDATE) - err = stm32_hash_update_req(hdev); -@@ -887,8 +897,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq) - static int stm32_hash_enqueue(struct ahash_request *req, unsigned int op) - { - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -- struct stm32_hash_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -- struct stm32_hash_dev *hdev = ctx->hdev; -+ struct stm32_hash_dev *hdev = rctx->hdev; - - rctx->op = op; - -@@ -899,14 +908,16 @@ static int stm32_hash_update(struct ahash_request *req) - { - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); - -- if (!req->nbytes || !(rctx->flags & HASH_FLAGS_CPU)) -+ if ((!req->nbytes) || !(rctx->flags & HASH_FLAGS_CPU)) - return 0; - -+ stm32_hash_find_dev(rctx); -+ - rctx->total = req->nbytes; - rctx->sg = req->src; - rctx->offset = 0; - -- if ((rctx->bufcnt + rctx->total < rctx->buflen)) { -+ if (rctx->bufcnt + rctx->total <= rctx->buflen) { - stm32_hash_append_sg(rctx); - return 0; - } -@@ -926,15 +937,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); -- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); -- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); - int err1, err2; - - rctx->flags |= HASH_FLAGS_FINUP; - -- if (hdev->dma_lch && stm32_hash_dma_aligned_data(req)) -- rctx->flags &= ~HASH_FLAGS_CPU; -- - err1 = stm32_hash_update(req); - - if (err1 == -EINPROGRESS || err1 == -EBUSY) -@@ -951,32 +957,81 @@ static int stm32_hash_finup(struct ahash_request *req) - - static int stm32_hash_digest(struct ahash_request *req) - { -- return stm32_hash_init(req) ?: stm32_hash_finup(req); -+ int ret; -+ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -+ -+ ret = stm32_hash_init(req); -+ if (ret) -+ return ret; -+ -+ if (stm32_hash_dma_aligned_data(req)) -+ rctx->flags &= ~HASH_FLAGS_CPU; -+ -+ return stm32_hash_finup(req); -+} -+ -+static int hash_swap_reg(struct stm32_hash_request_ctx *rctx) -+{ -+ switch ((rctx->flags & HASH_FLAGS_ALGO_MASK) >> -+ HASH_FLAGS_ALGO_SHIFT) { -+ case HASH_MD5: -+ case HASH_SHA1: -+ case HASH_SHA224: -+ case HASH_SHA256: -+ if (rctx->flags & HASH_FLAGS_HMAC) -+ return HASH_CSR_NB_SHA256_HMAC; -+ else -+ return HASH_CSR_NB_SHA256; -+ break; -+ -+ case HASH_SHA384: -+ case HASH_SHA512: -+ if (rctx->flags & HASH_FLAGS_HMAC) -+ return HASH_CSR_NB_SHA512_HMAC; -+ else -+ return HASH_CSR_NB_SHA512; -+ break; -+ -+ case HASH_SHA3_224: -+ case HASH_SHA3_256: -+ case HASH_SHA3_384: -+ case HASH_SHA3_512: -+ if (rctx->flags & HASH_FLAGS_HMAC) -+ return HASH_CSR_NB_SHA3_HMAC; -+ else -+ return HASH_CSR_NB_SHA3; -+ break; -+ -+ default: -+ return -EINVAL; -+ } - } - - static int stm32_hash_export(struct ahash_request *req, void *out) - { - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); -- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); -+ struct stm32_hash_dev *hdev = rctx->hdev; - u32 *preg; - unsigned int i; -+ int swap_reg; - - pm_runtime_get_sync(hdev->dev); - - while ((stm32_hash_read(hdev, HASH_SR) & HASH_SR_BUSY)) - cpu_relax(); - -- rctx->hw_context = kmalloc_array(3 + HASH_CSR_REGISTER_NUMBER, -- sizeof(u32), -- GFP_KERNEL); -+ swap_reg = hash_swap_reg(rctx); -+ if (swap_reg < 0) -+ return swap_reg; -+ -+ rctx->hw_context = kmalloc_array(3 + swap_reg, sizeof(u32), GFP_KERNEL); - - preg = rctx->hw_context; - - *preg++ = stm32_hash_read(hdev, HASH_IMR); - *preg++ = stm32_hash_read(hdev, HASH_STR); - *preg++ = stm32_hash_read(hdev, HASH_CR); -- for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) -+ for (i = 0; i < swap_reg; i++) - *preg++ = stm32_hash_read(hdev, HASH_CSR(i)); - - pm_runtime_mark_last_busy(hdev->dev); -@@ -990,14 +1045,14 @@ static int stm32_hash_export(struct ahash_request *req, void *out) - static int stm32_hash_import(struct ahash_request *req, const void *in) - { - struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); -- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); -- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); -+ struct stm32_hash_dev *hdev; - const u32 *preg = in; - u32 reg; - unsigned int i; -+ int swap_reg; - - memcpy(rctx, in, sizeof(*rctx)); -- -+ hdev = rctx->hdev; - preg = rctx->hw_context; - - pm_runtime_get_sync(hdev->dev); -@@ -1008,7 +1063,11 @@ static int stm32_hash_import(struct ahash_request *req, const void *in) - reg = *preg++ | HASH_CR_INIT; - stm32_hash_write(hdev, HASH_CR, reg); - -- for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) -+ swap_reg = hash_swap_reg(rctx); -+ if (swap_reg < 0) -+ return swap_reg; -+ -+ for (i = 0; i < swap_reg; i++) - stm32_hash_write(hdev, HASH_CSR(i), *preg++); - - pm_runtime_mark_last_busy(hdev->dev); -@@ -1034,8 +1093,7 @@ static int stm32_hash_setkey(struct crypto_ahash *tfm, - return 0; - } - --static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, -- const char *algs_hmac_name) -+static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, u32 algs_flags) - { - struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm); - -@@ -1044,8 +1102,8 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, - - ctx->keylen = 0; - -- if (algs_hmac_name) -- ctx->flags |= HASH_FLAGS_HMAC; -+ if (algs_flags) -+ ctx->flags |= algs_flags; - - ctx->enginectx.op.do_one_request = stm32_hash_one_request; - ctx->enginectx.op.prepare_request = stm32_hash_prepare_req; -@@ -1055,27 +1113,23 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, - - static int stm32_hash_cra_init(struct crypto_tfm *tfm) - { -- return stm32_hash_cra_init_algs(tfm, NULL); -+ return stm32_hash_cra_init_algs(tfm, 0); - } - --static int stm32_hash_cra_md5_init(struct crypto_tfm *tfm) -+static int stm32_hash_cra_hmac_init(struct crypto_tfm *tfm) - { -- return stm32_hash_cra_init_algs(tfm, "md5"); -+ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_HMAC); - } - --static int stm32_hash_cra_sha1_init(struct crypto_tfm *tfm) -+static int stm32_hash_cra_sha3_init(struct crypto_tfm *tfm) - { -- return stm32_hash_cra_init_algs(tfm, "sha1"); -+ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE); - } - --static int stm32_hash_cra_sha224_init(struct crypto_tfm *tfm) -+static int stm32_hash_cra_sha3_hmac_init(struct crypto_tfm *tfm) - { -- return stm32_hash_cra_init_algs(tfm, "sha224"); --} -- --static int stm32_hash_cra_sha256_init(struct crypto_tfm *tfm) --{ -- return stm32_hash_cra_init_algs(tfm, "sha256"); -+ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE | -+ HASH_FLAGS_HMAC); - } - - static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) -@@ -1110,8 +1164,6 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) - - reg = stm32_hash_read(hdev, HASH_SR); - if (reg & HASH_SR_OUTPUT_READY) { -- reg &= ~HASH_SR_OUTPUT_READY; -- stm32_hash_write(hdev, HASH_SR, reg); - hdev->flags |= HASH_FLAGS_OUTPUT_READY; - /* Disable IT*/ - stm32_hash_write(hdev, HASH_IMR, 0); -@@ -1121,7 +1173,7 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) - return IRQ_NONE; - } - --static struct ahash_alg algs_md5_sha1[] = { -+static struct ahash_alg algs_md5[] = { - { - .init = stm32_hash_init, - .update = stm32_hash_update, -@@ -1132,7 +1184,8 @@ static struct ahash_alg algs_md5_sha1[] = { - .import = stm32_hash_import, - .halg = { - .digestsize = MD5_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "md5", - .cra_driver_name = "stm32-md5", -@@ -1158,7 +1211,8 @@ static struct ahash_alg algs_md5_sha1[] = { - .setkey = stm32_hash_setkey, - .halg = { - .digestsize = MD5_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "hmac(md5)", - .cra_driver_name = "stm32-hmac-md5", -@@ -1168,11 +1222,14 @@ static struct ahash_alg algs_md5_sha1[] = { - .cra_blocksize = MD5_HMAC_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct stm32_hash_ctx), - .cra_alignmask = 3, -- .cra_init = stm32_hash_cra_md5_init, -+ .cra_init = stm32_hash_cra_hmac_init, - .cra_module = THIS_MODULE, - } - } -- }, -+ } -+}; -+ -+static struct ahash_alg algs_sha1[] = { - { - .init = stm32_hash_init, - .update = stm32_hash_update, -@@ -1183,7 +1240,8 @@ static struct ahash_alg algs_md5_sha1[] = { - .import = stm32_hash_import, - .halg = { - .digestsize = SHA1_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "sha1", - .cra_driver_name = "stm32-sha1", -@@ -1209,7 +1267,8 @@ static struct ahash_alg algs_md5_sha1[] = { - .setkey = stm32_hash_setkey, - .halg = { - .digestsize = SHA1_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "hmac(sha1)", - .cra_driver_name = "stm32-hmac-sha1", -@@ -1219,7 +1278,7 @@ static struct ahash_alg algs_md5_sha1[] = { - .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct stm32_hash_ctx), - .cra_alignmask = 3, -- .cra_init = stm32_hash_cra_sha1_init, -+ .cra_init = stm32_hash_cra_hmac_init, - .cra_module = THIS_MODULE, - } - } -@@ -1237,7 +1296,8 @@ static struct ahash_alg algs_sha224_sha256[] = { - .import = stm32_hash_import, - .halg = { - .digestsize = SHA224_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "sha224", - .cra_driver_name = "stm32-sha224", -@@ -1263,7 +1323,8 @@ static struct ahash_alg algs_sha224_sha256[] = { - .import = stm32_hash_import, - .halg = { - .digestsize = SHA224_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "hmac(sha224)", - .cra_driver_name = "stm32-hmac-sha224", -@@ -1273,7 +1334,7 @@ static struct ahash_alg algs_sha224_sha256[] = { - .cra_blocksize = SHA224_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct stm32_hash_ctx), - .cra_alignmask = 3, -- .cra_init = stm32_hash_cra_sha224_init, -+ .cra_init = stm32_hash_cra_hmac_init, - .cra_module = THIS_MODULE, - } - } -@@ -1288,7 +1349,8 @@ static struct ahash_alg algs_sha224_sha256[] = { - .import = stm32_hash_import, - .halg = { - .digestsize = SHA256_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "sha256", - .cra_driver_name = "stm32-sha256", -@@ -1314,7 +1376,8 @@ static struct ahash_alg algs_sha224_sha256[] = { - .setkey = stm32_hash_setkey, - .halg = { - .digestsize = SHA256_DIGEST_SIZE, -- .statesize = sizeof(struct stm32_hash_request_ctx), -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, - .base = { - .cra_name = "hmac(sha256)", - .cra_driver_name = "stm32-hmac-sha256", -@@ -1324,13 +1387,339 @@ static struct ahash_alg algs_sha224_sha256[] = { - .cra_blocksize = SHA256_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct stm32_hash_ctx), - .cra_alignmask = 3, -- .cra_init = stm32_hash_cra_sha256_init, -+ .cra_init = stm32_hash_cra_hmac_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+}; -+ -+ -+static struct ahash_alg algs_sha384_sha512[] = { -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .halg = { -+ .digestsize = SHA384_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "sha384", -+ .cra_driver_name = "stm32-sha384", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .setkey = stm32_hash_setkey, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .halg = { -+ .digestsize = SHA384_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "hmac(sha384)", -+ .cra_driver_name = "stm32-hmac-sha384", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_hmac_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .halg = { -+ .digestsize = SHA512_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "sha512", -+ .cra_driver_name = "stm32-sha512", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .setkey = stm32_hash_setkey, -+ .halg = { -+ .digestsize = SHA512_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "hmac(sha512)", -+ .cra_driver_name = "stm32-hmac-sha512", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_hmac_init, - .cra_module = THIS_MODULE, - } - } - }, - }; - -+static struct ahash_alg algs_sha3[] = { -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .halg = { -+ .digestsize = SHA3_224_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "sha3-224", -+ .cra_driver_name = "stm32-sha3-224", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_224_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .setkey = stm32_hash_setkey, -+ .halg = { -+ .digestsize = SHA3_224_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "hmac(sha3-224)", -+ .cra_driver_name = "stm32-hmac-sha3-224", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_224_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_hmac_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .halg = { -+ .digestsize = SHA3_256_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "sha3-256", -+ .cra_driver_name = "stm32-sha3-256", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_256_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .setkey = stm32_hash_setkey, -+ .halg = { -+ .digestsize = SHA3_256_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "hmac(sha3-256)", -+ .cra_driver_name = "stm32-hmac-sha3-256", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_256_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_hmac_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .halg = { -+ .digestsize = SHA3_384_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "sha3-384", -+ .cra_driver_name = "stm32-sha3-384", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .setkey = stm32_hash_setkey, -+ .halg = { -+ .digestsize = SHA3_384_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "hmac(sha3-384)", -+ .cra_driver_name = "stm32-hmac-sha3-384", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_hmac_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .halg = { -+ .digestsize = SHA3_512_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "sha3-512", -+ .cra_driver_name = "stm32-sha3-512", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ }, -+ { -+ .init = stm32_hash_init, -+ .update = stm32_hash_update, -+ .final = stm32_hash_final, -+ .finup = stm32_hash_finup, -+ .digest = stm32_hash_digest, -+ .export = stm32_hash_export, -+ .import = stm32_hash_import, -+ .setkey = stm32_hash_setkey, -+ .halg = { -+ .digestsize = SHA3_512_DIGEST_SIZE, -+ .statesize = sizeof(struct stm32_hash_request_ctx) + -+ HASH_MAX_BUFLEN, -+ .base = { -+ .cra_name = "hmac(sha3-512)", -+ .cra_driver_name = "stm32-hmac-sha3-512", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SHA3_512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct stm32_hash_ctx), -+ .cra_alignmask = 3, -+ .cra_init = stm32_hash_cra_sha3_hmac_init, -+ .cra_module = THIS_MODULE, -+ } -+ } -+ } -+}; -+ -+ - static int stm32_hash_register_algs(struct stm32_hash_dev *hdev) - { - unsigned int i, j; -@@ -1372,20 +1761,29 @@ static int stm32_hash_unregister_algs(struct stm32_hash_dev *hdev) - - static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f4[] = { - { -- .algs_list = algs_md5_sha1, -- .size = ARRAY_SIZE(algs_md5_sha1), -+ .algs_list = algs_md5, -+ .size = ARRAY_SIZE(algs_md5), -+ }, -+ { -+ .algs_list = algs_sha1, -+ .size = ARRAY_SIZE(algs_sha1), - }, - }; - - static const struct stm32_hash_pdata stm32_hash_pdata_stm32f4 = { -+ .alg_shift = 7, - .algs_info = stm32_hash_algs_info_stm32f4, - .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f4), - }; - - static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = { - { -- .algs_list = algs_md5_sha1, -- .size = ARRAY_SIZE(algs_md5_sha1), -+ .algs_list = algs_md5, -+ .size = ARRAY_SIZE(algs_md5), -+ }, -+ { -+ .algs_list = algs_sha1, -+ .size = ARRAY_SIZE(algs_sha1), - }, - { - .algs_list = algs_sha224_sha256, -@@ -1394,19 +1792,41 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = { - }; - - static const struct stm32_hash_pdata stm32_hash_pdata_stm32f7 = { -+ .alg_shift = 7, - .algs_info = stm32_hash_algs_info_stm32f7, - .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f7), - }; - --static const struct of_device_id stm32_hash_of_match[] = { -+ -+static struct stm32_hash_algs_info stm32_hash_algs_info_stm32mp13[] = { -+ { -+ .algs_list = algs_sha1, -+ .size = ARRAY_SIZE(algs_sha1), -+ }, -+ { -+ .algs_list = algs_sha224_sha256, -+ .size = ARRAY_SIZE(algs_sha224_sha256), -+ }, - { -- .compatible = "st,stm32f456-hash", -- .data = &stm32_hash_pdata_stm32f4, -+ .algs_list = algs_sha384_sha512, -+ .size = ARRAY_SIZE(algs_sha384_sha512), - }, - { -- .compatible = "st,stm32f756-hash", -- .data = &stm32_hash_pdata_stm32f7, -+ .algs_list = algs_sha3, -+ .size = ARRAY_SIZE(algs_sha3), - }, -+}; -+ -+static const struct stm32_hash_pdata stm32_hash_pdata_stm32mp13 = { -+ .alg_shift = 17, -+ .algs_info = stm32_hash_algs_info_stm32mp13, -+ .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32mp13), -+}; -+ -+static const struct of_device_id stm32_hash_of_match[] = { -+ { .compatible = "st,stm32f456-hash", .data = &stm32_hash_pdata_stm32f4 }, -+ { .compatible = "st,stm32f756-hash", .data = &stm32_hash_pdata_stm32f7 }, -+ { .compatible = "st,stm32mp13-hash", .data = &stm32_hash_pdata_stm32mp13 }, - {}, - }; - -@@ -1421,12 +1841,6 @@ static int stm32_hash_get_of_match(struct stm32_hash_dev *hdev, - return -EINVAL; - } - -- if (of_property_read_u32(dev->of_node, "dma-maxburst", -- &hdev->dma_maxburst)) { -- dev_info(dev, "dma-maxburst not specified, using 0\n"); -- hdev->dma_maxburst = 0; -- } -- - return 0; - } - -@@ -1494,6 +1908,8 @@ static int stm32_hash_probe(struct platform_device *pdev) - reset_control_deassert(hdev->rst); - } - -+ crypto_init_queue(&hdev->queue, HASH_QUEUE_LENGTH); -+ - hdev->dev = dev; - - platform_set_drvdata(pdev, hdev); -@@ -1502,7 +1918,7 @@ static int stm32_hash_probe(struct platform_device *pdev) - switch (ret) { - case 0: - break; -- case -ENOENT: -+ case -ENODEV: - dev_dbg(dev, "DMA mode not available\n"); - break; - default: -@@ -1524,7 +1940,8 @@ static int stm32_hash_probe(struct platform_device *pdev) - if (ret) - goto err_engine_start; - -- hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR); -+ hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR) & -+ HASH_HWCFG_DMA_MASK; - - /* Register algos */ - ret = stm32_hash_register_algs(hdev); -@@ -1633,6 +2050,6 @@ static struct platform_driver stm32_hash_driver = { - - module_platform_driver(stm32_hash_driver); - --MODULE_DESCRIPTION("STM32 SHA1/224/256 & MD5 (HMAC) hw accelerator driver"); -+MODULE_DESCRIPTION("STM32 SHA1/SHA2/SHA3 & MD5 (HMAC) hw accelerator driver"); - MODULE_AUTHOR("Lionel Debieve "); - MODULE_LICENSE("GPL v2"); --- -2.25.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0012-ARM-5.15.24-stm32mp1-r1-MMC.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0012-ARM-5.15.24-stm32mp1-r1-MMC.patch deleted file mode 100644 index f67539a..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0012-ARM-5.15.24-stm32mp1-r1-MMC.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 4ad9ff21f9950e378e159d614a4f3edb5cd187b6 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:00:10 +0200 -Subject: [PATCH 12/22] ARM-5.15.24-stm32mp1-r1-MMC - -Signed-off-by: Christophe Priouzeau ---- - Documentation/devicetree/bindings/mmc/arm,pl18x.yaml | 6 ++++++ - drivers/mmc/host/mmci.c | 12 ++++++++++-- - drivers/mmc/host/mmci.h | 1 + - drivers/mmc/host/mmci_stm32_sdmmc.c | 5 +++-- - 4 files changed, 20 insertions(+), 4 deletions(-) - -diff --git a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml -index 47595cb48..eed54bee7 100644 ---- a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml -+++ b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml -@@ -53,6 +53,12 @@ properties: - items: - - const: arm,pl18x - - const: arm,primecell -+ - description: Entry for STMicroelectronics variant of PL18x. -+ This dedicated compatible is used by bootloaders. -+ items: -+ - const: st,stm32-sdmmc2 -+ - const: arm,pl18x -+ - const: arm,primecell - - clocks: - description: One or two clocks, the "apb_pclk" and the "MCLK" -diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c -index 3765e2f4a..c15b9a2cd 100644 ---- a/drivers/mmc/host/mmci.c -+++ b/drivers/mmc/host/mmci.c -@@ -274,13 +274,14 @@ static struct variant_data variant_stm32_sdmmc = { - .busy_detect = true, - .busy_detect_flag = MCI_STM32_BUSYD0, - .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK, -+ .disable_keep_power = true, - .init = sdmmc_variant_init, - }; - - static struct variant_data variant_stm32_sdmmcv2 = { - .fifosize = 16 * 4, - .fifohalfsize = 8 * 4, -- .f_max = 208000000, -+ .f_max = 267000000, - .stm32_clkdiv = true, - .cmdreg_cpsm_enable = MCI_CPSM_STM32_ENABLE, - .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC, -@@ -301,6 +302,7 @@ static struct variant_data variant_stm32_sdmmcv2 = { - .busy_detect = true, - .busy_detect_flag = MCI_STM32_BUSYD0, - .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK, -+ .disable_keep_power = true, - .init = sdmmc_variant_init, - }; - -@@ -2168,7 +2170,8 @@ static int mmci_probe(struct amba_device *dev, - host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC; - - /* We support these PM capabilities. */ -- mmc->pm_caps |= MMC_PM_KEEP_POWER; -+ if (!variant->disable_keep_power) -+ mmc->pm_caps |= MMC_PM_KEEP_POWER; - - /* - * We can do SGIO -@@ -2431,6 +2434,11 @@ static const struct amba_id mmci_ids[] = { - .mask = 0xf0ffffff, - .data = &variant_stm32_sdmmcv2, - }, -+ { -+ .id = 0x20253180, -+ .mask = 0xf0ffffff, -+ .data = &variant_stm32_sdmmcv2, -+ }, - /* Qualcomm variants */ - { - .id = 0x00051180, -diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h -index e1a9b96a3..2cad1ef97 100644 ---- a/drivers/mmc/host/mmci.h -+++ b/drivers/mmc/host/mmci.h -@@ -361,6 +361,7 @@ struct variant_data { - u32 opendrain; - u8 dma_lli:1; - u32 stm32_idmabsize_mask; -+ u8 disable_keep_power:1; - void (*init)(struct mmci_host *host); - }; - -diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c -index a75d3dd34..9c13f2c31 100644 ---- a/drivers/mmc/host/mmci_stm32_sdmmc.c -+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c -@@ -241,11 +241,12 @@ static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired) - - /* - * SDMMC_FBCK is selected when an external Delay Block is needed -- * with SDR104. -+ * with SDR104 or HS200. - */ - if (host->mmc->ios.timing >= MMC_TIMING_UHS_SDR50) { - clk |= MCI_STM32_CLK_BUSSPEED; -- if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104) { -+ if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 || -+ host->mmc->ios.timing == MMC_TIMING_MMC_HS200) { - clk &= ~MCI_STM32_CLK_SEL_MSK; - clk |= MCI_STM32_CLK_SELFBCK; - } --- -2.25.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0016-ARM-5.15.24-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0016-ARM-5.15.24-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch deleted file mode 100644 index 9dce1ff..0000000 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0016-ARM-5.15.24-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch +++ /dev/null @@ -1,1703 +0,0 @@ -From 1670971dadf723ce3bb0e34c27fb7046e64fa74d Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:05:37 +0200 -Subject: [PATCH 16/22] ARM-5.15.24-stm32mp1-r1-PINCTRL-REGULATOR-SPI - -Signed-off-by: Christophe Priouzeau ---- - .../bindings/pinctrl/st,stm32-pinctrl.yaml | 8 + - .../regulator/protection-consumer.txt | 23 ++ - .../bindings/regulator/st,stm32-vrefbuf.yaml | 4 +- - drivers/pinctrl/stm32/pinctrl-stm32.c | 201 +++++++++++++----- - drivers/pinctrl/stm32/pinctrl-stm32.h | 19 +- - drivers/pinctrl/stm32/pinctrl-stm32mp135.c | 3 +- - drivers/pinctrl/stm32/pinctrl-stm32mp157.c | 3 +- - drivers/regulator/Kconfig | 11 + - drivers/regulator/Makefile | 1 + - drivers/regulator/protection-consumer.c | 137 ++++++++++++ - drivers/regulator/scmi-regulator.c | 99 ++++++--- - drivers/regulator/stm32-pwr.c | 85 +++++++- - drivers/regulator/stm32-vrefbuf.c | 69 +++++- - drivers/regulator/stpmic1_regulator.c | 182 ++++++++++++++-- - drivers/spi/spi-stm32-qspi.c | 11 +- - include/dt-bindings/pinctrl/stm32-pinfunc.h | 1 + - 16 files changed, 724 insertions(+), 133 deletions(-) - create mode 100644 Documentation/devicetree/bindings/regulator/protection-consumer.txt - create mode 100644 drivers/regulator/protection-consumer.c - -diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml -index dfee6d38a..7348f40d4 100644 ---- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml -+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml -@@ -140,9 +140,13 @@ patternProperties: - * ... - * 16 : Alternate Function 15 - * 17 : Analog -+ * 18 : Reserved - To simplify the usage, macro is available to generate "pinmux" field. - This macro is available here: - - include/dt-bindings/pinctrl/stm32-pinfunc.h -+ Setting the pinmux's function to the Reserved (RSVD) value is used to inform -+ the driver that it shall not apply the mux setting. This can be used to -+ reserve some pins, for example to a co-processor not running Linux. - Some examples of using macro: - /* GPIO A9 set as alernate function 2 */ - ... { -@@ -156,6 +160,10 @@ patternProperties: - ... { - pinmux = ; - }; -+ /* GPIO A9 reserved for co-processor */ -+ ... { -+ pinmux = ; -+ }; - - bias-disable: - type: boolean -diff --git a/Documentation/devicetree/bindings/regulator/protection-consumer.txt b/Documentation/devicetree/bindings/regulator/protection-consumer.txt -new file mode 100644 -index 000000000..bf8169e00 ---- /dev/null -+++ b/Documentation/devicetree/bindings/regulator/protection-consumer.txt -@@ -0,0 +1,23 @@ -+regulator protection bindings -+ -+ -+Required properties: -+ compatible: "protection-consumer" -+ protection-supply: the phandle of the regulator to control -+ -+Optional properties: -+-------------------- -+ interrupt -+ -+ -+Example: -+ -+ regulator_protection { -+ compatible = "protection-consumer"; -+ protection-supply = <&vdd>; -+ status = "okay"; -+ -+ interrupts = <15 2>; -+ interrupt-parent = <&gpiof>; -+ }; -+ -diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml -index 3cd4a254e..fe9c5e83c 100644 ---- a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml -+++ b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml -@@ -19,7 +19,9 @@ allOf: - - properties: - compatible: -- const: st,stm32-vrefbuf -+ enum: -+ - st,stm32-vrefbuf -+ - st,stm32mp13-vrefbuf - - reg: - maxItems: 1 -diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c -index 8934b4878..271dcdbb5 100644 ---- a/drivers/pinctrl/stm32/pinctrl-stm32.c -+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c -@@ -43,6 +43,7 @@ - #define STM32_GPIO_LCKR 0x1c - #define STM32_GPIO_AFRL 0x20 - #define STM32_GPIO_AFRH 0x24 -+#define STM32_GPIO_SECCFGR 0x30 - - /* custom bitfield to backup pin status */ - #define STM32_GPIO_BKP_MODE_SHIFT 0 -@@ -73,6 +74,7 @@ static const char * const stm32_gpio_functions[] = { - "af8", "af9", "af10", - "af11", "af12", "af13", - "af14", "af15", "analog", -+ "reserved", - }; - - struct stm32_pinctrl_group { -@@ -94,6 +96,7 @@ struct stm32_gpio_bank { - u32 bank_ioport_nr; - u32 pin_backup[STM32_GPIO_PINS_PER_BANK]; - u8 irq_type[STM32_GPIO_PINS_PER_BANK]; -+ bool secure_control; - }; - - struct stm32_pinctrl { -@@ -115,6 +118,7 @@ struct stm32_pinctrl { - u32 pkg; - u16 irqmux_map; - spinlock_t irqmux_lock; -+ u32 pin_base_shift; - }; - - static inline int stm32_gpio_pin(int gpio) -@@ -197,11 +201,7 @@ static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank, - if (!value) - offset += STM32_GPIO_PINS_PER_BANK; - -- clk_enable(bank->clk); -- - writel_relaxed(BIT(offset), bank->base + STM32_GPIO_BSRR); -- -- clk_disable(bank->clk); - } - - static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset) -@@ -228,15 +228,8 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) - static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) - { - struct stm32_gpio_bank *bank = gpiochip_get_data(chip); -- int ret; -- -- clk_enable(bank->clk); -- -- ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); -- -- clk_disable(bank->clk); - -- return ret; -+ return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); - } - - static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -@@ -294,6 +287,33 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) - return ret; - } - -+static int stm32_gpio_init_valid_mask(struct gpio_chip *chip, -+ unsigned long *valid_mask, -+ unsigned int ngpios) -+{ -+ struct stm32_gpio_bank *bank = gpiochip_get_data(chip); -+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); -+ unsigned int i; -+ u32 sec; -+ -+ /* All gpio are valid per default */ -+ bitmap_fill(valid_mask, ngpios); -+ -+ if (bank->secure_control) { -+ /* Tag secured pins as invalid */ -+ sec = readl_relaxed(bank->base + STM32_GPIO_SECCFGR); -+ -+ for (i = 0; i < ngpios; i++) { -+ if (sec & BIT(i)) { -+ clear_bit(i, valid_mask); -+ dev_dbg(pctl->dev, "No access to gpio %d - %d\n", bank->bank_nr, i); -+ } -+ } -+ } -+ -+ return 0; -+} -+ - static const struct gpio_chip stm32_gpio_template = { - .request = stm32_gpio_request, - .free = stm32_gpio_free, -@@ -304,6 +324,7 @@ static const struct gpio_chip stm32_gpio_template = { - .to_irq = stm32_gpio_to_irq, - .get_direction = stm32_gpio_get_direction, - .set_config = gpiochip_generic_config, -+ .init_valid_mask = stm32_gpio_init_valid_mask, - }; - - static void stm32_gpio_irq_trigger(struct irq_data *d) -@@ -514,7 +535,7 @@ stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin) - static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, - u32 pin_num, u32 fnum) - { -- int i; -+ int i, k; - - for (i = 0; i < pctl->npins; i++) { - const struct stm32_desc_pin *pin = pctl->pins + i; -@@ -523,7 +544,10 @@ static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, - if (pin->pin.number != pin_num) - continue; - -- while (func && func->name) { -+ if (fnum == STM32_PIN_RSVD) -+ return true; -+ -+ for (k = 0; k < STM32_CONFIG_NUM; k++) { - if (func->num == fnum) - return true; - func++; -@@ -750,7 +774,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, - unsigned long flags; - int err = 0; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - if (pctl->hwlock) { -@@ -779,7 +802,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, - - unlock: - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return err; - } -@@ -792,7 +814,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, - int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; - unsigned long flags; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - val = readl_relaxed(bank->base + alt_offset); -@@ -804,7 +825,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, - *mode = val >> (pin * 2); - - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - } - - static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, -@@ -829,6 +849,11 @@ static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, - return -EINVAL; - } - -+ if (function == STM32_PIN_RSVD) { -+ dev_dbg(pctl->dev, "Reserved pins, skipping HW update.\n"); -+ return 0; -+ } -+ - bank = gpiochip_get_data(range->gc); - pin = stm32_gpio_pin(g->pin); - -@@ -848,12 +873,32 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, - return stm32_pmx_set_mode(bank, pin, !input, 0); - } - -+static int stm32_pmx_request(struct pinctrl_dev *pctldev, unsigned gpio) -+{ -+ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); -+ struct pinctrl_gpio_range *range; -+ -+ range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, gpio); -+ if (!range) { -+ dev_err(pctl->dev, "No gpio range defined.\n"); -+ return -EINVAL; -+ } -+ -+ if (!gpiochip_line_is_valid(range->gc, stm32_gpio_pin(gpio))) { -+ dev_warn(pctl->dev, "Can't access gpio %d\n", gpio); -+ return -EACCES; -+ } -+ -+ return 0; -+} -+ - static const struct pinmux_ops stm32_pmx_ops = { - .get_functions_count = stm32_pmx_get_funcs_cnt, - .get_function_name = stm32_pmx_get_func_name, - .get_function_groups = stm32_pmx_get_func_groups, - .set_mux = stm32_pmx_set_mux, - .gpio_set_direction = stm32_pmx_gpio_set_direction, -+ .request = stm32_pmx_request, - .strict = true, - }; - -@@ -867,7 +912,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, - u32 val; - int err = 0; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - if (pctl->hwlock) { -@@ -891,7 +935,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, - - unlock: - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return err; - } -@@ -902,14 +945,12 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank, - unsigned long flags; - u32 val; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - val = readl_relaxed(bank->base + STM32_GPIO_TYPER); - val &= BIT(offset); - - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return (val >> offset); - } -@@ -922,7 +963,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, - u32 val; - int err = 0; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - if (pctl->hwlock) { -@@ -946,7 +986,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, - - unlock: - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return err; - } -@@ -957,14 +996,12 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank, - unsigned long flags; - u32 val; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR); - val &= GENMASK(offset * 2 + 1, offset * 2); - - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return (val >> (offset * 2)); - } -@@ -977,7 +1014,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, - u32 val; - int err = 0; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - if (pctl->hwlock) { -@@ -1001,7 +1037,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, - - unlock: - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return err; - } -@@ -1012,14 +1047,12 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank, - unsigned long flags; - u32 val; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - val = readl_relaxed(bank->base + STM32_GPIO_PUPDR); - val &= GENMASK(offset * 2 + 1, offset * 2); - - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return (val >> (offset * 2)); - } -@@ -1030,7 +1063,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, - unsigned long flags; - u32 val; - -- clk_enable(bank->clk); - spin_lock_irqsave(&bank->lock, flags); - - if (dir) -@@ -1041,7 +1073,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, - BIT(offset)); - - spin_unlock_irqrestore(&bank->lock, flags); -- clk_disable(bank->clk); - - return val; - } -@@ -1064,6 +1095,11 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, - bank = gpiochip_get_data(range->gc); - offset = stm32_gpio_pin(pin); - -+ if (!gpiochip_line_is_valid(range->gc, offset)) { -+ dev_warn(pctl->dev, "Can't access gpio %d\n", pin); -+ return -EACCES; -+ } -+ - switch (param) { - case PIN_CONFIG_DRIVE_PUSH_PULL: - ret = stm32_pconf_set_driving(bank, offset, 0); -@@ -1143,10 +1179,27 @@ static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - return 0; - } - -+static struct stm32_desc_pin * -+stm32_pconf_get_pin_desc_by_pin_number(struct stm32_pinctrl *pctl, -+ unsigned int pin_number) -+{ -+ struct stm32_desc_pin *pins = pctl->pins; -+ int i; -+ -+ for (i = 0; i < pctl->npins; i++) { -+ if (pins->pin.number == pin_number) -+ return pins; -+ pins++; -+ } -+ return NULL; -+} -+ - static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, - unsigned int pin) - { -+ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); -+ const struct stm32_desc_pin *pin_desc; - struct pinctrl_gpio_range *range; - struct stm32_gpio_bank *bank; - int offset; -@@ -1166,6 +1219,11 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, - bank = gpiochip_get_data(range->gc); - offset = stm32_gpio_pin(pin); - -+ if (!gpiochip_line_is_valid(range->gc, offset)) { -+ seq_puts(s, "NO ACCESS"); -+ return; -+ } -+ - stm32_pmx_get_mode(bank, offset, &mode, &alt); - bias = stm32_pconf_get_bias(bank, offset); - -@@ -1196,7 +1254,12 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, - case 2: - drive = stm32_pconf_get_driving(bank, offset); - speed = stm32_pconf_get_speed(bank, offset); -- seq_printf(s, "%d - %s - %s - %s %s", alt, -+ pin_desc = stm32_pconf_get_pin_desc_by_pin_number(pctl, pin); -+ if (!pin_desc) -+ return; -+ -+ seq_printf(s, "%d (%s) - %s - %s - %s %s", alt, -+ pin_desc->functions[alt + 1].name, - drive ? "open drain" : "push pull", - biasing[bias], - speeds[speed], "speed"); -@@ -1237,9 +1300,9 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, - if (IS_ERR(bank->base)) - return PTR_ERR(bank->base); - -- err = clk_prepare(bank->clk); -+ err = clk_prepare_enable(bank->clk); - if (err) { -- dev_err(dev, "failed to prepare clk (%d)\n", err); -+ dev_err(dev, "failed to prepare_enable clk (%d)\n", err); - return err; - } - -@@ -1278,26 +1341,35 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, - bank->gpio_chip.parent = dev; - bank->bank_nr = bank_nr; - bank->bank_ioport_nr = bank_ioport_nr; -+ bank->secure_control = pctl->match_data->secure_control; - spin_lock_init(&bank->lock); - -- /* create irq hierarchical domain */ -- bank->fwnode = of_node_to_fwnode(np); -+ if (pctl->domain) { -+ /* create irq hierarchical domain */ -+ bank->fwnode = of_node_to_fwnode(np); - -- bank->domain = irq_domain_create_hierarchy(pctl->domain, 0, -- STM32_GPIO_IRQ_LINE, bank->fwnode, -- &stm32_gpio_domain_ops, bank); -+ bank->domain = irq_domain_create_hierarchy(pctl->domain, 0, STM32_GPIO_IRQ_LINE, -+ bank->fwnode, &stm32_gpio_domain_ops, -+ bank); - -- if (!bank->domain) -- return -ENODEV; -+ if (!bank->domain) { -+ err = -ENODEV; -+ goto err_clk; -+ } -+ } - - err = gpiochip_add_data(&bank->gpio_chip, bank); - if (err) { - dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr); -- return err; -+ goto err_clk; - } - - dev_info(dev, "%s bank added\n", bank->gpio_chip.label); - return 0; -+ -+err_clk: -+ clk_disable_unprepare(bank->clk); -+ return err; - } - - static struct irq_domain *stm32_pctrl_get_irq_domain(struct device_node *np) -@@ -1405,7 +1477,8 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, - if (pctl->pkg && !(pctl->pkg & p->pkg)) - continue; - pins->pin = p->pin; -- pins->functions = p->functions; -+ memcpy((struct stm32_desc_pin *)pins->functions, p->functions, -+ STM32_CONFIG_NUM * sizeof(struct stm32_desc_function)); - pins++; - nb_pins_available++; - } -@@ -1415,17 +1488,6 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, - return 0; - } - --static void stm32_pctl_get_package(struct device_node *np, -- struct stm32_pinctrl *pctl) --{ -- if (of_property_read_u32(np, "st,package", &pctl->pkg)) { -- pctl->pkg = 0; -- dev_warn(pctl->dev, "No package detected, use default one\n"); -- } else { -- dev_dbg(pctl->dev, "package detected: %x\n", pctl->pkg); -- } --} -- - int stm32_pctl_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; -@@ -1458,6 +1520,8 @@ int stm32_pctl_probe(struct platform_device *pdev) - pctl->domain = stm32_pctrl_get_irq_domain(np); - if (IS_ERR(pctl->domain)) - return PTR_ERR(pctl->domain); -+ if (!pctl->domain) -+ dev_warn(dev, "pinctrl without interrupt support\n"); - - /* hwspinlock is optional */ - hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0); -@@ -1473,8 +1537,9 @@ int stm32_pctl_probe(struct platform_device *pdev) - pctl->dev = dev; - pctl->match_data = match->data; - -- /* get package information */ -- stm32_pctl_get_package(np, pctl); -+ /* get optional package information */ -+ if (!of_property_read_u32(np, "st,package", &pctl->pkg)) -+ dev_dbg(pctl->dev, "package detected: %x\n", pctl->pkg); - - pctl->pins = devm_kcalloc(pctl->dev, pctl->match_data->npins, - sizeof(*pctl->pins), GFP_KERNEL); -@@ -1514,6 +1579,7 @@ int stm32_pctl_probe(struct platform_device *pdev) - pctl->pctl_desc.pctlops = &stm32_pctrl_ops; - pctl->pctl_desc.pmxops = &stm32_pmx_ops; - pctl->dev = &pdev->dev; -+ pctl->pin_base_shift = pctl->match_data->pin_base_shift; - - pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc, - pctl); -@@ -1566,6 +1632,10 @@ int stm32_pctl_probe(struct platform_device *pdev) - ret = stm32_gpiolib_register_bank(pctl, child); - if (ret) { - of_node_put(child); -+ -+ for (i = 0; i < pctl->nbanks; i++) -+ clk_disable_unprepare(pctl->banks[i].clk); -+ - return ret; - } - -@@ -1592,6 +1662,9 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( - if (!range) - return 0; - -+ if (!gpiochip_line_is_valid(range->gc, offset)) -+ return 0; -+ - pin_is_irq = gpiochip_line_is_irq(range->gc, offset); - - if (!desc || (!pin_is_irq && !desc->gpio_owner)) -@@ -1638,12 +1711,26 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( - return 0; - } - -+int __maybe_unused stm32_pinctrl_suspend(struct device *dev) -+{ -+ struct stm32_pinctrl *pctl = dev_get_drvdata(dev); -+ int i; -+ -+ for (i = 0; i < pctl->nbanks; i++) -+ clk_disable(pctl->banks[i].clk); -+ -+ return 0; -+} -+ - int __maybe_unused stm32_pinctrl_resume(struct device *dev) - { - struct stm32_pinctrl *pctl = dev_get_drvdata(dev); - struct stm32_pinctrl_group *g = pctl->groups; - int i; - -+ for (i = 0; i < pctl->nbanks; i++) -+ clk_enable(pctl->banks[i].clk); -+ - for (i = 0; i < pctl->ngroups; i++, g++) - stm32_pinctrl_restore_gpio_regs(pctl, g->pin); - -diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h -index b0882d120..319dff763 100644 ---- a/drivers/pinctrl/stm32/pinctrl-stm32.h -+++ b/drivers/pinctrl/stm32/pinctrl-stm32.h -@@ -17,6 +17,8 @@ - #define STM32_PIN_GPIO 0 - #define STM32_PIN_AF(x) ((x) + 1) - #define STM32_PIN_ANALOG (STM32_PIN_AF(15) + 1) -+#define STM32_PIN_RSVD (STM32_PIN_ANALOG + 1) -+#define STM32_CONFIG_NUM (STM32_PIN_RSVD + 1) - - /* package information */ - #define STM32MP_PKG_AA BIT(0) -@@ -24,6 +26,8 @@ - #define STM32MP_PKG_AC BIT(2) - #define STM32MP_PKG_AD BIT(3) - -+#define STM32MP157_Z_BASE_SHIFT 400 -+ - struct stm32_desc_function { - const char *name; - const unsigned char num; -@@ -31,26 +35,26 @@ struct stm32_desc_function { - - struct stm32_desc_pin { - struct pinctrl_pin_desc pin; -- const struct stm32_desc_function *functions; -+ const struct stm32_desc_function functions[STM32_CONFIG_NUM]; - const unsigned int pkg; - }; - - #define STM32_PIN(_pin, ...) \ - { \ - .pin = _pin, \ -- .functions = (struct stm32_desc_function[]){ \ -- __VA_ARGS__, { } }, \ -+ .functions = { \ -+ __VA_ARGS__}, \ - } - - #define STM32_PIN_PKG(_pin, _pkg, ...) \ - { \ - .pin = _pin, \ - .pkg = _pkg, \ -- .functions = (struct stm32_desc_function[]){ \ -- __VA_ARGS__, { } }, \ -+ .functions = { \ -+ __VA_ARGS__}, \ - } - #define STM32_FUNCTION(_num, _name) \ -- { \ -+ [_num] = { \ - .num = _num, \ - .name = _name, \ - } -@@ -58,6 +62,8 @@ struct stm32_desc_pin { - struct stm32_pinctrl_match_data { - const struct stm32_desc_pin *pins; - const unsigned int npins; -+ bool secure_control; -+ const unsigned int pin_base_shift; - }; - - struct stm32_gpio_bank; -@@ -65,6 +71,7 @@ struct stm32_gpio_bank; - int stm32_pctl_probe(struct platform_device *pdev); - void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, - int pin, u32 *mode, u32 *alt); -+int stm32_pinctrl_suspend(struct device *dev); - int stm32_pinctrl_resume(struct device *dev); - - #endif /* __PINCTRL_STM32_H */ -diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp135.c b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c -index 4ab03520c..fde1df191 100644 ---- a/drivers/pinctrl/stm32/pinctrl-stm32mp135.c -+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c -@@ -1649,6 +1649,7 @@ static const struct stm32_desc_pin stm32mp135_pins[] = { - static struct stm32_pinctrl_match_data stm32mp135_match_data = { - .pins = stm32mp135_pins, - .npins = ARRAY_SIZE(stm32mp135_pins), -+ .secure_control = true, - }; - - static const struct of_device_id stm32mp135_pctrl_match[] = { -@@ -1660,7 +1661,7 @@ static const struct of_device_id stm32mp135_pctrl_match[] = { - }; - - static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = { -- SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume) -+ SET_LATE_SYSTEM_SLEEP_PM_OPS(stm32_pinctrl_suspend, stm32_pinctrl_resume) - }; - - static struct platform_driver stm32mp135_pinctrl_driver = { -diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c -index 2ccb99d64..2d4f8c1e6 100644 ---- a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c -+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c -@@ -2328,6 +2328,7 @@ static struct stm32_pinctrl_match_data stm32mp157_match_data = { - static struct stm32_pinctrl_match_data stm32mp157_z_match_data = { - .pins = stm32mp157_z_pins, - .npins = ARRAY_SIZE(stm32mp157_z_pins), -+ .pin_base_shift = STM32MP157_Z_BASE_SHIFT, - }; - - static const struct of_device_id stm32mp157_pctrl_match[] = { -@@ -2343,7 +2344,7 @@ static const struct of_device_id stm32mp157_pctrl_match[] = { - }; - - static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = { -- SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume) -+ SET_LATE_SYSTEM_SLEEP_PM_OPS(stm32_pinctrl_suspend, stm32_pinctrl_resume) - }; - - static struct platform_driver stm32mp157_pinctrl_driver = { -diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig -index 4fd13b062..285931c18 100644 ---- a/drivers/regulator/Kconfig -+++ b/drivers/regulator/Kconfig -@@ -37,6 +37,17 @@ config REGULATOR_FIXED_VOLTAGE - useful for systems which use a combination of software - managed regulators and simple non-configurable regulators. - -+config REGULATOR_PROTECTION_CONSUMER -+ tristate "Regulator protection consumer" -+ depends on OF -+ help -+ This driver handles regulator over-current detection in order to -+ protect regulators from crashing. In case of over-current event -+ or any IRQ, the protection consumer forces disable the regulator -+ that was declared as supply. -+ -+ If unsure, say no. -+ - config REGULATOR_VIRTUAL_CONSUMER - tristate "Virtual regulator consumer support" - help -diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile -index 9e382b50a..543e04fa2 100644 ---- a/drivers/regulator/Makefile -+++ b/drivers/regulator/Makefile -@@ -7,6 +7,7 @@ - obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o irq_helpers.o - obj-$(CONFIG_OF) += of_regulator.o - obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o -+obj-$(CONFIG_REGULATOR_PROTECTION_CONSUMER) += protection-consumer.o - obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o - obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o - -diff --git a/drivers/regulator/protection-consumer.c b/drivers/regulator/protection-consumer.c -new file mode 100644 -index 000000000..a4d299f85 ---- /dev/null -+++ b/drivers/regulator/protection-consumer.c -@@ -0,0 +1,137 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) STMicroelectronics 2021 -+// Author: Pascal Paillet for STMicroelectronics. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * struct protection_data - regulator driver data -+ * @reg: regulator consumer structure -+ * @nb: notifier_block structure -+ * @dev: device driver -+ */ -+struct protection_data { -+ struct regulator *reg; -+ struct notifier_block nb; -+ struct device *dev; -+}; -+ -+/** -+ * protection_irq_handler() - irq handler -+ * @irq: irq number -+ * @dev: struct protection_data -+ * -+ * force disable the regulator -+ */ -+static irqreturn_t protection_irq_handler(int irq, void *dev) -+{ -+ struct protection_data *protection = (struct protection_data *)dev; -+ -+ dev_warn(protection->dev, "Interrupt received on regulator\n"); -+ if (regulator_is_enabled(protection->reg)) -+ regulator_force_disable(protection->reg); -+ -+ return IRQ_HANDLED; -+} -+ -+/** -+ * regulator_event() - regulator framework callback -+ * @nb: notifier_block -+ * @event: regulator framework event -+ * @data: struct protection_data -+ * -+ * force disable the regulator in case of regulator event -+ * -+ * Return: 0 for successful probe else appropriate error -+ */ -+static int regulator_event(struct notifier_block *nb, unsigned long event, -+ void *data) -+{ -+ struct protection_data *protection = -+ container_of(nb, struct protection_data, nb); -+ -+ if ((event & REGULATOR_EVENT_OVER_CURRENT) || -+ (event & REGULATOR_EVENT_OVER_TEMP)) { -+ dev_warn(protection->dev, "Event received on regulator\n"); -+ if (regulator_is_enabled(protection->reg)) -+ regulator_force_disable(protection->reg); -+ } -+ -+ return 0; -+} -+ -+/** -+ * protection_probe() - probe -+ * @pdev: platform_device -+ * -+ * Return: 0 for successful probe else appropriate error -+ */ -+static int protection_probe(struct platform_device *pdev) -+{ -+ struct protection_data *protection; -+ int irq, ret; -+ -+ protection = devm_kzalloc(&pdev->dev, sizeof(struct protection_data), GFP_KERNEL); -+ if (!protection) -+ return -ENOMEM; -+ -+ protection->dev = &pdev->dev; -+ -+ protection->reg = devm_regulator_get(&pdev->dev, "protection"); -+ if (IS_ERR(protection->reg)) -+ return PTR_ERR(protection->reg); -+ -+ protection->nb.notifier_call = regulator_event; -+ ret = devm_regulator_register_notifier(protection->reg, &protection->nb); -+ if (ret != 0) { -+ dev_err(&pdev->dev, "Failed to register regulator notifier: %d\n", ret); -+ return ret; -+ } -+ -+ /* irq is optional, the driver can be used with regulator events */ -+ irq = platform_get_irq_optional(pdev, 0); -+ if (irq <= 0 && (irq != -ENXIO)) -+ return irq ? : -ENOENT; -+ -+ if (irq > 0) { -+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, -+ protection_irq_handler, -+ IRQF_ONESHOT | IRQF_SHARED, -+ pdev->name, protection); -+ if (ret) { -+ dev_err(&pdev->dev, "Request IRQ failed\n"); -+ return ret; -+ } -+ } -+ platform_set_drvdata(pdev, protection); -+ dev_dbg(&pdev->dev, "protection probed\n"); -+ -+ return 0; -+} -+ -+static const struct of_device_id protection_dt_match[] = { -+ { .compatible = "protection-consumer" }, -+ { }, -+}; -+ -+MODULE_DEVICE_TABLE(of, protection_dt_match); -+ -+static struct platform_driver protection_driver = { -+ .driver = { -+ .name = "protection-consumer", -+ .owner = THIS_MODULE, -+ .of_match_table = protection_dt_match, -+ }, -+ .probe = protection_probe, -+}; -+ -+module_platform_driver(protection_driver); -+ -+MODULE_AUTHOR(""); -+MODULE_DESCRIPTION("protection consumer driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/regulator/scmi-regulator.c b/drivers/regulator/scmi-regulator.c -index 1f02f60ad..dffd9f5ce 100644 ---- a/drivers/regulator/scmi-regulator.c -+++ b/drivers/regulator/scmi-regulator.c -@@ -219,10 +219,11 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) - */ - if (vinfo->negative_volts_allowed) { - dev_warn(dev, "Negative voltages NOT supported...skip %s\n", -- sreg->of_node->full_name); -+ vinfo->name); - return -EOPNOTSUPP; - } - -+ - sreg->desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", vinfo->name); - if (!sreg->desc.name) - return -ENOMEM; -@@ -230,8 +231,6 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) - sreg->desc.id = sreg->id; - sreg->desc.type = REGULATOR_VOLTAGE; - sreg->desc.owner = THIS_MODULE; -- sreg->desc.of_match_full_name = true; -- sreg->desc.of_match = sreg->of_node->full_name; - sreg->desc.regulators_node = "regulators"; - if (vinfo->segmented) - ret = scmi_config_linear_regulator_mappings(sreg, vinfo); -@@ -239,7 +238,6 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) - ret = scmi_config_discrete_regulator_mappings(sreg, vinfo); - if (ret) - return ret; -- - /* - * Using the scmi device here to have DT searched from Voltage - * protocol node down. -@@ -252,40 +250,59 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) - return 0; - } - -+static int scmi_find_domain_from_name(struct scmi_device *sdev, -+ struct device_node *np, -+ struct scmi_regulator_info *rinfo, -+ u32 *dom) -+{ -+ const char *name = of_get_property(np, "voltd-name", NULL); -+ int d; -+ -+ if (!name) -+ return -EINVAL; -+ -+ for (d = 0; d < rinfo->num_doms; d++) { -+ struct scmi_regulator *sreg = rinfo->sregv[d]; -+ -+ if (!sreg || !sreg->desc.name || strcmp(sreg->desc.name, name)) -+ continue; -+ -+ *dom=d; -+ return 0; -+ } -+ -+ dev_warn(&sdev->dev, "scmi voltage domain %s not found\n", name); -+ return -ENODEV; -+} -+ - static int process_scmi_regulator_of_node(struct scmi_device *sdev, -- struct scmi_protocol_handle *ph, - struct device_node *np, - struct scmi_regulator_info *rinfo) - { - u32 dom, ret; - - ret = of_property_read_u32(np, "reg", &dom); -- if (ret) -- return ret; -+ if (ret == -EINVAL) { -+ ret = scmi_find_domain_from_name(sdev, np, rinfo, &dom); -+ if (ret < 0) { -+ return ret; -+ } -+ } - - if (dom >= rinfo->num_doms) - return -ENODEV; - -- if (rinfo->sregv[dom]) { -- dev_err(&sdev->dev, -- "SCMI Voltage Domain %d already in use. Skipping: %s\n", -- dom, np->full_name); -- return -EINVAL; -- } -- -- rinfo->sregv[dom] = devm_kzalloc(&sdev->dev, -- sizeof(struct scmi_regulator), -- GFP_KERNEL); - if (!rinfo->sregv[dom]) -- return -ENOMEM; -+ return -EINVAL; - - rinfo->sregv[dom]->id = dom; - rinfo->sregv[dom]->sdev = sdev; -- rinfo->sregv[dom]->ph = ph; - - /* get hold of good nodes */ - of_node_get(np); - rinfo->sregv[dom]->of_node = np; -+ rinfo->sregv[dom]->desc.of_match_full_name = true; -+ rinfo->sregv[dom]->desc.of_match = rinfo->sregv[dom]->of_node->name; - - dev_dbg(&sdev->dev, - "Found SCMI Regulator entry -- OF node [%d] -> %s\n", -@@ -338,21 +355,38 @@ static int scmi_regulator_probe(struct scmi_device *sdev) - rinfo->num_doms = num_doms; - - /* -- * Start collecting into rinfo->sregv possibly good SCMI Regulators as -- * described by a well-formed DT entry and associated with an existing -- * plausible SCMI Voltage Domain number, all belonging to this SCMI -- * platform instance node (handle->dev->of_node). -+ * Start collecting into rinfo->sregv for each regulator that we -+ * can successfully reach via SCMI. - */ -- np = of_find_node_by_name(handle->dev->of_node, "regulators"); -- for_each_child_of_node(np, child) { -- ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo); -- /* abort on any mem issue */ -- if (ret == -ENOMEM) { -- of_node_put(child); -- return ret; -+ for (d = 0; d < num_doms; d++) { -+ struct scmi_regulator *sreg; -+ -+ sreg = devm_kzalloc(&sdev->dev, sizeof(struct scmi_regulator), -+ GFP_KERNEL); -+ if (!sreg) -+ return -ENOMEM; -+ -+ sreg->sdev = sdev; -+ sreg->id = d; -+ sreg->ph = ph; -+ -+ ret = scmi_regulator_common_init(sreg); -+ if (ret) { -+ devm_kfree(&sdev->dev, sreg); -+ continue; - } -+ -+ rinfo->sregv[d] = sreg; - } - -+ /* -+ * Map each DT entry with an existing SCMI Voltage Domain number -+ * all belonging to this SCMI platform instance node (handle->dev->of_node). -+ */ -+ np = of_find_node_by_name(handle->dev->of_node, "regulators"); -+ for_each_child_of_node(np, child) -+ process_scmi_regulator_of_node(sdev, child, rinfo); -+ - /* - * Register a regulator for each valid regulator-DT-entry that we - * can successfully reach via SCMI and has a valid associated voltage -@@ -365,9 +399,8 @@ static int scmi_regulator_probe(struct scmi_device *sdev) - if (!sreg) - continue; - -- ret = scmi_regulator_common_init(sreg); -- /* Skip invalid voltage domains */ -- if (ret) -+ /* Skip if not described in the device-tree */ -+ if (!sreg->of_node) - continue; - - sreg->rdev = devm_regulator_register(&sdev->dev, &sreg->desc, -diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c -index 2a42acb7c..2b328b970 100644 ---- a/drivers/regulator/stm32-pwr.c -+++ b/drivers/regulator/stm32-pwr.c -@@ -3,12 +3,15 @@ - // Authors: Gabriel Fernandez - // Pascal Paillet . - -+#include - #include - #include -+#include - #include - #include - #include - #include -+#include - #include - #include - -@@ -24,6 +27,11 @@ - #define REG_1_1_EN BIT(30) - #define REG_1_1_RDY BIT(31) - -+#define STM32_SMC_PWR 0x82001001 -+#define STM32_WRITE 0x1 -+#define STM32_SMC_REG_SET 0x2 -+#define STM32_SMC_REG_CLEAR 0x3 -+ - /* list of supported regulators */ - enum { - PWR_REG11, -@@ -39,10 +47,18 @@ static u32 ready_mask_table[STM32PWR_REG_NUM_REGS] = { - }; - - struct stm32_pwr_reg { -+ int tzen; - void __iomem *base; - u32 ready_mask; - }; - -+#define SMC(class, op, address, val)\ -+ ({\ -+ struct arm_smccc_res res;\ -+ arm_smccc_smc(class, op, address, val,\ -+ 0, 0, 0, 0, &res);\ -+ }) -+ - static int stm32_pwr_reg_is_ready(struct regulator_dev *rdev) - { - struct stm32_pwr_reg *priv = rdev_get_drvdata(rdev); -@@ -69,9 +85,15 @@ static int stm32_pwr_reg_enable(struct regulator_dev *rdev) - int ret; - u32 val; - -- val = readl_relaxed(priv->base + REG_PWR_CR3); -- val |= rdev->desc->enable_mask; -- writel_relaxed(val, priv->base + REG_PWR_CR3); -+ if (priv->tzen) { -+ SMC(STM32_SMC_PWR, STM32_SMC_REG_SET, REG_PWR_CR3, -+ rdev->desc->enable_mask); -+ } else { -+ val = readl_relaxed(priv->base + REG_PWR_CR3); -+ val |= rdev->desc->enable_mask; -+ writel_relaxed(val, priv->base + REG_PWR_CR3); -+ } -+ - - /* use an arbitrary timeout of 20ms */ - ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, val, -@@ -88,9 +110,14 @@ static int stm32_pwr_reg_disable(struct regulator_dev *rdev) - int ret; - u32 val; - -- val = readl_relaxed(priv->base + REG_PWR_CR3); -- val &= ~rdev->desc->enable_mask; -- writel_relaxed(val, priv->base + REG_PWR_CR3); -+ if (priv->tzen) { -+ SMC(STM32_SMC_PWR, STM32_SMC_REG_CLEAR, REG_PWR_CR3, -+ rdev->desc->enable_mask); -+ } else { -+ val = readl_relaxed(priv->base + REG_PWR_CR3); -+ val &= ~rdev->desc->enable_mask; -+ writel_relaxed(val, priv->base + REG_PWR_CR3); -+ } - - /* use an arbitrary timeout of 20ms */ - ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, !val, -@@ -121,12 +148,50 @@ static const struct regulator_ops stm32_pwr_reg_ops = { - .supply_name = _supply, \ - } \ - --static const struct regulator_desc stm32_pwr_desc[] = { -+static struct regulator_desc stm32_pwr_desc[] = { - PWR_REG(PWR_REG11, "reg11", 1100000, REG_1_1_EN, "vdd"), - PWR_REG(PWR_REG18, "reg18", 1800000, REG_1_8_EN, "vdd"), - PWR_REG(PWR_USB33, "usb33", 3300000, USB_3_3_EN, "vdd_3v3_usbfs"), - }; - -+static int is_stm32_soc_secured(struct platform_device *pdev, int *val) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct regmap *syscon; -+ u32 reg, mask; -+ int tzc_val = 0; -+ int err; -+ -+ syscon = syscon_regmap_lookup_by_phandle(np, "st,tzcr"); -+ if (IS_ERR(syscon)) { -+ if (PTR_ERR(syscon) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "tzcr syscon required\n"); -+ return PTR_ERR(syscon); -+ } -+ -+ err = of_property_read_u32_index(np, "st,tzcr", 1, ®); -+ if (err) { -+ dev_err(&pdev->dev, "tzcr offset required !\n"); -+ return err; -+ } -+ -+ err = of_property_read_u32_index(np, "st,tzcr", 2, &mask); -+ if (err) { -+ dev_err(&pdev->dev, "tzcr mask required !\n"); -+ return err; -+ } -+ -+ err = regmap_read(syscon, reg, &tzc_val); -+ if (err) { -+ dev_err(&pdev->dev, "failed to read tzcr status !\n"); -+ return err; -+ } -+ -+ *val = tzc_val & mask; -+ -+ return 0; -+} -+ - static int stm32_pwr_regulator_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; -@@ -135,6 +200,11 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) - struct regulator_dev *rdev; - struct regulator_config config = { }; - int i, ret = 0; -+ int tzen = 0; -+ -+ ret = is_stm32_soc_secured(pdev, &tzen); -+ if (ret) -+ return ret; - - base = of_iomap(np, 0); - if (!base) { -@@ -149,6 +219,7 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) - GFP_KERNEL); - if (!priv) - return -ENOMEM; -+ priv->tzen = tzen; - priv->base = base; - priv->ready_mask = ready_mask_table[i]; - config.driver_data = priv; -diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c -index 161622ea7..d7eb7607b 100644 ---- a/drivers/regulator/stm32-vrefbuf.c -+++ b/drivers/regulator/stm32-vrefbuf.c -@@ -31,6 +31,7 @@ struct stm32_vrefbuf { - void __iomem *base; - struct clk *clk; - struct device *dev; -+ u32 backup_val; - }; - - static const unsigned int stm32_vrefbuf_voltages[] = { -@@ -38,6 +39,11 @@ static const unsigned int stm32_vrefbuf_voltages[] = { - 2500000, 2048000, 1800000, 1500000, - }; - -+static const unsigned int stm32mp13_vrefbuf_voltages[] = { -+ /* Matches resp. VRS = 000b, 001b, 010b, 011b */ -+ 2500000, 2048000, 1800000, 1650000, -+}; -+ - static int stm32_vrefbuf_enable(struct regulator_dev *rdev) - { - struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); -@@ -180,11 +186,24 @@ static const struct regulator_desc stm32_vrefbuf_regu = { - .owner = THIS_MODULE, - }; - -+static const struct regulator_desc stm32mp13_vrefbuf_regu = { -+ .name = "vref", -+ .supply_name = "vdda", -+ .volt_table = stm32mp13_vrefbuf_voltages, -+ .n_voltages = ARRAY_SIZE(stm32mp13_vrefbuf_voltages), -+ .ops = &stm32_vrefbuf_volt_ops, -+ .off_on_delay = 1000, -+ .type = REGULATOR_VOLTAGE, -+ .owner = THIS_MODULE, -+}; -+ - static int stm32_vrefbuf_probe(struct platform_device *pdev) - { -+ struct device *dev = &pdev->dev; - struct stm32_vrefbuf *priv; - struct regulator_config config = { }; - struct regulator_dev *rdev; -+ const struct regulator_desc *desc; - int ret; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -@@ -213,14 +232,19 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) - goto err_pm_stop; - } - -+ desc = (const struct regulator_desc *) -+ of_match_device(dev->driver->of_match_table, dev)->data; -+ if (!desc) -+ return -EINVAL; -+ - config.dev = &pdev->dev; - config.driver_data = priv; - config.of_node = pdev->dev.of_node; - config.init_data = of_get_regulator_init_data(&pdev->dev, - pdev->dev.of_node, -- &stm32_vrefbuf_regu); -+ desc); - -- rdev = regulator_register(&stm32_vrefbuf_regu, &config); -+ rdev = regulator_register(desc, &config); - if (IS_ERR(rdev)) { - ret = PTR_ERR(rdev); - dev_err(&pdev->dev, "register failed with error %d\n", ret); -@@ -276,16 +300,51 @@ static int __maybe_unused stm32_vrefbuf_runtime_resume(struct device *dev) - return clk_prepare_enable(priv->clk); - } - -+#if defined(CONFIG_PM_SLEEP) -+static int stm32_vrefbuf_suspend(struct device *dev) -+{ -+ struct regulator_dev *rdev = dev_get_drvdata(dev); -+ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); -+ int ret; -+ -+ ret = pm_runtime_get_sync(priv->dev); -+ if (ret < 0) { -+ pm_runtime_put_noidle(priv->dev); -+ return ret; -+ } -+ -+ priv->backup_val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); -+ -+ return pm_runtime_force_suspend(dev); -+} -+ -+static int stm32_vrefbuf_resume(struct device *dev) -+{ -+ struct regulator_dev *rdev = dev_get_drvdata(dev); -+ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); -+ int ret; -+ -+ ret = pm_runtime_force_resume(dev); -+ if (ret < 0) -+ return ret; -+ -+ writel_relaxed(priv->backup_val, priv->base + STM32_VREFBUF_CSR); -+ -+ return 0; -+} -+#endif -+ - static const struct dev_pm_ops stm32_vrefbuf_pm_ops = { -- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, -- pm_runtime_force_resume) -+ SET_SYSTEM_SLEEP_PM_OPS(stm32_vrefbuf_suspend, -+ stm32_vrefbuf_resume) - SET_RUNTIME_PM_OPS(stm32_vrefbuf_runtime_suspend, - stm32_vrefbuf_runtime_resume, - NULL) - }; - - static const struct of_device_id __maybe_unused stm32_vrefbuf_of_match[] = { -- { .compatible = "st,stm32-vrefbuf", }, -+ { .compatible = "st,stm32-vrefbuf", .data = (void *)&stm32_vrefbuf_regu }, -+ { .compatible = "st,stm32mp13-vrefbuf", .data = (void *)&stm32mp13_vrefbuf_regu }, - {}, - }; - MODULE_DEVICE_TABLE(of, stm32_vrefbuf_of_match); -diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c -index 2d7597c76..c2cddba6d 100644 ---- a/drivers/regulator/stpmic1_regulator.c -+++ b/drivers/regulator/stpmic1_regulator.c -@@ -2,7 +2,9 @@ - // Copyright (C) STMicroelectronics 2018 - // Author: Pascal Paillet for STMicroelectronics. - -+#include - #include -+#include - #include - #include - #include -@@ -30,11 +32,27 @@ struct stpmic1_regulator_cfg { - u8 icc_mask; - }; - -+/** -+ * struct boost_data - this structure is used as driver data for the usb boost -+ * @boost_rdev: device for boost regulator -+ * @vbus_otg_rdev: device for vbus_otg regulator -+ * @sw_out_rdev: device for sw_out regulator -+ * @occ_timeout: overcurrent detection timeout -+ */ -+struct boost_data { -+ struct regulator_dev *boost_rdev; -+ struct regulator_dev *vbus_otg_rdev; -+ struct regulator_dev *sw_out_rdev; -+ ktime_t occ_timeout; -+}; -+ - static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode); - static unsigned int stpmic1_get_mode(struct regulator_dev *rdev); - static int stpmic1_set_icc(struct regulator_dev *rdev, int lim, int severity, - bool enable); - static unsigned int stpmic1_map_mode(unsigned int mode); -+static int regulator_enable_boost(struct regulator_dev *rdev); -+static int regulator_disable_boost(struct regulator_dev *rdev); - - enum { - STPMIC1_BUCK1 = 0, -@@ -182,8 +200,8 @@ static const struct regulator_ops stpmic1_vref_ddr_ops = { - - static const struct regulator_ops stpmic1_boost_regul_ops = { - .is_enabled = regulator_is_enabled_regmap, -- .enable = regulator_enable_regmap, -- .disable = regulator_disable_regmap, -+ .enable = regulator_enable_boost, -+ .disable = regulator_disable_boost, - .set_over_current_protection = stpmic1_set_icc, - }; - -@@ -529,6 +547,79 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) - return IRQ_HANDLED; - } - -+static int regulator_enable_boost(struct regulator_dev *rdev) -+{ -+ struct boost_data *usb_data = rdev_get_drvdata(rdev); -+ -+ usb_data->occ_timeout = ktime_add_us(ktime_get(), 100000); -+ -+ return regulator_enable_regmap(rdev); -+} -+ -+static int regulator_disable_boost(struct regulator_dev *rdev) -+{ -+ struct boost_data *usb_data = rdev_get_drvdata(rdev); -+ -+ usb_data->occ_timeout = 0; -+ -+ return regulator_disable_regmap(rdev); -+} -+ -+static void stpmic1_reset_boost(struct boost_data *usb_data) -+{ -+ int otg_on = 0; -+ int sw_out_on = 0; -+ -+ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "reset usb boost\n"); -+ -+ /* the boost was actually disabled by the over-current protection */ -+ regulator_disable_regmap(usb_data->boost_rdev); -+ -+ if (usb_data->vbus_otg_rdev) -+ otg_on = regulator_is_enabled_regmap(usb_data->vbus_otg_rdev); -+ if (otg_on) -+ regulator_disable_regmap(usb_data->vbus_otg_rdev); -+ -+ if (usb_data->sw_out_rdev) -+ sw_out_on = regulator_is_enabled_regmap(usb_data->sw_out_rdev); -+ if (sw_out_on) -+ regulator_disable_regmap(usb_data->sw_out_rdev); -+ -+ regulator_enable_regmap(usb_data->boost_rdev); -+ -+ /* sleep at least 5ms */ -+ usleep_range(5000, 10000); -+ -+ if (otg_on) -+ regulator_enable_regmap(usb_data->vbus_otg_rdev); -+ -+ if (sw_out_on) -+ regulator_enable_regmap(usb_data->sw_out_rdev); -+ -+} -+ -+static irqreturn_t stpmic1_boost_irq_handler(int irq, void *data) -+{ -+ struct boost_data *usb_data = (struct boost_data *)data; -+ -+ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "usb boost irq handler\n"); -+ -+ /* overcurrent detected on boost after timeout */ -+ if (usb_data->occ_timeout != 0 && -+ ktime_compare(ktime_get(), usb_data->occ_timeout) > 0) { -+ /* reset usb boost and usb power switches */ -+ stpmic1_reset_boost(usb_data); -+ return IRQ_HANDLED; -+ } -+ -+ /* Send an overcurrent notification */ -+ regulator_notifier_call_chain(usb_data->boost_rdev, -+ REGULATOR_EVENT_OVER_CURRENT, -+ NULL); -+ -+ return IRQ_HANDLED; -+} -+ - #define MATCH(_name, _id) \ - [STPMIC1_##_id] = { \ - .name = #_name, \ -@@ -552,9 +643,10 @@ static struct of_regulator_match stpmic1_matches[] = { - MATCH(pwr_sw2, SW_OUT), - }; - --static int stpmic1_regulator_register(struct platform_device *pdev, int id, -- struct of_regulator_match *match, -- const struct stpmic1_regulator_cfg *cfg) -+static struct regulator_dev * -+stpmic1_regulator_register(struct platform_device *pdev, int id, -+ struct of_regulator_match *match, -+ const struct stpmic1_regulator_cfg *cfg) - { - struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); - struct regulator_dev *rdev; -@@ -572,7 +664,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, "failed to register %s regulator\n", - cfg->desc.name); -- return PTR_ERR(rdev); -+ return rdev; - } - - /* set mask reset */ -@@ -584,7 +676,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, - cfg->mask_reset_mask); - if (ret) { - dev_err(&pdev->dev, "set mask reset failed\n"); -- return ret; -+ return ERR_PTR(ret); - } - } - -@@ -598,15 +690,60 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, - pdev->name, rdev); - if (ret) { - dev_err(&pdev->dev, "Request IRQ failed\n"); -- return ret; -+ return ERR_PTR(ret); - } - } -- return 0; -+ -+ return rdev; -+} -+ -+static struct regulator_dev * -+stpmic1_boost_register(struct platform_device *pdev, int id, -+ struct of_regulator_match *match, -+ const struct stpmic1_regulator_cfg *cfg, -+ struct boost_data *usb_data) -+{ -+ struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); -+ struct regulator_dev *rdev; -+ struct regulator_config config = {}; -+ int ret = 0; -+ int irq; -+ -+ config.dev = &pdev->dev; -+ config.init_data = match->init_data; -+ config.of_node = match->of_node; -+ config.regmap = pmic_dev->regmap; -+ config.driver_data = (void *)usb_data; -+ -+ rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config); -+ if (IS_ERR(rdev)) { -+ dev_err(&pdev->dev, "failed to register %s regulator\n", -+ cfg->desc.name); -+ return rdev; -+ } -+ -+ /* setup an irq handler for over-current detection */ -+ irq = of_irq_get(config.of_node, 0); -+ if (irq > 0) { -+ ret = devm_request_threaded_irq(&pdev->dev, -+ irq, NULL, -+ stpmic1_boost_irq_handler, -+ IRQF_ONESHOT, pdev->name, -+ usb_data); -+ if (ret) { -+ dev_err(&pdev->dev, "Request IRQ failed\n"); -+ return ERR_PTR(ret); -+ } -+ } -+ -+ return rdev; - } - - static int stpmic1_regulator_probe(struct platform_device *pdev) - { - int i, ret; -+ struct boost_data *usb_data; -+ struct regulator_dev *rdev; - - ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches, - ARRAY_SIZE(stpmic1_matches)); -@@ -616,11 +753,30 @@ static int stpmic1_regulator_probe(struct platform_device *pdev) - return ret; - } - -+ usb_data = devm_kzalloc(&pdev->dev, sizeof(*usb_data), GFP_KERNEL); -+ if (!usb_data) -+ return -ENOMEM; -+ - for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) { -- ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], -- &stpmic1_regulator_cfgs[i]); -- if (ret < 0) -- return ret; -+ if (i == STPMIC1_BOOST) { -+ rdev = -+ stpmic1_boost_register(pdev, i, &stpmic1_matches[i], -+ &stpmic1_regulator_cfgs[i], -+ usb_data); -+ -+ usb_data->boost_rdev = rdev; -+ } else { -+ rdev = -+ stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], -+ &stpmic1_regulator_cfgs[i]); -+ -+ if (i == STPMIC1_VBUS_OTG) -+ usb_data->vbus_otg_rdev = rdev; -+ else if (i == STPMIC1_SW_OUT) -+ usb_data->sw_out_rdev = rdev; -+ } -+ if (IS_ERR(rdev)) -+ return PTR_ERR(rdev); - } - - dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n"); -diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c -index ffdc55f87..1948a0090 100644 ---- a/drivers/spi/spi-stm32-qspi.c -+++ b/drivers/spi/spi-stm32-qspi.c -@@ -305,10 +305,8 @@ static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi, - u32 cr, sr; - int err = 0; - -- if (!op->data.nbytes) -- goto wait_nobusy; -- -- if (readl_relaxed(qspi->io_base + QSPI_SR) & SR_TCF) -+ if ((readl_relaxed(qspi->io_base + QSPI_SR) & SR_TCF) || -+ qspi->fmode == CCR_FMODE_APM) - goto out; - - reinit_completion(&qspi->data_completion); -@@ -327,7 +325,6 @@ static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi, - out: - /* clear flags */ - writel_relaxed(FCR_CTCF | FCR_CTEF, qspi->io_base + QSPI_FCR); --wait_nobusy: - if (!err) - err = stm32_qspi_wait_nobusy(qspi); - -@@ -372,10 +369,6 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) - op->dummy.buswidth, op->data.buswidth, - op->addr.val, op->data.nbytes); - -- err = stm32_qspi_wait_nobusy(qspi); -- if (err) -- goto abort; -- - cr = readl_relaxed(qspi->io_base + QSPI_CR); - cr &= ~CR_PRESC_MASK & ~CR_FSEL; - cr |= FIELD_PREP(CR_PRESC_MASK, flash->presc); -diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h -index e6fb8ada3..370a25a93 100644 ---- a/include/dt-bindings/pinctrl/stm32-pinfunc.h -+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h -@@ -26,6 +26,7 @@ - #define AF14 0xf - #define AF15 0x10 - #define ANALOG 0x11 -+#define RSVD 0x12 - - /* define Pins number*/ - #define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) --- -2.25.1 - diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0001-ARM-5.15.24-stm32mp1-r1-MACHINE.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0001-v5.15-stm32mp-r2-MACHINE.patch similarity index 87% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0001-ARM-5.15.24-stm32mp1-r1-MACHINE.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0001-v5.15-stm32mp-r2-MACHINE.patch index a933e42..b449f03 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0001-ARM-5.15.24-stm32mp1-r1-MACHINE.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0001-v5.15-stm32mp-r2-MACHINE.patch @@ -1,9 +1,9 @@ -From 4868d40c41f2fb7dea18d7b5fe14da02fc82e2f1 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:50:09 +0200 -Subject: [PATCH 01/22] ARM-5.15.24-stm32mp1-r1-MACHINE +From 84827f5873b8cd852cc79177e9a42b12760b3723 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 13 Oct 2022 12:22:34 +0200 +Subject: [PATCH 01/22] v5.15-stm32mp-r2 MACHINE -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- Documentation/arm/index.rst | 1 + .../arm/stm32/stm32mp13-overview.rst | 37 +++++++++++++++++++ @@ -14,7 +14,7 @@ Signed-off-by: Christophe Priouzeau create mode 100644 Documentation/arm/stm32/stm32mp13-overview.rst diff --git a/Documentation/arm/index.rst b/Documentation/arm/index.rst -index d4f34ae9e..2bda5461a 100644 +index d4f34ae9e6f4..2bda5461a80b 100644 --- a/Documentation/arm/index.rst +++ b/Documentation/arm/index.rst @@ -55,6 +55,7 @@ SoC-specific documents @@ -27,7 +27,7 @@ index d4f34ae9e..2bda5461a 100644 sunxi diff --git a/Documentation/arm/stm32/stm32mp13-overview.rst b/Documentation/arm/stm32/stm32mp13-overview.rst new file mode 100644 -index 000000000..3bb9492da +index 000000000000..3bb9492dad49 --- /dev/null +++ b/Documentation/arm/stm32/stm32mp13-overview.rst @@ -0,0 +1,37 @@ @@ -69,7 +69,7 @@ index 000000000..3bb9492da + +- Alexandre Torgue diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 644875d73..37b833761 100644 +index 644875d73ba1..37b8337617d7 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1244,7 +1244,7 @@ choice @@ -82,7 +82,7 @@ index 644875d73..37b833761 100644 help Say Y here if you want kernel low-level debugging support diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig -index 57699bd8f..ab6978451 100644 +index 57699bd8f107..ab69784518c9 100644 --- a/arch/arm/mach-stm32/Kconfig +++ b/arch/arm/mach-stm32/Kconfig @@ -46,8 +46,17 @@ if ARCH_MULTI_V7 @@ -104,7 +104,7 @@ index 57699bd8f..ab6978451 100644 endif diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c -index a766310d8..9ff06f2fc 100644 +index a766310d8dca..9ff06f2fcbf4 100644 --- a/arch/arm/mach-stm32/board-dt.c +++ b/arch/arm/mach-stm32/board-dt.c @@ -18,6 +18,11 @@ static const char *const stm32_compat[] __initconst = { @@ -120,5 +120,5 @@ index a766310d8..9ff06f2fc 100644 NULL }; -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0002-ARM-5.15.24-stm32mp1-r1-CLOCK.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0002-v5.15-stm32mp-r2-CLOCK.patch similarity index 72% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0002-ARM-5.15.24-stm32mp1-r1-CLOCK.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0002-v5.15-stm32mp-r2-CLOCK.patch index 594488e..4694f8d 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0002-ARM-5.15.24-stm32mp1-r1-CLOCK.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0002-v5.15-stm32mp-r2-CLOCK.patch @@ -1,27 +1,27 @@ -From 696e5d9592c88d2e0137dafa02cd293eb2776d15 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:50:45 +0200 -Subject: [PATCH 02/22] ARM-5.15.24-stm32mp1-r1-CLOCK +From 7fce50075a5475b4af7b4918076e0577457530c9 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:22:35 +0100 +Subject: [PATCH 02/22] v5.15-stm32mp-r2 CLOCK -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- drivers/clk/Kconfig | 5 + drivers/clk/Makefile | 1 + drivers/clk/clk-composite.c | 15 + drivers/clk/clk-scmi.c | 36 + - drivers/clk/clk-stm32mp1.c | 471 ++++-- + drivers/clk/clk-stm32mp1.c | 1656 ++++++++++++++++-- drivers/clk/clk.c | 7 +- drivers/clk/stm32/Makefile | 1 + - drivers/clk/stm32/clk-stm32-core.c | 722 ++++++++ - drivers/clk/stm32/clk-stm32-core.h | 243 +++ - drivers/clk/stm32/clk-stm32mp13.c | 1062 ++++++++++++ - drivers/clk/stm32/reset-stm32.c | 122 ++ + drivers/clk/stm32/clk-stm32-core.c | 864 ++++++++++ + drivers/clk/stm32/clk-stm32-core.h | 272 +++ + drivers/clk/stm32/clk-stm32mp13.c | 1760 ++++++++++++++++++++ + drivers/clk/stm32/reset-stm32.c | 161 ++ drivers/clk/stm32/reset-stm32.h | 7 + - drivers/clk/stm32/stm32mp13_rcc.h | 1751 ++++++++++++++++++++ + drivers/clk/stm32/stm32mp13_rcc.h | 1751 +++++++++++++++++++ drivers/clocksource/timer-stm32-lp.c | 4 +- include/dt-bindings/clock/stm32mp1-clks.h | 52 +- - include/dt-bindings/clock/stm32mp13-clks.h | 229 +++ - 16 files changed, 4521 insertions(+), 207 deletions(-) + include/dt-bindings/clock/stm32mp13-clks.h | 235 +++ + 16 files changed, 6619 insertions(+), 208 deletions(-) create mode 100644 drivers/clk/stm32/Makefile create mode 100644 drivers/clk/stm32/clk-stm32-core.c create mode 100644 drivers/clk/stm32/clk-stm32-core.h @@ -32,7 +32,7 @@ Signed-off-by: Christophe Priouzeau create mode 100644 include/dt-bindings/clock/stm32mp13-clks.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig -index c5b3dc973..c23287f7d 100644 +index c5b3dc97396a..c23287f7d108 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -334,6 +334,11 @@ config COMMON_CLK_VC5 @@ -48,7 +48,7 @@ index c5b3dc973..c23287f7d 100644 def_bool COMMON_CLK && MACH_STM32MP157 help diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index e42312121..6172bc25b 100644 +index e42312121e51..6172bc25bfe0 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -109,6 +109,7 @@ obj-y += socfpga/ @@ -60,7 +60,7 @@ index e42312121..6172bc25b 100644 obj-$(CONFIG_SUNXI_CCU) += sunxi-ng/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c -index 510a99656..8fcbb34de 100644 +index 510a9965633b..8fcbb34de2cd 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -42,6 +42,18 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, @@ -93,7 +93,7 @@ index 510a99656..8fcbb34de 100644 clk_composite_ops->determine_rate = clk_composite_determine_rate; diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c -index 1e357d364..3e87eefa8 100644 +index 1e357d364ca2..3e87eefa802f 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -9,6 +9,7 @@ @@ -161,10 +161,10 @@ index 1e357d364..3e87eefa8 100644 static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c -index 4bd1fe7d8..c0b3dc0e8 100644 +index 4bd1fe7d8af4..e50d27ccd9a9 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c -@@ -116,7 +116,7 @@ static const char * const ref3_parents[] = { +@@ -116,11 +116,11 @@ static const char * const ref3_parents[] = { }; static const char * const ref4_parents[] = { @@ -173,6 +173,11 @@ index 4bd1fe7d8..c0b3dc0e8 100644 }; static const char * const cpu_src[] = { +- "ck_hsi", "ck_hse", "pll1_p" ++ "ck_hsi", "ck_hse", "pll1_p", "pll1_p_div" + }; + + static const char * const axi_src[] = { @@ -294,6 +294,7 @@ static const struct clk_div_table ck_trace_div_table[] = { struct stm32_mmux { u8 nbr_clk; @@ -209,15 +214,12 @@ index 4bd1fe7d8..c0b3dc0e8 100644 + struct clk_mux *mux = to_clk_mux(mux_hw); + struct stm32_clk_mmux *clk_mmux = to_clk_mmux(mux); + int i = 0; -+ + +-#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw) + for (i = 0; i < clk_mmux->mmux->nbr_clk; i++) + if (__clk_is_enabled(clk_mmux->mmux->hws[i]->clk)) + return false; --#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw) -+ return true; -+} - -#define PLL_ON BIT(0) -#define PLL_RDY BIT(1) -#define DIVN_MASK 0x1FF @@ -230,9 +232,12 @@ index 4bd1fe7d8..c0b3dc0e8 100644 -#define FRACLE BIT(16) -#define PLL_MUX_SHIFT 0 -#define PLL_MUX_MASK 3 -+#define MMUX_SAFE_POSITION 0 ++ return true; ++} -static int __pll_is_enabled(struct clk_hw *hw) ++#define MMUX_SAFE_POSITION 0 ++ +static int clk_mmux_set_safe_position(struct clk_hw *hw) { - struct stm32_pll_obj *clk_elem = to_pll(hw); @@ -363,8 +368,7 @@ index 4bd1fe7d8..c0b3dc0e8 100644 + .disable = mp1_mgate_clk_disable_safe, + .is_enabled = clk_gate_is_enabled, +}; - -- reg = readl_relaxed(clk_elem->reg + 4); ++ +/* STM32 PLL */ +struct clk_pll_fractional_divider { + struct clk_hw hw; @@ -379,23 +383,18 @@ index 4bd1fe7d8..c0b3dc0e8 100644 + void __iomem *freg; + u8 fshift; + u8 fwidth; - -- divm = ((reg >> DIVM_SHIFT) & DIVM_MASK) + 1; -- divn = ((reg >> DIVN_SHIFT) & DIVN_MASK) + 1; -- rate = (u64)parent_rate * divn; ++ + /* lock pll enable/disable registers */ + spinlock_t *lock; +}; -- do_div(rate, divm); +- reg = readl_relaxed(clk_elem->reg + 4); +#define to_pll_fractional_divider(_hw)\ + container_of(_hw, struct clk_pll_fractional_divider, hw) -- frac = pll_frac_val(hw); -- if (frac) { -- rate_frac = (u64)parent_rate * (u64)frac; -- do_div(rate_frac, (divm * 8192)); -- } +- divm = ((reg >> DIVM_SHIFT) & DIVM_MASK) + 1; +- divn = ((reg >> DIVN_SHIFT) & DIVN_MASK) + 1; +- rate = (u64)parent_rate * divn; +static unsigned long clk_pll_frac_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ @@ -420,16 +419,22 @@ index 4bd1fe7d8..c0b3dc0e8 100644 + if (!n || !m) + return parent_rate; -- return rate + rate_frac; +- do_div(rate, divm); + rate = (u64)parent_rate * n; + do_div(rate, m); -+ + +- frac = pll_frac_val(hw); +- if (frac) { +- rate_frac = (u64)parent_rate * (u64)frac; +- do_div(rate_frac, (divm * 8192)); + val = readl(fd->freg); + f = (val & fmask) >> fd->fshift; + if (f) { + frate = (u64)parent_rate * (u64)f; + do_div(frate, (m * (1 << fd->fwidth))); -+ } + } +- +- return rate + rate_frac; + return rate + frate; } @@ -874,11 +879,1212 @@ index 4bd1fe7d8..c0b3dc0e8 100644 _GATE(RCC_DBGCFGR, 9, 0), _NO_MUX, _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)), +@@ -2338,6 +2455,8 @@ static int stm32_rcc_init(struct device *dev, void __iomem *base, + return 0; + } + ++static void stm32_clk_summary_debugfs_create(struct device *dev, void __iomem *base); ++ + static int stm32mp1_rcc_init(struct device *dev) + { + void __iomem *base; +@@ -2358,6 +2477,8 @@ static int stm32mp1_rcc_init(struct device *dev) + iounmap(base); + + of_node_put(dev_of_node(dev)); ++ } else { ++ stm32_clk_summary_debugfs_create(dev, base); + } + + return ret; +@@ -2429,3 +2550,1182 @@ static int __init stm32mp1_clocks_init(void) + return platform_driver_register(&stm32mp1_rcc_clocks_driver); + } + core_initcall(stm32mp1_clocks_init); ++ ++#ifdef CONFIG_DEBUG_FS ++ ++#include ++ ++#define NO_STM32_MUX 0xFFFF ++#define NO_STM32_DIV 0xFFFF ++#define NO_STM32_GATE 0xFFFF ++ ++enum enum_gate_cfg { ++ GATE_HSI, ++ GATE_CSI, ++ GATE_LSI, ++ GATE_HSE, ++ GATE_LSE, ++ GATE_PLL1, ++ GATE_PLL2, ++ GATE_PLL3, ++ GATE_PLL4, ++ GATE_PLL1_DIVP, ++ GATE_PLL1_DIVQ, ++ GATE_PLL1_DIVR, ++ GATE_PLL2_DIVP, ++ GATE_PLL2_DIVQ, ++ GATE_PLL2_DIVR, ++ GATE_PLL3_DIVP, ++ GATE_PLL3_DIVQ, ++ GATE_PLL3_DIVR, ++ GATE_PLL4_DIVP, ++ GATE_PLL4_DIVQ, ++ GATE_PLL4_DIVR, ++ GATE_RTCCK, ++ GATE_MCO1, ++ GATE_MCO2, ++ GATE_DBGCK, ++ GATE_TRACECK, ++ GATE_SAI1, ++ GATE_SAI2, ++ GATE_SAI3, ++ GATE_SAI4, ++ GATE_SPI1, ++ GATE_SPI2, ++ GATE_SPI3, ++ GATE_SPI4, ++ GATE_SPI5, ++ GATE_SPI6, ++ GATE_SPDIF, ++ GATE_I2C1, ++ GATE_I2C2, ++ GATE_I2C3, ++ GATE_I2C4, ++ GATE_I2C5, ++ GATE_I2C6, ++ GATE_USART2, ++ GATE_UART4, ++ GATE_USART3, ++ GATE_UART5, ++ GATE_USART1, ++ GATE_USART6, ++ GATE_UART7, ++ GATE_UART8, ++ GATE_LPTIM1, ++ GATE_LPTIM2, ++ GATE_LPTIM3, ++ GATE_LPTIM4, ++ GATE_LPTIM5, ++ GATE_LTDC, ++ GATE_DSI, ++ GATE_QSPI, ++ GATE_FMC, ++ GATE_SDMMC1, ++ GATE_SDMMC2, ++ GATE_SDMMC3, ++ GATE_USBO, ++ GATE_USBPHY, ++ GATE_RNG1, ++ GATE_RNG2, ++ GATE_FDCAN, ++ GATE_DAC12, ++ GATE_CEC, ++ GATE_ADC12, ++ GATE_GPU, ++ GATE_STGEN, ++ GATE_DFSDM, ++ GATE_ADFSDM, ++ GATE_TIM2, ++ GATE_TIM3, ++ GATE_TIM4, ++ GATE_TIM5, ++ GATE_TIM6, ++ GATE_TIM7, ++ GATE_TIM12, ++ GATE_TIM13, ++ GATE_TIM14, ++ GATE_MDIO, ++ GATE_TIM1, ++ GATE_TIM8, ++ GATE_TIM15, ++ GATE_TIM16, ++ GATE_TIM17, ++ GATE_SYSCFG, ++ GATE_VREF, ++ GATE_TMPSENS, ++ GATE_PMBCTRL, ++ GATE_HDP, ++ GATE_IWDG2, ++ GATE_STGENRO, ++ GATE_DMA1, ++ GATE_DMA2, ++ GATE_DMAMUX, ++ GATE_DCMI, ++ GATE_CRYP2, ++ GATE_HASH2, ++ GATE_CRC2, ++ GATE_HSEM, ++ GATE_IPCC, ++ GATE_GPIOA, ++ GATE_GPIOB, ++ GATE_GPIOC, ++ GATE_GPIOD, ++ GATE_GPIOE, ++ GATE_GPIOF, ++ GATE_GPIOG, ++ GATE_GPIOH, ++ GATE_GPIOI, ++ GATE_GPIOJ, ++ GATE_GPIOK, ++ GATE_MDMA, ++ GATE_ETHCK, ++ GATE_ETHTX, ++ GATE_ETHRX, ++ GATE_ETHMAC, ++ GATE_CRC1, ++ GATE_USBH, ++ GATE_ETHSTP, ++ GATE_RTCAPB, ++ GATE_TZC1, ++ GATE_TZC2, ++ GATE_TZPC, ++ GATE_IWDG1, ++ GATE_BSEC, ++ GATE_GPIOZ, ++ GATE_CRYP1, ++ GATE_HASH1, ++ GATE_BKPSRAM, ++ GATE_DDRPERFM, ++ ++ GATE_NB ++}; ++ ++struct cs_gate_cfg { ++ u16 offset; ++ u8 bit_idx; ++}; ++ ++#define CFG_GATE(_id, _offset, _bit_idx)\ ++ [(_id)] = {\ ++ .offset = (_offset),\ ++ .bit_idx = (_bit_idx),\ ++ } ++ ++static struct cs_gate_cfg stm32mp15_gates[] = { ++ CFG_GATE(GATE_HSI, RCC_OCENSETR, 0), ++ CFG_GATE(GATE_CSI, RCC_OCENSETR, 4), ++ CFG_GATE(GATE_LSI, RCC_RDLSICR, 0), ++ CFG_GATE(GATE_HSE, RCC_OCENSETR, 8), ++ CFG_GATE(GATE_LSE, RCC_BDCR, 0), ++ CFG_GATE(GATE_RTCCK, RCC_BDCR, 20), ++ CFG_GATE(GATE_PLL1, RCC_PLL1CR, 0), ++ CFG_GATE(GATE_PLL1_DIVP, RCC_PLL1CR, 4), ++ CFG_GATE(GATE_PLL1_DIVQ, RCC_PLL1CR, 5), ++ CFG_GATE(GATE_PLL1_DIVR, RCC_PLL1CR, 6), ++ CFG_GATE(GATE_PLL2, RCC_PLL2CR, 0), ++ CFG_GATE(GATE_PLL2_DIVP, RCC_PLL2CR, 4), ++ CFG_GATE(GATE_PLL2_DIVQ, RCC_PLL2CR, 5), ++ CFG_GATE(GATE_PLL2_DIVR, RCC_PLL2CR, 6), ++ CFG_GATE(GATE_PLL3, RCC_PLL3CR, 0), ++ CFG_GATE(GATE_PLL3_DIVP, RCC_PLL3CR, 4), ++ CFG_GATE(GATE_PLL3_DIVQ, RCC_PLL3CR, 5), ++ CFG_GATE(GATE_PLL3_DIVR, RCC_PLL3CR, 6), ++ CFG_GATE(GATE_PLL4, RCC_PLL4CR, 0), ++ CFG_GATE(GATE_PLL4_DIVP, RCC_PLL4CR, 4), ++ CFG_GATE(GATE_PLL4_DIVQ, RCC_PLL4CR, 5), ++ CFG_GATE(GATE_PLL4_DIVR, RCC_PLL4CR, 6), ++ CFG_GATE(GATE_MCO1, RCC_MCO1CFGR, 12), ++ CFG_GATE(GATE_MCO2, RCC_MCO2CFGR, 12), ++ CFG_GATE(GATE_DBGCK, RCC_DBGCFGR, 8), ++ CFG_GATE(GATE_TRACECK, RCC_DBGCFGR, 9), ++ CFG_GATE(GATE_MDIO, RCC_APB1ENSETR, 31), ++ CFG_GATE(GATE_DAC12, RCC_APB1ENSETR, 29), ++ CFG_GATE(GATE_CEC, RCC_APB1ENSETR, 27), ++ CFG_GATE(GATE_SPDIF, RCC_APB1ENSETR, 26), ++ CFG_GATE(GATE_I2C5, RCC_APB1ENSETR, 24), ++ CFG_GATE(GATE_I2C3, RCC_APB1ENSETR, 23), ++ CFG_GATE(GATE_I2C2, RCC_APB1ENSETR, 22), ++ CFG_GATE(GATE_I2C1, RCC_APB1ENSETR, 21), ++ CFG_GATE(GATE_UART8, RCC_APB1ENSETR, 19), ++ CFG_GATE(GATE_UART7, RCC_APB1ENSETR, 18), ++ CFG_GATE(GATE_UART5, RCC_APB1ENSETR, 17), ++ CFG_GATE(GATE_UART4, RCC_APB1ENSETR, 16), ++ CFG_GATE(GATE_USART3, RCC_APB1ENSETR, 15), ++ CFG_GATE(GATE_USART2, RCC_APB1ENSETR, 14), ++ CFG_GATE(GATE_SPI3, RCC_APB1ENSETR, 12), ++ CFG_GATE(GATE_SPI2, RCC_APB1ENSETR, 11), ++ CFG_GATE(GATE_LPTIM1, RCC_APB1ENSETR, 9), ++ CFG_GATE(GATE_TIM14, RCC_APB1ENSETR, 8), ++ CFG_GATE(GATE_TIM13, RCC_APB1ENSETR, 7), ++ CFG_GATE(GATE_TIM12, RCC_APB1ENSETR, 6), ++ CFG_GATE(GATE_TIM7, RCC_APB1ENSETR, 5), ++ CFG_GATE(GATE_TIM6, RCC_APB1ENSETR, 4), ++ CFG_GATE(GATE_TIM5, RCC_APB1ENSETR, 3), ++ CFG_GATE(GATE_TIM4, RCC_APB1ENSETR, 2), ++ CFG_GATE(GATE_TIM3, RCC_APB1ENSETR, 1), ++ CFG_GATE(GATE_TIM2, RCC_APB1ENSETR, 0), ++ CFG_GATE(GATE_FDCAN, RCC_APB2ENSETR, 24), ++ CFG_GATE(GATE_ADFSDM, RCC_APB2ENSETR, 21), ++ CFG_GATE(GATE_DFSDM, RCC_APB2ENSETR, 20), ++ CFG_GATE(GATE_SAI3, RCC_APB2ENSETR, 18), ++ CFG_GATE(GATE_SAI2, RCC_APB2ENSETR, 17), ++ CFG_GATE(GATE_SAI1, RCC_APB2ENSETR, 16), ++ CFG_GATE(GATE_USART6, RCC_APB2ENSETR, 13), ++ CFG_GATE(GATE_SPI5, RCC_APB2ENSETR, 10), ++ CFG_GATE(GATE_SPI4, RCC_APB2ENSETR, 9), ++ CFG_GATE(GATE_SPI1, RCC_APB2ENSETR, 8), ++ CFG_GATE(GATE_TIM17, RCC_APB2ENSETR, 4), ++ CFG_GATE(GATE_TIM16, RCC_APB2ENSETR, 3), ++ CFG_GATE(GATE_TIM15, RCC_APB2ENSETR, 2), ++ CFG_GATE(GATE_TIM8, RCC_APB2ENSETR, 1), ++ CFG_GATE(GATE_TIM1, RCC_APB2ENSETR, 0), ++ CFG_GATE(GATE_HDP, RCC_APB3ENSETR, 20), ++ CFG_GATE(GATE_PMBCTRL, RCC_APB3ENSETR, 17), ++ CFG_GATE(GATE_TMPSENS, RCC_APB3ENSETR, 16), ++ CFG_GATE(GATE_VREF, RCC_APB3ENSETR, 13), ++ CFG_GATE(GATE_SYSCFG, RCC_APB3ENSETR, 11), ++ CFG_GATE(GATE_SAI4, RCC_APB3ENSETR, 8), ++ CFG_GATE(GATE_LPTIM5, RCC_APB3ENSETR, 3), ++ CFG_GATE(GATE_LPTIM4, RCC_APB3ENSETR, 2), ++ CFG_GATE(GATE_LPTIM3, RCC_APB3ENSETR, 1), ++ CFG_GATE(GATE_LPTIM2, RCC_APB3ENSETR, 0), ++ CFG_GATE(GATE_STGENRO, RCC_APB4ENSETR, 20), ++ CFG_GATE(GATE_USBPHY, RCC_APB4ENSETR, 16), ++ CFG_GATE(GATE_IWDG2, RCC_APB4ENSETR, 15), ++ CFG_GATE(GATE_DDRPERFM, RCC_APB4ENSETR, 8), ++ CFG_GATE(GATE_DSI, RCC_APB4ENSETR, 4), ++ CFG_GATE(GATE_LTDC, RCC_APB4ENSETR, 0), ++ CFG_GATE(GATE_STGEN, RCC_APB5ENSETR, 20), ++ CFG_GATE(GATE_BSEC, RCC_APB5ENSETR, 16), ++ CFG_GATE(GATE_IWDG1, RCC_APB5ENSETR, 15), ++ CFG_GATE(GATE_TZPC, RCC_APB5ENSETR, 13), ++ CFG_GATE(GATE_TZC2, RCC_APB5ENSETR, 12), ++ CFG_GATE(GATE_TZC1, RCC_APB5ENSETR, 11), ++ CFG_GATE(GATE_RTCAPB, RCC_APB5ENSETR, 8), ++ CFG_GATE(GATE_USART1, RCC_APB5ENSETR, 4), ++ CFG_GATE(GATE_I2C6, RCC_APB5ENSETR, 3), ++ CFG_GATE(GATE_I2C4, RCC_APB5ENSETR, 2), ++ CFG_GATE(GATE_SPI6, RCC_APB5ENSETR, 0), ++ CFG_GATE(GATE_SDMMC3, RCC_AHB2ENSETR, 16), ++ CFG_GATE(GATE_USBO, RCC_AHB2ENSETR, 8), ++ CFG_GATE(GATE_ADC12, RCC_AHB2ENSETR, 5), ++ CFG_GATE(GATE_DMAMUX, RCC_AHB2ENSETR, 2), ++ CFG_GATE(GATE_DMA2, RCC_AHB2ENSETR, 1), ++ CFG_GATE(GATE_DMA1, RCC_AHB2ENSETR, 0), ++ CFG_GATE(GATE_IPCC, RCC_AHB3ENSETR, 12), ++ CFG_GATE(GATE_HSEM, RCC_AHB3ENSETR, 11), ++ CFG_GATE(GATE_CRC2, RCC_AHB3ENSETR, 7), ++ CFG_GATE(GATE_RNG2, RCC_AHB3ENSETR, 6), ++ CFG_GATE(GATE_HASH2, RCC_AHB3ENSETR, 5), ++ CFG_GATE(GATE_CRYP2, RCC_AHB3ENSETR, 4), ++ CFG_GATE(GATE_DCMI, RCC_AHB3ENSETR, 0), ++ CFG_GATE(GATE_GPIOK, RCC_AHB4ENSETR, 10), ++ CFG_GATE(GATE_GPIOJ, RCC_AHB4ENSETR, 9), ++ CFG_GATE(GATE_GPIOI, RCC_AHB4ENSETR, 8), ++ CFG_GATE(GATE_GPIOH, RCC_AHB4ENSETR, 7), ++ CFG_GATE(GATE_GPIOG, RCC_AHB4ENSETR, 6), ++ CFG_GATE(GATE_GPIOF, RCC_AHB4ENSETR, 5), ++ CFG_GATE(GATE_GPIOE, RCC_AHB4ENSETR, 4), ++ CFG_GATE(GATE_GPIOD, RCC_AHB4ENSETR, 3), ++ CFG_GATE(GATE_GPIOC, RCC_AHB4ENSETR, 2), ++ CFG_GATE(GATE_GPIOB, RCC_AHB4ENSETR, 1), ++ CFG_GATE(GATE_GPIOA, RCC_AHB4ENSETR, 0), ++ CFG_GATE(GATE_BKPSRAM, RCC_AHB5ENSETR, 8), ++ CFG_GATE(GATE_RNG1, RCC_AHB5ENSETR, 6), ++ CFG_GATE(GATE_HASH1, RCC_AHB5ENSETR, 5), ++ CFG_GATE(GATE_CRYP1, RCC_AHB5ENSETR, 4), ++ CFG_GATE(GATE_GPIOZ, RCC_AHB5ENSETR, 0), ++ CFG_GATE(GATE_USBH, RCC_AHB6ENSETR, 24), ++ CFG_GATE(GATE_CRC1, RCC_AHB6ENSETR, 20), ++ CFG_GATE(GATE_SDMMC2, RCC_AHB6ENSETR, 17), ++ CFG_GATE(GATE_SDMMC1, RCC_AHB6ENSETR, 16), ++ CFG_GATE(GATE_QSPI, RCC_AHB6ENSETR, 14), ++ CFG_GATE(GATE_FMC, RCC_AHB6ENSETR, 12), ++ CFG_GATE(GATE_ETHMAC, RCC_AHB6ENSETR, 10), ++ CFG_GATE(GATE_ETHRX, RCC_AHB6ENSETR, 9), ++ CFG_GATE(GATE_ETHTX, RCC_AHB6ENSETR, 8), ++ CFG_GATE(GATE_ETHCK, RCC_AHB6ENSETR, 7), ++ CFG_GATE(GATE_GPU, RCC_AHB6ENSETR, 5), ++ CFG_GATE(GATE_MDMA, RCC_AHB6ENSETR, 0), ++ CFG_GATE(GATE_ETHSTP, RCC_AHB6LPENSETR, 11), ++}; ++ ++enum enum_mux_cfg { ++ MUX_MPU, ++ MUX_AXI, ++ MUX_MCU, ++ MUX_PLL12, ++ MUX_PLL3, ++ MUX_PLL4, ++ MUX_CKPER, ++ MUX_RTC, ++ MUX_SDMMC12, ++ MUX_SDMMC3, ++ MUX_FMC, ++ MUX_QSPI, ++ MUX_RNG1, ++ MUX_RNG2, ++ MUX_USBPHY, ++ MUX_USBO, ++ MUX_STGEN, ++ MUX_SPDIF, ++ MUX_SPI1, ++ MUX_SPI23, ++ MUX_SPI45, ++ MUX_SPI6, ++ MUX_CEC, ++ MUX_I2C12, ++ MUX_I2C35, ++ MUX_I2C46, ++ MUX_LPTIM1, ++ MUX_LPTIM23, ++ MUX_LPTIM45, ++ MUX_USART1, ++ MUX_UART24, ++ MUX_UART35, ++ MUX_USART6, ++ MUX_UART78, ++ MUX_SAI1, ++ MUX_SAI2, ++ MUX_SAI3, ++ MUX_SAI4, ++ MUX_DSI, ++ MUX_FDCAN, ++ MUX_ADC12, ++ MUX_ETHCK, ++ MUX_MCO1, ++ MUX_MCO2, ++}; ++ ++struct cs_mux_cfg { ++ u16 offset; ++ u8 shift; ++ u8 width; ++ u8 flags; ++ u32 *table; ++}; ++ ++#define CFG_MUX(_id, _offset, _shift, _witdh, _flags)\ ++ [_id] = {\ ++ .offset = (_offset),\ ++ .shift = (_shift),\ ++ .width = (_witdh),\ ++ .flags = (_flags),\ ++ } ++ ++static const struct cs_mux_cfg stm32mp15_muxes[] = { ++ CFG_MUX(MUX_PLL12, RCC_RCK12SELR, 0, 2, 0), ++ CFG_MUX(MUX_PLL3, RCC_RCK3SELR, 0, 2, 0), ++ CFG_MUX(MUX_PLL4, RCC_RCK4SELR, 0, 2, 0), ++ CFG_MUX(MUX_CKPER, RCC_CPERCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_MPU, RCC_MPCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_AXI, RCC_ASSCKSELR, 0, 3, 0), ++ CFG_MUX(MUX_MCU, RCC_MSSCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_RTC, RCC_BDCR, 16, 2, 0), ++ CFG_MUX(MUX_SDMMC12, RCC_SDMMC12CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_SPI23, RCC_SPI2S23CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_SPI45, RCC_SPI2S45CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_I2C12, RCC_I2C12CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_I2C35, RCC_I2C35CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_LPTIM23, RCC_LPTIM23CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_UART24, RCC_UART24CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_UART35, RCC_UART35CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_UART78, RCC_UART78CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_SAI1, RCC_SAI1CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_ETHCK, RCC_ETHCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_I2C46, RCC_I2C46CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_RNG2, RCC_RNG2CKSELR, 0, 2, 0), ++ CFG_MUX(MUX_SDMMC3, RCC_SDMMC3CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_FMC, RCC_FMCCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_QSPI, RCC_QSPICKSELR, 0, 2, 0), ++ CFG_MUX(MUX_USBPHY, RCC_USBCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_USBO, RCC_USBCKSELR, 4, 1, 0), ++ CFG_MUX(MUX_SPDIF, RCC_SPDIFCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_SPI1, RCC_SPI2S1CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_CEC, RCC_CECCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_LPTIM1, RCC_LPTIM1CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_USART6, RCC_UART6CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_FDCAN, RCC_FDCANCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_SAI2, RCC_SAI2CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_SAI3, RCC_SAI3CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_SAI4, RCC_SAI4CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_ADC12, RCC_ADCCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_DSI, RCC_DSICKSELR, 0, 1, 0), ++ CFG_MUX(MUX_RNG1, RCC_RNG1CKSELR, 0, 2, 0), ++ CFG_MUX(MUX_STGEN, RCC_STGENCKSELR, 0, 2, 0), ++ CFG_MUX(MUX_USART1, RCC_UART1CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_SPI6, RCC_SPI6CKSELR, 0, 3, 0), ++ CFG_MUX(MUX_MCO1, RCC_MCO1CFGR, 0, 3, 0), ++ CFG_MUX(MUX_MCO2, RCC_MCO2CFGR, 0, 3, 0), ++}; ++ ++enum enum_div_cfg { ++ DIV_PLL1DIVP, ++ DIV_PLL2DIVP, ++ DIV_PLL2DIVQ, ++ DIV_PLL2DIVR, ++ DIV_PLL3DIVP, ++ DIV_PLL3DIVQ, ++ DIV_PLL3DIVR, ++ DIV_PLL4DIVP, ++ DIV_PLL4DIVQ, ++ DIV_PLL4DIVR, ++ DIV_MPU, ++ DIV_AXI, ++ DIV_MCU, ++ DIV_APB1, ++ DIV_APB2, ++ DIV_APB3, ++ DIV_APB4, ++ DIV_APB5, ++ DIV_RTC, ++ DIV_HSI, ++ DIV_MCO1, ++ DIV_MCO2, ++ DIV_TRACE, ++ DIV_ETHPTP, ++ DIV_NB ++}; ++ ++struct cs_div_cfg { ++ u16 offset; ++ u8 shift; ++ u8 width; ++ u8 flags; ++ const struct clk_div_table *table; ++}; ++ ++#define CFG_DIV(_id, _offset, _shift, _width, _flags, _table)\ ++ [(_id)] = {\ ++ .offset = (_offset),\ ++ .shift = (_shift),\ ++ .width = (_width),\ ++ .flags = (_flags),\ ++ .table = (_table),\ ++ } ++ ++static const struct cs_div_cfg stm32mp15_dividers[DIV_NB] = { ++ CFG_DIV(DIV_MPU, RCC_MPCKDIVR, 0, 4, 0, NULL), ++ CFG_DIV(DIV_AXI, RCC_AXIDIVR, 0, 3, 0, axi_div_table), ++ CFG_DIV(DIV_MCU, RCC_MCUDIVR, 0, 4, 0, mcu_div_table), ++ CFG_DIV(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table), ++ CFG_DIV(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table), ++ CFG_DIV(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table), ++ CFG_DIV(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table), ++ CFG_DIV(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table), ++ CFG_DIV(DIV_HSI, RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL), ++ CFG_DIV(DIV_PLL1DIVP, RCC_PLL1CFGR2, 0, 7, 0, NULL), ++ CFG_DIV(DIV_PLL2DIVP, RCC_PLL2CFGR2, 0, 7, 0, NULL), ++ CFG_DIV(DIV_PLL2DIVQ, RCC_PLL2CFGR2, 8, 7, 0, NULL), ++ CFG_DIV(DIV_PLL2DIVR, RCC_PLL2CFGR2, 16, 7, 0, NULL), ++ CFG_DIV(DIV_PLL3DIVP, RCC_PLL3CFGR2, 0, 7, 0, NULL), ++ CFG_DIV(DIV_PLL3DIVQ, RCC_PLL3CFGR2, 8, 7, 0, NULL), ++ CFG_DIV(DIV_PLL3DIVR, RCC_PLL3CFGR2, 16, 7, 0, NULL), ++ CFG_DIV(DIV_PLL4DIVP, RCC_PLL4CFGR2, 0, 7, 0, NULL), ++ CFG_DIV(DIV_PLL4DIVQ, RCC_PLL4CFGR2, 8, 7, 0, NULL), ++ CFG_DIV(DIV_PLL4DIVR, RCC_PLL4CFGR2, 16, 7, 0, NULL), ++ CFG_DIV(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL), ++ CFG_DIV(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL), ++ CFG_DIV(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL), ++ CFG_DIV(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table), ++ CFG_DIV(DIV_ETHPTP, RCC_ETHCKSELR, 4, 4, 0, NULL), ++}; ++ ++struct clk_stm32_clock_data { ++ const struct cs_gate_cfg *gates; ++ const struct cs_mux_cfg *muxes; ++ const struct cs_div_cfg *dividers; ++}; ++ ++struct clock_summary { ++ struct clk_summary *clocks; ++ int nb_clocks; ++ void __iomem *base; ++ struct clk_stm32_clock_data *clock_data; ++}; ++ ++struct clk_summary { ++ const char *name; ++ unsigned long rate; ++ int enabled; ++ int nb_parents; ++ int gate_id; ++ int mux_id; ++ int div_id; ++ void *data; ++ unsigned long (*get_rate)(struct clock_summary *cs, ++ struct clk_summary *c, ++ unsigned long parent_rate); ++ const char * const *parent_names; ++}; ++ ++static u8 clk_stm32_get_parent_mux(void __iomem *base, ++ struct clk_stm32_clock_data *data, ++ u16 mux_id) ++{ ++ const struct cs_mux_cfg *mux = &data->muxes[mux_id]; ++ u32 mask = BIT(mux->width) - 1; ++ u32 val; ++ ++ val = readl(base + mux->offset) >> mux->shift; ++ val &= mask; ++ ++ return val; ++} ++ ++static int clk_stm32_is_enabled_gate(void __iomem *base, ++ struct clk_stm32_clock_data *data, ++ u16 gate_id) ++{ ++ const struct cs_gate_cfg *gate = &data->gates[gate_id]; ++ ++ return (readl(base + gate->offset) & BIT(gate->bit_idx)) != 0; ++} ++ ++static unsigned int _get_table_div(const struct clk_div_table *table, ++ unsigned int val) ++{ ++ const struct clk_div_table *clkt; ++ ++ for (clkt = table; clkt->div; clkt++) ++ if (clkt->val == val) ++ return clkt->div; ++ return 0; ++} ++ ++static unsigned int _get_div(const struct clk_div_table *table, ++ unsigned int val, unsigned long flags, u8 width) ++{ ++ if (flags & CLK_DIVIDER_ONE_BASED) ++ return val; ++ if (flags & CLK_DIVIDER_POWER_OF_TWO) ++ return 1 << val; ++ if (table) ++ return _get_table_div(table, val); ++ return val + 1; ++} ++ ++static unsigned long clk_stm32_get_rate_divider(void __iomem *base, ++ struct clk_stm32_clock_data *data, ++ u16 div_id, ++ unsigned long parent_rate) ++{ ++ const struct cs_div_cfg *divider = &data->dividers[div_id]; ++ unsigned int val; ++ unsigned int div; ++ ++ val = readl(base + divider->offset) >> divider->shift; ++ val &= clk_div_mask(divider->width); ++ div = _get_div(divider->table, val, divider->flags, divider->width); ++ ++ if (!div) { ++ WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), ++ "%d: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", div_id); ++ return parent_rate; ++ } ++ ++ return DIV_ROUND_UP_ULL((u64)parent_rate, div); ++} ++ ++struct cs_pll { ++ u32 offset; ++}; ++ ++static unsigned long clk_summary_pll_frac_div_recalc_rate(struct clock_summary *cs, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ struct cs_pll *pll = (struct cs_pll *)c->data; ++ struct clk_pll_fractional_divider fracdiv; ++ struct clk_pll_fractional_divider *fd = &fracdiv; ++ void __iomem *reg; ++ u32 mmask; ++ u32 nmask; ++ u32 fmask; ++ unsigned long m, n, f; ++ u64 rate, frate = 0; ++ u32 val; ++ ++ reg = cs->base + pll->offset; ++ fd->mreg = reg + PLL_DIVMN_OFFSET; ++ fd->mshift = PLL_DIVM_SHIFT; ++ fd->mwidth = PLL_DIVM_WIDTH; ++ fd->mflags = CLK_FRAC_DIVIDER_ZERO_BASED; ++ fd->nreg = reg + PLL_DIVMN_OFFSET; ++ fd->nshift = PLL_DIVN_SHIFT; ++ fd->nwidth = PLL_DIVN_WIDTH; ++ fd->nflags = CLK_FRAC_DIVIDER_ZERO_BASED; ++ fd->freg = reg + PLL_FRAC_OFFSET; ++ fd->fshift = PLL_FRAC_SHIFT; ++ fd->fwidth = PLL_FRAC_WIDTH; ++ ++ mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift; ++ nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift; ++ fmask = GENMASK(fd->fwidth - 1, 0) << fd->fshift; ++ ++ val = readl(fd->mreg); ++ m = (val & mmask) >> fd->mshift; ++ if (fd->mflags & CLK_FRAC_DIVIDER_ZERO_BASED) ++ m++; ++ ++ val = readl(fd->nreg); ++ n = (val & nmask) >> fd->nshift; ++ if (fd->nflags & CLK_FRAC_DIVIDER_ZERO_BASED) ++ n++; ++ ++ if (!n || !m) ++ return parent_rate; ++ ++ rate = (u64)parent_rate * n; ++ do_div(rate, m); ++ ++ val = readl(fd->freg); ++ f = (val & fmask) >> fd->fshift; ++ if (f) { ++ frate = (u64)parent_rate * (u64)f; ++ do_div(frate, (m * (1 << fd->fwidth))); ++ } ++ ++ return rate + frate; ++} ++ ++static unsigned long clk_summary_hsediv2_recalc_rate(struct clock_summary *cs, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ return parent_rate / 2; ++} ++ ++static unsigned long clk_summary_osc_recalc_rate(struct clock_summary *cs, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ struct clk *clk = __clk_lookup(c->name); ++ ++ if (clk) ++ return clk_get_rate(clk); ++ ++ return 0; ++} ++ ++static unsigned long clk_summary_div_recalc_rate(struct clock_summary *cs, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ return clk_stm32_get_rate_divider(cs->base, cs->clock_data, c->div_id, parent_rate); ++} ++ ++static unsigned long clk_summary_rtc_recalc_rate(struct clock_summary *cs, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ u8 parent; ++ ++ parent = clk_stm32_get_parent_mux(cs->base, cs->clock_data, c->mux_id); ++ if (parent == HSE_RTC) ++ return clk_summary_div_recalc_rate(cs, c, parent_rate); ++ ++ return parent_rate; ++} ++ ++struct cs_stm32_timer { ++ u32 apbdiv; ++ u32 timpre; ++}; ++ ++static unsigned long clk_stm32_timer_recalc_rate(struct clock_summary *cs, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ struct cs_stm32_timer *tim = (struct cs_stm32_timer *)c->data; ++ void __iomem *rcc_base = cs->base; ++ u32 prescaler, timpre; ++ ++ prescaler = readl(rcc_base + tim->apbdiv) & APB_DIV_MASK; ++ ++ timpre = readl(rcc_base + tim->timpre) & TIM_PRE_MASK; ++ ++ if (prescaler == 0U) ++ return parent_rate; ++ ++ return parent_rate * (timpre + 1U) * 2U; ++} ++ ++#define CS_OSC(_name, _gate) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 0,\ ++ .gate_id = _gate,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = NO_STM32_DIV,\ ++ .get_rate = clk_summary_osc_recalc_rate,\ ++} ++ ++#define CS_DIV2(_name, _parent) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .gate_id = NO_STM32_GATE,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = NO_STM32_DIV,\ ++ .get_rate = clk_summary_hsediv2_recalc_rate,\ ++} ++ ++#define CS_PLL(_name, _parents, _gate, _mux, _offset)\ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = NO_STM32_DIV,\ ++ .data = &(struct cs_pll) {\ ++ .offset = _offset,\ ++ },\ ++ .get_rate = clk_summary_pll_frac_div_recalc_rate,\ ++} ++ ++#define CS_DIV(_name, _parent, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .div_id = _div,\ ++ .gate_id = NO_STM32_GATE,\ ++ .mux_id = NO_STM32_MUX,\ ++ .get_rate = clk_summary_div_recalc_rate,\ ++} ++ ++#define CS_MUX(_name, _parents, _mux) \ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .mux_id = _mux,\ ++ .gate_id = NO_STM32_GATE,\ ++ .div_id = NO_STM32_DIV,\ ++} ++ ++#define CS_GATE(_name, _parent, _gate) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .gate_id = _gate,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = NO_STM32_DIV,\ ++} ++ ++#define CS_GATEDIV(_name, _parent, _gate, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .gate_id = _gate,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = _div,\ ++ .get_rate = clk_summary_div_recalc_rate,\ ++} ++ ++#define CS_GATEMUX(_name, _parents, _gate, _mux) \ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = NO_STM32_DIV,\ ++} ++ ++#define CS_COMPOSITE(_name, _parents, _gate, _mux, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = _div,\ ++ .get_rate = clk_summary_div_recalc_rate,\ ++} ++ ++#define CS_RTC(_name, _parents, _gate, _mux, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = _div,\ ++ .get_rate = clk_summary_rtc_recalc_rate,\ ++} ++ ++#define CS_STM32_TIMER(_name, _parent, _apbdiv, _timpre) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .div_id = NO_STM32_DIV,\ ++ .gate_id = NO_STM32_GATE,\ ++ .mux_id = NO_STM32_MUX,\ ++ .data = &(struct cs_stm32_timer) {\ ++ .apbdiv = _apbdiv,\ ++ .timpre = _timpre,\ ++ },\ ++ .get_rate = clk_stm32_timer_recalc_rate,\ ++} ++ ++static struct clk_summary stm32mp15_clock_summary[] = { ++ CS_OSC("ck_hsi", GATE_HSI), ++ CS_OSC("ck_csi", GATE_CSI), ++ CS_OSC("ck_lsi", GATE_LSI), ++ CS_OSC("ck_hse", GATE_HSE), ++ CS_OSC("ck_lse", GATE_LSE), ++ CS_OSC("ck_usbo_48m", NO_STM32_GATE), ++ CS_DIV2("clk-hse-div2", "ck_hse"), ++ CS_MUX("ck_per", per_src, MUX_CKPER), ++ ++ CS_PLL("pll1", ref12_parents, GATE_PLL1, MUX_PLL12, RCC_PLL1CR), ++ CS_GATEDIV("pll1_p", "pll1", GATE_PLL1_DIVP, DIV_PLL1DIVP), ++ ++ CS_DIV("pll1_p_div", "pll1_p", DIV_MPU), ++ ++ CS_PLL("pll2", ref12_parents, GATE_PLL2, MUX_PLL12, RCC_PLL2CR), ++ CS_GATEDIV("pll2_p", "pll2", GATE_PLL2_DIVP, DIV_PLL2DIVP), ++ CS_GATEDIV("pll2_q", "pll2", GATE_PLL2_DIVQ, DIV_PLL2DIVQ), ++ CS_GATEDIV("pll2_r", "pll2", GATE_PLL2_DIVR, DIV_PLL2DIVR), ++ ++ CS_PLL("pll3", ref3_parents, GATE_PLL3, MUX_PLL3, RCC_PLL3CR), ++ CS_GATEDIV("pll3_p", "pll3", GATE_PLL3_DIVP, DIV_PLL3DIVP), ++ CS_GATEDIV("pll3_q", "pll3", GATE_PLL3_DIVQ, DIV_PLL3DIVQ), ++ CS_GATEDIV("pll3_r", "pll3", GATE_PLL3_DIVR, DIV_PLL3DIVR), ++ ++ CS_PLL("pll4", ref4_parents, GATE_PLL4, MUX_PLL4, RCC_PLL4CR), ++ CS_GATEDIV("pll4_p", "pll4", GATE_PLL4_DIVP, DIV_PLL4DIVP), ++ CS_GATEDIV("pll4_q", "pll4", GATE_PLL4_DIVQ, DIV_PLL4DIVQ), ++ CS_GATEDIV("pll4_r", "pll4", GATE_PLL4_DIVR, DIV_PLL4DIVR), ++ ++ CS_MUX("ck_mpu", cpu_src, MUX_MPU), ++ CS_MUX("ck_axi", axi_src, MUX_AXI), ++ CS_MUX("ck_mcu", mcu_src, MUX_MCU), ++ ++ CS_DIV("pclk1", "ck_mcu", DIV_APB1), ++ CS_DIV("pclk2", "ck_mcu", DIV_APB2), ++ CS_DIV("pclk3", "ck_mcu", DIV_APB3), ++ CS_DIV("pclk4", "ck_axi", DIV_APB4), ++ CS_DIV("pclk5", "ck_axi", DIV_APB5), ++ ++ CS_STM32_TIMER("ck1_tim", "pclk1", RCC_APB1DIVR, RCC_TIMG1PRER), ++ CS_STM32_TIMER("ck2_tim", "pclk2", RCC_APB2DIVR, RCC_TIMG2PRER), ++ ++ CS_GATE("tim2_k", "ck1_tim", GATE_TIM2), ++ CS_GATE("tim3_k", "ck1_tim", GATE_TIM3), ++ CS_GATE("tim4_k", "ck1_tim", GATE_TIM4), ++ CS_GATE("tim5_k", "ck1_tim", GATE_TIM5), ++ CS_GATE("tim6_k", "ck1_tim", GATE_TIM6), ++ CS_GATE("tim7_k", "ck1_tim", GATE_TIM7), ++ CS_GATE("tim12_k", "ck1_tim", GATE_TIM12), ++ CS_GATE("tim13_k", "ck1_tim", GATE_TIM13), ++ CS_GATE("tim14_k", "ck1_tim", GATE_TIM14), ++ CS_GATE("tim1_k", "ck2_tim", GATE_TIM1), ++ CS_GATE("tim8_k", "ck2_tim", GATE_TIM8), ++ CS_GATE("tim15_k", "ck2_tim", GATE_TIM15), ++ CS_GATE("tim16_k", "ck2_tim", GATE_TIM16), ++ CS_GATE("tim17_k", "ck2_tim", GATE_TIM17), ++ ++ CS_GATE("tim2", "pclk1", GATE_TIM2), ++ CS_GATE("tim3", "pclk1", GATE_TIM3), ++ CS_GATE("tim4", "pclk1", GATE_TIM4), ++ CS_GATE("tim5", "pclk1", GATE_TIM5), ++ CS_GATE("tim6", "pclk1", GATE_TIM6), ++ CS_GATE("tim7", "pclk1", GATE_TIM7), ++ CS_GATE("tim12", "pclk1", GATE_TIM12), ++ CS_GATE("tim13", "pclk1", GATE_TIM13), ++ CS_GATE("tim14", "pclk1", GATE_TIM14), ++ CS_GATE("lptim1", "pclk1", GATE_LPTIM1), ++ CS_GATE("spi2", "pclk1", GATE_SPI2), ++ CS_GATE("spi3", "pclk1", GATE_SPI3), ++ CS_GATE("usart2", "pclk1", GATE_USART2), ++ CS_GATE("usart3", "pclk1", GATE_USART3), ++ CS_GATE("uart4", "pclk1", GATE_UART4), ++ CS_GATE("uart5", "pclk1", GATE_UART5), ++ CS_GATE("uart7", "pclk1", GATE_UART7), ++ CS_GATE("uart8", "pclk1", GATE_UART8), ++ CS_GATE("i2c1", "pclk1", GATE_I2C1), ++ CS_GATE("i2c2", "pclk1", GATE_I2C2), ++ CS_GATE("i2c3", "pclk1", GATE_I2C3), ++ CS_GATE("i2c5", "pclk1", GATE_I2C5), ++ CS_GATE("spdif", "pclk1", GATE_SPDIF), ++ CS_GATE("cec", "pclk1", GATE_CEC), ++ CS_GATE("dac12", "pclk1", GATE_DAC12), ++ CS_GATE("mdio", "pclk1", GATE_MDIO), ++ CS_GATE("tim1", "pclk2", GATE_TIM1), ++ CS_GATE("tim8", "pclk2", GATE_TIM8), ++ CS_GATE("tim15", "pclk2", GATE_TIM15), ++ CS_GATE("tim16", "pclk2", GATE_TIM16), ++ CS_GATE("tim17", "pclk2", GATE_TIM17), ++ CS_GATE("spi1", "pclk2", GATE_SPI1), ++ CS_GATE("spi4", "pclk2", GATE_SPI4), ++ CS_GATE("spi5", "pclk2", GATE_SPI5), ++ CS_GATE("usart6", "pclk2", GATE_USART6), ++ CS_GATE("sai1", "pclk2", GATE_SAI1), ++ CS_GATE("sai2", "pclk2", GATE_SAI2), ++ CS_GATE("sai3", "pclk2", GATE_SAI3), ++ CS_GATE("dfsdm", "pclk2", GATE_DFSDM), ++ CS_GATE("fdcan", "pclk2", GATE_FDCAN), ++ CS_GATE("lptim2", "pclk3", GATE_LPTIM2), ++ CS_GATE("lptim3", "pclk3", GATE_LPTIM3), ++ CS_GATE("lptim4", "pclk3", GATE_LPTIM4), ++ CS_GATE("lptim5", "pclk3", GATE_LPTIM5), ++ CS_GATE("sai4", "pclk3", GATE_SAI4), ++ CS_GATE("syscfg", "pclk3", GATE_SYSCFG), ++ CS_GATE("vref", "pclk3", GATE_VREF), ++ CS_GATE("tmpsens", "pclk3", GATE_TMPSENS), ++ CS_GATE("pmbctrl", "pclk3", GATE_PMBCTRL), ++ CS_GATE("hdp", "pclk3", GATE_HDP), ++ CS_GATE("ltdc", "pclk4", GATE_LTDC), ++ CS_GATE("dsi", "pclk4", GATE_DSI), ++ CS_GATE("iwdg2", "pclk4", GATE_IWDG2), ++ CS_GATE("usbphy", "pclk4", GATE_USBPHY), ++ CS_GATE("stgenro", "pclk4", GATE_STGENRO), ++ CS_GATE("spi6", "pclk5", GATE_SPI6), ++ CS_GATE("i2c4", "pclk5", GATE_I2C4), ++ CS_GATE("i2c6", "pclk5", GATE_I2C6), ++ CS_GATE("usart1", "pclk5", GATE_USART1), ++ CS_GATE("rtcapb", "pclk5", GATE_RTCAPB), ++ CS_GATE("tzc1", "ck_axi", GATE_TZC1), ++ CS_GATE("tzc2", "ck_axi", GATE_TZC2), ++ CS_GATE("tzpc", "pclk5", GATE_TZPC), ++ CS_GATE("iwdg1", "pclk5", GATE_IWDG1), ++ CS_GATE("bsec", "pclk5", GATE_BSEC), ++ CS_GATE("stgen", "pclk5", GATE_STGEN), ++ CS_GATE("dma1", "ck_mcu", GATE_DMA1), ++ CS_GATE("dma2", "ck_mcu", GATE_DMA2), ++ CS_GATE("dmamux", "ck_mcu", GATE_DMAMUX), ++ CS_GATE("adc12", "ck_mcu", GATE_ADC12), ++ CS_GATE("usbo", "ck_mcu", GATE_USBO), ++ CS_GATE("sdmmc3", "ck_mcu", GATE_SDMMC3), ++ CS_GATE("dcmi", "ck_mcu", GATE_DCMI), ++ CS_GATE("cryp2", "ck_mcu", GATE_CRYP2), ++ CS_GATE("hash2", "ck_mcu", GATE_HASH2), ++ CS_GATE("rng2", "ck_mcu", GATE_RNG2), ++ CS_GATE("crc2", "ck_mcu", GATE_CRC2), ++ CS_GATE("hsem", "ck_mcu", GATE_HSEM), ++ CS_GATE("ipcc", "ck_mcu", GATE_IPCC), ++ CS_GATE("gpioa", "ck_mcu", GATE_GPIOA), ++ CS_GATE("gpiob", "ck_mcu", GATE_GPIOB), ++ CS_GATE("gpioc", "ck_mcu", GATE_GPIOC), ++ CS_GATE("gpiod", "ck_mcu", GATE_GPIOD), ++ CS_GATE("gpioe", "ck_mcu", GATE_GPIOE), ++ CS_GATE("gpiof", "ck_mcu", GATE_GPIOF), ++ CS_GATE("gpiog", "ck_mcu", GATE_GPIOG), ++ CS_GATE("gpioh", "ck_mcu", GATE_GPIOH), ++ CS_GATE("gpioi", "ck_mcu", GATE_GPIOI), ++ CS_GATE("gpioj", "ck_mcu", GATE_GPIOJ), ++ CS_GATE("gpiok", "ck_mcu", GATE_GPIOK), ++ CS_GATE("gpioz", "ck_axi", GATE_GPIOZ), ++ CS_GATE("cryp1", "ck_axi", GATE_CRYP1), ++ CS_GATE("hash1", "ck_axi", GATE_HASH1), ++ CS_GATE("rng1", "ck_axi", GATE_RNG1), ++ CS_GATE("bkpsram", "ck_axi", GATE_BKPSRAM), ++ CS_GATE("mdma", "ck_axi", GATE_MDMA), ++ CS_GATE("gpu", "ck_axi", GATE_GPU), ++ CS_GATE("ethtx", "ck_axi", GATE_ETHTX), ++ CS_GATE("ethrx", "ck_axi", GATE_ETHRX), ++ CS_GATE("ethmac", "ck_axi", GATE_ETHMAC), ++ CS_GATE("crc1", "ck_axi", GATE_CRC1), ++ CS_GATE("usbh", "ck_axi", GATE_USBH), ++ CS_GATE("ethstp", "ck_axi", GATE_ETHSTP), ++ CS_GATE("ddrperfm", "pclk4", GATE_DDRPERFM), ++ ++ CS_GATEMUX("sdmmc1_k", sdmmc12_src, GATE_SDMMC1, MUX_SDMMC12), ++ CS_GATEMUX("sdmmc2_k", sdmmc12_src, GATE_SDMMC2, MUX_SDMMC12), ++ CS_GATEMUX("sdmmc3_k", sdmmc3_src, GATE_SDMMC3, MUX_SDMMC3), ++ CS_GATEMUX("fmc_k", fmc_src, GATE_FMC, MUX_FMC), ++ CS_GATEMUX("qspi_k", qspi_src, GATE_QSPI, MUX_QSPI), ++ CS_GATEMUX("rng1_k", rng_src, GATE_RNG1, MUX_RNG1), ++ CS_GATEMUX("rng2_k", rng_src, GATE_RNG2, MUX_RNG2), ++ CS_GATEMUX("usbphy_k", usbphy_src, GATE_USBPHY, MUX_USBPHY), ++ CS_GATEMUX("stgen_k", stgen_src, GATE_STGEN, MUX_STGEN), ++ CS_GATEMUX("spdif_k", spdif_src, GATE_SPDIF, MUX_SPDIF), ++ CS_GATEMUX("spi1_k", spi123_src, GATE_SPI1, MUX_SPI1), ++ CS_GATEMUX("spi2_k", spi123_src, GATE_SPI2, MUX_SPI23), ++ CS_GATEMUX("spi3_k", spi123_src, GATE_SPI3, MUX_SPI23), ++ CS_GATEMUX("spi4_k", spi45_src, GATE_SPI4, MUX_SPI45), ++ CS_GATEMUX("spi5_k", spi45_src, GATE_SPI5, MUX_SPI45), ++ CS_GATEMUX("spi6_k", spi6_src, GATE_SPI6, MUX_SPI6), ++ CS_GATEMUX("cec_k", cec_src, GATE_CEC, MUX_CEC), ++ CS_GATEMUX("i2c1_k", i2c12_src, GATE_I2C1, MUX_I2C12), ++ CS_GATEMUX("i2c2_k", i2c12_src, GATE_I2C2, MUX_I2C12), ++ CS_GATEMUX("i2c3_k", i2c35_src, GATE_I2C3, MUX_I2C35), ++ CS_GATEMUX("i2c5_k", i2c35_src, GATE_I2C5, MUX_I2C35), ++ CS_GATEMUX("i2c4_k", i2c46_src, GATE_I2C4, MUX_I2C46), ++ CS_GATEMUX("i2c6_k", i2c46_src, GATE_I2C6, MUX_I2C46), ++ CS_GATEMUX("lptim1_k", lptim1_src, GATE_LPTIM1, MUX_LPTIM1), ++ CS_GATEMUX("lptim2_k", lptim23_src, GATE_LPTIM2, MUX_LPTIM23), ++ CS_GATEMUX("lptim3_k", lptim23_src, GATE_LPTIM3, MUX_LPTIM23), ++ CS_GATEMUX("lptim4_k", lptim45_src, GATE_LPTIM4, MUX_LPTIM45), ++ CS_GATEMUX("lptim5_k", lptim45_src, GATE_LPTIM5, MUX_LPTIM45), ++ CS_GATEMUX("usart1_k", usart1_src, GATE_USART1, MUX_USART1), ++ CS_GATEMUX("usart2_k", usart234578_src, GATE_USART2, MUX_UART24), ++ CS_GATEMUX("usart3_k", usart234578_src, GATE_USART3, MUX_UART35), ++ CS_GATEMUX("uart4_k", usart234578_src, GATE_UART4, MUX_UART24), ++ CS_GATEMUX("uart5_k", usart234578_src, GATE_UART5, MUX_UART35), ++ CS_GATEMUX("uart6_k", usart6_src, GATE_USART6, MUX_USART6), ++ CS_GATEMUX("uart7_k", usart234578_src, GATE_UART7, MUX_UART78), ++ CS_GATEMUX("uart8_k", usart234578_src, GATE_UART8, MUX_UART78), ++ CS_GATEMUX("fdcan_k", fdcan_src, GATE_FDCAN, MUX_FDCAN), ++ CS_GATEMUX("sai1_k", sai_src, GATE_SAI1, MUX_SAI1), ++ CS_GATEMUX("sai2_k", sai2_src, GATE_SAI2, MUX_SAI2), ++ CS_GATEMUX("sai3_k", sai_src, GATE_SAI3, MUX_SAI3), ++ CS_GATEMUX("sai4_k", sai_src, GATE_SAI4, MUX_SAI4), ++ CS_GATEMUX("adc12_k", adc12_src, GATE_ADC12, MUX_ADC12), ++ CS_GATEMUX("dsi_k", dsi_src, GATE_DSI, MUX_DSI), ++ CS_GATEMUX("adfsdm_k", sai_src, GATE_ADFSDM, MUX_SAI1), ++ CS_GATEMUX("usbo_k", usbo_src, GATE_USBO, MUX_USBO), ++ CS_GATEMUX("ethck_k", eth_src, GATE_ETHCK, MUX_ETHCK), ++ ++ CS_GATE("dfsdm_k", "ck_mcu", GATE_DFSDM), ++ CS_GATE("dsi_px", "pll4_q", GATE_DSI), ++ CS_GATE("ltdc_px", "pll4_q", GATE_LTDC), ++ CS_GATE("gpu_k", "pll2_q", GATE_GPU), ++ CS_GATE("dac12_k", "ck_lsi", GATE_DAC12), ++ ++ CS_COMPOSITE("ck_mco1", mco1_src, GATE_MCO1, MUX_MCO1, DIV_MCO1), ++ CS_COMPOSITE("ck_mco2", mco2_src, GATE_MCO2, MUX_MCO2, DIV_MCO2), ++ CS_GATE("ck_sys_dbg", "ck_axi", GATE_DBGCK), ++ ++ CS_COMPOSITE("ethptp_k", eth_src, NO_STM32_GATE, MUX_ETHCK, DIV_ETHPTP), ++ ++ CS_RTC("ck_rtc", rtc_src, GATE_RTCCK, MUX_RTC, DIV_RTC), ++ ++ CS_GATEDIV("ck_trace", "ck_axi", GATE_TRACECK, DIV_TRACE), ++}; ++ ++static void rcc_summary_show_one(struct seq_file *s, struct clk_summary *c, ++ int level) ++{ ++ char enabled; ++ ++ seq_printf(s, "%*s%-*s %11lu ", ++ level * 3 + 1, "", ++ 30 - level * 3, ++ c->name, ++ c->rate ++ ); ++ ++ switch (c->enabled) { ++ case 0: ++ enabled = 'N'; ++ break; ++ case 1: ++ enabled = 'Y'; ++ break; ++ default: ++ enabled = '?'; ++ break; ++ } ++ ++ seq_printf(s, " %9c\n", enabled); ++} ++ ++static int clock_summary_clk_is_enabled(struct clock_summary *cs, ++ struct clk_summary *c) ++{ ++ return clk_stm32_is_enabled_gate(cs->base, cs->clock_data, c->gate_id); ++} ++ ++static const char *clock_summary_get_parent_name(struct clock_summary *cs, ++ struct clk_summary *c) ++{ ++ int id = 0; ++ ++ if (c->nb_parents == 0) ++ return NULL; ++ ++ if (c->nb_parents > 1) ++ id = clk_stm32_get_parent_mux(cs->base, cs->clock_data, c->mux_id); ++ ++ return c->parent_names[id]; ++} ++ ++static void rcc_summary_show_subtree(struct seq_file *s, struct clk_summary *c, ++ unsigned long parent_rate, int level) ++{ ++ struct clock_summary *cs = (struct clock_summary *)s->private; ++ int i; ++ ++ if (c->get_rate) ++ c->rate = c->get_rate(cs, c, parent_rate); ++ else ++ c->rate = parent_rate; ++ ++ c->enabled = -1; ++ if (c->gate_id != NO_STM32_GATE) ++ c->enabled = clock_summary_clk_is_enabled(cs, c); ++ ++ rcc_summary_show_one(s, c, level); ++ ++ for (i = 0; i < cs->nb_clocks; i++) { ++ struct clk_summary *child = &cs->clocks[i]; ++ const char *parent_name = clock_summary_get_parent_name(cs, child); ++ ++ if (!parent_name) ++ continue; ++ ++ if (!strcmp(c->name, parent_name)) ++ rcc_summary_show_subtree(s, child, c->rate, level + 1); ++ } ++} ++ ++static int rcc_summary_show(struct seq_file *s, void *data) ++{ ++ struct clock_summary *cs = (struct clock_summary *)s->private; ++ int i; ++ ++ seq_puts(s, " hardware\n"); ++ seq_puts(s, " clock rate enable\n"); ++ seq_puts(s, "------------------------------------------------------\n"); ++ ++ for (i = 0; i < cs->nb_clocks; i++) { ++ struct clk_summary *c = &cs->clocks[i]; ++ ++ if (c->nb_parents == 0) ++ rcc_summary_show_subtree(s, c, 0, 0); ++ } ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(rcc_summary); ++ ++struct clk_stm32_clock_data stm32mp15_clock_data = { ++ .gates = stm32mp15_gates, ++ .muxes = stm32mp15_muxes, ++ .dividers = stm32mp15_dividers, ++}; ++ ++static struct clock_summary clock_summary_mp15 = { ++ .clocks = stm32mp15_clock_summary, ++ .nb_clocks = ARRAY_SIZE(stm32mp15_clock_summary), ++ .clock_data = &stm32mp15_clock_data, ++}; ++ ++static void stm32_clk_summary_debugfs_create(struct device *dev, void __iomem *base) ++{ ++ struct dentry *rootdir = debugfs_lookup("clk", NULL); ++ ++ clock_summary_mp15.base = base; ++ ++ debugfs_create_file("stm32_clk_summary", 0444, rootdir, ++ &clock_summary_mp15, &rcc_summary_fops); ++} ++ ++#else ++ ++static void stm32_clk_summary_debugfs_create(struct device *dev, void __iomem *base) ++{ ++} ++ ++#endif diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c -index ac11cefc3..a66dba8be 100644 +index 0674dbc62eb5..a4ef506665df 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c -@@ -1764,6 +1764,7 @@ static void clk_reparent(struct clk_core *core, struct clk_core *new_parent) +@@ -1781,6 +1781,7 @@ static void clk_reparent(struct clk_core *core, struct clk_core *new_parent) core->parent = new_parent; } @@ -886,7 +2092,7 @@ index ac11cefc3..a66dba8be 100644 static struct clk_core *__clk_set_parent_before(struct clk_core *core, struct clk_core *parent) { -@@ -1792,7 +1793,8 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core, +@@ -1809,7 +1810,8 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core, /* enable old_parent & parent if CLK_OPS_PARENT_ENABLE is set */ if (core->flags & CLK_OPS_PARENT_ENABLE) { @@ -896,7 +2102,7 @@ index ac11cefc3..a66dba8be 100644 clk_core_prepare_enable(parent); } -@@ -1826,7 +1828,8 @@ static void __clk_set_parent_after(struct clk_core *core, +@@ -1843,7 +1845,8 @@ static void __clk_set_parent_after(struct clk_core *core, /* re-balance ref counting if CLK_OPS_PARENT_ENABLE is set */ if (core->flags & CLK_OPS_PARENT_ENABLE) { clk_core_disable_unprepare(parent); @@ -908,17 +2114,17 @@ index ac11cefc3..a66dba8be 100644 diff --git a/drivers/clk/stm32/Makefile b/drivers/clk/stm32/Makefile new file mode 100644 -index 000000000..95bd2230b +index 000000000000..95bd2230bba0 --- /dev/null +++ b/drivers/clk/stm32/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_COMMON_CLK_STM32MP135) += clk-stm32mp13.o clk-stm32-core.o reset-stm32.o diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c new file mode 100644 -index 000000000..b977bfb1e +index 000000000000..e1467cfeb1bf --- /dev/null +++ b/drivers/clk/stm32/clk-stm32-core.c -@@ -0,0 +1,722 @@ +@@ -0,0 +1,864 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved @@ -940,6 +2146,9 @@ index 000000000..b977bfb1e + +static DEFINE_SPINLOCK(rlock); + ++static void stm32_clk_summary_debugfs_create(struct device *dev, ++ const struct stm32_rcc_match_data *data); ++ +static int stm32_rcc_clock_init(struct device *dev, + const struct of_device_id *match, + void __iomem *base) @@ -948,6 +2157,7 @@ index 000000000..b977bfb1e + struct clk_hw_onecell_data *clk_data = data->hw_clks; + struct clk_hw **hws; + int n, max_binding; ++ int ret; + + max_binding = data->maxbinding; + @@ -956,6 +2166,8 @@ index 000000000..b977bfb1e + if (!clk_data) + return -ENOMEM; + ++ data->clock_data->base = base; ++ + clk_data->num = max_binding; + + hws = clk_data->hws; @@ -985,8 +2197,14 @@ index 000000000..b977bfb1e + hws[cfg_clock->id] = hw; + } + -+ return of_clk_add_hw_provider(dev_of_node(dev), of_clk_hw_onecell_get, -+ clk_data); ++ ret = of_clk_add_hw_provider(dev_of_node(dev), of_clk_hw_onecell_get, clk_data); ++ if (ret) ++ return ret; ++ ++ if (data->clock_summary) ++ stm32_clk_summary_debugfs_create(dev, data); ++ ++ return ret; +} + +int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, @@ -1641,12 +2859,142 @@ index 000000000..b977bfb1e + + return hw; +} ++ ++#ifdef CONFIG_DEBUG_FS ++ ++#include ++ ++static void rcc_summary_show_one(struct seq_file *s, struct clk_summary *c, ++ int level) ++{ ++ char enabled; ++ ++ seq_printf(s, "%*s%-*s %11lu ", ++ level * 3 + 1, "", ++ 30 - level * 3, ++ c->name, ++ c->rate ++ ); ++ ++ switch (c->enabled) { ++ case 0: ++ enabled = 'N'; ++ break; ++ case 1: ++ enabled = 'Y'; ++ break; ++ default: ++ enabled = '?'; ++ break; ++ } ++ ++ seq_printf(s, " %9c\n", enabled); ++} ++ ++static int clock_summary_clk_is_enabled(struct clk_stm32_clock_data *data, ++ struct clk_summary *c) ++{ ++ return clk_stm32_is_enabled_gate(data->base, data, c->gate_id); ++} ++ ++static const char *clock_summary_get_parent_name(struct clk_stm32_clock_data *data, ++ struct clk_summary *c) ++{ ++ int id = 0; ++ ++ if (c->nb_parents == 0) ++ return NULL; ++ ++ if (c->nb_parents > 1) { ++ if (c->get_parent) ++ id = c->get_parent(data, c); ++ else ++ id = clk_stm32_get_parent_mux(data->base, data, c->mux_id); ++ } ++ ++ return c->parent_names[id]; ++} ++ ++static void rcc_summary_show_subtree(struct seq_file *s, struct clk_summary *c, ++ unsigned long parent_rate, int level) ++{ ++ struct stm32_rcc_match_data *match_data = (struct stm32_rcc_match_data *)s->private; ++ struct clk_stm32_clock_data *data = match_data->clock_data; ++ struct clock_summary *cs = match_data->clock_summary; ++ int i; ++ ++ if (c->get_rate) ++ c->rate = c->get_rate(data, c, parent_rate); ++ else ++ c->rate = parent_rate; ++ ++ c->enabled = -1; ++ ++ if (c->is_enabled) ++ c->enabled = c->is_enabled(data, c); ++ ++ else if (c->gate_id != NO_STM32_GATE) ++ c->enabled = clock_summary_clk_is_enabled(data, c); ++ ++ rcc_summary_show_one(s, c, level); ++ ++ for (i = 0; i < cs->nb_clocks; i++) { ++ struct clk_summary *child = &cs->clocks[i]; ++ const char *parent_name = clock_summary_get_parent_name(data, child); ++ ++ if (!parent_name) ++ continue; ++ ++ if (!strcmp(c->name, parent_name)) ++ rcc_summary_show_subtree(s, child, c->rate, level + 1); ++ } ++} ++ ++static int rcc_summary_show(struct seq_file *s, void *data) ++{ ++ struct stm32_rcc_match_data *match_data = (struct stm32_rcc_match_data *)s->private; ++ struct clock_summary *cs = match_data->clock_summary; ++ ++ int i; ++ ++ seq_puts(s, " hardware\n"); ++ seq_puts(s, " clock rate enable\n"); ++ seq_puts(s, "------------------------------------------------------\n"); ++ ++ for (i = 0; i < cs->nb_clocks; i++) { ++ struct clk_summary *c = &cs->clocks[i]; ++ ++ if (c->nb_parents == 0) ++ rcc_summary_show_subtree(s, c, 0, 0); ++ } ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(rcc_summary); ++ ++static void stm32_clk_summary_debugfs_create(struct device *dev, ++ const struct stm32_rcc_match_data *data) ++{ ++ struct dentry *rootdir = debugfs_lookup("clk", NULL); ++ ++ debugfs_create_file("stm32_clk_summary", 0444, rootdir, (void *)data, &rcc_summary_fops); ++} ++ ++#else ++ ++static void stm32_clk_summary_debugfs_create(struct device *dev, ++ const struct stm32_rcc_match_data *data) ++ ++{ ++} ++#endif diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h new file mode 100644 -index 000000000..63e62878b +index 000000000000..2e0a73d27136 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32-core.h -@@ -0,0 +1,243 @@ +@@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved @@ -1706,6 +3054,7 @@ index 000000000..63e62878b +}; + +struct clk_stm32_clock_data { ++ void __iomem *base; + u16 *gate_cpt; + const struct stm32_gate_cfg *gates; + const struct stm32_mux_cfg *muxes; @@ -1713,6 +3062,31 @@ index 000000000..63e62878b + struct clk_hw *(*is_multi_mux)(struct clk_hw *hw); +}; + ++struct clock_summary { ++ struct clk_summary *clocks; ++ int nb_clocks; ++}; ++ ++struct clk_summary { ++ const char *name; ++ unsigned long rate; ++ int enabled; ++ int nb_parents; ++ int gate_id; ++ int mux_id; ++ int div_id; ++ void *data; ++ ++ bool (*is_enabled)(struct clk_stm32_clock_data *data, ++ struct clk_summary *c); ++ u8 (*get_parent)(struct clk_stm32_clock_data *data, ++ struct clk_summary *c); ++ unsigned long (*get_rate)(struct clk_stm32_clock_data *data, ++ struct clk_summary *c, ++ unsigned long parent_rate); ++ const char * const *parent_names; ++}; ++ +struct stm32_rcc_match_data { + struct clk_hw_onecell_data *hw_clks; + unsigned int num_clocks; @@ -1722,6 +3096,9 @@ index 000000000..63e62878b + int (*multi_mux)(void __iomem *base, const struct clock_config *cfg); + int (*check_security)(void __iomem *base, const struct clock_config *cfg); + u32 clear_offset; ++ u32 reset_us; ++ ++ struct clock_summary *clock_summary; +}; + +int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match, @@ -1892,10 +3269,10 @@ index 000000000..63e62878b + &clk_stm32_composite_register) diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c new file mode 100644 -index 000000000..9c60a1c7f +index 000000000000..15ee05df8336 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32mp13.c -@@ -0,0 +1,1062 @@ +@@ -0,0 +1,1760 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved @@ -2027,6 +3404,54 @@ index 000000000..9c60a1c7f +}; + +enum enum_gate_cfg { ++ GATE_LSE, ++ GATE_LSE_RDY, ++ GATE_LSI, ++ GATE_LSI_RDY, ++ GATE_HSI, ++ GATE_HSI_RDY, ++ GATE_CSI, ++ GATE_CSI_RDY, ++ GATE_HSE, ++ GATE_HSE_RDY, ++ GATE_PLL1, ++ GATE_PLL1_RDY, ++ GATE_PLL2, ++ GATE_PLL2_RDY, ++ GATE_PLL3, ++ GATE_PLL3_RDY, ++ GATE_PLL4, ++ GATE_PLL4_RDY, ++ GATE_HSIDIVRDY, ++ GATE_MPUSRCRDY, ++ GATE_AXISSRCRDY, ++ GATE_MCUSSRCRDY, ++ GATE_PLL12SRCRDY, ++ GATE_PLL3SRCRDY, ++ GATE_PLL4SRCRDY, ++ GATE_MPUDIVRDY, ++ GATE_AXIDIVRDY, ++ GATE_MLAHBDIVRDY, ++ GATE_APB1DIVRDY, ++ GATE_APB2DIVRDY, ++ GATE_APB3DIVRDY, ++ GATE_APB4DIVRDY, ++ GATE_APB5DIVRDY, ++ GATE_APB6DIVRDY, ++ GATE_RTCCK, ++ GATE_RTCAPB, ++ GATE_PLL1_DIVP, ++ GATE_PLL1_DIVQ, ++ GATE_PLL1_DIVR, ++ GATE_PLL2_DIVP, ++ GATE_PLL2_DIVQ, ++ GATE_PLL2_DIVR, ++ GATE_PLL3_DIVP, ++ GATE_PLL3_DIVQ, ++ GATE_PLL3_DIVR, ++ GATE_PLL4_DIVP, ++ GATE_PLL4_DIVQ, ++ GATE_PLL4_DIVR, + GATE_MCO1, + GATE_MCO2, + GATE_DBGCK, @@ -2159,6 +3584,53 @@ index 000000000..9c60a1c7f + _CFG_GATE(_id, _offset, _bit_idx, RCC_CLR) + +static struct stm32_gate_cfg stm32mp13_gates[] = { ++ CFG_GATE(GATE_LSE, RCC_BDCR, 0), ++ CFG_GATE(GATE_LSE_RDY, RCC_BDCR, 2), ++ CFG_GATE(GATE_RTCCK, RCC_BDCR, 20), ++ CFG_GATE(GATE_LSI, RCC_RDLSICR, 0), ++ CFG_GATE(GATE_LSI_RDY, RCC_RDLSICR, 1), ++ CFG_GATE_SETCLR(GATE_HSI, RCC_OCENSETR, 0), ++ CFG_GATE(GATE_HSI_RDY, RCC_OCRDYR, 0), ++ CFG_GATE_SETCLR(GATE_CSI, RCC_OCENSETR, 4), ++ CFG_GATE(GATE_CSI_RDY, RCC_OCRDYR, 4), ++ CFG_GATE_SETCLR(GATE_HSE, RCC_OCENSETR, 8), ++ CFG_GATE(GATE_HSE_RDY, RCC_OCRDYR, 8), ++ CFG_GATE(GATE_HSIDIVRDY, RCC_OCRDYR, 2), ++ CFG_GATE(GATE_MPUSRCRDY, RCC_MPCKSELR, 31), ++ CFG_GATE(GATE_AXISSRCRDY, RCC_ASSCKSELR, 31), ++ CFG_GATE(GATE_MCUSSRCRDY, RCC_MSSCKSELR, 31), ++ CFG_GATE(GATE_PLL12SRCRDY, RCC_RCK12SELR, 31), ++ CFG_GATE(GATE_PLL3SRCRDY, RCC_RCK3SELR, 31), ++ CFG_GATE(GATE_PLL4SRCRDY, RCC_RCK4SELR, 31), ++ CFG_GATE(GATE_MPUDIVRDY, RCC_MPCKDIVR, 31), ++ CFG_GATE(GATE_AXIDIVRDY, RCC_AXIDIVR, 31), ++ CFG_GATE(GATE_MLAHBDIVRDY, RCC_MLAHBDIVR, 31), ++ CFG_GATE(GATE_APB1DIVRDY, RCC_APB1DIVR, 31), ++ CFG_GATE(GATE_APB2DIVRDY, RCC_APB2DIVR, 31), ++ CFG_GATE(GATE_APB3DIVRDY, RCC_APB3DIVR, 31), ++ CFG_GATE(GATE_APB4DIVRDY, RCC_APB4DIVR, 31), ++ CFG_GATE(GATE_APB5DIVRDY, RCC_APB5DIVR, 31), ++ CFG_GATE(GATE_APB6DIVRDY, RCC_APB6DIVR, 31), ++ CFG_GATE(GATE_PLL1, RCC_PLL1CR, 0), ++ CFG_GATE(GATE_PLL1_RDY, RCC_PLL1CR, 1), ++ CFG_GATE(GATE_PLL1_DIVP, RCC_PLL1CR, 4), ++ CFG_GATE(GATE_PLL1_DIVQ, RCC_PLL1CR, 5), ++ CFG_GATE(GATE_PLL1_DIVR, RCC_PLL1CR, 6), ++ CFG_GATE(GATE_PLL2, RCC_PLL2CR, 0), ++ CFG_GATE(GATE_PLL2_RDY, RCC_PLL2CR, 1), ++ CFG_GATE(GATE_PLL2_DIVP, RCC_PLL2CR, 4), ++ CFG_GATE(GATE_PLL2_DIVQ, RCC_PLL2CR, 5), ++ CFG_GATE(GATE_PLL2_DIVR, RCC_PLL2CR, 6), ++ CFG_GATE(GATE_PLL3, RCC_PLL3CR, 0), ++ CFG_GATE(GATE_PLL3_RDY, RCC_PLL3CR, 1), ++ CFG_GATE(GATE_PLL3_DIVP, RCC_PLL3CR, 4), ++ CFG_GATE(GATE_PLL3_DIVQ, RCC_PLL3CR, 5), ++ CFG_GATE(GATE_PLL3_DIVR, RCC_PLL3CR, 6), ++ CFG_GATE(GATE_PLL4, RCC_PLL4CR, 0), ++ CFG_GATE(GATE_PLL4_RDY, RCC_PLL4CR, 1), ++ CFG_GATE(GATE_PLL4_DIVP, RCC_PLL4CR, 4), ++ CFG_GATE(GATE_PLL4_DIVQ, RCC_PLL4CR, 5), ++ CFG_GATE(GATE_PLL4_DIVR, RCC_PLL4CR, 6), + CFG_GATE(GATE_MCO1, RCC_MCO1CFGR, 12), + CFG_GATE(GATE_MCO2, RCC_MCO2CFGR, 12), + CFG_GATE(GATE_DBGCK, RCC_DBGCFGR, 8), @@ -2213,6 +3685,7 @@ index 000000000..9c60a1c7f + CFG_GATE_SETCLR(GATE_USBPHY, RCC_MP_APB4ENSETR, 16), + CFG_GATE_SETCLR(GATE_STGENRO, RCC_MP_APB4ENSETR, 20), + CFG_GATE_SETCLR(GATE_LTDC, RCC_MP_NS_APB4ENSETR, 0), ++ CFG_GATE(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8), + CFG_GATE_SETCLR(GATE_TZC, RCC_MP_APB5ENSETR, 11), + CFG_GATE_SETCLR(GATE_ETZPC, RCC_MP_APB5ENSETR, 13), + CFG_GATE_SETCLR(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15), @@ -2277,6 +3750,14 @@ index 000000000..9c60a1c7f +}; + +enum enum_mux_cfg { ++ MUX_MPU, ++ MUX_AXI, ++ MUX_MLAHB, ++ MUX_PLL12, ++ MUX_PLL3, ++ MUX_PLL4, ++ MUX_RTC, ++ MUX_CKPER, + MUX_I2C12, + MUX_LPTIM45, + MUX_SPI23, @@ -2337,6 +3818,14 @@ index 000000000..9c60a1c7f + _CFG_MUX(_id, _offset, _shift, _witdh, MUX_NO_RDY, MUX_SAFE) + +static const struct stm32_mux_cfg stm32mp13_muxes[] = { ++ CFG_MUX(MUX_MPU, RCC_MPCKSELR, 0, 2), ++ CFG_MUX(MUX_AXI, RCC_ASSCKSELR, 0, 3), ++ CFG_MUX(MUX_MLAHB, RCC_MSSCKSELR, 0, 2), ++ CFG_MUX(MUX_PLL12, RCC_RCK12SELR, 0, 2), ++ CFG_MUX(MUX_PLL3, RCC_RCK3SELR, 0, 2), ++ CFG_MUX(MUX_PLL4, RCC_RCK4SELR, 0, 2), ++ CFG_MUX(MUX_CKPER, RCC_CPERCKSELR, 0, 2), ++ CFG_MUX(MUX_RTC, RCC_BDCR, 16, 2), + CFG_MUX(MUX_I2C12, RCC_I2C12CKSELR, 0, 3), + CFG_MUX(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3), + CFG_MUX(MUX_SPI23, RCC_SPI2S23CKSELR, 0, 3), @@ -2379,6 +3868,27 @@ index 000000000..9c60a1c7f +}; + +enum enum_div_cfg { ++ DIV_PLL1DIVP, ++ DIV_PLL2DIVP, ++ DIV_PLL2DIVQ, ++ DIV_PLL2DIVR, ++ DIV_PLL3DIVP, ++ DIV_PLL3DIVQ, ++ DIV_PLL3DIVR, ++ DIV_PLL4DIVP, ++ DIV_PLL4DIVQ, ++ DIV_PLL4DIVR, ++ DIV_MPU, ++ DIV_AXI, ++ DIV_MLAHB, ++ DIV_APB1, ++ DIV_APB2, ++ DIV_APB3, ++ DIV_APB4, ++ DIV_APB5, ++ DIV_APB6, ++ DIV_RTC, ++ DIV_HSI, + DIV_MCO1, + DIV_MCO2, + DIV_TRACE, @@ -2403,7 +3913,50 @@ index 000000000..9c60a1c7f + .ready = (_ready),\ + } + ++static const struct clk_div_table axi_div_table[] = { ++ { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, ++ { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 }, ++ { 0 }, ++}; ++ ++static const struct clk_div_table mlahb_div_table[] = { ++ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, ++ { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 }, ++ { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 }, ++ { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 }, ++ { 0 }, ++}; ++ ++static const struct clk_div_table apb_div_table[] = { ++ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, ++ { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, ++ { 0 }, ++}; ++ +static const struct stm32_div_cfg stm32mp13_dividers[DIV_NB] = { ++ CFG_DIV(DIV_MPU, RCC_MPCKDIVR, 0, 4, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_AXI, RCC_AXIDIVR, 0, 3, 0, axi_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_MLAHB, RCC_MLAHBDIVR, 0, 4, 0, mlahb_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_APB6, RCC_APB6DIVR, 0, 3, 0, apb_div_table, DIV_NO_RDY), ++ CFG_DIV(DIV_HSI, RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL, DIV_NO_RDY), ++ ++ CFG_DIV(DIV_PLL1DIVP, RCC_PLL1CFGR2, 0, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL2DIVP, RCC_PLL2CFGR2, 0, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL2DIVQ, RCC_PLL2CFGR2, 8, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL2DIVR, RCC_PLL2CFGR2, 16, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL3DIVP, RCC_PLL3CFGR2, 0, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL3DIVQ, RCC_PLL3CFGR2, 8, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL3DIVR, RCC_PLL3CFGR2, 16, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL4DIVP, RCC_PLL4CFGR2, 0, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL4DIVQ, RCC_PLL4CFGR2, 8, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_PLL4DIVR, RCC_PLL4CFGR2, 16, 7, 0, NULL, DIV_NO_RDY), ++ CFG_DIV(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_RDY), ++ + CFG_DIV(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL, DIV_NO_RDY), + CFG_DIV(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL, DIV_NO_RDY), + CFG_DIV(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table, DIV_NO_RDY), @@ -2555,8 +4108,12 @@ index 000000000..9c60a1c7f +static CLK_STM32_GATE(tim16_k, "timg3_ck", CLK_SET_RATE_PARENT, GATE_TIM16); +static CLK_STM32_GATE(tim17_k, "timg3_ck", CLK_SET_RATE_PARENT, GATE_TIM17); + ++static CLK_STM32_GATE(spi2, "pclk1", 0, GATE_SPI2); ++static CLK_STM32_GATE(spi3, "pclk1", 0, GATE_SPI3); ++ +static CLK_STM32_GATE(sai1, "pclk2", 0, GATE_SAI1); +static CLK_STM32_GATE(sai2, "pclk2", 0, GATE_SAI2); ++static CLK_STM32_GATE(spi1, "pclk2", 0, GATE_SPI1); + +static CLK_STM32_GATE(syscfg, "pclk3", 0, GATE_SYSCFG); +static CLK_STM32_GATE(vref, "pclk3", 0, GATE_VREF); @@ -2582,6 +4139,9 @@ index 000000000..9c60a1c7f +static CLK_STM32_GATE(iwdg1, "pclk5", 0, GATE_IWDG1APB); +static CLK_STM32_GATE(bsec, "pclk5", 0, GATE_BSEC); + ++static CLK_STM32_GATE(spi4, "pclk6", 0, GATE_SPI4); ++static CLK_STM32_GATE(spi5, "pclk6", 0, GATE_SPI5); ++ +static CLK_STM32_GATE(dma1, "ck_mlahb", 0, GATE_DMA1); +static CLK_STM32_GATE(dma2, "ck_mlahb", 0, GATE_DMA2); +static CLK_STM32_GATE(dmamux1, "ck_mlahb", 0, GATE_DMAMUX1); @@ -2693,6 +4253,11 @@ index 000000000..9c60a1c7f + STM32_GATE_CFG(TIM17_K, tim17_k, SECF_TIM17), + + /* Peripheral clocks */ ++ STM32_GATE_CFG(SPI1, spi1, SECF_NONE), ++ STM32_GATE_CFG(SPI2, spi2, SECF_NONE), ++ STM32_GATE_CFG(SPI3, spi3, SECF_NONE), ++ STM32_GATE_CFG(SPI4, spi4, SECF_SPI4), ++ STM32_GATE_CFG(SPI5, spi5, SECF_SPI5), + STM32_GATE_CFG(SAI1, sai1, SECF_NONE), + STM32_GATE_CFG(SAI2, sai2, SECF_NONE), + STM32_GATE_CFG(SYSCFG, syscfg, SECF_NONE), @@ -2843,6 +4408,10 @@ index 000000000..9c60a1c7f + +u16 stm32mp13_cpt_gate[GATE_NB]; + ++#ifdef CONFIG_DEBUG_FS ++static struct clock_summary clock_summary_mp13; ++#endif ++ +struct clk_stm32_clock_data stm32mp13_clock_data = { + .gate_cpt = stm32mp13_cpt_gate, + .gates = stm32mp13_gates, @@ -2858,6 +4427,10 @@ index 000000000..9c60a1c7f + .check_security = &stm32mp13_check_security, + .maxbinding = STM32MP1_LAST_CLK, + .clear_offset = RCC_CLR, ++ .reset_us = 2, ++#ifdef CONFIG_DEBUG_FS ++ .clock_summary = &clock_summary_mp13, ++#endif +}; + +static const struct of_device_id stm32mp13_match_data[] = { @@ -2869,6 +4442,7 @@ index 000000000..9c60a1c7f +}; +MODULE_DEVICE_TABLE(of, stm32mp13_match_data); + ++ +static int stm32mp1_rcc_init(struct device *dev) +{ + void __iomem *rcc_base; @@ -2958,12 +4532,513 @@ index 000000000..9c60a1c7f + return platform_driver_register(&stm32mp13_rcc_clocks_driver); +} +core_initcall(stm32mp13_clocks_init); ++ ++#ifdef CONFIG_DEBUG_FS ++ ++/* STM32 PLL */ ++struct clk_pll_fractional_divider { ++ struct clk_hw hw; ++ void __iomem *mreg; ++ u8 mshift; ++ u8 mwidth; ++ u8 mflags; ++ void __iomem *nreg; ++ u8 nshift; ++ u8 nwidth; ++ u8 nflags; ++ void __iomem *freg; ++ u8 fshift; ++ u8 fwidth; ++ ++ /* lock pll enable/disable registers */ ++ spinlock_t *lock; ++}; ++ ++struct cs_pll { ++ u32 offset; ++}; ++ ++#define PLL_BIT_ON 0 ++#define PLL_BIT_RDY 1 ++#define PLL_MUX_SHIFT 0 ++#define PLL_MUX_MASK 3 ++#define PLL_DIVMN_OFFSET 4 ++#define PLL_DIVM_SHIFT 16 ++#define PLL_DIVM_WIDTH 6 ++#define PLL_DIVN_SHIFT 0 ++#define PLL_DIVN_WIDTH 9 ++#define PLL_FRAC_OFFSET 0xC ++#define PLL_FRAC_SHIFT 3 ++#define PLL_FRAC_WIDTH 13 ++ ++static unsigned long clk_summary_pll_frac_div_recalc_rate(struct clk_stm32_clock_data *data, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ struct cs_pll *pll = (struct cs_pll *)c->data; ++ struct clk_pll_fractional_divider fracdiv; ++ struct clk_pll_fractional_divider *fd = &fracdiv; ++ void __iomem *reg; ++ u32 mmask; ++ u32 nmask; ++ u32 fmask; ++ unsigned long m, n, f; ++ u64 rate, frate = 0; ++ u32 val; ++ ++ reg = data->base + pll->offset; ++ fd->mreg = reg + PLL_DIVMN_OFFSET; ++ fd->mshift = PLL_DIVM_SHIFT; ++ fd->mwidth = PLL_DIVM_WIDTH; ++ fd->mflags = CLK_FRAC_DIVIDER_ZERO_BASED; ++ fd->nreg = reg + PLL_DIVMN_OFFSET; ++ fd->nshift = PLL_DIVN_SHIFT; ++ fd->nwidth = PLL_DIVN_WIDTH; ++ fd->nflags = CLK_FRAC_DIVIDER_ZERO_BASED; ++ fd->freg = reg + PLL_FRAC_OFFSET; ++ fd->fshift = PLL_FRAC_SHIFT; ++ fd->fwidth = PLL_FRAC_WIDTH; ++ ++ mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift; ++ nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift; ++ fmask = GENMASK(fd->fwidth - 1, 0) << fd->fshift; ++ ++ val = readl(fd->mreg); ++ m = (val & mmask) >> fd->mshift; ++ if (fd->mflags & CLK_FRAC_DIVIDER_ZERO_BASED) ++ m++; ++ ++ val = readl(fd->nreg); ++ n = (val & nmask) >> fd->nshift; ++ if (fd->nflags & CLK_FRAC_DIVIDER_ZERO_BASED) ++ n++; ++ ++ if (!n || !m) ++ return parent_rate; ++ ++ rate = (u64)parent_rate * n; ++ do_div(rate, m); ++ ++ val = readl(fd->freg); ++ f = (val & fmask) >> fd->fshift; ++ if (f) { ++ frate = (u64)parent_rate * (u64)f; ++ do_div(frate, (m * (1 << fd->fwidth))); ++ } ++ ++ return rate + frate; ++} ++ ++static unsigned long clk_summary_hsediv2_recalc_rate(struct clk_stm32_clock_data *data, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ return parent_rate / 2; ++} ++ ++static unsigned long clk_summary_osc_recalc_rate(struct clk_stm32_clock_data *data, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ struct clk *clk = __clk_lookup(c->name); ++ ++ if (clk) ++ return clk_get_rate(clk); ++ ++ return 0; ++} ++ ++static unsigned long clk_summary_div_recalc_rate(struct clk_stm32_clock_data *data, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ return clk_stm32_get_rate_divider(data->base, data, c->div_id, parent_rate); ++} ++ ++/* The divider of RTC clock concerns only ck_hse clock */ ++#define HSE_RTC 3 ++ ++static unsigned long clk_summary_rtc_recalc_rate(struct clk_stm32_clock_data *data, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ u8 parent; ++ ++ parent = clk_stm32_get_parent_mux(data->base, data, c->mux_id); ++ if (parent == HSE_RTC) ++ return clk_summary_div_recalc_rate(data, c, parent_rate); ++ ++ return parent_rate; ++} ++ ++struct cs_stm32_timer { ++ u32 apbdiv; ++ u32 timpre; ++}; ++ ++#define APB_DIV_MASK 0x07 ++#define TIM_PRE_MASK 0x01 ++ ++static unsigned long clk_stm32_timer_recalc_rate(struct clk_stm32_clock_data *data, ++ struct clk_summary *c, ++ unsigned long parent_rate) ++{ ++ struct cs_stm32_timer *tim = (struct cs_stm32_timer *)c->data; ++ void __iomem *rcc_base = data->base; ++ u32 prescaler, timpre; ++ ++ prescaler = readl(rcc_base + tim->apbdiv) & APB_DIV_MASK; ++ ++ timpre = readl(rcc_base + tim->timpre) & TIM_PRE_MASK; ++ ++ if (prescaler == 0U) ++ return parent_rate; ++ ++ return parent_rate * (timpre + 1U) * 2U; ++} ++ ++#define CS_OSC(_name, _gate) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 0,\ ++ .gate_id = _gate,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = NO_STM32_DIV,\ ++ .get_rate = clk_summary_osc_recalc_rate,\ ++} ++#define CS_DIV2(_name, _parent) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .gate_id = NO_STM32_GATE,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = NO_STM32_DIV,\ ++ .get_rate = clk_summary_hsediv2_recalc_rate,\ ++} ++ ++#define CS_PLL(_name, _parents, _gate, _mux, _offset)\ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = NO_STM32_DIV,\ ++ .data = &(struct cs_pll) {\ ++ .offset = _offset,\ ++ },\ ++ .get_rate = clk_summary_pll_frac_div_recalc_rate,\ ++} ++ ++#define CS_DIV(_name, _parent, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .div_id = _div,\ ++ .gate_id = NO_STM32_GATE,\ ++ .mux_id = NO_STM32_MUX,\ ++ .get_rate = clk_summary_div_recalc_rate,\ ++} ++ ++#define CS_MUX(_name, _parents, _mux) \ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .mux_id = _mux,\ ++ .gate_id = NO_STM32_GATE,\ ++ .div_id = NO_STM32_DIV,\ ++} ++ ++#define CS_GATE(_name, _parent, _gate) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .gate_id = _gate,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = NO_STM32_DIV,\ ++} ++ ++#define CS_GATEDIV(_name, _parent, _gate, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .gate_id = _gate,\ ++ .mux_id = NO_STM32_MUX,\ ++ .div_id = _div,\ ++ .get_rate = clk_summary_div_recalc_rate,\ ++} ++ ++#define CS_GATEMUX(_name, _parents, _gate, _mux) \ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = NO_STM32_DIV,\ ++} ++ ++#define CS_COMPOSITE(_name, _parents, _gate, _mux, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = ARRAY_SIZE(_parents),\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = _div,\ ++ .get_rate = clk_summary_div_recalc_rate,\ ++} ++ ++#define CS_RTC(_name, _parents, _gate, _mux, _div) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 4,\ ++ .parent_names = _parents,\ ++ .gate_id = _gate,\ ++ .mux_id = _mux,\ ++ .div_id = _div,\ ++ .get_rate = clk_summary_rtc_recalc_rate,\ ++} ++ ++#define CS_STM32_TIMER(_name, _parent, _apbdiv, _timpre) \ ++{\ ++ .name = _name,\ ++ .nb_parents = 1,\ ++ .parent_names = PARENT(_parent),\ ++ .div_id = NO_STM32_DIV,\ ++ .gate_id = NO_STM32_GATE,\ ++ .mux_id = NO_STM32_MUX,\ ++ .data = &(struct cs_stm32_timer) {\ ++ .apbdiv = _apbdiv,\ ++ .timpre = _timpre,\ ++ },\ ++ .get_rate = clk_stm32_timer_recalc_rate,\ ++} ++ ++static const char * const ref12_parents[] = { ++ "ck_hsi", "ck_hse" ++}; ++ ++static const char * const ref3_parents[] = { ++ "ck_hsi", "ck_hse", "ck_csi" ++}; ++ ++static const char * const ref4_parents[] = { ++ "ck_hsi", "ck_hse", "ck_csi", "i2s_ckin" ++}; ++ ++static const char * const cpu_src[] = { ++ "ck_hsi", "ck_hse", "pll1_p", "pll1_p_div" ++}; ++ ++static const char * const axi_src[] = { ++ "ck_hsi", "ck_hse", "pll2_p" ++}; ++ ++static const char * const mlahb_src[] = { ++ "ck_hsi", "ck_hse", "ck_csi", "pll3_p" ++}; ++ ++static const char * const per_src[] = { ++ "ck_hsi", "ck_csi", "ck_hse" ++}; ++ ++static const char * const rtc_src[] = { ++ "off", "ck_lse", "ck_lsi", "ck_hse" ++}; ++ ++static struct clk_summary stm32mp13_clock_summary[] = { ++ CS_OSC("ck_hsi", GATE_HSI), ++ CS_OSC("ck_csi", GATE_CSI), ++ CS_OSC("ck_lsi", GATE_LSI), ++ CS_OSC("ck_hse", GATE_HSE), ++ CS_OSC("ck_lse", GATE_LSE), ++ ++ CS_OSC("ck_usbo_48m", NO_STM32_GATE), ++ CS_DIV2("clk-hse-div2", "ck_hse"), ++ ++ CS_PLL("pll1", ref12_parents, GATE_PLL1, MUX_PLL12, RCC_PLL1CR), ++ ++ CS_GATEDIV("pll1_p", "pll1", GATE_PLL1_DIVP, DIV_PLL1DIVP), ++ ++ CS_DIV("pll1_p_div", "pll1_p", DIV_MPU), ++ ++ CS_PLL("pll2", ref12_parents, GATE_PLL2, MUX_PLL12, RCC_PLL2CR), ++ CS_GATEDIV("pll2_p", "pll2", GATE_PLL2_DIVP, DIV_PLL2DIVP), ++ CS_GATEDIV("pll2_q", "pll2", GATE_PLL2_DIVQ, DIV_PLL2DIVQ), ++ CS_GATEDIV("pll2_r", "pll2", GATE_PLL2_DIVR, DIV_PLL2DIVR), ++ ++ CS_PLL("pll3", ref3_parents, GATE_PLL3, MUX_PLL3, RCC_PLL3CR), ++ CS_GATEDIV("pll3_p", "pll3", GATE_PLL3_DIVP, DIV_PLL3DIVP), ++ CS_GATEDIV("pll3_q", "pll3", GATE_PLL3_DIVQ, DIV_PLL3DIVQ), ++ CS_GATEDIV("pll3_r", "pll3", GATE_PLL3_DIVR, DIV_PLL3DIVR), ++ ++ CS_PLL("pll4", ref4_parents, GATE_PLL4, MUX_PLL4, RCC_PLL4CR), ++ CS_GATEDIV("pll4_p", "pll4", GATE_PLL4_DIVP, DIV_PLL4DIVP), ++ CS_GATEDIV("pll4_q", "pll4", GATE_PLL4_DIVQ, DIV_PLL4DIVQ), ++ CS_GATEDIV("pll4_r", "pll4", GATE_PLL4_DIVR, DIV_PLL4DIVR), ++ ++ CS_MUX("ck_mpu", cpu_src, MUX_MPU), ++ CS_MUX("ck_axi", axi_src, MUX_AXI), ++ CS_MUX("ck_mlahb", mlahb_src, MUX_MLAHB), ++ CS_MUX("ck_per", per_src, MUX_CKPER), ++ ++ CS_DIV("pclk1", "ck_mlahb", DIV_APB1), ++ CS_DIV("pclk2", "ck_mlahb", DIV_APB2), ++ CS_DIV("pclk3", "ck_mlahb", DIV_APB3), ++ CS_DIV("pclk4", "ck_axi", DIV_APB4), ++ CS_DIV("pclk5", "ck_axi", DIV_APB5), ++ CS_DIV("pclk6", "ck_mlahb", DIV_APB6), ++ ++ CS_STM32_TIMER("timg1_ck", "pclk1", RCC_APB1DIVR, RCC_TIMG1PRER), ++ CS_STM32_TIMER("timg2_ck", "pclk2", RCC_APB2DIVR, RCC_TIMG2PRER), ++ CS_STM32_TIMER("timg3_ck", "pclk1", RCC_APB6DIVR, RCC_TIMG3PRER), ++ ++ CS_GATE("tim2_k", "timg1_ck", GATE_TIM2), ++ CS_GATE("tim3_k", "timg1_ck", GATE_TIM3), ++ CS_GATE("tim4_k", "timg1_ck", GATE_TIM4), ++ CS_GATE("tim5_k", "timg1_ck", GATE_TIM5), ++ CS_GATE("tim6_k", "timg1_ck", GATE_TIM6), ++ CS_GATE("tim7_k", "timg1_ck", GATE_TIM7), ++ CS_GATE("tim1_k", "timg2_ck", GATE_TIM1), ++ CS_GATE("tim8_k", "timg2_ck", GATE_TIM8), ++ CS_GATE("tim12_k", "timg3_ck", GATE_TIM12), ++ CS_GATE("tim13_k", "timg3_ck", GATE_TIM13), ++ CS_GATE("tim14_k", "timg3_ck", GATE_TIM14), ++ CS_GATE("tim15_k", "timg3_ck", GATE_TIM15), ++ CS_GATE("tim16_k", "timg3_ck", GATE_TIM16), ++ CS_GATE("tim17_k", "timg3_ck", GATE_TIM17), ++ ++ CS_GATE("spi2", "pclk1", GATE_SPI2), ++ CS_GATE("spi3", "pclk1", GATE_SPI3), ++ ++ CS_GATE("sai1", "pclk2", GATE_SAI1), ++ CS_GATE("sai2", "pclk2", GATE_SAI2), ++ CS_GATE("spi1", "pclk2", GATE_SPI1), ++ ++ CS_GATE("syscfg", "pclk3", GATE_SYSCFG), ++ CS_GATE("vref", "pclk3", GATE_VREF), ++ CS_GATE("dts", "pclk3", GATE_DTS), ++ CS_GATE("pmbctrl", "pclk3", GATE_PMBCTRL), ++ CS_GATE("hdp", "pclk3", GATE_HDP), ++ ++ CS_GATE("iwdg2", "pclk4", GATE_IWDG2APB), ++ CS_GATE("stgenro", "pclk4", GATE_STGENRO), ++ CS_GATE("gpioa", "pclk4", GATE_GPIOA), ++ CS_GATE("gpiob", "pclk4", GATE_GPIOB), ++ CS_GATE("gpioc", "pclk4", GATE_GPIOC), ++ CS_GATE("gpiod", "pclk4", GATE_GPIOD), ++ CS_GATE("gpioe", "pclk4", GATE_GPIOE), ++ CS_GATE("gpiof", "pclk4", GATE_GPIOF), ++ CS_GATE("gpiog", "pclk4", GATE_GPIOG), ++ CS_GATE("gpioh", "pclk4", GATE_GPIOH), ++ CS_GATE("gpioi", "pclk4", GATE_GPIOI), ++ CS_GATE("tsc", "pclk4", GATE_TSC), ++ CS_GATE("ddrperfm", "pclk4", GATE_DDRPERFM), ++ ++ CS_GATE("tzpc", "pclk5", GATE_TZC), ++ CS_GATE("iwdg1", "pclk5", GATE_IWDG1APB), ++ CS_GATE("bsec", "pclk5", GATE_BSEC), ++ ++ CS_GATE("spi4", "pclk6", GATE_SPI4), ++ CS_GATE("spi5", "pclk6", GATE_SPI5), ++ ++ CS_GATE("dma1", "ck_mlahb", GATE_DMA1), ++ CS_GATE("dma2", "ck_mlahb", GATE_DMA2), ++ CS_GATE("dmamux1", "ck_mlahb", GATE_DMAMUX1), ++ CS_GATE("dma3", "ck_mlahb", GATE_DMA3), ++ CS_GATE("dmamux2", "ck_mlahb", GATE_DMAMUX2), ++ CS_GATE("adc1", "ck_mlahb", GATE_ADC1), ++ CS_GATE("adc2", "ck_mlahb", GATE_ADC2), ++ ++ CS_GATE("pka", "ck_axi", GATE_PKA), ++ CS_GATE("cryp1", "ck_axi", GATE_CRYP1), ++ CS_GATE("hash1", "ck_axi", GATE_HASH1), ++ CS_GATE("bkpsram", "ck_axi", GATE_BKPSRAM), ++ CS_GATE("mdma", "ck_axi", GATE_MDMA), ++ CS_GATE("eth1tx", "ck_axi", GATE_ETH1TX), ++ CS_GATE("eth1rx", "ck_axi", GATE_ETH1RX), ++ CS_GATE("eth1mac", "ck_axi", GATE_ETH1MAC), ++ CS_GATE("eth2tx", "ck_axi", GATE_ETH2TX), ++ CS_GATE("eth2rx", "ck_axi", GATE_ETH2RX), ++ CS_GATE("eth2mac", "ck_axi", GATE_ETH2MAC), ++ CS_GATE("crc1", "ck_axi", GATE_CRC1), ++ CS_GATE("usbh", "ck_axi", GATE_USBH), ++ CS_GATE("eth1stp", "ck_axi", GATE_ETH1STP), ++ CS_GATE("eth2stp", "ck_axi", GATE_ETH2STP), ++ ++ CS_GATEMUX("sdmmc1_k", sdmmc12_src, GATE_SDMMC1, MUX_SDMMC1), ++ CS_GATEMUX("sdmmc2_k", sdmmc12_src, GATE_SDMMC2, MUX_SDMMC2), ++ CS_GATEMUX("fmc_k", fmc_src, GATE_FMC, MUX_FMC), ++ CS_GATEMUX("qspi_k", qspi_src, GATE_QSPI, MUX_QSPI), ++ CS_GATEMUX("spi2_k", spi123_src, GATE_SPI2, MUX_SPI23), ++ CS_GATEMUX("spi3_k", spi123_src, GATE_SPI3, MUX_SPI23), ++ CS_GATEMUX("i2c1_k", i2c12_src, GATE_I2C1, MUX_I2C12), ++ CS_GATEMUX("i2c2_k", i2c12_src, GATE_I2C2, MUX_I2C12), ++ CS_GATEMUX("lptim4_k", lptim45_src, GATE_LPTIM4, MUX_LPTIM45), ++ CS_GATEMUX("lptim5_k", lptim45_src, GATE_LPTIM5, MUX_LPTIM45), ++ CS_GATEMUX("usart3_k", usart34578_src, GATE_USART3, MUX_UART35), ++ CS_GATEMUX("uart5_k", usart34578_src, GATE_UART5, MUX_UART35), ++ CS_GATEMUX("uart7_k", usart34578_src, GATE_UART7, MUX_UART78), ++ CS_GATEMUX("uart8_k", usart34578_src, GATE_UART8, MUX_UART78), ++ CS_GATEMUX("sai1_k", sai1_src, GATE_SAI1, MUX_SAI1), ++ CS_GATEMUX("adfsdm_k", sai1_src, GATE_ADFSDM, MUX_SAI1), ++ CS_GATEMUX("sai2_k", sai2_src, GATE_SAI2, MUX_SAI2), ++ CS_GATEMUX("adc1_k", adc12_src, GATE_ADC1, MUX_ADC1), ++ CS_GATEMUX("adc2_k", adc12_src, GATE_ADC2, MUX_ADC2), ++ CS_GATEMUX("rng1_k", rng1_src, GATE_RNG1, MUX_RNG1), ++ CS_GATEMUX("usbphy_k", usbphy_src, GATE_USBPHY, MUX_USBPHY), ++ CS_GATEMUX("stgen_k", stgen_src, GATE_STGENC, MUX_STGEN), ++ CS_GATEMUX("spdif_k", spdif_src, GATE_SPDIF, MUX_SPDIF), ++ CS_GATEMUX("spi1_k", spi123_src, GATE_SPI1, MUX_SPI1), ++ CS_GATEMUX("spi4_k", spi4_src, GATE_SPI4, MUX_SPI4), ++ CS_GATEMUX("spi5_k", spi5_src, GATE_SPI5, MUX_SPI5), ++ CS_GATEMUX("i2c3_k", i2c345_src, GATE_I2C3, MUX_I2C3), ++ CS_GATEMUX("i2c4_k", i2c345_src, GATE_I2C4, MUX_I2C4), ++ CS_GATEMUX("i2c5_k", i2c345_src, GATE_I2C5, MUX_I2C5), ++ CS_GATEMUX("lptim1_k", lptim1_src, GATE_LPTIM1, MUX_LPTIM1), ++ CS_GATEMUX("lptim2_k", lptim23_src, GATE_LPTIM2, MUX_LPTIM2), ++ CS_GATEMUX("lptim3_k", lptim23_src, GATE_LPTIM3, MUX_LPTIM3), ++ CS_GATEMUX("usart1_k", usart12_src, GATE_USART1, MUX_UART1), ++ CS_GATEMUX("usart2_k", usart12_src, GATE_USART2, MUX_UART2), ++ CS_GATEMUX("uart4_k", usart34578_src, GATE_UART4, MUX_UART4), ++ CS_GATEMUX("uart6_k", usart6_src, GATE_USART6, MUX_UART6), ++ CS_GATEMUX("fdcan_k", fdcan_src, GATE_FDCAN, MUX_FDCAN), ++ CS_GATEMUX("dcmipp_k", dcmipp_src, GATE_DCMIPP, MUX_DCMIPP), ++ CS_GATEMUX("usbo_k", usbo_src, GATE_USBO, MUX_USBO), ++ CS_GATEMUX("eth1ck_k", eth12_src, GATE_ETH1CK, MUX_ETH1), ++ CS_GATEMUX("eth2ck_k", eth12_src, GATE_ETH2CK, MUX_ETH2), ++ CS_GATEMUX("saes_k", saes_src, GATE_SAES, MUX_SAES), ++ CS_GATE("dfsdm_k", "ck_mlahb", GATE_DFSDM), ++ CS_GATE("ltdc_px", "pll4_q", GATE_LTDC), ++ CS_COMPOSITE("eth1ptp_k", eth12_src, NO_STM32_GATE, MUX_ETH1, DIV_ETH1PTP), ++ CS_COMPOSITE("eth2ptp_k", eth12_src, NO_STM32_GATE, MUX_ETH2, DIV_ETH2PTP), ++ CS_COMPOSITE("ck_mco1", mco1_src, GATE_MCO1, MUX_MCO1, DIV_MCO1), ++ CS_COMPOSITE("ck_mco2", mco2_src, GATE_MCO2, MUX_MCO2, DIV_MCO2), ++ CS_GATE("ck_sys_dbg", "ck_axi", GATE_DBGCK), ++ CS_GATEDIV("ck_trace", "ck_axi", GATE_TRACECK, DIV_TRACE), ++ CS_GATE("rtcapb", "pclk5", GATE_RTCAPB), ++ CS_RTC("ck_rtc", rtc_src, GATE_RTCCK, MUX_RTC, DIV_RTC), ++}; ++ ++static struct clock_summary clock_summary_mp13 = { ++ .clocks = stm32mp13_clock_summary, ++ .nb_clocks = ARRAY_SIZE(stm32mp13_clock_summary), ++}; ++ ++ ++#endif diff --git a/drivers/clk/stm32/reset-stm32.c b/drivers/clk/stm32/reset-stm32.c new file mode 100644 -index 000000000..eb7ed08f9 +index 000000000000..8239b154ad86 --- /dev/null +++ b/drivers/clk/stm32/reset-stm32.c -@@ -0,0 +1,122 @@ +@@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2021 - All Rights Reserved @@ -2987,6 +5062,7 @@ index 000000000..eb7ed08f9 + struct reset_controller_dev rcdev; + void __iomem *membase; + u32 clear_offset; ++ unsigned int reset_us; +}; + +static inline struct stm32_reset_data * @@ -3059,9 +5135,46 @@ index 000000000..eb7ed08f9 + return !!(reg & BIT(offset)); +} + ++static int stm32_check_deassert(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; ++ ++ return readl_poll_timeout(data->membase + (bank * reg_width), reg, ++ !(reg & BIT(offset)), 10, 10 * USEC_PER_MSEC); ++} ++ ++static int stm32_reset(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ struct stm32_reset_data *data = to_stm32_reset_data(rcdev); ++ int ret; ++ ++ ret = stm32_reset_assert(rcdev, id); ++ if (ret) ++ return ret; ++ ++ if (!data->reset_us) ++ usleep_range(data->reset_us, data->reset_us * 2); ++ ++ ret = stm32_reset_deassert(rcdev, id); ++ if (ret) ++ return ret; ++ ++ ret = stm32_check_deassert(rcdev, id); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ +static const struct reset_control_ops stm32_reset_ops = { + .assert = stm32_reset_assert, + .deassert = stm32_reset_deassert, ++ .reset = stm32_reset, + .status = stm32_reset_status, +}; + @@ -3083,12 +5196,13 @@ index 000000000..eb7ed08f9 + reset_data->rcdev.of_node = dev_of_node(dev); + reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK; + reset_data->clear_offset = data->clear_offset; ++ reset_data->reset_us = data->reset_us; + + return reset_controller_register(&reset_data->rcdev); +} diff --git a/drivers/clk/stm32/reset-stm32.h b/drivers/clk/stm32/reset-stm32.h new file mode 100644 -index 000000000..63a4a35b5 +index 000000000000..63a4a35b5b5a --- /dev/null +++ b/drivers/clk/stm32/reset-stm32.h @@ -0,0 +1,7 @@ @@ -3101,7 +5215,7 @@ index 000000000..63a4a35b5 +int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match, void __iomem *base); diff --git a/drivers/clk/stm32/stm32mp13_rcc.h b/drivers/clk/stm32/stm32mp13_rcc.h new file mode 100644 -index 000000000..f01a98c85 +index 000000000000..f01a98c8563f --- /dev/null +++ b/drivers/clk/stm32/stm32mp13_rcc.h @@ -0,0 +1,1751 @@ @@ -4857,7 +6971,7 @@ index 000000000..f01a98c85 +#endif /* STM32MP13_RCC_H */ + diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c -index db2841d0b..90c10f378 100644 +index db2841d0beb8..90c10f378df2 100644 --- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c @@ -168,9 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev) @@ -4872,7 +6986,7 @@ index db2841d0b..90c10f378 100644 ret = dev_pm_set_wake_irq(&pdev->dev, irq); if (ret) diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h -index e02770b98..2e23e0384 100644 +index e02770b98e6c..2e23e0384b0a 100644 --- a/include/dt-bindings/clock/stm32mp1-clks.h +++ b/include/dt-bindings/clock/stm32mp1-clks.h @@ -179,6 +179,12 @@ @@ -4942,10 +7056,10 @@ index e02770b98..2e23e0384 100644 #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ diff --git a/include/dt-bindings/clock/stm32mp13-clks.h b/include/dt-bindings/clock/stm32mp13-clks.h new file mode 100644 -index 000000000..02befd25e +index 000000000000..2a110340ff2f --- /dev/null +++ b/include/dt-bindings/clock/stm32mp13-clks.h -@@ -0,0 +1,229 @@ +@@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2020 - All Rights Reserved @@ -5141,7 +7255,13 @@ index 000000000..02befd25e +#define SAI1 160 +#define SAI2 161 + -+#define STM32MP1_LAST_CLK 162 ++#define SPI1 162 ++#define SPI2 163 ++#define SPI3 164 ++#define SPI4 165 ++#define SPI5 166 ++ ++#define STM32MP1_LAST_CLK 167 + +/* SCMI clock identifiers */ +#define CK_SCMI_HSE 0 @@ -5176,5 +7296,5 @@ index 000000000..02befd25e + +#endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0003-ARM-5.15.24-stm32mp1-r1-CPUFREQ.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0003-v5.15-stm32mp-r2-CPUFREQ.patch similarity index 62% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0003-ARM-5.15.24-stm32mp1-r1-CPUFREQ.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0003-v5.15-stm32mp-r2-CPUFREQ.patch index 8264d77..c531b2b 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0003-ARM-5.15.24-stm32mp1-r1-CPUFREQ.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0003-v5.15-stm32mp-r2-CPUFREQ.patch @@ -1,19 +1,88 @@ -From 1aacc70479e14dd5ca0e60a969478957a390dbda Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:51:10 +0200 -Subject: [PATCH 03/22] ARM-5.15.24-stm32mp1-r1-CPUFREQ +From 7b129c9db71e9dcb515a4585861898b6a3644f1b Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:23:32 +0100 +Subject: [PATCH 03/22] v5.15-stm32mp-r2 CPUFREQ -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- - drivers/cpufreq/Kconfig.arm | 7 ++ - drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/cpufreq-dt-platdev.c | 1 + - drivers/cpufreq/stm32-cpufreq.c | 103 +++++++++++++++++++++++++++ - 4 files changed, 112 insertions(+) + .../bindings/cpufreq/stm32-cpufreq.txt | 61 +++++++++++ + drivers/cpufreq/Kconfig.arm | 7 ++ + drivers/cpufreq/Makefile | 1 + + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + drivers/cpufreq/stm32-cpufreq.c | 103 ++++++++++++++++++ + 5 files changed, 173 insertions(+) + create mode 100644 Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt create mode 100644 drivers/cpufreq/stm32-cpufreq.c +diff --git a/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt +new file mode 100644 +index 000000000000..1292eb2612a0 +--- /dev/null ++++ b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt +@@ -0,0 +1,61 @@ ++STM32 CPUFreq and OPP bindings ++============================== ++ ++STM32 CPUFreq driver needs to read chip information from the SoC to list ++available OPPs. Then it depends on cpufreq-dt bindings. ++ ++Required properties: ++-------------------- ++- clocks: Phandle to the cpu clock "cpu". ++- clocks-name: Should contain "cpu". ++- nvmem-cells: Phandle to nvmem cell that contains "part_number". ++- nvmem-cell-names: Must be "part_number". ++- operating-points-v2: Phandle to operating points table. See ../power/opp.txt ++ for more details. ++ ++Optional properties: ++-------------------- ++See cpufreq-dt.txt for optional properties. ++ ++Examples: ++--------- ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <0>; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ nvmem-cells = <&part_number_otp>; ++ nvmem-cell-names = "part_number"; ++ }; ++ ++ cpu1: cpu@1 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <1>; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ }; ++ ++ cpu0_opp_table: cpu0-opp-table { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-650000000 { ++ opp-hz = /bits/ 64 <650000000>; ++ opp-microvolt = <1200000>; ++ opp-supported-hw = <0x1>; ++ }; ++ opp-800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1350000>; ++ opp-supported-hw = <0x2>; ++ }; ++ }; diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index 954749afb..eac08e907 100644 +index 954749afb5fe..eac08e90768c 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -311,6 +311,13 @@ config ARM_STI_CPUFREQ @@ -31,7 +100,7 @@ index 954749afb..eac08e907 100644 tristate "Tegra20/30 CPUFreq support" depends on ARCH_TEGRA && CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 48ee58590..d34de1b92 100644 +index 48ee5859030c..d34de1b927bf 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ) += scmi-cpufreq.o @@ -43,7 +112,7 @@ index 48ee58590..d34de1b92 100644 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c -index ca1d103ec..f205e6e97 100644 +index ca1d103ec449..f205e6e9703e 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -150,6 +150,7 @@ static const struct of_device_id blocklist[] __initconst = { @@ -56,7 +125,7 @@ index ca1d103ec..f205e6e97 100644 { .compatible = "ti,am43", }, diff --git a/drivers/cpufreq/stm32-cpufreq.c b/drivers/cpufreq/stm32-cpufreq.c new file mode 100644 -index 000000000..d7b1b16ea +index 000000000000..d7b1b16ea1d1 --- /dev/null +++ b/drivers/cpufreq/stm32-cpufreq.c @@ -0,0 +1,103 @@ @@ -164,5 +233,5 @@ index 000000000..d7b1b16ea +MODULE_AUTHOR("Alexandre Torgue "); +MODULE_LICENSE("GPL v2"); -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0020-ARM-5.15.24-stm32mp1-r1-CPUIDLE-POWER.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0004-v5.15-stm32mp-r2-CPUIDLE-POWER.patch similarity index 75% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0020-ARM-5.15.24-stm32mp1-r1-CPUIDLE-POWER.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0004-v5.15-stm32mp-r2-CPUIDLE-POWER.patch index 3f96c8a..48e0e80 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0020-ARM-5.15.24-stm32mp1-r1-CPUIDLE-POWER.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0004-v5.15-stm32mp-r2-CPUIDLE-POWER.patch @@ -1,88 +1,19 @@ -From 4627c869d60932edc00dd979d9b1bd374518c5c8 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:08:46 +0200 -Subject: [PATCH 20/22] ARM-5.15.24-stm32mp1-r1-CPUIDLE-POWER +From dc62943bb269dbe5f3294beda26e299bb00f0e97 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 16:49:53 +0100 +Subject: [PATCH 04/22] v5.15-stm32mp-r2 CPUIDLE-POWER -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- - .../bindings/cpufreq/stm32-cpufreq.txt | 61 ++++ - drivers/cpuidle/Kconfig.arm | 8 + - drivers/cpuidle/Makefile | 1 + - drivers/cpuidle/cpuidle-stm32.c | 276 ++++++++++++++++++ - kernel/power/suspend.c | 1 - - 5 files changed, 346 insertions(+), 1 deletion(-) - create mode 100644 Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt + drivers/cpuidle/Kconfig.arm | 8 + + drivers/cpuidle/Makefile | 1 + + drivers/cpuidle/cpuidle-stm32.c | 276 ++++++++++++++++++++++++++++++++ + kernel/power/suspend.c | 1 - + 4 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 drivers/cpuidle/cpuidle-stm32.c -diff --git a/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt -new file mode 100644 -index 000000000..1292eb261 ---- /dev/null -+++ b/Documentation/devicetree/bindings/cpufreq/stm32-cpufreq.txt -@@ -0,0 +1,61 @@ -+STM32 CPUFreq and OPP bindings -+============================== -+ -+STM32 CPUFreq driver needs to read chip information from the SoC to list -+available OPPs. Then it depends on cpufreq-dt bindings. -+ -+Required properties: -+-------------------- -+- clocks: Phandle to the cpu clock "cpu". -+- clocks-name: Should contain "cpu". -+- nvmem-cells: Phandle to nvmem cell that contains "part_number". -+- nvmem-cell-names: Must be "part_number". -+- operating-points-v2: Phandle to operating points table. See ../power/opp.txt -+ for more details. -+ -+Optional properties: -+-------------------- -+See cpufreq-dt.txt for optional properties. -+ -+Examples: -+--------- -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu0: cpu@0 { -+ compatible = "arm,cortex-a7"; -+ device_type = "cpu"; -+ reg = <0>; -+ clocks = <&rcc CK_MPU>; -+ clock-names = "cpu"; -+ operating-points-v2 = <&cpu0_opp_table>; -+ nvmem-cells = <&part_number_otp>; -+ nvmem-cell-names = "part_number"; -+ }; -+ -+ cpu1: cpu@1 { -+ compatible = "arm,cortex-a7"; -+ device_type = "cpu"; -+ reg = <1>; -+ clocks = <&rcc CK_MPU>; -+ clock-names = "cpu"; -+ operating-points-v2 = <&cpu0_opp_table>; -+ }; -+ }; -+ -+ cpu0_opp_table: cpu0-opp-table { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-650000000 { -+ opp-hz = /bits/ 64 <650000000>; -+ opp-microvolt = <1200000>; -+ opp-supported-hw = <0x1>; -+ }; -+ opp-800000000 { -+ opp-hz = /bits/ 64 <800000000>; -+ opp-microvolt = <1350000>; -+ opp-supported-hw = <0x2>; -+ }; -+ }; diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm -index 334f83e56..4de5db493 100644 +index 334f83e56120..4de5db493d42 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -91,6 +91,14 @@ config ARM_EXYNOS_CPUIDLE @@ -101,7 +32,7 @@ index 334f83e56..4de5db493 100644 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 26bbc5e74..cc1eccc73 100644 +index 26bbc5e74123..cc1eccc73d65 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o @@ -114,7 +45,7 @@ index 26bbc5e74..cc1eccc73 100644 # MIPS drivers diff --git a/drivers/cpuidle/cpuidle-stm32.c b/drivers/cpuidle/cpuidle-stm32.c new file mode 100644 -index 000000000..2fef170d6 +index 000000000000..2fef170d6877 --- /dev/null +++ b/drivers/cpuidle/cpuidle-stm32.c @@ -0,0 +1,276 @@ @@ -395,7 +326,7 @@ index 000000000..2fef170d6 +MODULE_DESCRIPTION("STM32 cpu idle driver"); +MODULE_LICENSE("GPL v2"); diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c -index 13d905dd3..371f2765d 100644 +index 13d905dd3267..371f2765da18 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -34,7 +34,6 @@ @@ -407,5 +338,5 @@ index 13d905dd3..371f2765d 100644 [PM_SUSPEND_MEM] = "mem", }; -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0005-v5.15-stm32mp-r2-CRYPTO.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0005-v5.15-stm32mp-r2-CRYPTO.patch new file mode 100644 index 0000000..9427380 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0005-v5.15-stm32mp-r2-CRYPTO.patch @@ -0,0 +1,2687 @@ +From 0d2fcaf7ef322a9caec811097a3877d9a89eaae4 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:26:07 +0100 +Subject: [PATCH 05/22] v5.15-stm32mp-r2 CRYPTO + +Signed-off-by: Romuald JEANNE +--- + .../bindings/crypto/st,stm32-cryp.yaml | 9 + + .../bindings/crypto/st,stm32-hash.yaml | 1 + + drivers/crypto/stm32/stm32-cryp.c | 741 ++++++++++++- + drivers/crypto/stm32/stm32-hash.c | 999 ++++++++++++------ + 4 files changed, 1409 insertions(+), 341 deletions(-) + +diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml b/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml +index a4574552502a..6c3f8f7bfd67 100644 +--- a/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml ++++ b/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml +@@ -27,6 +27,15 @@ properties: + resets: + maxItems: 1 + ++ dmas: ++ maxItems: 2 ++ minItems: 2 ++ ++ dma-names: ++ items: ++ - const: in ++ - const: out ++ + required: + - compatible + - reg +diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml +index 6dd658f0912c..1a944608d8ff 100644 +--- a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml ++++ b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml +@@ -14,6 +14,7 @@ properties: + enum: + - st,stm32f456-hash + - st,stm32f756-hash ++ - st,stm32mp13-hash + + reg: + maxItems: 1 +diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c +index 81eb136b6c11..d76641596db4 100644 +--- a/drivers/crypto/stm32/stm32-cryp.c ++++ b/drivers/crypto/stm32/stm32-cryp.c +@@ -5,7 +5,10 @@ + */ + + #include ++#include + #include ++#include ++#include + #include + #include + #include +@@ -37,6 +40,8 @@ + /* Mode mask = bits [15..0] */ + #define FLG_MODE_MASK GENMASK(15, 0) + /* Bit [31..16] status */ ++#define FLG_IN_OUT_DMA BIT(16) ++#define FLG_HEADER_DMA BIT(17) + + /* Registers */ + #define CRYP_CR 0x00000000 +@@ -62,6 +67,21 @@ + #define CRYP_CSGCMCCM0R 0x00000050 + #define CRYP_CSGCM0R 0x00000070 + ++static const struct debugfs_reg32 stm32_cryp_regs[] = { ++ { ++ .name = "cr", ++ .offset = CRYP_CR ++ }, ++ { ++ .name = "sr", ++ .offset = CRYP_SR ++ }, ++ { ++ .name = "dmacr", ++ .offset = CRYP_DMACR ++ } ++}; ++ + /* Registers values */ + #define CR_DEC_NOT_ENC 0x00000004 + #define CR_TDES_ECB 0x00000000 +@@ -92,8 +112,12 @@ + #define CR_PH_MASK 0x00030000 + #define CR_NBPBL_SHIFT 20 + +-#define SR_BUSY 0x00000010 +-#define SR_OFNE 0x00000004 ++#define SR_IFNF BIT(1) ++#define SR_OFNE BIT(2) ++#define SR_BUSY BIT(8) ++ ++#define DMACR_DIEN BIT(0) ++#define DMACR_DOEN BIT(1) + + #define IMSCR_IN BIT(0) + #define IMSCR_OUT BIT(1) +@@ -104,7 +128,16 @@ + /* Misc */ + #define AES_BLOCK_32 (AES_BLOCK_SIZE / sizeof(u32)) + #define GCM_CTR_INIT 2 +-#define CRYP_AUTOSUSPEND_DELAY 50 ++#define CRYP_AUTOSUSPEND_DELAY 50 ++ ++#define CRYP_DMA_BURST_MEM 16 ++#define CRYP_DMA_BURST_REG 4 ++ ++enum stm32_dma_mode { ++ NO_DMA, ++ DMA_PLAIN_SG, ++ DMA_NEED_SG_TRUNC ++}; + + struct stm32_cryp_caps { + bool swap_final; +@@ -127,11 +160,13 @@ struct stm32_cryp { + struct list_head list; + struct device *dev; + void __iomem *regs; ++ phys_addr_t phys_base; + struct clk *clk; + unsigned long flags; + u32 irq_status; + const struct stm32_cryp_caps *caps; + struct stm32_cryp_ctx *ctx; ++ struct dentry *dbgdir; + + struct crypto_engine *engine; + +@@ -145,8 +180,19 @@ struct stm32_cryp { + size_t header_in; + size_t payload_out; + ++ /* DMA process fields */ ++ struct scatterlist *in_sg; ++ struct scatterlist *header_sg; + struct scatterlist *out_sg; ++ size_t in_sg_len; ++ size_t header_sg_len; ++ size_t out_sg_len; + ++ struct dma_chan *dma_lch_in; ++ struct dma_chan *dma_lch_out; ++ enum stm32_dma_mode dma_mode; ++ ++ /* IT process fields */ + struct scatter_walk in_walk; + struct scatter_walk out_walk; + +@@ -232,6 +278,11 @@ static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp) + !(status & SR_BUSY), 10, 100000); + } + ++static inline void stm32_cryp_enable(struct stm32_cryp *cryp) ++{ ++ writel_relaxed(readl_relaxed(cryp->regs + CRYP_CR) | CR_CRYPEN, cryp->regs + CRYP_CR); ++} ++ + static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp) + { + u32 status; +@@ -240,6 +291,14 @@ static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp) + !(status & CR_CRYPEN), 10, 100000); + } + ++static inline int stm32_cryp_wait_input(struct stm32_cryp *cryp) ++{ ++ u32 status; ++ ++ return readl_relaxed_poll_timeout(cryp->regs + CRYP_SR, status, ++ status & SR_IFNF, 10, 100000); ++} ++ + static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp) + { + u32 status; +@@ -248,8 +307,13 @@ static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp) + status & SR_OFNE, 10, 100000); + } + ++static void stm32_cryp_irq_read_data(struct stm32_cryp *cryp); ++static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp); ++static void stm32_cryp_irq_write_gcmccm_header(struct stm32_cryp *cryp); + static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp); + static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err); ++static int stm32_cryp_dma_start(struct stm32_cryp *cryp); ++static int stm32_cryp_it_start(struct stm32_cryp *cryp); + + static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx) + { +@@ -535,9 +599,6 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) + /* Disable interrupt */ + stm32_cryp_write(cryp, CRYP_IMSCR, 0); + +- /* Set key */ +- stm32_cryp_hw_write_key(cryp); +- + /* Set configuration */ + cfg = CR_DATA8 | CR_FFLUSH; + +@@ -563,23 +624,36 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) + /* AES ECB/CBC decrypt: run key preparation first */ + if (is_decrypt(cryp) && + ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) { +- stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP | CR_CRYPEN); ++ /* Configure in key preparation mode */ ++ stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP); ++ ++ /* Set key only after full configuration done */ ++ stm32_cryp_hw_write_key(cryp); + ++ /* Start prepare key */ ++ stm32_cryp_enable(cryp); + /* Wait for end of processing */ + ret = stm32_cryp_wait_busy(cryp); + if (ret) { + dev_err(cryp->dev, "Timeout (key preparation)\n"); + return ret; + } +- } + +- cfg |= hw_mode; ++ cfg |= hw_mode | CR_DEC_NOT_ENC; + +- if (is_decrypt(cryp)) +- cfg |= CR_DEC_NOT_ENC; ++ /* Apply updated config (Decrypt + algo) and flush */ ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ } else { ++ cfg |= hw_mode; ++ if (is_decrypt(cryp)) ++ cfg |= CR_DEC_NOT_ENC; + +- /* Apply config and flush (valid when CRYPEN = 0) */ +- stm32_cryp_write(cryp, CRYP_CR, cfg); ++ /* Apply config and flush */ ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ ++ /* Set key only after configuration done */ ++ stm32_cryp_hw_write_key(cryp); ++ } + + switch (hw_mode) { + case CR_AES_GCM: +@@ -607,9 +681,7 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) + } + + /* Enable now */ +- cfg |= CR_CRYPEN; +- +- stm32_cryp_write(cryp, CRYP_CR, cfg); ++ stm32_cryp_enable(cryp); + + return 0; + } +@@ -629,11 +701,223 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err) + if (is_gcm(cryp) || is_ccm(cryp)) + crypto_finalize_aead_request(cryp->engine, cryp->areq, err); + else +- crypto_finalize_skcipher_request(cryp->engine, cryp->req, +- err); ++ crypto_finalize_skcipher_request(cryp->engine, cryp->req, err); + } + +-static int stm32_cryp_cpu_start(struct stm32_cryp *cryp) ++static void stm32_cryp_header_dma_callback(void *param) ++{ ++ struct stm32_cryp *cryp = (struct stm32_cryp *)param; ++ int ret; ++ u32 reg; ++ ++ dma_unmap_sg(cryp->dev, cryp->header_sg, cryp->header_sg_len, DMA_TO_DEVICE); ++ ++ reg = stm32_cryp_read(cryp, CRYP_DMACR); ++ stm32_cryp_write(cryp, CRYP_DMACR, reg & ~(DMACR_DOEN | DMACR_DIEN)); ++ ++ kfree(cryp->header_sg); ++ ++ reg = stm32_cryp_read(cryp, CRYP_CR); ++ ++ if (cryp->header_in) { ++ stm32_cryp_write(cryp, CRYP_CR, reg | CR_CRYPEN); ++ ++ ret = stm32_cryp_wait_input(cryp); ++ if (ret) { ++ dev_err(cryp->dev, "input header ready timeout after dma\n"); ++ stm32_cryp_finish_req(cryp, ret); ++ return; ++ } ++ stm32_cryp_irq_write_gcmccm_header(cryp); ++ WARN_ON(cryp->header_in); ++ } ++ ++ if (stm32_cryp_get_input_text_len(cryp)) { ++ /* Phase 3 : payload */ ++ reg = stm32_cryp_read(cryp, CRYP_CR); ++ stm32_cryp_write(cryp, CRYP_CR, reg & ~CR_CRYPEN); ++ ++ reg &= ~CR_PH_MASK; ++ reg |= CR_PH_PAYLOAD | CR_CRYPEN; ++ stm32_cryp_write(cryp, CRYP_CR, reg); ++ ++ if (cryp->flags & FLG_IN_OUT_DMA) { ++ ret = stm32_cryp_dma_start(cryp); ++ if (ret) ++ stm32_cryp_finish_req(cryp, ret); ++ } else { ++ stm32_cryp_it_start(cryp); ++ } ++ } else { ++ /* ++ * Phase 4 : tag. ++ * Nothing to read, nothing to write => end request ++ */ ++ stm32_cryp_finish_req(cryp, 0); ++ } ++} ++static void stm32_cryp_dma_callback(void *param) ++{ ++ struct stm32_cryp *cryp = (struct stm32_cryp *)param; ++ int ret; ++ u32 reg; ++ ++ dma_sync_sg_for_device(cryp->dev, cryp->out_sg, cryp->out_sg_len, DMA_FROM_DEVICE); ++ dma_unmap_sg(cryp->dev, cryp->in_sg, cryp->in_sg_len, DMA_TO_DEVICE); ++ dma_unmap_sg(cryp->dev, cryp->out_sg, cryp->out_sg_len, DMA_FROM_DEVICE); ++ ++ reg = stm32_cryp_read(cryp, CRYP_DMACR); ++ stm32_cryp_write(cryp, CRYP_DMACR, reg & ~(DMACR_DOEN | DMACR_DIEN)); ++ ++ reg = stm32_cryp_read(cryp, CRYP_CR); ++ ++ if (is_gcm(cryp) || is_ccm(cryp)) { ++ kfree(cryp->in_sg); ++ kfree(cryp->out_sg); ++ } else { ++ if (cryp->in_sg != cryp->req->src) ++ kfree(cryp->in_sg); ++ if (cryp->out_sg != cryp->req->dst) ++ kfree(cryp->out_sg); ++ } ++ ++ if (cryp->payload_in) { ++ stm32_cryp_write(cryp, CRYP_CR, reg | CR_CRYPEN); ++ ++ ret = stm32_cryp_wait_input(cryp); ++ if (ret) { ++ dev_err(cryp->dev, "input ready timeout after dma\n"); ++ stm32_cryp_finish_req(cryp, ret); ++ return; ++ } ++ stm32_cryp_irq_write_data(cryp); ++ ++ ret = stm32_cryp_wait_output(cryp); ++ if (ret) { ++ dev_err(cryp->dev, "output ready timeout after dma\n"); ++ stm32_cryp_finish_req(cryp, ret); ++ return; ++ } ++ stm32_cryp_irq_read_data(cryp); ++ } ++ ++ stm32_cryp_finish_req(cryp, 0); ++} ++ ++static int stm32_cryp_header_dma_start(struct stm32_cryp *cryp) ++{ ++ int err; ++ struct dma_async_tx_descriptor *tx_in; ++ u32 reg; ++ size_t align_size; ++ ++ err = dma_map_sg(cryp->dev, cryp->header_sg, cryp->header_sg_len, DMA_TO_DEVICE); ++ if (!err) { ++ dev_err(cryp->dev, "dma_map_sg() error\n"); ++ return err; ++ } ++ ++ dma_sync_sg_for_device(cryp->dev, cryp->header_sg, cryp->header_sg_len, DMA_TO_DEVICE); ++ ++ tx_in = dmaengine_prep_slave_sg(cryp->dma_lch_in, cryp->header_sg, cryp->header_sg_len, ++ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!tx_in) { ++ dev_err(cryp->dev, "IN prep_slave_sg() failed\n"); ++ return -EINVAL; ++ } ++ ++ tx_in->callback_param = cryp; ++ tx_in->callback = stm32_cryp_header_dma_callback; ++ ++ /* Advance scatterwalk to not DMA'ed data */ ++ align_size = ALIGN_DOWN(cryp->header_in, cryp->hw_blocksize); ++ scatterwalk_copychunks(NULL, &cryp->in_walk, align_size, 2); ++ cryp->header_in -= align_size; ++ ++ err = dma_submit_error(dmaengine_submit(tx_in)); ++ if (err < 0) { ++ dev_err(cryp->dev, "DMA in submit failed\n"); ++ return err; ++ } ++ dma_async_issue_pending(cryp->dma_lch_in); ++ ++ reg = stm32_cryp_read(cryp, CRYP_DMACR); ++ stm32_cryp_write(cryp, CRYP_DMACR, reg | DMACR_DIEN); ++ ++ return 0; ++} ++ ++static int stm32_cryp_dma_start(struct stm32_cryp *cryp) ++{ ++ int err; ++ size_t align_size; ++ struct dma_async_tx_descriptor *tx_in, *tx_out; ++ u32 reg; ++ ++ err = dma_map_sg(cryp->dev, cryp->in_sg, cryp->in_sg_len, DMA_TO_DEVICE); ++ if (!err) { ++ dev_err(cryp->dev, "dma_map_sg() error\n"); ++ return err; ++ } ++ ++ err = dma_map_sg(cryp->dev, cryp->out_sg, cryp->out_sg_len, DMA_FROM_DEVICE); ++ if (!err) { ++ dev_err(cryp->dev, "dma_map_sg() error\n"); ++ return err; ++ } ++ ++ dma_sync_sg_for_device(cryp->dev, cryp->in_sg, cryp->in_sg_len, DMA_TO_DEVICE); ++ ++ tx_in = dmaengine_prep_slave_sg(cryp->dma_lch_in, cryp->in_sg, cryp->in_sg_len, ++ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!tx_in) { ++ dev_err(cryp->dev, "IN prep_slave_sg() failed\n"); ++ return -EINVAL; ++ } ++ ++ /* No callback necessary */ ++ tx_in->callback_param = cryp; ++ tx_in->callback = NULL; ++ ++ tx_out = dmaengine_prep_slave_sg(cryp->dma_lch_out, cryp->out_sg, cryp->out_sg_len, ++ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!tx_out) { ++ dev_err(cryp->dev, "OUT prep_slave_sg() failed\n"); ++ return -EINVAL; ++ } ++ ++ tx_out->callback = stm32_cryp_dma_callback; ++ tx_out->callback_param = cryp; ++ ++ /* Advance scatterwalk to not DMA'ed data */ ++ align_size = ALIGN_DOWN(cryp->payload_in, cryp->hw_blocksize); ++ scatterwalk_copychunks(NULL, &cryp->in_walk, align_size, 2); ++ cryp->payload_in -= align_size; ++ ++ err = dma_submit_error(dmaengine_submit(tx_in)); ++ if (err < 0) { ++ dev_err(cryp->dev, "DMA in submit failed\n"); ++ return err; ++ } ++ dma_async_issue_pending(cryp->dma_lch_in); ++ ++ /* Advance scatterwalk to not DMA'ed data */ ++ scatterwalk_copychunks(NULL, &cryp->out_walk, align_size, 2); ++ cryp->payload_out -= align_size; ++ err = dma_submit_error(dmaengine_submit(tx_out)); ++ if (err < 0) { ++ dev_err(cryp->dev, "DMA out submit failed\n"); ++ return err; ++ } ++ dma_async_issue_pending(cryp->dma_lch_out); ++ ++ reg = stm32_cryp_read(cryp, CRYP_DMACR); ++ stm32_cryp_write(cryp, CRYP_DMACR, reg | DMACR_DOEN | DMACR_DIEN); ++ ++ return 0; ++} ++ ++static int stm32_cryp_it_start(struct stm32_cryp *cryp) + { + /* Enable interrupt and let the IRQ handler do everything */ + stm32_cryp_write(cryp, CRYP_IMSCR, IMSCR_IN | IMSCR_OUT); +@@ -980,13 +1264,254 @@ static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req) + return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC); + } + ++static enum stm32_dma_mode stm32_cryp_dma_check_sg(struct scatterlist *test_sg, size_t len, ++ size_t block_size) ++{ ++ struct scatterlist *sg; ++ int i; ++ ++ if (len <= 16) ++ return NO_DMA; /* Faster */ ++ ++ for_each_sg(test_sg, sg, sg_nents(test_sg), i) { ++ if (!IS_ALIGNED(sg->length, block_size) && !sg_is_last(sg)) ++ return NO_DMA; ++ ++ if (sg->offset % sizeof(u32)) ++ return NO_DMA; ++ ++ if (sg_is_last(sg) && !IS_ALIGNED(sg->length, AES_BLOCK_SIZE)) ++ return DMA_NEED_SG_TRUNC; ++ } ++ ++ return DMA_PLAIN_SG; ++} ++ ++static enum stm32_dma_mode stm32_cryp_dma_check(struct stm32_cryp *cryp, struct scatterlist *in_sg, ++ struct scatterlist *out_sg) ++{ ++ enum stm32_dma_mode ret = DMA_PLAIN_SG; ++ ++ if (!is_aes(cryp)) ++ return NO_DMA; ++ ++ if (!cryp->dma_lch_in || !cryp->dma_lch_out) ++ return NO_DMA; ++ ++ ret = stm32_cryp_dma_check_sg(in_sg, cryp->payload_in, AES_BLOCK_SIZE); ++ if (ret == NO_DMA) ++ return ret; ++ ++ ret = stm32_cryp_dma_check_sg(out_sg, cryp->payload_out, AES_BLOCK_SIZE); ++ if (ret == NO_DMA) ++ return ret; ++ ++ /* Check CTR counter overflow */ ++ if (is_aes(cryp) && is_ctr(cryp)) { ++ u32 c; ++ __be32 iv3; ++ ++ memcpy(&iv3, &cryp->req->iv[3*sizeof(u32)], sizeof(iv3)); ++ c = be32_to_cpu(iv3); ++ if ((c + cryp->payload_in) < cryp->payload_in) ++ return NO_DMA; ++ } ++ ++ /* Workaround */ ++ if (is_aes(cryp) && is_ctr(cryp) && ret == DMA_NEED_SG_TRUNC) ++ return NO_DMA; ++ ++ return ret; ++} ++ ++static int stm32_cryp_truncate_sg(struct scatterlist **new_sg, int *new_sg_len, ++ struct scatterlist *sg, off_t skip, size_t size) ++{ ++ struct scatterlist *cur; ++ size_t alloc_sg_len; ++ ++ *new_sg_len = 0; ++ ++ if (!sg || !size) { ++ *new_sg = NULL; ++ return 0; ++ } ++ ++ alloc_sg_len = sg_nents_for_len(sg, skip + size); ++ if (alloc_sg_len < 0) ++ return alloc_sg_len; ++ ++ /* We allocate to much sg entry, but it is easier */ ++ *new_sg = kmalloc_array(alloc_sg_len, sizeof(struct scatterlist), GFP_KERNEL); ++ if (!*new_sg) ++ return -ENOMEM; ++ ++ sg_init_table(*new_sg, alloc_sg_len); ++ ++ cur = *new_sg; ++ while (sg && size) { ++ unsigned int len = sg->length; ++ unsigned int offset = sg->offset; ++ ++ if (skip > len) { ++ skip -= len; ++ sg = sg_next(sg); ++ continue; ++ } ++ ++ if (skip) { ++ len -= skip; ++ offset += skip; ++ skip = 0; ++ } ++ ++ if (size < len) ++ len = size; ++ ++ if (len > 0) { ++ (*new_sg_len)++; ++ size -= len; ++ sg_set_page(cur, sg_page(sg), len, offset); ++ if (size == 0) ++ sg_mark_end(cur); ++ cur = sg_next(cur); ++ } ++ ++ sg = sg_next(sg); ++ } ++ ++ return 0; ++} ++ ++static int stm32_cryp_cipher_prepare(struct stm32_cryp *cryp, struct scatterlist *in_sg, ++ struct scatterlist *out_sg) ++{ ++ size_t align_size; ++ ++ cryp->dma_mode = stm32_cryp_dma_check(cryp, in_sg, out_sg); ++ ++ scatterwalk_start(&cryp->in_walk, in_sg); ++ scatterwalk_start(&cryp->out_walk, out_sg); ++ ++ if (cryp->dma_mode == NO_DMA) { ++ cryp->flags &= ~FLG_IN_OUT_DMA; ++ ++ if (is_ctr(cryp)) ++ memset(cryp->last_ctr, 0, sizeof(cryp->last_ctr)); ++ ++ } else if (cryp->dma_mode == DMA_NEED_SG_TRUNC) { ++ int ret; ++ ++ cryp->flags |= FLG_IN_OUT_DMA; ++ ++ align_size = ALIGN_DOWN(cryp->payload_in, cryp->hw_blocksize); ++ ret = stm32_cryp_truncate_sg(&cryp->in_sg, &cryp->in_sg_len, in_sg, 0, align_size); ++ if (ret) ++ return ret; ++ ++ ret = stm32_cryp_truncate_sg(&cryp->out_sg, &cryp->out_sg_len, out_sg, 0, ++ align_size); ++ if (ret) { ++ kfree(cryp->in_sg); ++ return ret; ++ } ++ } else { ++ cryp->flags |= FLG_IN_OUT_DMA; ++ ++ cryp->in_sg = in_sg; ++ cryp->out_sg = out_sg; ++ ++ cryp->in_sg_len = sg_nents_for_len(cryp->in_sg, cryp->payload_in); ++ if (cryp->in_sg_len < 0) ++ return cryp->in_sg_len; ++ ++ cryp->out_sg_len = sg_nents_for_len(out_sg, cryp->payload_out); ++ if (cryp->out_sg_len < 0) ++ return cryp->out_sg_len; ++ } ++ ++ return 0; ++} ++ ++static int stm32_cryp_aead_prepare(struct stm32_cryp *cryp, struct scatterlist *in_sg, ++ struct scatterlist *out_sg) ++{ ++ size_t align_size; ++ off_t skip; ++ int ret, ret2; ++ ++ cryp->header_sg = NULL; ++ cryp->in_sg = NULL; ++ cryp->out_sg = NULL; ++ ++ if (!cryp->dma_lch_in || !cryp->dma_lch_out) { ++ cryp->dma_mode = NO_DMA; ++ cryp->flags &= ~(FLG_IN_OUT_DMA | FLG_HEADER_DMA); ++ ++ return 0; ++ } ++ ++ /* CCM hw_init may have advanced in header */ ++ skip = cryp->areq->assoclen - cryp->header_in; ++ ++ align_size = ALIGN_DOWN(cryp->header_in, cryp->hw_blocksize); ++ ret = stm32_cryp_truncate_sg(&cryp->header_sg, &cryp->header_sg_len, in_sg, skip, ++ align_size); ++ if (ret) ++ return ret; ++ ++ ret = stm32_cryp_dma_check_sg(cryp->header_sg, align_size, AES_BLOCK_SIZE); ++ if (ret == NO_DMA) { ++ /* We cannot DMA the header */ ++ kfree(cryp->header_sg); ++ cryp->header_sg = NULL; ++ ++ cryp->flags &= ~FLG_HEADER_DMA; ++ } else { ++ cryp->flags |= FLG_HEADER_DMA; ++ } ++ ++ /* Now skip all header to be at payload start */ ++ skip = cryp->areq->assoclen; ++ align_size = ALIGN_DOWN(cryp->payload_in, cryp->hw_blocksize); ++ ret = stm32_cryp_truncate_sg(&cryp->in_sg, &cryp->in_sg_len, in_sg, skip, align_size); ++ if (ret) { ++ kfree(cryp->header_sg); ++ return ret; ++ } ++ ++ /* For out buffer align_size is same as in buffer */ ++ ret = stm32_cryp_truncate_sg(&cryp->out_sg, &cryp->out_sg_len, out_sg, skip, align_size); ++ if (ret) { ++ kfree(cryp->header_sg); ++ kfree(cryp->in_sg); ++ return ret; ++ } ++ ++ ret = stm32_cryp_dma_check_sg(cryp->in_sg, align_size, AES_BLOCK_SIZE); ++ ret2 = stm32_cryp_dma_check_sg(cryp->out_sg, align_size, AES_BLOCK_SIZE); ++ if (ret == NO_DMA || ret2 == NO_DMA) { ++ kfree(cryp->in_sg); ++ cryp->in_sg = NULL; ++ ++ kfree(cryp->out_sg); ++ cryp->out_sg = NULL; ++ ++ cryp->flags &= ~FLG_IN_OUT_DMA; ++ } else { ++ cryp->flags |= FLG_IN_OUT_DMA; ++ } ++ ++ return 0; ++} ++ + static int stm32_cryp_prepare_req(struct skcipher_request *req, + struct aead_request *areq) + { + struct stm32_cryp_ctx *ctx; + struct stm32_cryp *cryp; + struct stm32_cryp_reqctx *rctx; +- struct scatterlist *in_sg; ++ struct scatterlist *in_sg, *out_sg; + int ret; + + if (!req && !areq) +@@ -1016,6 +1541,15 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, + cryp->payload_in = req->cryptlen; + cryp->payload_out = req->cryptlen; + cryp->authsize = 0; ++ ++ in_sg = req->src; ++ out_sg = req->dst; ++ ++ ret = stm32_cryp_cipher_prepare(cryp, in_sg, out_sg); ++ if (ret) ++ return ret; ++ ++ ret = stm32_cryp_hw_init(cryp); + } else { + /* + * Length of input and output data: +@@ -1045,23 +1579,22 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, + cryp->header_in = areq->assoclen; + cryp->payload_out = cryp->payload_in; + } +- } + +- in_sg = req ? req->src : areq->src; +- scatterwalk_start(&cryp->in_walk, in_sg); +- +- cryp->out_sg = req ? req->dst : areq->dst; +- scatterwalk_start(&cryp->out_walk, cryp->out_sg); ++ in_sg = areq->src; ++ out_sg = areq->dst; + +- if (is_gcm(cryp) || is_ccm(cryp)) { ++ scatterwalk_start(&cryp->in_walk, in_sg); ++ scatterwalk_start(&cryp->out_walk, out_sg); + /* In output, jump after assoc data */ + scatterwalk_copychunks(NULL, &cryp->out_walk, cryp->areq->assoclen, 2); +- } + +- if (is_ctr(cryp)) +- memset(cryp->last_ctr, 0, sizeof(cryp->last_ctr)); ++ ret = stm32_cryp_hw_init(cryp); ++ if (ret) ++ return ret; ++ ++ ret = stm32_cryp_aead_prepare(cryp, in_sg, out_sg); ++ } + +- ret = stm32_cryp_hw_init(cryp); + return ret; + } + +@@ -1087,7 +1620,10 @@ static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq) + if (!cryp) + return -ENODEV; + +- return stm32_cryp_cpu_start(cryp); ++ if (cryp->flags & FLG_IN_OUT_DMA) ++ return stm32_cryp_dma_start(cryp); ++ else ++ return stm32_cryp_it_start(cryp); + } + + static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, void *areq) +@@ -1108,13 +1644,20 @@ static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq) + if (!cryp) + return -ENODEV; + +- if (unlikely(!cryp->payload_in && !cryp->header_in)) { ++ if (!stm32_cryp_get_input_text_len(cryp) && !cryp->header_in && ++ !(cryp->flags & FLG_HEADER_DMA)) { + /* No input data to process: get tag and finish */ + stm32_cryp_finish_req(cryp, 0); + return 0; + } + +- return stm32_cryp_cpu_start(cryp); ++ if (cryp->flags & FLG_HEADER_DMA) ++ return stm32_cryp_header_dma_start(cryp); ++ ++ if (!cryp->header_in && cryp->flags & FLG_IN_OUT_DMA) ++ return stm32_cryp_dma_start(cryp); ++ ++ return stm32_cryp_it_start(cryp); + } + + static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) +@@ -1540,11 +2083,70 @@ static irqreturn_t stm32_cryp_irq(int irq, void *arg) + return IRQ_WAKE_THREAD; + } + ++static int stm32_cryp_dma_init(struct stm32_cryp *cryp) ++{ ++ struct dma_slave_config dma_conf; ++ struct dma_chan *chan; ++ int err; ++ ++ memset(&dma_conf, 0, sizeof(dma_conf)); ++ ++ dma_conf.direction = DMA_MEM_TO_DEV; ++ dma_conf.dst_addr = cryp->phys_base + CRYP_DIN; ++ dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dma_conf.src_maxburst = CRYP_DMA_BURST_MEM; ++ dma_conf.dst_maxburst = CRYP_DMA_BURST_REG; ++ dma_conf.device_fc = false; ++ ++ chan = dma_request_chan(cryp->dev, "in"); ++ if (IS_ERR(chan)) ++ return PTR_ERR(chan); ++ ++ cryp->dma_lch_in = chan; ++ err = dmaengine_slave_config(cryp->dma_lch_in, &dma_conf); ++ if (err) { ++ dma_release_channel(cryp->dma_lch_in); ++ cryp->dma_lch_in = NULL; ++ dev_err(cryp->dev, "Couldn't configure DMA in slave.\n"); ++ return err; ++ } ++ ++ memset(&dma_conf, 0, sizeof(dma_conf)); ++ ++ dma_conf.direction = DMA_DEV_TO_MEM; ++ dma_conf.src_addr = cryp->phys_base + CRYP_DOUT; ++ dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dma_conf.src_maxburst = CRYP_DMA_BURST_REG; ++ dma_conf.dst_maxburst = CRYP_DMA_BURST_MEM; ++ dma_conf.device_fc = false; ++ ++ chan = dma_request_chan(cryp->dev, "out"); ++ if (IS_ERR(chan)) { ++ dma_release_channel(cryp->dma_lch_in); ++ cryp->dma_lch_in = NULL; ++ return PTR_ERR(chan); ++ } ++ ++ cryp->dma_lch_out = chan; ++ ++ err = dmaengine_slave_config(cryp->dma_lch_out, &dma_conf); ++ if (err) { ++ dma_release_channel(cryp->dma_lch_out); ++ cryp->dma_lch_out = NULL; ++ dev_err(cryp->dev, "Couldn't configure DMA out slave.\n"); ++ dma_release_channel(cryp->dma_lch_in); ++ cryp->dma_lch_in = NULL; ++ return err; ++ } ++ ++ return 0; ++} ++ + static struct skcipher_alg crypto_algs[] = { + { + .base.cra_name = "ecb(aes)", + .base.cra_driver_name = "stm32-ecb-aes", +- .base.cra_priority = 200, ++ .base.cra_priority = 1200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +@@ -1561,7 +2163,7 @@ static struct skcipher_alg crypto_algs[] = { + { + .base.cra_name = "cbc(aes)", + .base.cra_driver_name = "stm32-cbc-aes", +- .base.cra_priority = 200, ++ .base.cra_priority = 1200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +@@ -1579,7 +2181,7 @@ static struct skcipher_alg crypto_algs[] = { + { + .base.cra_name = "ctr(aes)", + .base.cra_driver_name = "stm32-ctr-aes", +- .base.cra_priority = 200, ++ .base.cra_priority = 1200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +@@ -1597,7 +2199,7 @@ static struct skcipher_alg crypto_algs[] = { + { + .base.cra_name = "ecb(des)", + .base.cra_driver_name = "stm32-ecb-des", +- .base.cra_priority = 200, ++ .base.cra_priority = 1200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +@@ -1614,7 +2216,7 @@ static struct skcipher_alg crypto_algs[] = { + { + .base.cra_name = "cbc(des)", + .base.cra_driver_name = "stm32-cbc-des", +- .base.cra_priority = 200, ++ .base.cra_priority = 1200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +@@ -1632,7 +2234,7 @@ static struct skcipher_alg crypto_algs[] = { + { + .base.cra_name = "ecb(des3_ede)", + .base.cra_driver_name = "stm32-ecb-des3", +- .base.cra_priority = 200, ++ .base.cra_priority = 1200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +@@ -1649,7 +2251,7 @@ static struct skcipher_alg crypto_algs[] = { + { + .base.cra_name = "cbc(des3_ede)", + .base.cra_driver_name = "stm32-cbc-des3", +- .base.cra_priority = 200, ++ .base.cra_priority = 1200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +@@ -1726,6 +2328,25 @@ static const struct of_device_id stm32_dt_ids[] = { + }; + MODULE_DEVICE_TABLE(of, stm32_dt_ids); + ++static void cryp_debugfs(struct stm32_cryp *cryp) ++{ ++ struct debugfs_regset32 *regset; ++ ++ cryp->dbgdir = debugfs_create_dir("stm32_cryp", NULL); ++ if (IS_ERR_OR_NULL(cryp->dbgdir)) ++ return; ++ ++ regset = devm_kzalloc(cryp->dev, sizeof(*regset), GFP_KERNEL); ++ if (!regset) ++ return; ++ ++ regset->regs = stm32_cryp_regs; ++ regset->nregs = ARRAY_SIZE(stm32_cryp_regs); ++ regset->base = cryp->regs; ++ ++ debugfs_create_regset32("regset", 0444, cryp->dbgdir, regset); ++} ++ + static int stm32_cryp_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -1747,6 +2368,8 @@ static int stm32_cryp_probe(struct platform_device *pdev) + if (IS_ERR(cryp->regs)) + return PTR_ERR(cryp->regs); + ++ cryp->phys_base = platform_get_resource(pdev, IORESOURCE_MEM, 0)->start; ++ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; +@@ -1761,7 +2384,8 @@ static int stm32_cryp_probe(struct platform_device *pdev) + + cryp->clk = devm_clk_get(dev, NULL); + if (IS_ERR(cryp->clk)) { +- dev_err(dev, "Could not get clock\n"); ++ dev_err_probe(dev, PTR_ERR(cryp->clk), "Could not get clock\n"); ++ + return PTR_ERR(cryp->clk); + } + +@@ -1779,7 +2403,11 @@ static int stm32_cryp_probe(struct platform_device *pdev) + pm_runtime_enable(dev); + + rst = devm_reset_control_get(dev, NULL); +- if (!IS_ERR(rst)) { ++ if (IS_ERR(rst)) { ++ ret = PTR_ERR(rst); ++ if (ret == -EPROBE_DEFER) ++ goto err_rst; ++ } else { + reset_control_assert(rst); + udelay(2); + reset_control_deassert(rst); +@@ -1787,6 +2415,17 @@ static int stm32_cryp_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, cryp); + ++ ret = stm32_cryp_dma_init(cryp); ++ switch (ret) { ++ case 0: ++ break; ++ case -ENODEV: ++ dev_dbg(dev, "DMA mode not available\n"); ++ break; ++ default: ++ goto err_dma; ++ } ++ + spin_lock(&cryp_list.lock); + list_add(&cryp->list, &cryp_list.dev_list); + spin_unlock(&cryp_list.lock); +@@ -1815,6 +2454,7 @@ static int stm32_cryp_probe(struct platform_device *pdev) + if (ret) + goto err_aead_algs; + ++ cryp_debugfs(cryp); + dev_info(dev, "Initialized\n"); + + pm_runtime_put_sync(dev); +@@ -1831,6 +2471,12 @@ static int stm32_cryp_probe(struct platform_device *pdev) + list_del(&cryp->list); + spin_unlock(&cryp_list.lock); + ++ if (cryp->dma_lch_in) ++ dma_release_channel(cryp->dma_lch_in); ++ if (cryp->dma_lch_out) ++ dma_release_channel(cryp->dma_lch_out); ++err_dma: ++err_rst: + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + +@@ -1851,6 +2497,9 @@ static int stm32_cryp_remove(struct platform_device *pdev) + if (ret < 0) + return ret; + ++ debugfs_remove_recursive(cryp->dbgdir); ++ cryp->dbgdir = NULL; ++ + crypto_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs)); + crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); + +@@ -1860,6 +2509,12 @@ static int stm32_cryp_remove(struct platform_device *pdev) + list_del(&cryp->list); + spin_unlock(&cryp_list.lock); + ++ if (cryp->dma_lch_in) ++ dma_release_channel(cryp->dma_lch_in); ++ ++ if (cryp->dma_lch_out) ++ dma_release_channel(cryp->dma_lch_out); ++ + pm_runtime_disable(cryp->dev); + pm_runtime_put_noidle(cryp->dev); + +diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c +index d33006d43f76..05efad85dd66 100644 +--- a/drivers/crypto/stm32/stm32-hash.c ++++ b/drivers/crypto/stm32/stm32-hash.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + + #define HASH_CR 0x00 +@@ -49,11 +50,6 @@ + #define HASH_CR_DMAA BIT(14) + #define HASH_CR_LKEY BIT(16) + +-#define HASH_CR_ALGO_SHA1 0x0 +-#define HASH_CR_ALGO_MD5 0x80 +-#define HASH_CR_ALGO_SHA224 0x40000 +-#define HASH_CR_ALGO_SHA256 0x40080 +- + /* Interrupt */ + #define HASH_DINIE BIT(0) + #define HASH_DCIE BIT(1) +@@ -62,9 +58,6 @@ + #define HASH_MASK_CALC_COMPLETION BIT(0) + #define HASH_MASK_DATA_INPUT BIT(1) + +-/* Context swap register */ +-#define HASH_CSR_REGISTER_NUMBER 53 +- + /* Status Flags */ + #define HASH_SR_DATA_INPUT_READY BIT(0) + #define HASH_SR_OUTPUT_READY BIT(1) +@@ -75,6 +68,18 @@ + #define HASH_STR_NBLW_MASK GENMASK(4, 0) + #define HASH_STR_DCAL BIT(8) + ++/* HWCFGR Register */ ++#define HASH_HWCFG_DMA_MASK GENMASK(3, 0) ++ ++/* CSR register */ ++#define HASH_CSR_NB_SHA256_HMAC 54 ++#define HASH_CSR_NB_SHA256 22 ++#define HASH_CSR_NB_SHA512_HMAC 103 ++#define HASH_CSR_NB_SHA512 91 ++#define HASH_CSR_NB_SHA3_HMAC 88 ++#define HASH_CSR_NB_SHA3 72 ++#define HASH_CSR_NB_MAX HASH_CSR_NB_SHA512_HMAC ++ + #define HASH_FLAGS_INIT BIT(0) + #define HASH_FLAGS_OUTPUT_READY BIT(1) + #define HASH_FLAGS_CPU BIT(2) +@@ -83,20 +88,19 @@ + #define HASH_FLAGS_HMAC_INIT BIT(5) + #define HASH_FLAGS_HMAC_FINAL BIT(6) + #define HASH_FLAGS_HMAC_KEY BIT(7) +- ++#define HASH_FLAGS_SHA3_MODE BIT(8) + #define HASH_FLAGS_FINAL BIT(15) + #define HASH_FLAGS_FINUP BIT(16) +-#define HASH_FLAGS_ALGO_MASK GENMASK(21, 18) +-#define HASH_FLAGS_MD5 BIT(18) +-#define HASH_FLAGS_SHA1 BIT(19) +-#define HASH_FLAGS_SHA224 BIT(20) +-#define HASH_FLAGS_SHA256 BIT(21) +-#define HASH_FLAGS_ERRORS BIT(22) +-#define HASH_FLAGS_HMAC BIT(23) ++#define HASH_FLAGS_ALGO_MASK GENMASK(20, 17) ++#define HASH_FLAGS_ALGO_SHIFT 17 ++#define HASH_FLAGS_ERRORS BIT(21) ++#define HASH_FLAGS_HMAC BIT(22) + + #define HASH_OP_UPDATE 1 + #define HASH_OP_FINAL 2 + ++#define HASH_BURST_LEVEL 4 ++ + enum stm32_hash_data_format { + HASH_DATA_32_BITS = 0x0, + HASH_DATA_16_BITS = 0x1, +@@ -104,49 +108,63 @@ enum stm32_hash_data_format { + HASH_DATA_1_BIT = 0x3 + }; + +-#define HASH_BUFLEN 256 +-#define HASH_LONG_KEY 64 +-#define HASH_MAX_KEY_SIZE (SHA256_BLOCK_SIZE * 8) +-#define HASH_QUEUE_LENGTH 16 +-#define HASH_DMA_THRESHOLD 50 ++enum stm32_hash_algo { ++ HASH_SHA1 = 0, ++ HASH_MD5 = 1, ++ HASH_SHA224 = 2, ++ HASH_SHA256 = 3, ++ HASH_SHA3_224 = 4, ++ HASH_SHA3_256 = 5, ++ HASH_SHA3_384 = 6, ++ HASH_SHA3_512 = 7, ++ HASH_SHA384 = 12, ++ HASH_SHA512 = 15, ++}; ++ ++#define HASH_HW_FIFO_INIT_SIZE (17 * sizeof(u32)) ++#define HASH_HW_FIFO_SIZE (16 * sizeof(u32)) + ++#define HASH_MAX_KEY_SIZE (SHA512_BLOCK_SIZE * 8) ++#define HASH_QUEUE_LENGTH 60 + #define HASH_AUTOSUSPEND_DELAY 50 + + struct stm32_hash_ctx { + struct crypto_engine_ctx enginectx; +- struct stm32_hash_dev *hdev; + unsigned long flags; + + u8 key[HASH_MAX_KEY_SIZE]; + int keylen; + }; + +-struct stm32_hash_request_ctx { ++struct stm32_hash_state { + struct stm32_hash_dev *hdev; + unsigned long flags; +- unsigned long op; + +- u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32)); +- size_t digcnt; ++ /* Data not yet sent to hw */ ++ u8 buffer[HASH_HW_FIFO_INIT_SIZE] __aligned(sizeof(u32)); + size_t bufcnt; + size_t buflen; + ++ /* HW Context */ ++ u32 hw_context[3 + HASH_CSR_NB_MAX]; ++}; ++ ++struct stm32_hash_request_ctx { ++ struct stm32_hash_state state; ++ ++ /* ++ * Each new request will update following fields ++ */ ++ unsigned long op; ++ + /* DMA */ + struct scatterlist *sg; + unsigned int offset; + unsigned int total; + struct scatterlist sg_key; + +- dma_addr_t dma_addr; + size_t dma_ct; + int nents; +- +- u8 data_type; +- +- u8 buffer[HASH_BUFLEN] __aligned(sizeof(u32)); +- +- /* Export Context */ +- u32 *hw_context; + }; + + struct stm32_hash_algs_info { +@@ -155,8 +173,9 @@ struct stm32_hash_algs_info { + }; + + struct stm32_hash_pdata { +- struct stm32_hash_algs_info *algs_info; +- size_t algs_info_size; ++ const int alg_shift; ++ const struct stm32_hash_algs_info *algs_info; ++ size_t algs_info_size; + }; + + struct stm32_hash_dev { +@@ -167,10 +186,10 @@ struct stm32_hash_dev { + void __iomem *io_base; + phys_addr_t phys_base; + u32 dma_mode; +- u32 dma_maxburst; + + struct ahash_request *req; + struct crypto_engine *engine; ++ struct crypto_queue queue; + + int err; + unsigned long flags; +@@ -212,11 +231,107 @@ static inline int stm32_hash_wait_busy(struct stm32_hash_dev *hdev) + !(status & HASH_SR_BUSY), 10, 10000); + } + +-static void stm32_hash_set_nblw(struct stm32_hash_dev *hdev, int length) ++static inline int stm32_hash_wait_dinis(struct stm32_hash_dev *hdev) ++{ ++ u32 status; ++ ++ return readl_relaxed_poll_timeout(hdev->io_base + HASH_SR, status, ++ (status & HASH_SR_DATA_INPUT_READY), 10, 10000); ++} ++ ++static int hash_swap_reg(struct stm32_hash_request_ctx *rctx) + { ++ switch ((rctx->state.flags & HASH_FLAGS_ALGO_MASK) >> HASH_FLAGS_ALGO_SHIFT) { ++ case HASH_MD5: ++ case HASH_SHA1: ++ case HASH_SHA224: ++ case HASH_SHA256: ++ if (rctx->state.flags & HASH_FLAGS_HMAC) ++ return HASH_CSR_NB_SHA256_HMAC; ++ else ++ return HASH_CSR_NB_SHA256; ++ break; ++ ++ case HASH_SHA384: ++ case HASH_SHA512: ++ if (rctx->state.flags & HASH_FLAGS_HMAC) ++ return HASH_CSR_NB_SHA512_HMAC; ++ else ++ return HASH_CSR_NB_SHA512; ++ break; ++ ++ case HASH_SHA3_224: ++ case HASH_SHA3_256: ++ case HASH_SHA3_384: ++ case HASH_SHA3_512: ++ if (rctx->state.flags & HASH_FLAGS_HMAC) ++ return HASH_CSR_NB_SHA3_HMAC; ++ else ++ return HASH_CSR_NB_SHA3; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int stm32_hash_save_hw_context(struct stm32_hash_dev *hdev) ++{ ++ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); ++ u32 *preg; ++ unsigned int i; ++ int swap_reg; ++ ++ swap_reg = hash_swap_reg(rctx); ++ if (swap_reg < 0) ++ return swap_reg; ++ ++ if (stm32_hash_wait_busy(hdev)) ++ return -ETIMEDOUT; ++ ++ preg = rctx->state.hw_context; ++ ++ *preg++ = stm32_hash_read(hdev, HASH_IMR); ++ *preg++ = stm32_hash_read(hdev, HASH_STR); ++ *preg++ = stm32_hash_read(hdev, HASH_CR); ++ for (i = 0; i < swap_reg; i++) ++ *preg++ = stm32_hash_read(hdev, HASH_CSR(i)); ++ ++ return 0; ++} ++ ++static int stm32_hash_restore_hw_context(struct stm32_hash_dev *hdev) ++{ ++ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); ++ u32 *preg; + u32 reg; ++ unsigned int i; ++ int swap_reg; ++ ++ swap_reg = hash_swap_reg(rctx); ++ if (swap_reg < 0) ++ return swap_reg; ++ ++ if (stm32_hash_wait_busy(hdev)) ++ return -ETIMEDOUT; ++ ++ preg = rctx->state.hw_context; ++ ++ stm32_hash_write(hdev, HASH_IMR, *preg++); ++ stm32_hash_write(hdev, HASH_STR, *preg++); ++ reg = *preg++ | HASH_CR_INIT; ++ stm32_hash_write(hdev, HASH_CR, reg); ++ ++ for (i = 0; i < swap_reg; i++) ++ stm32_hash_write(hdev, HASH_CSR(i), *preg++); ++ ++ return 0; ++} ++ ++static void stm32_hash_set_nblw(struct stm32_hash_dev *hdev, int length) ++{ ++ u32 reg = stm32_hash_read(hdev, HASH_STR); + +- reg = stm32_hash_read(hdev, HASH_STR); + reg &= ~(HASH_STR_NBLW_MASK); + reg |= (8U * ((length) % 4U)); + stm32_hash_write(hdev, HASH_STR, reg); +@@ -254,53 +369,44 @@ static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev) + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); + struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); +- ++ u32 alg = (rctx->state.flags & HASH_FLAGS_ALGO_MASK) >> HASH_FLAGS_ALGO_SHIFT; + u32 reg = HASH_CR_INIT; + +- if (!(hdev->flags & HASH_FLAGS_INIT)) { +- switch (rctx->flags & HASH_FLAGS_ALGO_MASK) { +- case HASH_FLAGS_MD5: +- reg |= HASH_CR_ALGO_MD5; +- break; +- case HASH_FLAGS_SHA1: +- reg |= HASH_CR_ALGO_SHA1; +- break; +- case HASH_FLAGS_SHA224: +- reg |= HASH_CR_ALGO_SHA224; +- break; +- case HASH_FLAGS_SHA256: +- reg |= HASH_CR_ALGO_SHA256; +- break; +- default: +- reg |= HASH_CR_ALGO_MD5; +- } ++ if (hdev->pdata->alg_shift == 7) ++ reg |= ((alg & BIT(1)) << 17) | ((alg & BIT(0)) << 7); ++ else ++ reg |= alg << hdev->pdata->alg_shift; + +- reg |= (rctx->data_type << HASH_CR_DATATYPE_POS); ++ reg |= (HASH_DATA_8_BITS << HASH_CR_DATATYPE_POS); + +- if (rctx->flags & HASH_FLAGS_HMAC) { +- hdev->flags |= HASH_FLAGS_HMAC; +- reg |= HASH_CR_MODE; +- if (ctx->keylen > HASH_LONG_KEY) +- reg |= HASH_CR_LKEY; +- } ++ if (rctx->state.flags & HASH_FLAGS_HMAC) { ++ hdev->flags |= HASH_FLAGS_HMAC; ++ reg |= HASH_CR_MODE; ++ if (ctx->keylen > crypto_ahash_blocksize(tfm)) ++ reg |= HASH_CR_LKEY; ++ } + +- stm32_hash_write(hdev, HASH_IMR, HASH_DCIE); ++ stm32_hash_write(hdev, HASH_IMR, HASH_DCIE); ++ stm32_hash_write(hdev, HASH_CR, reg); ++ stm32_hash_read(hdev, HASH_SR); + +- stm32_hash_write(hdev, HASH_CR, reg); ++ rctx->state.flags |= HASH_FLAGS_INIT; + +- hdev->flags |= HASH_FLAGS_INIT; ++ dev_dbg(hdev->dev, "Write Control %x\n", reg); + +- dev_dbg(hdev->dev, "Write Control %x\n", reg); +- } ++ /* ++ * After first buflen is fill up, the new buflen is smaller of one u32 ++ */ ++ rctx->state.buflen = HASH_HW_FIFO_SIZE; + } + + static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) + { + size_t count; + +- while ((rctx->bufcnt < rctx->buflen) && rctx->total) { ++ while ((rctx->state.bufcnt < rctx->state.buflen) && rctx->total) { + count = min(rctx->sg->length - rctx->offset, rctx->total); +- count = min(count, rctx->buflen - rctx->bufcnt); ++ count = min(count, rctx->state.buflen - rctx->state.bufcnt); + + if (count <= 0) { + if ((rctx->sg->length == 0) && !sg_is_last(rctx->sg)) { +@@ -311,10 +417,10 @@ static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) + } + } + +- scatterwalk_map_and_copy(rctx->buffer + rctx->bufcnt, rctx->sg, ++ scatterwalk_map_and_copy(rctx->state.buffer + rctx->state.bufcnt, rctx->sg, + rctx->offset, count, 0); + +- rctx->bufcnt += count; ++ rctx->state.bufcnt += count; + rctx->offset += count; + rctx->total -= count; + +@@ -328,11 +434,12 @@ static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) + } + } + +-static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, +- const u8 *buf, size_t length, int final) ++static int stm32_hash_xmit_cpu(struct stm32_hash_request_ctx *rctx, ++ size_t length, int final) + { ++ const u32 *buffer = (const u32 *)rctx->state.buffer; ++ struct stm32_hash_dev *hdev = rctx->state.hdev; + unsigned int count, len32; +- const u32 *buffer = (const u32 *)buf; + u32 reg; + + if (final) +@@ -345,10 +452,8 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, + + hdev->flags |= HASH_FLAGS_CPU; + +- stm32_hash_write_ctrl(hdev); +- +- if (stm32_hash_wait_busy(hdev)) +- return -ETIMEDOUT; ++ if (!(rctx->state.flags & HASH_FLAGS_INIT)) ++ stm32_hash_write_ctrl(hdev); + + if ((hdev->flags & HASH_FLAGS_HMAC) && + (!(hdev->flags & HASH_FLAGS_HMAC_KEY))) { +@@ -371,6 +476,7 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, + return -ETIMEDOUT; + stm32_hash_write_key(hdev); + } ++ + return -EINPROGRESS; + } + +@@ -382,28 +488,30 @@ static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev) + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); + int bufcnt, err = 0, final; + +- dev_dbg(hdev->dev, "%s flags %lx\n", __func__, rctx->flags); ++ dev_dbg(hdev->dev, "%s flags %lx\n", __func__, rctx->state.flags); + +- final = (rctx->flags & HASH_FLAGS_FINUP); ++ final = (rctx->state.flags & HASH_FLAGS_FINUP); + +- while ((rctx->total >= rctx->buflen) || +- (rctx->bufcnt + rctx->total >= rctx->buflen)) { ++ while ((rctx->total > rctx->state.buflen) || ++ (rctx->state.bufcnt + rctx->total > rctx->state.buflen)) { + stm32_hash_append_sg(rctx); +- bufcnt = rctx->bufcnt; +- rctx->bufcnt = 0; +- err = stm32_hash_xmit_cpu(hdev, rctx->buffer, bufcnt, 0); ++ bufcnt = rctx->state.bufcnt; ++ rctx->state.bufcnt = 0; ++ err = stm32_hash_xmit_cpu(rctx, bufcnt, 0); + } + + stm32_hash_append_sg(rctx); + + if (final) { +- bufcnt = rctx->bufcnt; +- rctx->bufcnt = 0; +- err = stm32_hash_xmit_cpu(hdev, rctx->buffer, bufcnt, +- (rctx->flags & HASH_FLAGS_FINUP)); ++ bufcnt = rctx->state.bufcnt; ++ rctx->state.bufcnt = 0; ++ err = stm32_hash_xmit_cpu(rctx, bufcnt, ++ (rctx->state.flags & HASH_FLAGS_FINUP)); + } ++ if (err) ++ return err; + +- return err; ++ return stm32_hash_save_hw_context(hdev); + } + + static int stm32_hash_xmit_dma(struct stm32_hash_dev *hdev, +@@ -482,7 +590,7 @@ static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev) + struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); + int err; + +- if (ctx->keylen < HASH_DMA_THRESHOLD || (hdev->dma_mode == 1)) { ++ if (ctx->keylen < rctx->state.buflen || (hdev->dma_mode == 1)) { + err = stm32_hash_write_key(hdev); + if (stm32_hash_wait_busy(hdev)) + return -ETIMEDOUT; +@@ -517,8 +625,8 @@ static int stm32_hash_dma_init(struct stm32_hash_dev *hdev) + dma_conf.direction = DMA_MEM_TO_DEV; + dma_conf.dst_addr = hdev->phys_base + HASH_DIN; + dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +- dma_conf.src_maxburst = hdev->dma_maxburst; +- dma_conf.dst_maxburst = hdev->dma_maxburst; ++ dma_conf.src_maxburst = HASH_BURST_LEVEL; ++ dma_conf.dst_maxburst = HASH_BURST_LEVEL; + dma_conf.device_fc = false; + + chan = dma_request_chan(hdev->dev, "in"); +@@ -546,17 +654,17 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) + struct scatterlist sg[1], *tsg; + int err = 0, len = 0, reg, ncp = 0; + unsigned int i; +- u32 *buffer = (void *)rctx->buffer; ++ u32 *buffer = (void *)rctx->state.buffer; + + rctx->sg = hdev->req->src; + rctx->total = hdev->req->nbytes; + + rctx->nents = sg_nents(rctx->sg); +- + if (rctx->nents < 0) + return -EINVAL; + +- stm32_hash_write_ctrl(hdev); ++ if (!(rctx->state.flags & HASH_FLAGS_INIT)) ++ stm32_hash_write_ctrl(hdev); + + if (hdev->flags & HASH_FLAGS_HMAC) { + err = stm32_hash_hmac_dma_send(hdev); +@@ -565,16 +673,16 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) + } + + for_each_sg(rctx->sg, tsg, rctx->nents, i) { +- len = sg->length; +- + sg[0] = *tsg; ++ ++ len = sg->length; + if (sg_is_last(sg)) { + if (hdev->dma_mode == 1) { + len = (ALIGN(sg->length, 16) - 16); + + ncp = sg_pcopy_to_buffer( + rctx->sg, rctx->nents, +- rctx->buffer, sg->length - len, ++ rctx->state.buffer, sg->length - len, + rctx->total - sg->length + len); + + sg->length = len; +@@ -633,21 +741,17 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) + return err; + } + +-static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx) ++static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_request_ctx *rctx) + { +- struct stm32_hash_dev *hdev = NULL, *tmp; ++ struct stm32_hash_dev *hdev = NULL; + +- spin_lock_bh(&stm32_hash.lock); +- if (!ctx->hdev) { +- list_for_each_entry(tmp, &stm32_hash.dev_list, list) { +- hdev = tmp; +- break; +- } +- ctx->hdev = hdev; +- } else { +- hdev = ctx->hdev; +- } ++ if (rctx->state.hdev) ++ return rctx->state.hdev; + ++ spin_lock_bh(&stm32_hash.lock); ++ hdev = list_first_entry(&stm32_hash.dev_list, struct stm32_hash_dev, list); ++ list_move_tail(&hdev->list, &stm32_hash.dev_list); ++ rctx->state.hdev = hdev; + spin_unlock_bh(&stm32_hash.lock); + + return hdev; +@@ -656,16 +760,17 @@ static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx) + static bool stm32_hash_dma_aligned_data(struct ahash_request *req) + { + struct scatterlist *sg; +- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); +- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); ++ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); ++ struct stm32_hash_dev *hdev = rctx->state.hdev; + int i; + +- if (req->nbytes <= HASH_DMA_THRESHOLD) ++ if ((!hdev->dma_lch) || (req->nbytes <= rctx->state.buflen)) + return false; + + if (sg_nents(req->src) > 1) { + if (hdev->dma_mode == 1) + return false; ++ + for_each_sg(req->src, sg, sg_nents(req->src), i) { + if ((!IS_ALIGNED(sg->length, sizeof(u32))) && + (!sg_is_last(sg))) +@@ -684,42 +789,66 @@ static int stm32_hash_init(struct ahash_request *req) + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); +- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); ++ struct stm32_hash_dev *hdev; ++ bool sha3_mode = ctx->flags & HASH_FLAGS_SHA3_MODE; ++ ++ rctx->state.hdev = NULL; ++ hdev = stm32_hash_find_dev(rctx); ++ if (!hdev) ++ return -ENODEV; + +- rctx->hdev = hdev; ++ rctx->state.flags = HASH_FLAGS_CPU; + +- rctx->flags = HASH_FLAGS_CPU; ++ if (sha3_mode) ++ rctx->state.flags |= HASH_FLAGS_SHA3_MODE; + +- rctx->digcnt = crypto_ahash_digestsize(tfm); +- switch (rctx->digcnt) { ++ switch (crypto_ahash_digestsize(tfm)) { + case MD5_DIGEST_SIZE: +- rctx->flags |= HASH_FLAGS_MD5; ++ rctx->state.flags |= HASH_MD5 << HASH_FLAGS_ALGO_SHIFT; + break; + case SHA1_DIGEST_SIZE: +- rctx->flags |= HASH_FLAGS_SHA1; ++ rctx->state.flags |= HASH_SHA1 << HASH_FLAGS_ALGO_SHIFT; + break; + case SHA224_DIGEST_SIZE: +- rctx->flags |= HASH_FLAGS_SHA224; ++ if (sha3_mode) ++ rctx->state.flags |= HASH_SHA3_224 << HASH_FLAGS_ALGO_SHIFT; ++ else ++ rctx->state.flags |= HASH_SHA224 << HASH_FLAGS_ALGO_SHIFT; + break; + case SHA256_DIGEST_SIZE: +- rctx->flags |= HASH_FLAGS_SHA256; ++ if (sha3_mode) ++ rctx->state.flags |= HASH_SHA3_256 << HASH_FLAGS_ALGO_SHIFT; ++ else ++ rctx->state.flags |= HASH_SHA256 << HASH_FLAGS_ALGO_SHIFT; ++ break; ++ case SHA384_DIGEST_SIZE: ++ if (sha3_mode) ++ rctx->state.flags |= HASH_SHA3_384 << HASH_FLAGS_ALGO_SHIFT; ++ else ++ rctx->state.flags |= HASH_SHA384 << HASH_FLAGS_ALGO_SHIFT; ++ break; ++ case SHA512_DIGEST_SIZE: ++ if (sha3_mode) ++ rctx->state.flags |= HASH_SHA3_512 << HASH_FLAGS_ALGO_SHIFT; ++ else ++ rctx->state.flags |= HASH_SHA512 << HASH_FLAGS_ALGO_SHIFT; + break; + default: + return -EINVAL; + } + +- rctx->bufcnt = 0; +- rctx->buflen = HASH_BUFLEN; ++ rctx->state.buflen = HASH_HW_FIFO_INIT_SIZE; ++ rctx->state.bufcnt = 0; + rctx->total = 0; + rctx->offset = 0; +- rctx->data_type = HASH_DATA_8_BITS; + +- memset(rctx->buffer, 0, HASH_BUFLEN); ++ memset(rctx->state.buffer, 0, rctx->state.buflen); ++ memset(rctx->state.hw_context, 0, sizeof(rctx->state.hw_context)); + + if (ctx->flags & HASH_FLAGS_HMAC) +- rctx->flags |= HASH_FLAGS_HMAC; ++ rctx->state.flags |= HASH_FLAGS_HMAC; + +- dev_dbg(hdev->dev, "%s Flags %lx\n", __func__, rctx->flags); ++ dev_dbg(hdev->dev, "%s Flags %lx\n", __func__, rctx->state.flags); + + return 0; + } +@@ -734,55 +863,39 @@ static int stm32_hash_final_req(struct stm32_hash_dev *hdev) + struct ahash_request *req = hdev->req; + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); + int err; +- int buflen = rctx->bufcnt; ++ int buflen = rctx->state.bufcnt; + +- rctx->bufcnt = 0; ++ rctx->state.bufcnt = 0; + +- if (!(rctx->flags & HASH_FLAGS_CPU)) ++ if (!(rctx->state.flags & HASH_FLAGS_CPU)) + err = stm32_hash_dma_send(hdev); + else +- err = stm32_hash_xmit_cpu(hdev, rctx->buffer, buflen, 1); +- ++ err = stm32_hash_xmit_cpu(rctx, buflen, 1); + + return err; + } + +-static void stm32_hash_copy_hash(struct ahash_request *req) ++static int stm32_hash_finish(struct ahash_request *req) + { + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); +- __be32 *hash = (void *)rctx->digest; +- unsigned int i, hashsize; +- +- switch (rctx->flags & HASH_FLAGS_ALGO_MASK) { +- case HASH_FLAGS_MD5: +- hashsize = MD5_DIGEST_SIZE; +- break; +- case HASH_FLAGS_SHA1: +- hashsize = SHA1_DIGEST_SIZE; +- break; +- case HASH_FLAGS_SHA224: +- hashsize = SHA224_DIGEST_SIZE; +- break; +- case HASH_FLAGS_SHA256: +- hashsize = SHA256_DIGEST_SIZE; +- break; +- default: +- return; +- } ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ unsigned int hashsize = crypto_ahash_digestsize(tfm); ++ __be32 hash[SHA512_DIGEST_SIZE / sizeof(__be32)]; ++ unsigned int i; ++ u32 reg; + + for (i = 0; i < hashsize / sizeof(u32); i++) +- hash[i] = cpu_to_be32(stm32_hash_read(rctx->hdev, ++ hash[i] = cpu_to_be32(stm32_hash_read(rctx->state.hdev, + HASH_HREG(i))); +-} + +-static int stm32_hash_finish(struct ahash_request *req) +-{ +- struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); ++ reg = stm32_hash_read(rctx->state.hdev, HASH_SR); ++ reg &= ~HASH_SR_OUTPUT_READY; ++ stm32_hash_write(rctx->state.hdev, HASH_SR, reg); + + if (!req->result) + return -EINVAL; + +- memcpy(req->result, rctx->digest, rctx->digcnt); ++ memcpy(req->result, hash, hashsize); + + return 0; + } +@@ -790,18 +903,18 @@ static int stm32_hash_finish(struct ahash_request *req) + static void stm32_hash_finish_req(struct ahash_request *req, int err) + { + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); +- struct stm32_hash_dev *hdev = rctx->hdev; ++ struct stm32_hash_dev *hdev = rctx->state.hdev; + + if (!err && (HASH_FLAGS_FINAL & hdev->flags)) { +- stm32_hash_copy_hash(req); + err = stm32_hash_finish(req); + hdev->flags &= ~(HASH_FLAGS_FINAL | HASH_FLAGS_CPU | +- HASH_FLAGS_INIT | HASH_FLAGS_DMA_READY | ++ HASH_FLAGS_DMA_READY | + HASH_FLAGS_OUTPUT_READY | HASH_FLAGS_HMAC | + HASH_FLAGS_HMAC_INIT | HASH_FLAGS_HMAC_FINAL | +- HASH_FLAGS_HMAC_KEY); ++ HASH_FLAGS_HMAC_KEY | HASH_FLAGS_SHA3_MODE); ++ rctx->state.flags &= ~HASH_FLAGS_INIT; + } else { +- rctx->flags |= HASH_FLAGS_ERRORS; ++ rctx->state.flags |= HASH_FLAGS_ERRORS; + } + + pm_runtime_mark_last_busy(hdev->dev); +@@ -810,20 +923,24 @@ static void stm32_hash_finish_req(struct ahash_request *req, int err) + crypto_finalize_hash_request(hdev->engine, req, err); + } + +-static int stm32_hash_hw_init(struct stm32_hash_dev *hdev, +- struct stm32_hash_request_ctx *rctx) ++static int stm32_hash_hw_init(struct stm32_hash_request_ctx *rctx) + { ++ int ret = 0; ++ struct stm32_hash_dev *hdev = rctx->state.hdev; ++ + pm_runtime_get_sync(hdev->dev); + +- if (!(HASH_FLAGS_INIT & hdev->flags)) { ++ if (!(HASH_FLAGS_INIT & rctx->state.flags)) { + stm32_hash_write(hdev, HASH_CR, HASH_CR_INIT); + stm32_hash_write(hdev, HASH_STR, 0); + stm32_hash_write(hdev, HASH_DIN, 0); + stm32_hash_write(hdev, HASH_IMR, 0); + hdev->err = 0; ++ } else { ++ ret = stm32_hash_restore_hw_context(hdev); + } + +- return 0; ++ return ret; + } + + static int stm32_hash_one_request(struct crypto_engine *engine, void *areq); +@@ -839,38 +956,30 @@ static int stm32_hash_prepare_req(struct crypto_engine *engine, void *areq) + { + struct ahash_request *req = container_of(areq, struct ahash_request, + base); +- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); +- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); +- struct stm32_hash_request_ctx *rctx; +- +- if (!hdev) +- return -ENODEV; ++ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); ++ struct stm32_hash_dev *hdev = rctx->state.hdev; + + hdev->req = req; + +- rctx = ahash_request_ctx(req); +- + dev_dbg(hdev->dev, "processing new req, op: %lu, nbytes %d\n", + rctx->op, req->nbytes); + +- return stm32_hash_hw_init(hdev, rctx); ++ return 0; + } + + static int stm32_hash_one_request(struct crypto_engine *engine, void *areq) + { + struct ahash_request *req = container_of(areq, struct ahash_request, + base); +- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); +- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); +- struct stm32_hash_request_ctx *rctx; ++ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); ++ struct stm32_hash_dev *hdev = rctx->state.hdev; + int err = 0; + +- if (!hdev) +- return -ENODEV; +- + hdev->req = req; + +- rctx = ahash_request_ctx(req); ++ err = stm32_hash_hw_init(rctx); ++ if (err) ++ return err; + + if (rctx->op == HASH_OP_UPDATE) + err = stm32_hash_update_req(hdev); +@@ -887,8 +996,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq) + static int stm32_hash_enqueue(struct ahash_request *req, unsigned int op) + { + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); +- struct stm32_hash_ctx *ctx = crypto_tfm_ctx(req->base.tfm); +- struct stm32_hash_dev *hdev = ctx->hdev; ++ struct stm32_hash_dev *hdev = rctx->state.hdev; + + rctx->op = op; + +@@ -899,14 +1007,16 @@ static int stm32_hash_update(struct ahash_request *req) + { + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); + +- if (!req->nbytes || !(rctx->flags & HASH_FLAGS_CPU)) ++ if ((!req->nbytes) || !(rctx->state.flags & HASH_FLAGS_CPU)) + return 0; + ++ stm32_hash_find_dev(rctx); ++ + rctx->total = req->nbytes; + rctx->sg = req->src; + rctx->offset = 0; + +- if ((rctx->bufcnt + rctx->total < rctx->buflen)) { ++ if (rctx->state.bufcnt + rctx->total <= rctx->state.buflen) { + stm32_hash_append_sg(rctx); + return 0; + } +@@ -918,7 +1028,7 @@ static int stm32_hash_final(struct ahash_request *req) + { + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); + +- rctx->flags |= HASH_FLAGS_FINUP; ++ rctx->state.flags |= HASH_FLAGS_FINUP; + + return stm32_hash_enqueue(req, HASH_OP_FINAL); + } +@@ -926,14 +1036,9 @@ 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); +- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); +- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); + int err1, err2; + +- rctx->flags |= HASH_FLAGS_FINUP; +- +- if (hdev->dma_lch && stm32_hash_dma_aligned_data(req)) +- rctx->flags &= ~HASH_FLAGS_CPU; ++ rctx->state.flags |= HASH_FLAGS_FINUP; + + err1 = stm32_hash_update(req); + +@@ -951,38 +1056,24 @@ static int stm32_hash_finup(struct ahash_request *req) + + static int stm32_hash_digest(struct ahash_request *req) + { +- return stm32_hash_init(req) ?: stm32_hash_finup(req); +-} +- +-static int stm32_hash_export(struct ahash_request *req, void *out) +-{ ++ int ret; + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); +- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); +- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); +- u32 *preg; +- unsigned int i; + +- pm_runtime_get_sync(hdev->dev); +- +- while ((stm32_hash_read(hdev, HASH_SR) & HASH_SR_BUSY)) +- cpu_relax(); +- +- rctx->hw_context = kmalloc_array(3 + HASH_CSR_REGISTER_NUMBER, +- sizeof(u32), +- GFP_KERNEL); ++ ret = stm32_hash_init(req); ++ if (ret) ++ return ret; + +- preg = rctx->hw_context; ++ if (stm32_hash_dma_aligned_data(req)) ++ rctx->state.flags &= ~HASH_FLAGS_CPU; + +- *preg++ = stm32_hash_read(hdev, HASH_IMR); +- *preg++ = stm32_hash_read(hdev, HASH_STR); +- *preg++ = stm32_hash_read(hdev, HASH_CR); +- for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) +- *preg++ = stm32_hash_read(hdev, HASH_CSR(i)); ++ return stm32_hash_finup(req); ++} + +- pm_runtime_mark_last_busy(hdev->dev); +- pm_runtime_put_autosuspend(hdev->dev); ++static int stm32_hash_export(struct ahash_request *req, void *out) ++{ ++ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); + +- memcpy(out, rctx, sizeof(*rctx)); ++ memcpy(out, &rctx->state, sizeof(rctx->state)); + + return 0; + } +@@ -990,31 +1081,8 @@ static int stm32_hash_export(struct ahash_request *req, void *out) + static int stm32_hash_import(struct ahash_request *req, const void *in) + { + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); +- struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); +- struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); +- const u32 *preg = in; +- u32 reg; +- unsigned int i; +- +- memcpy(rctx, in, sizeof(*rctx)); +- +- preg = rctx->hw_context; +- +- pm_runtime_get_sync(hdev->dev); +- +- stm32_hash_write(hdev, HASH_IMR, *preg++); +- stm32_hash_write(hdev, HASH_STR, *preg++); +- stm32_hash_write(hdev, HASH_CR, *preg); +- reg = *preg++ | HASH_CR_INIT; +- stm32_hash_write(hdev, HASH_CR, reg); +- +- for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) +- stm32_hash_write(hdev, HASH_CSR(i), *preg++); + +- pm_runtime_mark_last_busy(hdev->dev); +- pm_runtime_put_autosuspend(hdev->dev); +- +- kfree(rctx->hw_context); ++ memcpy(&rctx->state, in, sizeof(rctx->state)); + + return 0; + } +@@ -1034,8 +1102,7 @@ static int stm32_hash_setkey(struct crypto_ahash *tfm, + return 0; + } + +-static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, +- const char *algs_hmac_name) ++static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, u32 algs_flags) + { + struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm); + +@@ -1044,8 +1111,8 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, + + ctx->keylen = 0; + +- if (algs_hmac_name) +- ctx->flags |= HASH_FLAGS_HMAC; ++ if (algs_flags) ++ ctx->flags |= algs_flags; + + ctx->enginectx.op.do_one_request = stm32_hash_one_request; + ctx->enginectx.op.prepare_request = stm32_hash_prepare_req; +@@ -1055,27 +1122,23 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, + + static int stm32_hash_cra_init(struct crypto_tfm *tfm) + { +- return stm32_hash_cra_init_algs(tfm, NULL); ++ return stm32_hash_cra_init_algs(tfm, 0); + } + +-static int stm32_hash_cra_md5_init(struct crypto_tfm *tfm) ++static int stm32_hash_cra_hmac_init(struct crypto_tfm *tfm) + { +- return stm32_hash_cra_init_algs(tfm, "md5"); ++ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_HMAC); + } + +-static int stm32_hash_cra_sha1_init(struct crypto_tfm *tfm) ++static int stm32_hash_cra_sha3_init(struct crypto_tfm *tfm) + { +- return stm32_hash_cra_init_algs(tfm, "sha1"); ++ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE); + } + +-static int stm32_hash_cra_sha224_init(struct crypto_tfm *tfm) ++static int stm32_hash_cra_sha3_hmac_init(struct crypto_tfm *tfm) + { +- return stm32_hash_cra_init_algs(tfm, "sha224"); +-} +- +-static int stm32_hash_cra_sha256_init(struct crypto_tfm *tfm) +-{ +- return stm32_hash_cra_init_algs(tfm, "sha256"); ++ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE | ++ HASH_FLAGS_HMAC); + } + + static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) +@@ -1110,8 +1173,6 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) + + reg = stm32_hash_read(hdev, HASH_SR); + if (reg & HASH_SR_OUTPUT_READY) { +- reg &= ~HASH_SR_OUTPUT_READY; +- stm32_hash_write(hdev, HASH_SR, reg); + hdev->flags |= HASH_FLAGS_OUTPUT_READY; + /* Disable IT*/ + stm32_hash_write(hdev, HASH_IMR, 0); +@@ -1121,7 +1182,7 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) + return IRQ_NONE; + } + +-static struct ahash_alg algs_md5_sha1[] = { ++static struct ahash_alg algs_md5[] = { + { + .init = stm32_hash_init, + .update = stm32_hash_update, +@@ -1132,7 +1193,7 @@ static struct ahash_alg algs_md5_sha1[] = { + .import = stm32_hash_import, + .halg = { + .digestsize = MD5_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "md5", + .cra_driver_name = "stm32-md5", +@@ -1158,7 +1219,7 @@ static struct ahash_alg algs_md5_sha1[] = { + .setkey = stm32_hash_setkey, + .halg = { + .digestsize = MD5_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(md5)", + .cra_driver_name = "stm32-hmac-md5", +@@ -1168,11 +1229,14 @@ static struct ahash_alg algs_md5_sha1[] = { + .cra_blocksize = MD5_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, +- .cra_init = stm32_hash_cra_md5_init, ++ .cra_init = stm32_hash_cra_hmac_init, + .cra_module = THIS_MODULE, + } + } +- }, ++ } ++}; ++ ++static struct ahash_alg algs_sha1[] = { + { + .init = stm32_hash_init, + .update = stm32_hash_update, +@@ -1183,7 +1247,7 @@ static struct ahash_alg algs_md5_sha1[] = { + .import = stm32_hash_import, + .halg = { + .digestsize = SHA1_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha1", + .cra_driver_name = "stm32-sha1", +@@ -1209,7 +1273,7 @@ static struct ahash_alg algs_md5_sha1[] = { + .setkey = stm32_hash_setkey, + .halg = { + .digestsize = SHA1_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha1)", + .cra_driver_name = "stm32-hmac-sha1", +@@ -1219,7 +1283,7 @@ static struct ahash_alg algs_md5_sha1[] = { + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, +- .cra_init = stm32_hash_cra_sha1_init, ++ .cra_init = stm32_hash_cra_hmac_init, + .cra_module = THIS_MODULE, + } + } +@@ -1237,7 +1301,7 @@ static struct ahash_alg algs_sha224_sha256[] = { + .import = stm32_hash_import, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha224", + .cra_driver_name = "stm32-sha224", +@@ -1263,7 +1327,7 @@ static struct ahash_alg algs_sha224_sha256[] = { + .import = stm32_hash_import, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha224)", + .cra_driver_name = "stm32-hmac-sha224", +@@ -1273,7 +1337,7 @@ static struct ahash_alg algs_sha224_sha256[] = { + .cra_blocksize = SHA224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, +- .cra_init = stm32_hash_cra_sha224_init, ++ .cra_init = stm32_hash_cra_hmac_init, + .cra_module = THIS_MODULE, + } + } +@@ -1288,7 +1352,7 @@ static struct ahash_alg algs_sha224_sha256[] = { + .import = stm32_hash_import, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha256", + .cra_driver_name = "stm32-sha256", +@@ -1314,7 +1378,7 @@ static struct ahash_alg algs_sha224_sha256[] = { + .setkey = stm32_hash_setkey, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, +- .statesize = sizeof(struct stm32_hash_request_ctx), ++ .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha256)", + .cra_driver_name = "stm32-hmac-sha256", +@@ -1324,11 +1388,323 @@ static struct ahash_alg algs_sha224_sha256[] = { + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, +- .cra_init = stm32_hash_cra_sha256_init, ++ .cra_init = stm32_hash_cra_hmac_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++}; ++ ++static struct ahash_alg algs_sha384_sha512[] = { ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .halg = { ++ .digestsize = SHA384_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "sha384", ++ .cra_driver_name = "stm32-sha384", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA384_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .setkey = stm32_hash_setkey, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .halg = { ++ .digestsize = SHA384_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "hmac(sha384)", ++ .cra_driver_name = "stm32-hmac-sha384", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA384_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_hmac_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .halg = { ++ .digestsize = SHA512_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "sha512", ++ .cra_driver_name = "stm32-sha512", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA512_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .setkey = stm32_hash_setkey, ++ .halg = { ++ .digestsize = SHA512_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "hmac(sha512)", ++ .cra_driver_name = "stm32-hmac-sha512", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA512_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_hmac_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++}; ++ ++static struct ahash_alg algs_sha3[] = { ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .halg = { ++ .digestsize = SHA3_224_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "sha3-224", ++ .cra_driver_name = "stm32-sha3-224", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_224_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .setkey = stm32_hash_setkey, ++ .halg = { ++ .digestsize = SHA3_224_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "hmac(sha3-224)", ++ .cra_driver_name = "stm32-hmac-sha3-224", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_224_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_hmac_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .halg = { ++ .digestsize = SHA3_256_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "sha3-256", ++ .cra_driver_name = "stm32-sha3-256", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_256_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .setkey = stm32_hash_setkey, ++ .halg = { ++ .digestsize = SHA3_256_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "hmac(sha3-256)", ++ .cra_driver_name = "stm32-hmac-sha3-256", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_256_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_hmac_init, + .cra_module = THIS_MODULE, + } + } + }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .halg = { ++ .digestsize = SHA3_384_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "sha3-384", ++ .cra_driver_name = "stm32-sha3-384", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_384_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .setkey = stm32_hash_setkey, ++ .halg = { ++ .digestsize = SHA3_384_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "hmac(sha3-384)", ++ .cra_driver_name = "stm32-hmac-sha3-384", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_384_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_hmac_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .halg = { ++ .digestsize = SHA3_512_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "sha3-512", ++ .cra_driver_name = "stm32-sha3-512", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_512_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ { ++ .init = stm32_hash_init, ++ .update = stm32_hash_update, ++ .final = stm32_hash_final, ++ .finup = stm32_hash_finup, ++ .digest = stm32_hash_digest, ++ .export = stm32_hash_export, ++ .import = stm32_hash_import, ++ .setkey = stm32_hash_setkey, ++ .halg = { ++ .digestsize = SHA3_512_DIGEST_SIZE, ++ .statesize = sizeof(struct stm32_hash_state), ++ .base = { ++ .cra_name = "hmac(sha3-512)", ++ .cra_driver_name = "stm32-hmac-sha3-512", ++ .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = SHA3_512_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct stm32_hash_ctx), ++ .cra_alignmask = 3, ++ .cra_init = stm32_hash_cra_sha3_hmac_init, ++ .cra_module = THIS_MODULE, ++ } ++ } ++ } + }; + + static int stm32_hash_register_algs(struct stm32_hash_dev *hdev) +@@ -1372,20 +1748,29 @@ static int stm32_hash_unregister_algs(struct stm32_hash_dev *hdev) + + static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f4[] = { + { +- .algs_list = algs_md5_sha1, +- .size = ARRAY_SIZE(algs_md5_sha1), ++ .algs_list = algs_md5, ++ .size = ARRAY_SIZE(algs_md5), ++ }, ++ { ++ .algs_list = algs_sha1, ++ .size = ARRAY_SIZE(algs_sha1), + }, + }; + + static const struct stm32_hash_pdata stm32_hash_pdata_stm32f4 = { ++ .alg_shift = 7, + .algs_info = stm32_hash_algs_info_stm32f4, + .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f4), + }; + + static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = { + { +- .algs_list = algs_md5_sha1, +- .size = ARRAY_SIZE(algs_md5_sha1), ++ .algs_list = algs_md5, ++ .size = ARRAY_SIZE(algs_md5), ++ }, ++ { ++ .algs_list = algs_sha1, ++ .size = ARRAY_SIZE(algs_sha1), + }, + { + .algs_list = algs_sha224_sha256, +@@ -1394,19 +1779,40 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = { + }; + + static const struct stm32_hash_pdata stm32_hash_pdata_stm32f7 = { ++ .alg_shift = 7, + .algs_info = stm32_hash_algs_info_stm32f7, + .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f7), + }; + +-static const struct of_device_id stm32_hash_of_match[] = { ++static struct stm32_hash_algs_info stm32_hash_algs_info_stm32mp13[] = { + { +- .compatible = "st,stm32f456-hash", +- .data = &stm32_hash_pdata_stm32f4, ++ .algs_list = algs_sha1, ++ .size = ARRAY_SIZE(algs_sha1), + }, + { +- .compatible = "st,stm32f756-hash", +- .data = &stm32_hash_pdata_stm32f7, ++ .algs_list = algs_sha224_sha256, ++ .size = ARRAY_SIZE(algs_sha224_sha256), ++ }, ++ { ++ .algs_list = algs_sha384_sha512, ++ .size = ARRAY_SIZE(algs_sha384_sha512), + }, ++ { ++ .algs_list = algs_sha3, ++ .size = ARRAY_SIZE(algs_sha3), ++ }, ++}; ++ ++static const struct stm32_hash_pdata stm32_hash_pdata_stm32mp13 = { ++ .alg_shift = 17, ++ .algs_info = stm32_hash_algs_info_stm32mp13, ++ .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32mp13), ++}; ++ ++static const struct of_device_id stm32_hash_of_match[] = { ++ { .compatible = "st,stm32f456-hash", .data = &stm32_hash_pdata_stm32f4 }, ++ { .compatible = "st,stm32f756-hash", .data = &stm32_hash_pdata_stm32f7 }, ++ { .compatible = "st,stm32mp13-hash", .data = &stm32_hash_pdata_stm32mp13 }, + {}, + }; + +@@ -1421,12 +1827,6 @@ static int stm32_hash_get_of_match(struct stm32_hash_dev *hdev, + return -EINVAL; + } + +- if (of_property_read_u32(dev->of_node, "dma-maxburst", +- &hdev->dma_maxburst)) { +- dev_info(dev, "dma-maxburst not specified, using 0\n"); +- hdev->dma_maxburst = 0; +- } +- + return 0; + } + +@@ -1494,6 +1894,8 @@ static int stm32_hash_probe(struct platform_device *pdev) + reset_control_deassert(hdev->rst); + } + ++ crypto_init_queue(&hdev->queue, HASH_QUEUE_LENGTH); ++ + hdev->dev = dev; + + platform_set_drvdata(pdev, hdev); +@@ -1502,7 +1904,7 @@ static int stm32_hash_probe(struct platform_device *pdev) + switch (ret) { + case 0: + break; +- case -ENOENT: ++ case -ENODEV: + dev_dbg(dev, "DMA mode not available\n"); + break; + default: +@@ -1524,7 +1926,8 @@ static int stm32_hash_probe(struct platform_device *pdev) + if (ret) + goto err_engine_start; + +- hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR); ++ hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR) & ++ HASH_HWCFG_DMA_MASK; + + /* Register algos */ + ret = stm32_hash_register_algs(hdev); +@@ -1633,6 +2036,6 @@ static struct platform_driver stm32_hash_driver = { + + module_platform_driver(stm32_hash_driver); + +-MODULE_DESCRIPTION("STM32 SHA1/224/256 & MD5 (HMAC) hw accelerator driver"); ++MODULE_DESCRIPTION("STM32 SHA1/SHA2/SHA3 & MD5 (HMAC) hw accelerator driver"); + MODULE_AUTHOR("Lionel Debieve "); + MODULE_LICENSE("GPL v2"); +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0005-ARM-5.15.24-stm32mp1-r1-DMA.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0006-v5.15-stm32mp-r2-DMA.patch similarity index 95% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0005-ARM-5.15.24-stm32mp1-r1-DMA.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0006-v5.15-stm32mp-r2-DMA.patch index d729d85..703d542 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0005-ARM-5.15.24-stm32mp1-r1-DMA.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0006-v5.15-stm32mp-r2-DMA.patch @@ -1,19 +1,19 @@ -From 20c1092971871e4018f8ca5de96282711289cb6f Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:52:37 +0200 -Subject: [PATCH 05/22] ARM-5.15.24-stm32mp1-r1-DMA +From 62911b17f33f57875c1b18ed211d5fa0f731ad42 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:26:34 +0100 +Subject: [PATCH 06/22] v5.15-stm32mp-r2 DMA -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../devicetree/bindings/dma/st,stm32-dma.yaml | 47 + .../bindings/dma/st,stm32-mdma.yaml | 12 +- drivers/dma/stm32-dma.c | 1169 +++++++++++++++-- drivers/dma/stm32-dmamux.c | 2 +- - drivers/dma/stm32-mdma.c | 170 ++- - 5 files changed, 1246 insertions(+), 154 deletions(-) + drivers/dma/stm32-mdma.c | 147 ++- + 5 files changed, 1240 insertions(+), 137 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml -index 4bf676fd2..99351fe0f 100644 +index 4bf676fd25dc..99351fe0fa17 100644 --- a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml +++ b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml @@ -47,6 +47,14 @@ description: | @@ -85,7 +85,7 @@ index 4bf676fd2..99351fe0f 100644 ... diff --git a/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml -index c30be840b..c4bb58014 100644 +index c30be840be1c..c4bb58014374 100644 --- a/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml +++ b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml @@ -10,8 +10,8 @@ description: | @@ -129,7 +129,7 @@ index c30be840b..c4bb58014 100644 dma-requests = <32>; st,ahb-addr-masks = <0x20000000>, <0x00000000>; diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c -index 7dfc743ac..7c6078c6c 100644 +index 7dfc743ac433..7c6078c6c3bf 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -14,12 +14,14 @@ @@ -1728,7 +1728,7 @@ index 7dfc743ac..7c6078c6c 100644 -subsys_initcall(stm32_dma_init); +device_initcall(stm32_dma_init); diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c -index a42164389..f9f77bb09 100644 +index d5d55732adba..eee0c5aa5fb5 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -267,7 +267,7 @@ static int stm32_dmamux_probe(struct platform_device *pdev) @@ -1741,18 +1741,10 @@ index a42164389..f9f77bb09 100644 udelay(2); reset_control_deassert(rst); diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c -index f17a9ffcd..133534663 100644 +index 21a7bdc88970..1335346635de 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c -@@ -40,7 +40,6 @@ - STM32_MDMA_SHIFT(mask)) - - #define STM32_MDMA_GISR0 0x0000 /* MDMA Int Status Reg 1 */ --#define STM32_MDMA_GISR1 0x0004 /* MDMA Int Status Reg 2 */ - - /* MDMA Channel x interrupt/status register */ - #define STM32_MDMA_CISR(x) (0x40 + 0x40 * (x)) /* x = 0..62 */ -@@ -79,6 +78,7 @@ +@@ -78,6 +78,7 @@ #define STM32_MDMA_CCR_WEX BIT(14) #define STM32_MDMA_CCR_HEX BIT(13) #define STM32_MDMA_CCR_BEX BIT(12) @@ -1760,13 +1752,7 @@ index f17a9ffcd..133534663 100644 #define STM32_MDMA_CCR_PL_MASK GENMASK(7, 6) #define STM32_MDMA_CCR_PL(n) STM32_MDMA_SET(n, \ STM32_MDMA_CCR_PL_MASK) -@@ -196,11 +196,13 @@ - - #define STM32_MDMA_MAX_BUF_LEN 128 - #define STM32_MDMA_MAX_BLOCK_LEN 65536 --#define STM32_MDMA_MAX_CHANNELS 63 -+#define STM32_MDMA_MAX_CHANNELS 32 - #define STM32_MDMA_MAX_REQUESTS 256 +@@ -200,6 +201,8 @@ #define STM32_MDMA_MAX_BURST 128 #define STM32_MDMA_VERY_HIGH_PRIORITY 0x3 @@ -1775,7 +1761,7 @@ index f17a9ffcd..133534663 100644 enum stm32_mdma_trigger_mode { STM32_MDMA_BUFFER, STM32_MDMA_BLOCK, -@@ -227,6 +229,7 @@ struct stm32_mdma_chan_config { +@@ -226,6 +229,7 @@ struct stm32_mdma_chan_config { u32 transfer_config; u32 mask_addr; u32 mask_data; @@ -1783,7 +1769,7 @@ index f17a9ffcd..133534663 100644 }; struct stm32_mdma_hwdesc { -@@ -252,6 +255,7 @@ struct stm32_mdma_desc { +@@ -251,6 +255,7 @@ struct stm32_mdma_desc { u32 ccr; bool cyclic; u32 count; @@ -1791,7 +1777,7 @@ index f17a9ffcd..133534663 100644 struct stm32_mdma_desc_node node[]; }; -@@ -276,6 +280,7 @@ struct stm32_mdma_device { +@@ -275,6 +280,7 @@ struct stm32_mdma_device { u32 nr_channels; u32 nr_requests; u32 nr_ahb_addr_masks; @@ -1799,7 +1785,7 @@ index f17a9ffcd..133534663 100644 struct stm32_mdma_chan chan[STM32_MDMA_MAX_CHANNELS]; u32 ahb_addr_masks[]; }; -@@ -566,13 +571,24 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, +@@ -565,13 +571,24 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, dst_addr = chan->dma_config.dst_addr; /* Set device data size */ @@ -1824,7 +1810,7 @@ index f17a9ffcd..133534663 100644 dst_best_burst = stm32_mdma_get_best_burst(buf_len, tlen, dst_maxburst, dst_addr_width); -@@ -615,13 +631,24 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, +@@ -614,13 +631,24 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, src_addr = chan->dma_config.src_addr; /* Set device data size */ @@ -1849,7 +1835,7 @@ index f17a9ffcd..133534663 100644 src_best_burst = stm32_mdma_get_best_burst(buf_len, tlen, src_maxburst, src_addr_width); -@@ -729,6 +756,7 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, +@@ -728,6 +756,7 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, { struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); struct dma_slave_config *dma_config = &chan->dma_config; @@ -1857,7 +1843,7 @@ index f17a9ffcd..133534663 100644 struct scatterlist *sg; dma_addr_t src_addr, dst_addr; u32 ccr, ctcr, ctbr; -@@ -751,6 +779,8 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, +@@ -750,6 +779,8 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, } else { src_addr = dma_config->src_addr; dst_addr = sg_dma_address(sg); @@ -1866,7 +1852,7 @@ index f17a9ffcd..133534663 100644 ret = stm32_mdma_set_xfer_param(chan, direction, &ccr, &ctcr, &ctbr, dst_addr, sg_dma_len(sg)); -@@ -769,8 +799,6 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, +@@ -768,8 +799,6 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, /* Enable interrupts */ ccr &= ~STM32_MDMA_CCR_IRQ_MASK; ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE; @@ -1875,7 +1861,7 @@ index f17a9ffcd..133534663 100644 desc->ccr = ccr; return 0; -@@ -782,7 +810,9 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, +@@ -781,7 +810,9 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, unsigned long flags, void *context) { struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c); @@ -1885,7 +1871,7 @@ index f17a9ffcd..133534663 100644 int i, ret; /* -@@ -804,6 +834,20 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, +@@ -803,6 +834,20 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, if (ret < 0) goto xfer_setup_err; @@ -1906,7 +1892,7 @@ index f17a9ffcd..133534663 100644 desc->cyclic = false; return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -@@ -825,9 +869,10 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, +@@ -824,9 +869,10 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c); struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); struct dma_slave_config *dma_config = &chan->dma_config; @@ -1918,7 +1904,7 @@ index f17a9ffcd..133534663 100644 int i, ret; /* -@@ -881,12 +926,29 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, +@@ -880,12 +926,29 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, desc->ccr = ccr; /* Configure hwdesc list */ @@ -1950,7 +1936,7 @@ index f17a9ffcd..133534663 100644 dst_addr = buf_addr + i * period_len; } -@@ -896,6 +958,7 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, +@@ -895,6 +958,7 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, } desc->cyclic = true; @@ -1958,7 +1944,7 @@ index f17a9ffcd..133534663 100644 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -@@ -1280,14 +1343,28 @@ static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan, +@@ -1279,14 +1343,28 @@ static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan, { struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); struct stm32_mdma_hwdesc *hwdesc = desc->node[0].hwdesc; @@ -1990,7 +1976,7 @@ index f17a9ffcd..133534663 100644 cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id)); residue += cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK; -@@ -1307,24 +1384,36 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c, +@@ -1306,24 +1384,36 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c, struct dma_tx_state *state) { struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c); @@ -2032,39 +2018,7 @@ index f17a9ffcd..133534663 100644 dma_set_residue(state, residue); spin_unlock_irqrestore(&chan->vchan.lock, flags); -@@ -1345,26 +1434,16 @@ static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan) - static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) - { - struct stm32_mdma_device *dmadev = devid; -- struct stm32_mdma_chan *chan = devid; -+ struct stm32_mdma_chan *chan; - u32 reg, id, ccr, ien, status; - - /* Find out which channel generates the interrupt */ - status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0); -- if (status) { -- id = __ffs(status); -- } else { -- status = readl_relaxed(dmadev->base + STM32_MDMA_GISR1); -- if (!status) { -- dev_dbg(mdma2dev(dmadev), "spurious it\n"); -- return IRQ_NONE; -- } -- id = __ffs(status); -- /* -- * As GISR0 provides status for channel id from 0 to 31, -- * so GISR1 provides status for channel id from 32 to 62 -- */ -- id += 32; -+ if (!status) { -+ dev_dbg(mdma2dev(dmadev), "spurious it\n"); -+ return IRQ_NONE; - } -+ id = __ffs(status); - - chan = &dmadev->chan[id]; - if (!chan) { -@@ -1382,9 +1461,12 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) +@@ -1371,9 +1461,12 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) if (!(status & ien)) { spin_unlock(&chan->vchan.lock); @@ -2080,7 +2034,7 @@ index f17a9ffcd..133534663 100644 return IRQ_NONE; } -@@ -1484,15 +1566,28 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c) +@@ -1473,15 +1566,28 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c) chan->desc_pool = NULL; } @@ -2110,7 +2064,7 @@ index f17a9ffcd..133534663 100644 dev_err(mdma2dev(dmadev), "Bad number of args\n"); return NULL; } -@@ -1502,6 +1597,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, +@@ -1491,6 +1597,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, config.transfer_config = dma_spec->args[2]; config.mask_addr = dma_spec->args[3]; config.mask_data = dma_spec->args[4]; @@ -2118,7 +2072,7 @@ index f17a9ffcd..133534663 100644 if (config.request >= dmadev->nr_requests) { dev_err(mdma2dev(dmadev), "Bad request line\n"); -@@ -1513,7 +1609,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, +@@ -1502,7 +1609,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, return NULL; } @@ -2127,7 +2081,7 @@ index f17a9ffcd..133534663 100644 if (!c) { dev_err(mdma2dev(dmadev), "No more channels available\n"); return NULL; -@@ -1642,6 +1738,10 @@ static int stm32_mdma_probe(struct platform_device *pdev) +@@ -1631,6 +1738,10 @@ static int stm32_mdma_probe(struct platform_device *pdev) for (i = 0; i < dmadev->nr_channels; i++) { chan = &dmadev->chan[i]; chan->id = i; @@ -2139,5 +2093,5 @@ index f17a9ffcd..133534663 100644 vchan_init(&chan->vchan, dd); } -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0006-ARM-5.15.24-stm32mp1-r1-DRM.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0007-v5.15-stm32mp-r2-DRM.patch similarity index 76% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0006-ARM-5.15.24-stm32mp1-r1-DRM.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0007-v5.15-stm32mp-r2-DRM.patch index 8894369..6d61c18 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0006-ARM-5.15.24-stm32mp1-r1-DRM.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0007-v5.15-stm32mp-r2-DRM.patch @@ -1,31 +1,34 @@ -From f595fb2c09e4d443332aae91899ce97f09200c4d Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:53:18 +0200 -Subject: [PATCH 06/22] ARM-5.15.24-stm32mp1-r1-DRM +From 1f085af24db6752b0028d1aea4a451f772922b12 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:27:37 +0100 +Subject: [PATCH 07/22] v5.15-stm32mp-r2 DRM -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- - drivers/gpu/drm/bridge/sii902x.c | 100 +- - drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 5 +- - drivers/gpu/drm/drm_bridge.c | 10 +- - drivers/gpu/drm/panel/Kconfig | 9 + - drivers/gpu/drm/panel/Makefile | 1 + - .../gpu/drm/panel/panel-orisetech-otm8009a.c | 101 +- - drivers/gpu/drm/panel/panel-raydium-rm68200.c | 7 +- - drivers/gpu/drm/panel/panel-rocktech-hx8394.c | 397 ++++++++ - drivers/gpu/drm/panel/panel-simple.c | 16 + - drivers/gpu/drm/stm/drv.c | 5 + - drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 114 ++- - drivers/gpu/drm/stm/ltdc.c | 922 +++++++++++++++--- - drivers/gpu/drm/stm/ltdc.h | 15 +- - drivers/video/backlight/gpio_backlight.c | 7 +- - drivers/video/fbdev/simplefb.c | 21 +- - include/drm/bridge/dw_mipi_dsi.h | 4 +- - 16 files changed, 1502 insertions(+), 232 deletions(-) + drivers/gpu/drm/bridge/sii902x.c | 100 +- + drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 5 +- + drivers/gpu/drm/drm_atomic_uapi.c | 4 + + drivers/gpu/drm/drm_bridge.c | 10 +- + drivers/gpu/drm/drm_connector.c | 62 + + drivers/gpu/drm/panel/Kconfig | 9 + + drivers/gpu/drm/panel/Makefile | 1 + + .../gpu/drm/panel/panel-orisetech-otm8009a.c | 101 +- + drivers/gpu/drm/panel/panel-raydium-rm68200.c | 7 +- + drivers/gpu/drm/panel/panel-rocktech-hx8394.c | 397 ++++++ + drivers/gpu/drm/panel/panel-simple.c | 16 + + drivers/gpu/drm/stm/drv.c | 6 + + drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 118 +- + drivers/gpu/drm/stm/ltdc.c | 1118 ++++++++++++++--- + drivers/gpu/drm/stm/ltdc.h | 25 +- + drivers/video/backlight/gpio_backlight.c | 7 +- + drivers/video/fbdev/simplefb.c | 21 +- + include/drm/bridge/dw_mipi_dsi.h | 4 +- + include/drm/drm_connector.h | 14 + + 19 files changed, 1763 insertions(+), 262 deletions(-) create mode 100644 drivers/gpu/drm/panel/panel-rocktech-hx8394.c diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c -index 89558e581..69208ead5 100644 +index 89558e581530..69208ead5384 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -16,6 +16,7 @@ @@ -211,7 +214,7 @@ index 89558e581..69208ead5 100644 .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 e44e18a01..3f6564762 100644 +index 56c3fd08c6a0..2a58b0b7ace5 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -998,7 +998,10 @@ dw_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, @@ -226,11 +229,33 @@ index e44e18a01..3f6564762 100644 return mode_status; } +diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c +index f195c7013137..9301aa72e6cb 100644 +--- a/drivers/gpu/drm/drm_atomic_uapi.c ++++ b/drivers/gpu/drm/drm_atomic_uapi.c +@@ -773,6 +773,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, + state->content_type = val; + } else if (property == connector->scaling_mode_property) { + state->scaling_mode = val; ++ } else if (property == connector->dithering_property) { ++ state->dithering = val; + } else if (property == config->content_protection_property) { + if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) { + DRM_DEBUG_KMS("only drivers can set CP Enabled\n"); +@@ -862,6 +864,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, + *val = state->colorspace; + } else if (property == connector->scaling_mode_property) { + *val = state->scaling_mode; ++ } else if (property == connector->dithering_property) { ++ *val = state->dithering; + } else if (property == config->hdr_output_metadata_property) { + *val = state->hdr_output_metadata ? + state->hdr_output_metadata->base.id : 0; diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c -index a8ed66751..01494544e 100644 +index 7ee29f073857..798d2cff102f 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c -@@ -228,11 +228,13 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, +@@ -227,11 +227,13 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, list_del(&bridge->chain_node); #ifdef CONFIG_OF @@ -248,11 +273,91 @@ index a8ed66751..01494544e 100644 #endif return ret; +diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c +index e9b7926d9b66..c035729fa995 100644 +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -824,6 +824,12 @@ static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { + { DRM_MODE_SCALE_ASPECT, "Full aspect" }, + }; + ++static const struct drm_prop_enum_list drm_dithering_enum_list[] = { ++ { DRM_MODE_DITHERING_OFF, "Off" }, ++ { DRM_MODE_DITHERING_ON, "On" }, ++ { DRM_MODE_DITHERING_AUTO, "Automatic" }, ++}; ++ + static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { + { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" }, + { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" }, +@@ -1776,6 +1782,62 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, + } + EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property); + ++/** ++ * drm_connector_attach_dithering_property - attach atomic dithering property ++ * @connector: connector to attach dithering property on. ++ * @dithering_mask: or'ed mask of BIT(%DRM_MODE_DITHERING_\*). ++ * ++ * This is used to add support for dithering to atomic drivers. ++ * ++ * Returns: ++ * Zero on success, negative errno on failure. ++ */ ++int drm_connector_attach_dithering_property(struct drm_connector *connector, ++ u32 dithering_mask) ++{ ++ struct drm_device *dev = connector->dev; ++ struct drm_property *dithering_property; ++ int i; ++ const unsigned int valid_dithering_mask = ++ (1U << ARRAY_SIZE(drm_dithering_enum_list)) - 1; ++ ++ if (WARN_ON(hweight32(dithering_mask) < 2 || ++ dithering_mask & ~valid_dithering_mask)) ++ return -EINVAL; ++ ++ dithering_property = ++ drm_property_create(dev, DRM_MODE_PROP_ENUM, "dithering", ++ hweight32(dithering_mask)); ++ ++ if (!dithering_property) ++ return -ENOMEM; ++ ++ for (i = 0; i < ARRAY_SIZE(drm_dithering_enum_list); i++) { ++ int ret; ++ ++ if (!(BIT(i) & dithering_mask)) ++ continue; ++ ++ ret = drm_property_add_enum(dithering_property, ++ drm_dithering_enum_list[i].type, ++ drm_dithering_enum_list[i].name); ++ ++ if (ret) { ++ drm_property_destroy(dev, dithering_property); ++ ++ return ret; ++ } ++ } ++ ++ drm_object_attach_property(&connector->base, ++ dithering_property, 0); ++ ++ connector->dithering_property = dithering_property; ++ ++ return 0; ++} ++EXPORT_SYMBOL(drm_connector_attach_dithering_property); ++ + /** + * drm_mode_create_aspect_ratio_property - create aspect ratio property + * @dev: DRM device diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig -index 418638e6e..f1a60de49 100644 +index 479ffdb64486..c49fb01b1ce5 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig -@@ -357,6 +357,15 @@ config DRM_PANEL_RAYDIUM_RM68200 +@@ -359,6 +359,15 @@ config DRM_PANEL_RAYDIUM_RM68200 Say Y here if you want to enable support for Raydium RM68200 720x1280 DSI video mode panel. @@ -269,7 +374,7 @@ index 418638e6e..f1a60de49 100644 tristate "Ronbo Electronics RB070D30 panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile -index c8132050b..57d794897 100644 +index c8132050bcec..57d7948975c2 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o @@ -281,7 +386,7 @@ index c8132050b..57d794897 100644 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c -index f80b44a8a..70b2bb72d 100644 +index f80b44a8a700..70b2bb72dbbc 100644 --- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c +++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c @@ -60,6 +60,9 @@ @@ -429,7 +534,7 @@ index f80b44a8a..70b2bb72d 100644 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 412c0dbcb..d5542266e 100644 +index 412c0dbcb2b6..d5542266e754 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm68200.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm68200.c @@ -91,7 +91,7 @@ static const struct drm_display_mode default_mode = { @@ -462,7 +567,7 @@ index 412c0dbcb..d5542266e 100644 diff --git a/drivers/gpu/drm/panel/panel-rocktech-hx8394.c b/drivers/gpu/drm/panel/panel-rocktech-hx8394.c new file mode 100644 -index 000000000..6a5926cc7 +index 000000000000..6a5926cc79ba --- /dev/null +++ b/drivers/gpu/drm/panel/panel-rocktech-hx8394.c @@ -0,0 +1,397 @@ @@ -864,7 +969,7 @@ index 000000000..6a5926cc7 +MODULE_DESCRIPTION("DRM Driver for rocktech HX8394 MIPI DSI panel"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c -index b7b654f2d..7f4dd49c0 100644 +index 8dd7013c75f2..6934f3680a14 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -575,6 +575,7 @@ static int panel_dpi_probe(struct device *dev, @@ -898,7 +1003,7 @@ index b7b654f2d..7f4dd49c0 100644 bus_flags = 0; vm.flags = timing->flags; diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c -index 222869b23..9f441aadf 100644 +index 222869b232ae..85c94b8f5d54 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -14,6 +14,7 @@ @@ -909,7 +1014,15 @@ index 222869b23..9f441aadf 100644 #include #include #include -@@ -183,6 +184,10 @@ static int stm_drm_platform_probe(struct platform_device *pdev) +@@ -93,6 +94,7 @@ static int drv_load(struct drm_device *ddev) + ddev->mode_config.max_width = STM_MAX_FB_WIDTH; + ddev->mode_config.max_height = STM_MAX_FB_HEIGHT; + ddev->mode_config.funcs = &drv_mode_config_funcs; ++ ddev->mode_config.normalize_zpos = true; + + ret = ltdc_load(ddev); + if (ret) +@@ -183,6 +185,10 @@ static int stm_drm_platform_probe(struct platform_device *pdev) DRM_DEBUG("%s\n", __func__); @@ -921,7 +1034,7 @@ index 222869b23..9f441aadf 100644 ddev = drm_dev_alloc(&drv_driver, dev); diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c -index 32cb41b22..89897d5f5 100644 +index 32cb41b2202f..1750b6a25e87 100644 --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c @@ -247,14 +247,6 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, @@ -1051,7 +1164,24 @@ index 32cb41b22..89897d5f5 100644 .phy_ops = &dw_mipi_dsi_stm_phy_ops, }; -@@ -417,6 +507,14 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) +@@ -354,15 +444,13 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct dw_mipi_dsi_stm *dsi; + struct clk *pclk; +- struct resource *res; + int ret; + + dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); + if (!dsi) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- dsi->base = devm_ioremap_resource(dev, res); ++ dsi->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(dsi->base)) { + ret = PTR_ERR(dsi->base); + DRM_ERROR("Unable to get dsi registers %d\n", ret); +@@ -417,6 +505,14 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) goto err_dsi_probe; } @@ -1067,7 +1197,7 @@ index 32cb41b22..89897d5f5 100644 dw_mipi_dsi_stm_plat_data.priv_data = dsi; diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c -index 195de30eb..22cf21440 100644 +index 9d235b60b428..3dcd63f20ee0 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -18,6 +18,7 @@ @@ -1165,18 +1295,40 @@ index 195de30eb..22cf21440 100644 #define GCR_PCPOL BIT(28) /* Pixel Clock POLarity-Inverted */ #define GCR_DEPOL BIT(29) /* Data Enable POLarity-High */ #define GCR_VSPOL BIT(30) /* Vertical Synchro POLarity-High */ -@@ -164,6 +173,10 @@ +@@ -153,20 +162,29 @@ + #define BCCR_BCWHITE GENMASK(23, 0) /* Background Color WHITE */ + + #define IER_LIE BIT(0) /* Line Interrupt Enable */ +-#define IER_FUIE BIT(1) /* Fifo Underrun Interrupt Enable */ ++#define IER_FUWIE BIT(1) /* Fifo Underrun Warning Interrupt Enable */ + #define IER_TERRIE BIT(2) /* Transfer ERRor Interrupt Enable */ +-#define IER_RRIE BIT(3) /* Register Reload Interrupt enable */ ++#define IER_RRIE BIT(3) /* Register Reload Interrupt Enable */ ++#define IER_FUEIE BIT(6) /* Fifo Underrun Error Interrupt Enable */ ++#define IER_CRCIE BIT(7) /* CRC Error Interrupt Enable */ + + #define CPSR_CYPOS GENMASK(15, 0) /* Current Y position */ + + #define ISR_LIF BIT(0) /* Line Interrupt Flag */ +-#define ISR_FUIF BIT(1) /* Fifo Underrun Interrupt Flag */ ++#define ISR_FUWIF BIT(1) /* Fifo Underrun Warning Interrupt Flag */ #define ISR_TERRIF BIT(2) /* Transfer ERRor Interrupt Flag */ #define ISR_RRIF BIT(3) /* Register Reload Interrupt Flag */ - ++#define ISR_FUEIF BIT(6) /* Fifo Underrun Error Interrupt Flag */ ++#define ISR_CRCIF BIT(7) /* CRC Error Interrupt Flag */ ++ +#define EDCR_OCYEN BIT(25) /* Output Conversion to YCbCr 422: ENable */ +#define EDCR_OCYSEL BIT(26) /* Output Conversion to YCbCr 422: SELection of the CCIR */ +#define EDCR_OCYCO BIT(27) /* Output Conversion to YCbCr 422: Chrominance Order */ -+ + #define LXCR_LEN BIT(0) /* Layer ENable */ #define LXCR_COLKEN BIT(1) /* Color Keying Enable */ #define LXCR_CLUTEN BIT(4) /* Color Look-Up Table ENable */ -@@ -175,6 +188,7 @@ ++#define LXCR_HMEN BIT(8) /* Horizontal Mirroring ENable */ + + #define LXWHPCR_WHSTPOS GENMASK(11, 0) /* Window Horizontal StarT POSition */ + #define LXWHPCR_WHSPPOS GENMASK(27, 16) /* Window Horizontal StoP POSition */ +@@ -175,17 +193,38 @@ #define LXWVPCR_WVSPPOS GENMASK(26, 16) /* Window Vertical StoP POSition */ #define LXPFCR_PF GENMASK(2, 0) /* Pixel Format */ @@ -1184,7 +1336,13 @@ index 195de30eb..22cf21440 100644 #define LXCACR_CONSTA GENMASK(7, 0) /* CONSTant Alpha */ -@@ -186,6 +200,24 @@ + #define LXBFCR_BF2 GENMASK(2, 0) /* Blending Factor 2 */ + #define LXBFCR_BF1 GENMASK(10, 8) /* Blending Factor 1 */ ++#define LXBFCR_BOR GENMASK(18, 16) /* Blending ORder */ + + #define LXCFBLR_CFBLL GENMASK(12, 0) /* Color Frame Buffer Line Length */ +-#define LXCFBLR_CFBP GENMASK(28, 16) /* Color Frame Buffer Pitch in bytes */ ++#define LXCFBLR_CFBP GENMASK(31, 16) /* Color Frame Buffer Pitch in bytes */ #define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */ @@ -1205,14 +1363,17 @@ index 195de30eb..22cf21440 100644 + +#define LXRCR_IMR BIT(0) /* IMmediate Reload */ +#define LXRCR_VBR BIT(1) /* Vertical Blanking Reload */ ++#define LXRCR_GRMSK BIT(2) /* Global (centralized) Reload MaSKed */ + #define CLUT_SIZE 256 #define CONSTA_MAX 0xFF /* CONSTant Alpha MAX= 1.0 */ -@@ -196,13 +228,24 @@ +@@ -196,13 +235,26 @@ #define NB_PF 8 /* Max nb of HW pixel format */ ++#define FUT_DFT 128 /* Default value of fifo underrun threshold */ ++ +/* + * Skip the first value and the second in case CRC was enabled during + * the thread irq. This is to be sure CRC value is relevant for the @@ -1234,7 +1395,7 @@ index 195de30eb..22cf21440 100644 PF_ARGB1555, /* ARGB A:1 bit RGB:15 bits [16 bits] */ PF_ARGB4444, /* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */ /* Indexed formats */ -@@ -234,36 +277,198 @@ static const enum ltdc_pix_fmt ltdc_pix_fmt_a1[NB_PF] = { +@@ -234,36 +286,198 @@ static const enum ltdc_pix_fmt ltdc_pix_fmt_a1[NB_PF] = { PF_ARGB4444 /* 0x07 */ }; @@ -1457,7 +1618,7 @@ index 195de30eb..22cf21440 100644 static inline struct ltdc_device *crtc_to_ltdc(struct drm_crtc *crtc) { -@@ -289,16 +494,30 @@ static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) +@@ -289,16 +503,30 @@ static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) case DRM_FORMAT_XRGB8888: pf = PF_ARGB8888; break; @@ -1488,7 +1649,7 @@ index 195de30eb..22cf21440 100644 case DRM_FORMAT_ARGB1555: case DRM_FORMAT_XRGB1555: pf = PF_ARGB1555; -@@ -319,49 +538,158 @@ static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) +@@ -319,49 +547,159 @@ static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) return pf; } @@ -1549,7 +1710,7 @@ index 195de30eb..22cf21440 100644 - return 0; + ret = NB_PF; /* error case, trace msg is handled by the caller */ + break; - } ++ } + + if (ret == PF_FLEXIBLE) { + regmap_write(ldev->regmap, LTDC_L1FPF0R + lofs, @@ -1557,17 +1718,22 @@ index 195de30eb..22cf21440 100644 + + regmap_write(ldev->regmap, LTDC_L1FPF1R + lofs, + (psize << 18) + (blen << 14) + (bpos << 9) + (glen << 5) + gpos); -+ } + } + + return ret; - } - --static inline u32 get_pixelformat_without_alpha(u32 drm) ++} ++ +/* + * All non-alpha color formats derived from native alpha color formats are + * either characterized by a FourCC format code + */ +static inline u32 is_xrgb(u32 drm) ++{ ++ return ((drm & 0xFF) == 'X' || ((drm >> 8) & 0xFF) == 'X'); + } + +-static inline u32 get_pixelformat_without_alpha(u32 drm) ++static inline void ltdc_set_ycbcr_config(struct drm_plane *plane, u32 drm_pix_fmt) { - switch (drm) { - case DRM_FORMAT_ARGB4444: @@ -1582,45 +1748,40 @@ index 195de30eb..22cf21440 100644 - return DRM_FORMAT_XRGB8888; - case DRM_FORMAT_RGBA8888: - return DRM_FORMAT_RGBX8888; -- default: -- return 0; -+ return ((drm & 0xFF) == 'X' || ((drm >> 8) & 0xFF) == 'X'); -+} -+ -+static inline void ltdc_set_ycbcr_config(struct drm_plane *plane, u32 drm_pix_fmt) -+{ + struct ltdc_device *ldev = plane_to_ltdc(plane); + struct drm_plane_state *state = plane->state; + u32 lofs = plane->index * LAY_OFS; + u32 val; + + switch (drm_pix_fmt) { -+ case DRM_FORMAT_YUYV: -+ val = (YCM_I << 4) | LxPCR_YF | LxPCR_CBF; -+ break; -+ case DRM_FORMAT_YVYU: -+ val = (YCM_I << 4) | LxPCR_YF; -+ break; -+ case DRM_FORMAT_UYVY: -+ val = (YCM_I << 4) | LxPCR_CBF; -+ break; -+ case DRM_FORMAT_VYUY: -+ val = (YCM_I << 4); -+ break; -+ case DRM_FORMAT_NV12: -+ val = (YCM_SP << 4) | LxPCR_CBF; -+ break; -+ case DRM_FORMAT_NV21: -+ val = (YCM_SP << 4); -+ break; -+ case DRM_FORMAT_YUV420: -+ case DRM_FORMAT_YVU420: -+ val = (YCM_FP << 4); -+ break; -+ default: -+ /* RGB or not a YCbCr supported format */ -+ break; - } ++ case DRM_FORMAT_YUYV: ++ val = (YCM_I << 4) | LxPCR_YF | LxPCR_CBF; ++ break; ++ case DRM_FORMAT_YVYU: ++ val = (YCM_I << 4) | LxPCR_YF; ++ break; ++ case DRM_FORMAT_UYVY: ++ val = (YCM_I << 4) | LxPCR_CBF; ++ break; ++ case DRM_FORMAT_VYUY: ++ val = (YCM_I << 4); ++ break; ++ case DRM_FORMAT_NV12: ++ val = (YCM_SP << 4) | LxPCR_CBF; ++ break; ++ case DRM_FORMAT_NV21: ++ val = (YCM_SP << 4); ++ break; ++ case DRM_FORMAT_YUV420: ++ case DRM_FORMAT_YVU420: ++ val = (YCM_FP << 4); ++ break; + default: +- return 0; ++ /* RGB or not a YCbCr supported format */ ++ DRM_ERROR("Unsupported pixel format: %u\n", drm_pix_fmt); ++ return; ++ } + + /* Enable limited range */ + if (state->color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) @@ -1668,7 +1829,7 @@ index 195de30eb..22cf21440 100644 + if (ldev->crc_skip_count < CRC_SKIP_FRAMES) { + ldev->crc_skip_count++; + return; -+ } + } + + /* Get the CRC of the frame */ + ret = regmap_read(ldev->regmap, LTDC_CCRCR, &crc); @@ -1680,7 +1841,7 @@ index 195de30eb..22cf21440 100644 } static irqreturn_t ltdc_irq_thread(int irq, void *arg) -@@ -371,9 +699,14 @@ static irqreturn_t ltdc_irq_thread(int irq, void *arg) +@@ -371,15 +709,21 @@ static irqreturn_t ltdc_irq_thread(int irq, void *arg) struct drm_crtc *crtc = drm_crtc_from_index(ddev, 0); /* Line IRQ : trigger the vblank event */ @@ -1688,15 +1849,26 @@ index 195de30eb..22cf21440 100644 + if (ldev->irq_status & ISR_LIF) { drm_crtc_handle_vblank(crtc); +- /* Save FIFO Underrun & Transfer Error status */ + /* Early return if CRC is not active */ + if (ldev->crc_active) + ltdc_irq_crc_handle(ldev, crtc); + } + - /* Save FIFO Underrun & Transfer Error status */ mutex_lock(&ldev->err_lock); - if (ldev->irq_status & ISR_FUIF) -@@ -391,8 +724,8 @@ static irqreturn_t ltdc_irq(int irq, void *arg) +- if (ldev->irq_status & ISR_FUIF) +- ldev->error_status |= ISR_FUIF; + if (ldev->irq_status & ISR_TERRIF) +- ldev->error_status |= ISR_TERRIF; ++ ldev->transfer_err++; ++ if (ldev->irq_status & ISR_FUEIF) ++ ldev->fifo_err++; ++ if (ldev->irq_status & ISR_FUWIF) ++ ldev->fifo_warn++; + mutex_unlock(&ldev->err_lock); + + return IRQ_HANDLED; +@@ -391,8 +735,8 @@ static irqreturn_t ltdc_irq(int irq, void *arg) struct ltdc_device *ldev = ddev->dev_private; /* Read & Clear the interrupt status */ @@ -1707,7 +1879,7 @@ index 195de30eb..22cf21440 100644 return IRQ_WAKE_THREAD; } -@@ -416,7 +749,7 @@ static void ltdc_crtc_update_clut(struct drm_crtc *crtc) +@@ -416,7 +760,7 @@ static void ltdc_crtc_update_clut(struct drm_crtc *crtc) for (i = 0; i < CLUT_SIZE; i++, lut++) { val = ((lut->red << 8) & 0xff0000) | (lut->green & 0xff00) | (lut->blue >> 8) | (i << 24); @@ -1716,7 +1888,7 @@ index 195de30eb..22cf21440 100644 } } -@@ -425,19 +758,27 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, +@@ -425,19 +769,27 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, { struct ltdc_device *ldev = crtc_to_ltdc(crtc); struct drm_device *ddev = crtc->dev; @@ -1739,7 +1911,7 @@ index 195de30eb..22cf21440 100644 /* Enable IRQ */ - reg_set(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE); -+ regmap_set_bits(ldev->regmap, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE); ++ regmap_set_bits(ldev->regmap, LTDC_IER, IER_FUWIE | IER_FUEIE | IER_RRIE | IER_TERRIE); /* Commit shadow registers = update planes at next vblank */ - reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR); @@ -1748,12 +1920,24 @@ index 195de30eb..22cf21440 100644 drm_crtc_vblank_on(crtc); } -@@ -453,12 +794,13 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc, +@@ -447,18 +799,32 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc, + { + struct ltdc_device *ldev = crtc_to_ltdc(crtc); + struct drm_device *ddev = crtc->dev; ++ int layer_index = 0; + + DRM_DEBUG_DRIVER("\n"); + drm_crtc_vblank_off(crtc); ++ /* Disable all layers */ ++ for (layer_index = 0; layer_index < ldev->caps.nb_layers; layer_index++) ++ regmap_write_bits(ldev->regmap, LTDC_L1CR + layer_index * LAY_OFS, ++ LXCR_CLUTEN | LXCR_LEN, 0); ++ /* disable IRQ */ - reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE); -+ regmap_clear_bits(ldev->regmap, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE); ++ regmap_clear_bits(ldev->regmap, LTDC_IER, IER_FUWIE | IER_FUEIE | IER_RRIE | IER_TERRIE); /* immediately commit disable of layers before switching off LTDC */ - reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR); @@ -1762,10 +1946,17 @@ index 195de30eb..22cf21440 100644 - pm_runtime_put_sync(ddev->dev); + pm_runtime_put_sync_suspend(ddev->dev); ++ ++ /* clear interrupt error counters */ ++ mutex_lock(&ldev->err_lock); ++ ldev->transfer_err = 0; ++ ldev->fifo_err = 0; ++ ldev->fifo_warn = 0; ++ mutex_unlock(&ldev->err_lock); } #define CLK_TOLERANCE_HZ 50 -@@ -533,6 +875,7 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) +@@ -533,6 +899,7 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) struct drm_display_mode *mode = &crtc->state->adjusted_mode; u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h; u32 total_width, total_height; @@ -1773,12 +1964,15 @@ index 195de30eb..22cf21440 100644 u32 bus_flags = 0; u32 val; int ret; -@@ -558,8 +901,11 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) +@@ -560,10 +927,13 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) + drm_connector_list_iter_end(&iter); + } - if (bridge && bridge->timings) +- if (bridge && bridge->timings) ++ if (bridge && bridge->timings) { bus_flags = bridge->timings->input_bus_flags; - else if (connector) -+ else if (connector) { ++ } else if (connector) { bus_flags = connector->display_info.bus_flags; + if (connector->display_info.num_bus_formats) + bus_formats = connector->display_info.bus_formats[0]; @@ -1786,14 +1980,17 @@ index 195de30eb..22cf21440 100644 if (!pm_runtime_active(ddev->dev)) { ret = pm_runtime_get_sync(ddev->dev); -@@ -604,26 +950,56 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) +@@ -608,26 +978,59 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) val |= GCR_PCPOL; - reg_update_bits(ldev->regs, LTDC_GCR, - GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val); ++ if (connector && connector->state->dithering == DRM_MODE_DITHERING_ON) ++ val |= GCR_DEN; ++ + regmap_update_bits(ldev->regmap, LTDC_GCR, -+ GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val); ++ GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL | GCR_DEN, val); /* Set Synchronization size */ val = (hsync << 16) | vsync; @@ -1816,7 +2013,8 @@ index 195de30eb..22cf21440 100644 + regmap_update_bits(ldev->regmap, LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val); + + regmap_write(ldev->regmap, LTDC_LIPCR, (accum_act_h + 1)); -+ + +- reg_write(ldev->regs, LTDC_LIPCR, (accum_act_h + 1)); + /* Configure the output format (hw version dependent) */ + if (ldev->caps.ycbcr_output) { + /* Input video dynamic_range & colorimetry */ @@ -1830,8 +2028,7 @@ index 195de30eb..22cf21440 100644 + else + /* ITU-R BT.709 */ + val = EDCR_OCYSEL; - -- reg_write(ldev->regs, LTDC_LIPCR, (accum_act_h + 1)); ++ + switch (bus_formats) { + case MEDIA_BUS_FMT_YUYV8_1X16: + /* enable ycbcr output converter */ @@ -1850,7 +2047,7 @@ index 195de30eb..22cf21440 100644 } static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, -@@ -638,7 +1014,8 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, +@@ -642,7 +1045,8 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, ltdc_crtc_update_clut(crtc); /* Commit shadow registers = update planes at next vblank */ @@ -1860,7 +2057,7 @@ index 195de30eb..22cf21440 100644 if (event) { crtc->state->event = NULL; -@@ -680,10 +1057,14 @@ static bool ltdc_crtc_get_scanout_position(struct drm_crtc *crtc, +@@ -684,10 +1088,14 @@ static bool ltdc_crtc_get_scanout_position(struct drm_crtc *crtc, * simplify the code and only test if line > vactive_end */ if (pm_runtime_active(ddev->dev)) { @@ -1879,7 +2076,7 @@ index 195de30eb..22cf21440 100644 if (line > vactive_end) *vpos = line - vtotal - vactive_start; -@@ -719,7 +1100,7 @@ static int ltdc_crtc_enable_vblank(struct drm_crtc *crtc) +@@ -723,7 +1131,7 @@ static int ltdc_crtc_enable_vblank(struct drm_crtc *crtc) DRM_DEBUG_DRIVER("\n"); if (state->enable) @@ -1888,7 +2085,7 @@ index 195de30eb..22cf21440 100644 else return -EPERM; -@@ -731,7 +1112,49 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc) +@@ -735,7 +1143,61 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc) struct ltdc_device *ldev = crtc_to_ltdc(crtc); DRM_DEBUG_DRIVER("\n"); @@ -1936,13 +2133,28 @@ index 195de30eb..22cf21440 100644 + + *values_cnt = 1; + return 0; ++} ++ ++static void ltdc_crtc_atomic_print_state(struct drm_printer *p, ++ const struct drm_crtc_state *state) ++{ ++ struct drm_crtc *crtc = state->crtc; ++ struct ltdc_device *ldev = crtc_to_ltdc(crtc); ++ ++ drm_printf(p, "\ttransfer_error=%d\n", ldev->transfer_err); ++ drm_printf(p, "\tfifo_underrun_error=%d\n", ldev->fifo_err); ++ drm_printf(p, "\tfifo_underrun_warning=%d\n", ldev->fifo_warn); ++ drm_printf(p, "\tfifo_underrun_threshold=%d\n", ldev->fifo_threshold); } static const struct drm_crtc_funcs ltdc_crtc_funcs = { -@@ -746,6 +1169,20 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = { +@@ -748,6 +1210,22 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = { + .enable_vblank = ltdc_crtc_enable_vblank, + .disable_vblank = ltdc_crtc_disable_vblank, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, - }; - ++ .atomic_print_state = ltdc_crtc_atomic_print_state, ++}; ++ +static const struct drm_crtc_funcs ltdc_crtc_with_crc_support_funcs = { + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, @@ -1955,12 +2167,11 @@ index 195de30eb..22cf21440 100644 + .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, + .set_crc_source = ltdc_crtc_set_crc_source, + .verify_crc_source = ltdc_crtc_verify_crc_source, -+}; -+ ++ .atomic_print_state = ltdc_crtc_atomic_print_state, + }; + /* - * DRM_PLANE - */ -@@ -769,7 +1206,8 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane, +@@ -773,7 +1251,8 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane, /* Reject scaling */ if (src_w != new_plane_state->crtc_w || src_h != new_plane_state->crtc_h) { @@ -1970,7 +2181,7 @@ index 195de30eb..22cf21440 100644 return -EINVAL; } -@@ -780,6 +1218,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, +@@ -784,6 +1263,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) { struct ltdc_device *ldev = plane_to_ltdc(plane); @@ -1978,22 +2189,23 @@ index 195de30eb..22cf21440 100644 struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state, plane); struct drm_framebuffer *fb = newstate->fb; -@@ -789,7 +1228,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, +@@ -793,7 +1273,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, u32 y0 = newstate->crtc_y; u32 y1 = newstate->crtc_y + newstate->crtc_h - 1; u32 src_x, src_y, src_w, src_h; - u32 val, pitch_in_bytes, line_length, paddr, ahbp, avbp, bpcr; -+ u32 val, pitch_in_bytes, line_length, line_number, paddr, ahbp, avbp, bpcr; ++ u32 val, pitch_in_bytes, line_length, line_number, ahbp, avbp, bpcr; ++ u32 paddr, paddr1, paddr2; enum ltdc_pix_fmt pf; if (!newstate->crtc || !fb) { -@@ -809,19 +1248,23 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, +@@ -813,19 +1294,23 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, newstate->crtc_w, newstate->crtc_h, newstate->crtc_x, newstate->crtc_y); - bpcr = reg_read(ldev->regs, LTDC_BPCR); + if (!pm_runtime_active(ddev->dev)) -+ return; ++ return; + + regmap_read(ldev->regmap, LTDC_BPCR, &bpcr); + @@ -2016,7 +2228,7 @@ index 195de30eb..22cf21440 100644 /* Specifies the pixel format */ pf = to_ltdc_pixelformat(fb->format->format); -@@ -829,24 +1272,27 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, +@@ -833,24 +1318,20 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, if (ldev->caps.pix_fmt_hw[val] == pf) break; @@ -2030,16 +2242,15 @@ index 195de30eb..22cf21440 100644 val = 0; /* set by default ARGB 32 bits */ } - reg_update_bits(ldev->regs, LTDC_L1PFCR + lofs, LXPFCR_PF, val); -+ regmap_write_bits(ldev->regmap, LTDC_L1PFCR + lofs, LXPFCR_PF, val); - - /* 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; - val = ((pitch_in_bytes << 16) | line_length); +- +- /* 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; +- val = ((pitch_in_bytes << 16) | line_length); - reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs, - LXCFBLR_CFBLL | LXCFBLR_CFBP, val); -+ regmap_write_bits(ldev->regmap, LTDC_L1CFBLR + lofs, LXCFBLR_CFBLL | LXCFBLR_CFBP, val); ++ regmap_write_bits(ldev->regmap, LTDC_L1PFCR + lofs, LXPFCR_PF, val); /* Specifies the constant alpha value */ - val = CONSTA_MAX; @@ -2049,87 +2260,135 @@ index 195de30eb..22cf21440 100644 /* Specifies the blending factors */ val = BF1_PAXCA | BF2_1PAXCA; -@@ -858,24 +1304,97 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, +@@ -862,35 +1343,168 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, plane->type != DRM_PLANE_TYPE_PRIMARY) val = BF1_PAXCA | BF2_1PAXCA; - reg_update_bits(ldev->regs, LTDC_L1BFCR + lofs, - LXBFCR_BF2 | LXBFCR_BF1, val); -+ regmap_write_bits(ldev->regmap, LTDC_L1BFCR + lofs, LXBFCR_BF2 | LXBFCR_BF1, val); - - /* Configures the frame buffer line number */ +- +- /* Configures the frame buffer line number */ - val = y1 - y0 + 1; - reg_update_bits(ldev->regs, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, val); -+ line_number = y1 - y0 + 1; -+ regmap_write_bits(ldev->regmap, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, line_number); ++ if (ldev->caps.dynamic_zorder) { ++ val |= (newstate->normalized_zpos << 16); ++ regmap_write_bits(ldev->regmap, LTDC_L1BFCR + lofs, ++ LXBFCR_BF2 | LXBFCR_BF1 | LXBFCR_BOR, val); ++ } else { ++ regmap_write_bits(ldev->regmap, LTDC_L1BFCR + lofs, ++ LXBFCR_BF2 | LXBFCR_BF1, val); ++ } /* Sets the FB address */ paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 0); ++ if (newstate->rotation & DRM_MODE_REFLECT_X) ++ paddr += (fb->format->cpp[0] * (x1 - x0 + 1)) - 1; ++ ++ if (newstate->rotation & DRM_MODE_REFLECT_Y) ++ paddr += (fb->pitches[0] * (y1 - y0)); ++ DRM_DEBUG_DRIVER("fb: phys 0x%08x", paddr); - reg_write(ldev->regs, LTDC_L1CFBAR + lofs, paddr); + regmap_write(ldev->regmap, LTDC_L1CFBAR + lofs, paddr); + ++ /* Configures the color frame buffer pitch in bytes & line length */ ++ line_length = fb->format->cpp[0] * ++ (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1; ++ ++ if (newstate->rotation & DRM_MODE_REFLECT_Y) ++ /* Compute negative value (signed on 16 bits) for the picth */ ++ pitch_in_bytes = 0x10000 - fb->pitches[0]; ++ else ++ pitch_in_bytes = fb->pitches[0]; ++ ++ val = (pitch_in_bytes << 16) | line_length; ++ regmap_write_bits(ldev->regmap, LTDC_L1CFBLR + lofs, LXCFBLR_CFBLL | LXCFBLR_CFBP, val); ++ ++ /* Configures the frame buffer line number */ ++ line_number = y1 - y0 + 1; ++ regmap_write_bits(ldev->regmap, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, line_number); ++ + if (ldev->caps.ycbcr_input) { + if (fb->format->is_yuv) { + switch (fb->format->format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: -+ /* Configure the auxiliary frame buffer address 0 & 1 */ -+ paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); -+ regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr); -+ regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr + 1); ++ /* Configure the auxiliary frame buffer address 0 */ ++ paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); + -+ /* Configure the buffer length */ -+ val = ((pitch_in_bytes << 16) | line_length); -+ regmap_write(ldev->regmap, LTDC_L1AFBLR + lofs, val); ++ if (newstate->rotation & DRM_MODE_REFLECT_X) ++ paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; + -+ /* Configure the frame buffer line number */ -+ val = (line_number >> 1); -+ regmap_write(ldev->regmap, LTDC_L1AFBLNR + lofs, val); ++ if (newstate->rotation & DRM_MODE_REFLECT_Y) ++ paddr1 += (fb->pitches[1] * (y1 - y0 - 1)) >> 1; ++ ++ regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr1); + break; + case DRM_FORMAT_YUV420: -+ /* Configure the auxiliary frame buffer address 0 */ -+ paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); -+ regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr); ++ /* Configure the auxiliary frame buffer address 0 & 1 */ ++ paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); ++ paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); + -+ /* Configure the auxiliary frame buffer address 1 */ -+ paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); -+ regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr); ++ if (newstate->rotation & DRM_MODE_REFLECT_X) { ++ paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; ++ paddr2 += ((fb->format->cpp[2] * (x1 - x0 + 1)) >> 1) - 1; ++ } + -+ line_length = ((fb->format->cpp[0] * (x1 - x0 + 1)) >> 1) + -+ (ldev->caps.bus_width >> 3) - 1; ++ if (newstate->rotation & DRM_MODE_REFLECT_Y) { ++ paddr1 += (fb->pitches[1] * (y1 - y0 - 1)) >> 1; ++ paddr2 += (fb->pitches[2] * (y1 - y0 - 1)) >> 1; ++ } + -+ /* Configure the buffer length */ -+ val = (((pitch_in_bytes >> 1) << 16) | line_length); -+ regmap_write(ldev->regmap, LTDC_L1AFBLR + lofs, val); -+ -+ /* Configure the frame buffer line number */ -+ val = (line_number >> 1); -+ regmap_write(ldev->regmap, LTDC_L1AFBLNR + lofs, val); ++ regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr1); ++ regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr2); + break; + case DRM_FORMAT_YVU420: -+ /* Configure the auxiliary frame buffer address 0 */ -+ paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); -+ regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr); ++ /* Configure the auxiliary frame buffer address 0 & 1 */ ++ paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); ++ paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); + -+ /* Configure the auxiliary frame buffer address 1 */ -+ paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); -+ regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr); ++ if (newstate->rotation & DRM_MODE_REFLECT_X) { ++ paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; ++ paddr2 += ((fb->format->cpp[2] * (x1 - x0 + 1)) >> 1) - 1; ++ } + -+ line_length = ((fb->format->cpp[0] * (x1 - x0 + 1)) >> 1) + -+ (ldev->caps.bus_width >> 3) - 1; ++ if (newstate->rotation & DRM_MODE_REFLECT_Y) { ++ paddr1 += (fb->pitches[1] * (y1 - y0 - 1)) >> 1; ++ paddr2 += (fb->pitches[2] * (y1 - y0 - 1)) >> 1; ++ } + -+ /* Configure the buffer length */ -+ val = (((pitch_in_bytes >> 1) << 16) | line_length); -+ regmap_write(ldev->regmap, LTDC_L1AFBLR + lofs, val); -+ -+ /* Configure the frame buffer line number */ -+ val = (line_number >> 1); -+ regmap_write(ldev->regmap, LTDC_L1AFBLNR + lofs, val); ++ regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr1); ++ regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr2); + break; + } + ++ /* ++ * Set the length and the number of lines of the auxiliary ++ * buffers if the framebuffer contains more than one plane. ++ */ ++ if (fb->format->num_planes > 1) { ++ if (newstate->rotation & DRM_MODE_REFLECT_Y) ++ /* ++ * Compute negative value (signed on 16 bits) ++ * for the picth ++ */ ++ pitch_in_bytes = 0x10000 - fb->pitches[1]; ++ else ++ pitch_in_bytes = fb->pitches[1]; ++ ++ line_length = ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) + ++ (ldev->caps.bus_width >> 3) - 1; ++ ++ /* Configure the auxiliary buffer length */ ++ val = (pitch_in_bytes << 16) | line_length; ++ regmap_write(ldev->regmap, LTDC_L1AFBLR + lofs, val); ++ ++ /* Configure the auxiliary frame buffer line number */ ++ val = line_number >> 1; ++ regmap_write(ldev->regmap, LTDC_L1AFBLNR + lofs, val); ++ } ++ + /* Configure YCbC conversion coefficient */ + ltdc_set_ycbcr_coeffs(plane); + @@ -2146,35 +2405,68 @@ index 195de30eb..22cf21440 100644 val |= LXCR_LEN; - reg_update_bits(ldev->regs, LTDC_L1CR + lofs, - LXCR_LEN | LXCR_CLUTEN, val); -+ regmap_write_bits(ldev->regmap, LTDC_L1CR + lofs, LXCR_CLUTEN | LXCR_LEN, val); ++ ++ /* Enable horizontal mirroring if requested */ ++ if (newstate->rotation & DRM_MODE_REFLECT_X) ++ val |= LXCR_HMEN; ++ ++ regmap_write_bits(ldev->regmap, LTDC_L1CR + lofs, LXCR_LEN | LXCR_CLUTEN | LXCR_HMEN, val); + + /* Commit shadow registers = update plane at next vblank */ + if (ldev->caps.plane_reg_shadow) -+ regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs, LXRCR_VBR, LXRCR_VBR); ++ regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs, ++ LXRCR_IMR | LXRCR_VBR | LXRCR_GRMSK, LXRCR_VBR); ldev->plane_fpsi[plane->index].counter++; -@@ -897,10 +1416,18 @@ static void ltdc_plane_atomic_disable(struct drm_plane *plane, + mutex_lock(&ldev->err_lock); +- if (ldev->error_status & ISR_FUIF) { +- DRM_WARN("ltdc fifo underrun: please verify display mode\n"); +- ldev->error_status &= ~ISR_FUIF; ++ if (ldev->transfer_err) { ++ DRM_WARN("ltdc transfer error: %d\n", ldev->transfer_err); ++ ldev->transfer_err = 0; + } +- if (ldev->error_status & ISR_TERRIF) { +- DRM_WARN("ltdc transfer error\n"); +- ldev->error_status &= ~ISR_TERRIF; ++ ++ if (ldev->caps.fifo_threshold) { ++ if (ldev->fifo_err) { ++ DRM_WARN("ltdc fifo underrun: please verify display mode\n"); ++ ldev->fifo_err = 0; ++ } ++ } else { ++ if (ldev->fifo_warn >= ldev->fifo_threshold) { ++ DRM_WARN("ltdc fifo underrun: please verify display mode\n"); ++ ldev->fifo_warn = 0; ++ } + } + mutex_unlock(&ldev->err_lock); + } +@@ -901,10 +1515,19 @@ static void ltdc_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state, plane); struct ltdc_device *ldev = plane_to_ltdc(plane); + struct drm_device *ddev = plane->dev; u32 lofs = plane->index * LAY_OFS; +- /* disable layer */ +- reg_clear(ldev->regs, LTDC_L1CR + lofs, LXCR_LEN); + if (!pm_runtime_active(ddev->dev)) + return; + - /* disable layer */ -- reg_clear(ldev->regs, LTDC_L1CR + lofs, LXCR_LEN); -+ regmap_write_bits(ldev->regmap, LTDC_L1CR + lofs, LXCR_CLUTEN | LXCR_LEN, 0); ++ /* Disable layer */ ++ regmap_write_bits(ldev->regmap, LTDC_L1CR + lofs, LXCR_LEN | LXCR_CLUTEN | LXCR_HMEN, 0); + + /* Commit shadow registers = update plane at next vblank */ + if (ldev->caps.plane_reg_shadow) -+ regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs, LXRCR_VBR, LXRCR_VBR); ++ regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs, ++ LXRCR_IMR | LXRCR_VBR | LXRCR_GRMSK, LXRCR_VBR); DRM_DEBUG_DRIVER("CRTC:%d plane:%d\n", oldstate->crtc->base.id, plane->base.id); -@@ -953,36 +1480,55 @@ static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = { +@@ -957,36 +1580,57 @@ static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = { }; static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, @@ -2203,8 +2495,10 @@ index 195de30eb..22cf21440 100644 - continue; - formats[nb_fmt++] = drm_fmt; + /* Allocate the biggest size according to supported color formats */ -+ formats = devm_kzalloc(dev, (ldev->caps.pix_fmt_nb + ARRAY_SIZE(ltdc_drm_fmt_ycbcr_cp) + -+ ARRAY_SIZE(ltdc_drm_fmt_ycbcr_sp) + ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp)) * ++ formats = devm_kzalloc(dev, (ldev->caps.pix_fmt_nb + ++ ARRAY_SIZE(ltdc_drm_fmt_ycbcr_cp) + ++ ARRAY_SIZE(ltdc_drm_fmt_ycbcr_sp) + ++ ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp)) * + sizeof(*formats), GFP_KERNEL); - /* Add the no-alpha related format if any & supported */ @@ -2221,11 +2515,11 @@ index 195de30eb..22cf21440 100644 + if (ldev->caps.non_alpha_only_l1) + if (type != DRM_PLANE_TYPE_PRIMARY && is_xrgb(drm_fmt)) + continue; /* XR24 & RX24 like formats supported only on primary layer */ - -- formats[nb_fmt++] = drm_fmt_no_alpha; ++ + formats[nb_fmt++] = drm_fmt; + } -+ + +- formats[nb_fmt++] = drm_fmt_no_alpha; + /* Add YCbCr supported pixel formats */ + if (ldev->caps.ycbcr_input) { + regmap_read(ldev->regmap, LTDC_L1C1R + lofs, &val); @@ -2247,7 +2541,7 @@ index 195de30eb..22cf21440 100644 } plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL); -@@ -995,8 +1541,21 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, +@@ -999,8 +1643,21 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, if (ret < 0) return NULL; @@ -2269,11 +2563,25 @@ index 195de30eb..22cf21440 100644 DRM_DEBUG_DRIVER("plane:%d created\n", plane->base.id); return plane; -@@ -1018,14 +1577,21 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) +@@ -1019,17 +1676,42 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) + { + struct ltdc_device *ldev = ddev->dev_private; + struct drm_plane *primary, *overlay; ++ int supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; unsigned int i; int ret; ++ struct drm_connector *connector = NULL; ++ struct drm_connector_list_iter iter; - primary = ltdc_plane_create(ddev, DRM_PLANE_TYPE_PRIMARY); ++ /* Add the dithering property to all connectors */ ++ drm_connector_list_iter_begin(ddev, &iter); ++ drm_for_each_connector_iter(connector, &iter) ++ drm_connector_attach_dithering_property(connector, ++ BIT(DRM_MODE_DITHERING_OFF) | ++ BIT(DRM_MODE_DITHERING_ON)); ++ drm_connector_list_iter_end(&iter); ++ + primary = ltdc_plane_create(ddev, DRM_PLANE_TYPE_PRIMARY, 0); if (!primary) { DRM_ERROR("Can not create primary plane\n"); @@ -2282,7 +2590,14 @@ index 195de30eb..22cf21440 100644 - ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL, - <dc_crtc_funcs, NULL); -+ drm_plane_create_zpos_immutable_property(primary, 0); ++ if (ldev->caps.dynamic_zorder) ++ drm_plane_create_zpos_property(primary, 0, 0, ldev->caps.nb_layers - 1); ++ else ++ drm_plane_create_zpos_immutable_property(primary, 0); ++ ++ if (ldev->caps.plane_rotation) ++ drm_plane_create_rotation_property(primary, DRM_MODE_ROTATE_0, ++ supported_rotations); + + /* Init CRTC according to its hardware features */ + if (ldev->caps.crc) @@ -2294,7 +2609,7 @@ index 195de30eb..22cf21440 100644 if (ret) { DRM_ERROR("Can not initialize CRTC\n"); goto cleanup; -@@ -1040,12 +1606,13 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) +@@ -1044,12 +1726,20 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) /* Add planes. Note : the first layer is used by primary plane */ for (i = 1; i < ldev->caps.nb_layers; i++) { @@ -2305,11 +2620,18 @@ index 195de30eb..22cf21440 100644 DRM_ERROR("Can not create overlay plane %d\n", i); goto cleanup; } -+ drm_plane_create_zpos_immutable_property(overlay, i); ++ if (ldev->caps.dynamic_zorder) ++ drm_plane_create_zpos_property(overlay, i, 0, ldev->caps.nb_layers - 1); ++ else ++ drm_plane_create_zpos_immutable_property(overlay, i); ++ ++ if (ldev->caps.plane_rotation) ++ drm_plane_create_rotation_property(overlay, DRM_MODE_ROTATE_0, ++ supported_rotations); } return 0; -@@ -1063,7 +1630,7 @@ static void ltdc_encoder_disable(struct drm_encoder *encoder) +@@ -1067,7 +1757,7 @@ static void ltdc_encoder_disable(struct drm_encoder *encoder) DRM_DEBUG_DRIVER("\n"); /* Disable LTDC */ @@ -2318,16 +2640,21 @@ index 195de30eb..22cf21440 100644 /* Set to sleep state the pinctrl whatever type of encoder */ pinctrl_pm_select_sleep_state(ddev->dev); -@@ -1077,7 +1644,7 @@ static void ltdc_encoder_enable(struct drm_encoder *encoder) +@@ -1080,8 +1770,12 @@ static void ltdc_encoder_enable(struct drm_encoder *encoder) + DRM_DEBUG_DRIVER("\n"); ++ /* set fifo underrun threshold register */ ++ if (ldev->caps.fifo_threshold) ++ regmap_write(ldev->regmap, LTDC_FUT, ldev->fifo_threshold); ++ /* Enable LTDC */ - reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN); + regmap_set_bits(ldev->regmap, LTDC_GCR, GCR_LTDCEN); } static void ltdc_encoder_mode_set(struct drm_encoder *encoder, -@@ -1140,21 +1707,25 @@ static int ltdc_get_caps(struct drm_device *ddev) +@@ -1144,21 +1838,25 @@ static int ltdc_get_caps(struct drm_device *ddev) * at least 1 layer must be managed & the number of layers * must not exceed LTDC_MAX_LAYER */ @@ -2357,7 +2684,7 @@ index 195de30eb..22cf21440 100644 /* * Hw older versions support non-alpha color formats derived * from native alpha color formats only on the primary layer. -@@ -1167,13 +1738,40 @@ static int ltdc_get_caps(struct drm_device *ddev) +@@ -1171,13 +1869,49 @@ static int ltdc_get_caps(struct drm_device *ddev) if (ldev->caps.hw_version == HWVER_10200) ldev->caps.pad_max_freq_hz = 65000000; ldev->caps.nb_irq = 2; @@ -2365,6 +2692,9 @@ index 195de30eb..22cf21440 100644 + ldev->caps.ycbcr_output = false; + ldev->caps.plane_reg_shadow = false; + ldev->caps.crc = false; ++ ldev->caps.dynamic_zorder = false; ++ ldev->caps.plane_rotation = false; ++ ldev->caps.fifo_threshold = false; break; case HWVER_20101: - ldev->caps.reg_ofs = REG_OFS_4; @@ -2381,6 +2711,9 @@ index 195de30eb..22cf21440 100644 + ldev->caps.ycbcr_output = false; + ldev->caps.plane_reg_shadow = false; + ldev->caps.crc = false; ++ ldev->caps.dynamic_zorder = false; ++ ldev->caps.plane_rotation = false; ++ ldev->caps.fifo_threshold = false; + break; + case HWVER_40100: + ldev->caps.layer_ofs = LAY_OFS_1; @@ -2396,32 +2729,64 @@ index 195de30eb..22cf21440 100644 + ldev->caps.ycbcr_output = true; + ldev->caps.plane_reg_shadow = true; + ldev->caps.crc = true; ++ ldev->caps.dynamic_zorder = true; ++ ldev->caps.plane_rotation = true; ++ ldev->caps.fifo_threshold = true; break; default: return -ENODEV; -@@ -1291,9 +1889,15 @@ int ltdc_load(struct drm_device *ddev) +@@ -1295,9 +2029,12 @@ int ltdc_load(struct drm_device *ddev) goto err; } +- /* Disable interrupts */ +- reg_clear(ldev->regs, LTDC_IER, +- IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE); + ldev->regmap = devm_regmap_init_mmio(&pdev->dev, ldev->regs, &stm32_ltdc_regmap_cfg); + if (IS_ERR(ldev->regmap)) { + DRM_ERROR("Unable to regmap ltdc registers\n"); + ret = PTR_ERR(ldev->regmap); + goto err; + } -+ - /* Disable interrupts */ -- reg_clear(ldev->regs, LTDC_IER, -- IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE); -+ regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE); ret = ltdc_get_caps(ddev); if (ret) { +@@ -1306,8 +2043,22 @@ int ltdc_load(struct drm_device *ddev) + goto err; + } + ++ /* Disable interrupts */ ++ if (ldev->caps.fifo_threshold) ++ regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE | IER_RRIE | IER_FUWIE | ++ IER_TERRIE); ++ else ++ regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE | IER_RRIE | IER_FUWIE | ++ IER_TERRIE | IER_FUEIE); ++ + DRM_DEBUG_DRIVER("ltdc hw version 0x%08x\n", ldev->caps.hw_version); + ++ /* initialize default value for fifo underrun threshold & clear interrupt error counters */ ++ ldev->transfer_err = 0; ++ ldev->fifo_err = 0; ++ ldev->fifo_warn = 0; ++ ldev->fifo_threshold = FUT_DFT; ++ + for (i = 0; i < ldev->caps.nb_irq; i++) { + irq = platform_get_irq(pdev, i); + if (irq < 0) { +@@ -1322,7 +2073,6 @@ int ltdc_load(struct drm_device *ddev) + DRM_ERROR("Failed to register LTDC interrupt\n"); + goto err; + } +- + } + + crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h -index f153b908c..59fc5d1bb 100644 +index f153b908c70e..12ee90c8b504 100644 --- a/drivers/gpu/drm/stm/ltdc.h +++ b/drivers/gpu/drm/stm/ltdc.h -@@ -14,12 +14,20 @@ +@@ -14,12 +14,23 @@ struct ltdc_caps { u32 hw_version; /* hardware version */ u32 nb_layers; /* number of supported layers */ @@ -2441,18 +2806,26 @@ index f153b908c..59fc5d1bb 100644 + bool ycbcr_output; /* ycbcr output converter supported */ + bool plane_reg_shadow; /* plane shadow registers ability */ + bool crc; /* cyclic redundancy check supported */ ++ bool dynamic_zorder; /* dynamic z-order */ ++ bool plane_rotation; /* plane rotation */ ++ bool fifo_threshold; /* fifo underrun threshold supported */ }; #define LTDC_MAX_LAYER 4 -@@ -31,6 +39,7 @@ struct fps_info { +@@ -31,13 +42,19 @@ struct fps_info { struct ltdc_device { void __iomem *regs; + struct regmap *regmap; struct clk *pixel_clk; /* lcd pixel clock */ - struct mutex err_lock; /* protecting error_status */ +- struct mutex err_lock; /* protecting error_status */ ++ struct mutex err_lock; /* protecting transfer_err, fifo_err, fifo_warn */ ++ u32 transfer_err; /* transfer error counter */ ++ u32 fifo_err; /* fifo underrun error counter */ ++ u32 fifo_warn; /* fifo underrun warning counter */ ++ u32 fifo_threshold; /* fifo underrun threshold */ struct ltdc_caps caps; -@@ -38,6 +47,8 @@ struct ltdc_device { +- u32 error_status; u32 irq_status; struct fps_info plane_fpsi[LTDC_MAX_LAYER]; struct drm_atomic_state *suspend_state; @@ -2462,7 +2835,7 @@ index f153b908c..59fc5d1bb 100644 int ltdc_load(struct drm_device *ddev); diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c -index 6f78d928f..d3fa3a8be 100644 +index 6f78d928f054..d3fa3a8bef4d 100644 --- a/drivers/video/backlight/gpio_backlight.c +++ b/drivers/video/backlight/gpio_backlight.c @@ -53,6 +53,7 @@ static int gpio_backlight_probe(struct platform_device *pdev) @@ -2487,10 +2860,10 @@ index 6f78d928f..d3fa3a8be 100644 init_brightness = backlight_get_brightness(bl); ret = gpiod_direction_output(gbl->gpiod, init_brightness); diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c -index b63074fd8..575418871 100644 +index a2e3a4690025..efce6ef8532d 100644 --- a/drivers/video/fbdev/simplefb.c +++ b/drivers/video/fbdev/simplefb.c -@@ -541,26 +541,7 @@ static struct platform_driver simplefb_driver = { +@@ -547,26 +547,7 @@ static struct platform_driver simplefb_driver = { .remove = simplefb_remove, }; @@ -2519,7 +2892,7 @@ index b63074fd8..575418871 100644 MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Simple framebuffer driver"); diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h -index bda8aa7c2..5286a53a1 100644 +index bda8aa7c2280..5286a53a1875 100644 --- a/include/drm/bridge/dw_mipi_dsi.h +++ b/include/drm/bridge/dw_mipi_dsi.h @@ -51,7 +51,9 @@ struct dw_mipi_dsi_plat_data { @@ -2533,6 +2906,45 @@ index bda8aa7c2..5286a53a1 100644 const struct dw_mipi_dsi_phy_ops *phy_ops; const struct dw_mipi_dsi_host_ops *host_ops; +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index 1f43d7c6724a..ea40115df680 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -749,6 +749,12 @@ struct drm_connector_state { + */ + unsigned int scaling_mode; + ++ /** ++ * @dithering: Connector property to control the ++ * dithering. ++ */ ++ unsigned int dithering; ++ + /** + * @content_protection: Connector property to request content + * protection. This is most commonly used for HDCP. +@@ -1360,6 +1366,12 @@ struct drm_connector { + */ + struct drm_property *scaling_mode_property; + ++ /** ++ * @dithering_property: Optional atomic property to control the ++ * dithering. ++ */ ++ struct drm_property *dithering_property; ++ + /** + * @vrr_capable_property: Optional property to help userspace + * query hardware support for variable refresh rate on a connector. +@@ -1680,6 +1692,8 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev); + int drm_connector_attach_content_type_property(struct drm_connector *dev); + int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, + u32 scaling_mode_mask); ++int drm_connector_attach_dithering_property(struct drm_connector *connector, ++ u32 dithering_mask); + int drm_connector_attach_vrr_capable_property( + struct drm_connector *connector); + int drm_connector_attach_colorspace_property(struct drm_connector *connector); -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0007-ARM-5.15.24-stm32mp1-r1-HWSPINLOCK.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0008-v5.15-stm32mp-r2-HWSPINLOCK.patch similarity index 96% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0007-ARM-5.15.24-stm32mp1-r1-HWSPINLOCK.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0008-v5.15-stm32mp-r2-HWSPINLOCK.patch index 5445d80..059a7a2 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0007-ARM-5.15.24-stm32mp1-r1-HWSPINLOCK.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0008-v5.15-stm32mp-r2-HWSPINLOCK.patch @@ -1,9 +1,9 @@ -From 924efc211ec362bf6b42a5f18327ad6b8b0652a2 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:53:54 +0200 -Subject: [PATCH 07/22] ARM-5.15.24-stm32mp1-r1-HWSPINLOCK +From 8fade81923d0fc70c09d3f2beae3466cc5e71c2d Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:28:58 +0100 +Subject: [PATCH 08/22] v5.15-stm32mp-r2 HWSPINLOCK -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../devicetree/bindings/hwlock/hwlock.txt | 27 +++++-- .../bindings/hwlock/st,stm32-hwspinlock.yaml | 4 +- @@ -14,7 +14,7 @@ Signed-off-by: Christophe Priouzeau 6 files changed, 131 insertions(+), 50 deletions(-) diff --git a/Documentation/devicetree/bindings/hwlock/hwlock.txt b/Documentation/devicetree/bindings/hwlock/hwlock.txt -index 085d1f5c9..e98088a40 100644 +index 085d1f5c916a..e98088a409ba 100644 --- a/Documentation/devicetree/bindings/hwlock/hwlock.txt +++ b/Documentation/devicetree/bindings/hwlock/hwlock.txt @@ -13,7 +13,7 @@ hwlock providers: @@ -69,7 +69,7 @@ index 085d1f5c9..e98088a40 100644 + }; \ No newline at end of file diff --git a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml -index 47cf9c8d9..539a1dc05 100644 +index 47cf9c8d97e9..539a1dc052b7 100644 --- a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml +++ b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml @@ -12,7 +12,7 @@ maintainers: @@ -91,7 +91,7 @@ index 47cf9c8d9..539a1dc05 100644 clocks = <&rcc HSEM>; clock-names = "hsem"; diff --git a/Documentation/locking/hwspinlock.rst b/Documentation/locking/hwspinlock.rst -index 6f03713b7..605bd2dc8 100644 +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). @@ -124,7 +124,7 @@ index 6f03713b7..605bd2dc8 100644 }; diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c -index fd5f5c5a5..a2197af89 100644 +index fd5f5c5a5244..a2197af8973d 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -29,6 +29,8 @@ @@ -309,7 +309,7 @@ index fd5f5c5a5..a2197af89 100644 return ret; } diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h -index 29892767b..e1f9c9600 100644 +index 29892767bb7a..e1f9c9600635 100644 --- a/drivers/hwspinlock/hwspinlock_internal.h +++ b/drivers/hwspinlock/hwspinlock_internal.h @@ -35,11 +35,13 @@ struct hwspinlock_ops { @@ -327,7 +327,7 @@ index 29892767b..e1f9c9600 100644 }; diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c -index 3ad0ce0da..5bd11a7fa 100644 +index 3ad0ce0da4d9..5bd11a7fab65 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 = { @@ -427,5 +427,5 @@ index 3ad0ce0da..5bd11a7fa 100644 .name = "stm32_hwspinlock", .of_match_table = stm32_hwpinlock_ids, -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0008-ARM-5.15.24-stm32mp1-r1-I2C-IIO-IRQCHIP.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0009-v5.15-stm32mp-r2-I2C-IIO-IRQCHIP.patch similarity index 66% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0008-ARM-5.15.24-stm32mp1-r1-I2C-IIO-IRQCHIP.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0009-v5.15-stm32mp-r2-I2C-IIO-IRQCHIP.patch index 80eb937..a4ffa1c 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0008-ARM-5.15.24-stm32mp1-r1-I2C-IIO-IRQCHIP.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0009-v5.15-stm32mp-r2-I2C-IIO-IRQCHIP.patch @@ -1,26 +1,28 @@ -From 21a6408507c420ae565837508928fe7795caeb84 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:55:14 +0200 -Subject: [PATCH 08/22] ARM-5.15.24-stm32mp1-r1-I2C-IIO-IRQCHIP +From e02af9ac4cbbe463217ac8c34eee18170d57e5af Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:36:23 +0100 +Subject: [PATCH 09/22] v5.15-stm32mp-r2 I2C-IIO-IRQCHIP -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../devicetree/bindings/i2c/st,stm32-i2c.yaml | 2 + .../iio/adc/sigma-delta-modulator.yaml | 3 + - .../bindings/iio/adc/st,stm32-adc.yaml | 175 ++++- - drivers/i2c/busses/i2c-stm32f7.c | 129 ++-- - drivers/iio/adc/sd_adc_modulator.c | 89 ++- - drivers/iio/adc/stm32-adc-core.c | 209 +++++- - drivers/iio/adc/stm32-adc-core.h | 72 ++ - drivers/iio/adc/stm32-adc.c | 656 +++++++++++++++--- + .../bindings/iio/adc/st,stm32-adc.yaml | 175 +++- + drivers/i2c/busses/i2c-stm32f7.c | 265 +++--- + drivers/iio/adc/sd_adc_modulator.c | 89 +- + drivers/iio/adc/stm32-adc-core.c | 208 ++++- + drivers/iio/adc/stm32-adc-core.h | 90 ++ + drivers/iio/adc/stm32-adc.c | 861 ++++++++++++++++-- drivers/iio/adc/stm32-dfsdm-adc.c | 108 ++- - drivers/iio/adc/stm32-dfsdm-core.c | 91 ++- + drivers/iio/adc/stm32-dfsdm-core.c | 91 +- drivers/iio/adc/stm32-dfsdm.h | 69 +- - drivers/irqchip/irq-stm32-exti.c | 146 +++- - 12 files changed, 1482 insertions(+), 267 deletions(-) + drivers/irqchip/irq-stm32-exti.c | 427 ++++++--- + include/linux/irqdomain.h | 4 + + kernel/irq/irqdomain.c | 6 +- + 14 files changed, 1965 insertions(+), 433 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml -index d747f4990..5df3dbd60 100644 +index d747f4990ad8..5df3dbd6091f 100644 --- a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml @@ -17,6 +17,7 @@ allOf: @@ -40,7 +42,7 @@ index d747f4990..5df3dbd60 100644 reg: diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml -index a390343d0..bf5d71fb6 100644 +index a390343d0c2a..bf5d71fb60da 100644 --- a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml +++ b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml @@ -21,6 +21,9 @@ properties: @@ -54,7 +56,7 @@ index a390343d0..bf5d71fb6 100644 - compatible - '#io-channel-cells' diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml -index a58334c3b..0f1fce4c4 100644 +index a58334c3bb76..47883701e331 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml @@ -27,6 +27,7 @@ properties: @@ -202,7 +204,7 @@ index a58334c3b..0f1fce4c4 100644 + label: + description: | + Unique name to identify which channel this is. -+ Reserved label names "vddcore", "vrefint" and "vbat" ++ Reserved label names "vddcore", "vddcpu", "vddq_ddr", "vrefint" and "vbat" + are used to identify internal channels with matching names. + + diff-channels: @@ -321,7 +323,7 @@ index a58334c3b..0f1fce4c4 100644 + ... diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c -index 50d5ae81d..1225172c0 100644 +index 50d5ae81d227..791baea3623b 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -410,6 +410,12 @@ static const struct stm32f7_i2c_setup stm32mp15_setup = { @@ -365,7 +367,59 @@ index 50d5ae81d..1225172c0 100644 /* Disable interrupts */ stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_XFER_IRQ_MASK); -@@ -1521,7 +1528,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) +@@ -1492,17 +1499,11 @@ static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev) + static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) + { + struct stm32f7_i2c_dev *i2c_dev = data; +- struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; +- struct stm32_i2c_dma *dma = i2c_dev->dma; +- void __iomem *base = i2c_dev->base; +- u32 status, mask; +- int ret = IRQ_HANDLED; ++ u32 status; + +- /* Check if the interrupt if for a slave device */ +- if (!i2c_dev->master_mode) { +- ret = stm32f7_i2c_slave_isr_event(i2c_dev); +- return ret; +- } ++ /* Check if the interrupt is for a slave device */ ++ if (!i2c_dev->master_mode) ++ return IRQ_WAKE_THREAD; + + status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR); + +@@ -1514,6 +1515,29 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) + if (status & STM32F7_I2C_ISR_RXNE) + stm32f7_i2c_read_rx_data(i2c_dev); + ++ /* Wake up the thread if other flags are raised */ ++ if (status & ++ (STM32F7_I2C_ISR_NACKF | STM32F7_I2C_ISR_STOPF | ++ STM32F7_I2C_ISR_TC | STM32F7_I2C_ISR_TCR)) ++ return IRQ_WAKE_THREAD; ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) ++{ ++ struct stm32f7_i2c_dev *i2c_dev = data; ++ struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; ++ struct stm32_i2c_dma *dma = i2c_dev->dma; ++ void __iomem *base = i2c_dev->base; ++ u32 status, mask; ++ int ret; ++ ++ if (!i2c_dev->master_mode) ++ return stm32f7_i2c_slave_isr_event(i2c_dev); ++ ++ status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR); ++ + /* NACK received */ + if (status & STM32F7_I2C_ISR_NACKF) { + dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", +@@ -1521,38 +1545,33 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); if (i2c_dev->use_dma) { stm32f7_i2c_disable_dma_req(i2c_dev); @@ -374,16 +428,157 @@ index 50d5ae81d..1225172c0 100644 } f7_msg->result = -ENXIO; } -@@ -1588,7 +1595,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) - if (!ret) { - dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); - stm32f7_i2c_disable_dma_req(i2c_dev); -- dmaengine_terminate_all(dma->chan_using); -+ dmaengine_terminate_async(dma->chan_using); - f7_msg->result = -ETIMEDOUT; + +- /* STOP detection flag */ +- if (status & STM32F7_I2C_ISR_STOPF) { +- /* Disable interrupts */ +- if (stm32f7_i2c_is_slave_registered(i2c_dev)) +- mask = STM32F7_I2C_XFER_IRQ_MASK; ++ if (status & STM32F7_I2C_ISR_TCR) { ++ if (f7_msg->smbus) ++ stm32f7_i2c_smbus_reload(i2c_dev); + else +- mask = STM32F7_I2C_ALL_IRQ_MASK; +- stm32f7_i2c_disable_irq(i2c_dev, mask); +- +- /* Clear STOP flag */ +- writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR); +- +- if (i2c_dev->use_dma && !f7_msg->result) { +- ret = IRQ_WAKE_THREAD; +- } else { +- i2c_dev->master_mode = false; +- complete(&i2c_dev->complete); +- } ++ stm32f7_i2c_reload(i2c_dev); } -@@ -1665,7 +1672,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) + /* Transfer complete */ + if (status & STM32F7_I2C_ISR_TC) { ++ /* Wait for dma transfer completion before sending next message */ ++ if (i2c_dev->use_dma && !f7_msg->result) { ++ ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ); ++ if (!ret) { ++ dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); ++ stm32f7_i2c_disable_dma_req(i2c_dev); ++ dmaengine_terminate_async(dma->chan_using); ++ f7_msg->result = -ETIMEDOUT; ++ } ++ } + if (f7_msg->stop) { + mask = STM32F7_I2C_CR2_STOP; + stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask); +- } else if (i2c_dev->use_dma && !f7_msg->result) { +- ret = IRQ_WAKE_THREAD; + } else if (f7_msg->smbus) { + stm32f7_i2c_smbus_rep_start(i2c_dev); + } else { +@@ -1562,47 +1581,18 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) + } + } + +- if (status & STM32F7_I2C_ISR_TCR) { +- if (f7_msg->smbus) +- stm32f7_i2c_smbus_reload(i2c_dev); ++ /* STOP detection flag */ ++ if (status & STM32F7_I2C_ISR_STOPF) { ++ /* Disable interrupts */ ++ if (stm32f7_i2c_is_slave_registered(i2c_dev)) ++ mask = STM32F7_I2C_XFER_IRQ_MASK; + else +- stm32f7_i2c_reload(i2c_dev); +- } +- +- return ret; +-} +- +-static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) +-{ +- struct stm32f7_i2c_dev *i2c_dev = data; +- struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; +- struct stm32_i2c_dma *dma = i2c_dev->dma; +- u32 status; +- int ret; +- +- /* +- * Wait for dma transfer completion before sending next message or +- * notity the end of xfer to the client +- */ +- ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ); +- if (!ret) { +- dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); +- stm32f7_i2c_disable_dma_req(i2c_dev); +- dmaengine_terminate_all(dma->chan_using); +- f7_msg->result = -ETIMEDOUT; +- } ++ mask = STM32F7_I2C_ALL_IRQ_MASK; ++ stm32f7_i2c_disable_irq(i2c_dev, mask); + +- status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR); ++ /* Clear STOP flag */ ++ writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR); + +- if (status & STM32F7_I2C_ISR_TC) { +- if (f7_msg->smbus) { +- stm32f7_i2c_smbus_rep_start(i2c_dev); +- } else { +- i2c_dev->msg_id++; +- i2c_dev->msg++; +- stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg); +- } +- } else { + i2c_dev->master_mode = false; + complete(&i2c_dev->complete); + } +@@ -1610,10 +1600,11 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) + return IRQ_HANDLED; + } + +-static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) ++static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data) + { + struct stm32f7_i2c_dev *i2c_dev = data; + struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; ++ u16 addr = f7_msg->addr; + void __iomem *base = i2c_dev->base; + struct device *dev = i2c_dev->dev; + struct stm32_i2c_dma *dma = i2c_dev->dma; +@@ -1623,8 +1614,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) + + /* Bus error */ + if (status & STM32F7_I2C_ISR_BERR) { +- dev_err(dev, "<%s>: Bus error accessing addr 0x%x\n", +- __func__, f7_msg->addr); ++ dev_err(dev, "Bus error accessing addr 0x%x\n", addr); + writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR); + stm32f7_i2c_release_bus(&i2c_dev->adap); + f7_msg->result = -EIO; +@@ -1632,21 +1622,19 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) + + /* Arbitration loss */ + if (status & STM32F7_I2C_ISR_ARLO) { +- dev_dbg(dev, "<%s>: Arbitration loss accessing addr 0x%x\n", +- __func__, f7_msg->addr); ++ dev_dbg(dev, "Arbitration loss accessing addr 0x%x\n", addr); + writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR); + f7_msg->result = -EAGAIN; + } + + if (status & STM32F7_I2C_ISR_PECERR) { +- dev_err(dev, "<%s>: PEC error in reception accessing addr 0x%x\n", +- __func__, f7_msg->addr); ++ dev_err(dev, "PEC error in reception accessing addr 0x%x\n", addr); + writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR); + f7_msg->result = -EINVAL; + } + + if (status & STM32F7_I2C_ISR_ALERT) { +- dev_dbg(dev, "<%s>: SMBus alert received\n", __func__); ++ dev_dbg(dev, "SMBus alert received\n"); + writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR); + i2c_handle_smbus_alert(i2c_dev->alert->ara); + return IRQ_HANDLED; +@@ -1665,7 +1653,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) /* Disable dma */ if (i2c_dev->use_dma) { stm32f7_i2c_disable_dma_req(i2c_dev); @@ -392,7 +587,7 @@ index 50d5ae81d..1225172c0 100644 } i2c_dev->master_mode = false; -@@ -1702,6 +1709,9 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, +@@ -1702,6 +1690,9 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, i2c_dev->adap.timeout); ret = f7_msg->result; if (ret) { @@ -402,7 +597,7 @@ index 50d5ae81d..1225172c0 100644 /* * It is possible that some unsent data have already been * written into TXDR. To avoid sending old data in a -@@ -1716,7 +1726,7 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, +@@ -1716,7 +1707,7 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n", i2c_dev->msg->addr); if (i2c_dev->use_dma) @@ -411,7 +606,7 @@ index 50d5ae81d..1225172c0 100644 stm32f7_i2c_wait_free_bus(i2c_dev); ret = -ETIMEDOUT; } -@@ -1761,6 +1771,9 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, +@@ -1761,6 +1752,9 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, i2c_dev->adap.timeout); ret = f7_msg->result; if (ret) { @@ -421,7 +616,7 @@ index 50d5ae81d..1225172c0 100644 /* * It is possible that some unsent data have already been * written into TXDR. To avoid sending old data in a -@@ -1774,7 +1787,7 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, +@@ -1774,7 +1768,7 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, if (!timeout) { dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr); if (i2c_dev->use_dma) @@ -430,7 +625,21 @@ index 50d5ae81d..1225172c0 100644 stm32f7_i2c_wait_free_bus(i2c_dev); ret = -ETIMEDOUT; goto pm_free; -@@ -2343,63 +2356,23 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) +@@ -2163,8 +2157,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) + goto clk_free; + } + +- ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0, +- pdev->name, i2c_dev); ++ ret = devm_request_threaded_irq(&pdev->dev, irq_error, ++ NULL, ++ stm32f7_i2c_isr_error_thread, ++ IRQF_ONESHOT, ++ pdev->name, i2c_dev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq error %i\n", + irq_error); +@@ -2343,63 +2340,23 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) return 0; } @@ -445,8 +654,7 @@ index 50d5ae81d..1225172c0 100644 -} - -static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev) -+static void __maybe_unused stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) - { +-{ - struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); - int ret; - @@ -462,7 +670,8 @@ index 50d5ae81d..1225172c0 100644 -} - -static int __maybe_unused stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) --{ ++static void __maybe_unused stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) + { - int ret; struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs; @@ -496,7 +705,7 @@ index 50d5ae81d..1225172c0 100644 cr1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR1); if (cr1 & STM32F7_I2C_CR1_PE) stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, -@@ -2415,29 +2388,48 @@ static int __maybe_unused stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_d +@@ -2415,29 +2372,48 @@ static int __maybe_unused stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_d writel_relaxed(backup_regs->oar1, i2c_dev->base + STM32F7_I2C_OAR1); writel_relaxed(backup_regs->oar2, i2c_dev->base + STM32F7_I2C_OAR2); stm32f7_i2c_write_fm_plus_bits(i2c_dev, true); @@ -556,7 +765,7 @@ index 50d5ae81d..1225172c0 100644 return 0; } -@@ -2447,16 +2439,12 @@ static int __maybe_unused stm32f7_i2c_resume(struct device *dev) +@@ -2447,16 +2423,12 @@ static int __maybe_unused stm32f7_i2c_resume(struct device *dev) struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); int ret; @@ -578,7 +787,7 @@ index 50d5ae81d..1225172c0 100644 i2c_mark_adapter_resumed(&i2c_dev->adap); -@@ -2472,6 +2460,7 @@ static const struct dev_pm_ops stm32f7_i2c_pm_ops = { +@@ -2472,6 +2444,7 @@ static const struct dev_pm_ops stm32f7_i2c_pm_ops = { static const struct of_device_id stm32f7_i2c_match[] = { { .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup}, { .compatible = "st,stm32mp15-i2c", .data = &stm32mp15_setup}, @@ -587,7 +796,7 @@ index 50d5ae81d..1225172c0 100644 }; MODULE_DEVICE_TABLE(of, stm32f7_i2c_match); diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c -index 327cc2097..ceb150296 100644 +index 327cc2097f6c..ceb15029673c 100644 --- a/drivers/iio/adc/sd_adc_modulator.c +++ b/drivers/iio/adc/sd_adc_modulator.c @@ -9,10 +9,8 @@ @@ -713,7 +922,7 @@ index 327cc2097..ceb150296 100644 static struct platform_driver iio_sd_mod_adc = { diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c -index c088cb990..77ac38ae8 100644 +index 42faca457ace..0f4a5dddb892 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -9,6 +9,7 @@ @@ -739,15 +948,16 @@ index c088cb990..77ac38ae8 100644 + * @ipid: adc identification number * @has_syscfg: SYSCFG capability flags * @num_irqs: number of interrupt lines - */ -@@ -69,13 +72,17 @@ struct stm32_adc_priv_cfg { + * @num_adcs: maximum number of ADC instances in the common registers +@@ -70,6 +73,7 @@ struct stm32_adc_priv_cfg { const struct stm32_adc_common_regs *regs; int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); u32 max_clk_rate_hz; + u32 ipid; unsigned int has_syscfg; unsigned int num_irqs; - }; + unsigned int num_adcs; +@@ -77,7 +81,10 @@ struct stm32_adc_priv_cfg { /** * struct stm32_adc_priv - stm32 ADC core private data @@ -758,7 +968,7 @@ index c088cb990..77ac38ae8 100644 * @domain: irq domain reference * @aclk: clock reference for the analog circuitry * @bclk: bus clock common for all ADCs, depends on part used -@@ -92,7 +99,10 @@ struct stm32_adc_priv_cfg { +@@ -94,7 +101,10 @@ struct stm32_adc_priv_cfg { * @syscfg: reference to syscon, system control registers */ struct stm32_adc_priv { @@ -769,7 +979,7 @@ index c088cb990..77ac38ae8 100644 struct irq_domain *domain; struct clk *aclk; struct clk *bclk; -@@ -315,6 +325,16 @@ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { +@@ -317,6 +327,16 @@ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { .eocie_msk = STM32H7_EOCIE, }; @@ -786,11 +996,11 @@ index c088cb990..77ac38ae8 100644 static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = { 0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2, }; -@@ -352,34 +372,94 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) +@@ -354,34 +374,94 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) * before invoking the interrupt handler (e.g. call ISR only for * IRQ-enabled ADCs). */ -- for (i = 0; i < priv->cfg->num_irqs; i++) { +- for (i = 0; i < priv->cfg->num_adcs; i++) { + for (i = 0; i < priv->nb_adc_max; i++) { if ((status & priv->cfg->regs->eoc_msk[i] && stm32_adc_eoc_enabled(priv, i)) || @@ -829,7 +1039,9 @@ index c088cb990..77ac38ae8 100644 + +static int stm32_adc_core_domain_alloc(struct irq_domain *dm, unsigned int virq, + unsigned int nr_irqs, void *data) -+{ + { +- irq_set_chip_and_handler(irq, NULL, NULL); +- irq_set_chip_data(irq, NULL); + irq_hw_number_t hwirq; + struct stm32_adc_priv *priv = dm->host_data; + struct irq_fwspec *fwspec = data; @@ -870,9 +1082,7 @@ index c088cb990..77ac38ae8 100644 + +static void stm32_adc_core_domain_free(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs) - { -- irq_set_chip_and_handler(irq, NULL, NULL); -- irq_set_chip_data(irq, NULL); ++{ + struct irq_data *irq_data; + + irq_set_chip_and_handler(virq, NULL, NULL); @@ -893,7 +1103,7 @@ index c088cb990..77ac38ae8 100644 .xlate = irq_domain_xlate_onecell, }; -@@ -387,22 +467,49 @@ static int stm32_adc_irq_probe(struct platform_device *pdev, +@@ -389,22 +469,49 @@ static int stm32_adc_irq_probe(struct platform_device *pdev, struct stm32_adc_priv *priv) { struct device_node *np = pdev->dev.of_node; @@ -947,7 +1157,7 @@ index c088cb990..77ac38ae8 100644 if (!priv->domain) { dev_err(&pdev->dev, "Failed to add irq domain\n"); return -ENOMEM; -@@ -422,12 +529,14 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, +@@ -424,12 +531,14 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, int hwirq; unsigned int i; @@ -964,7 +1174,7 @@ index c088cb990..77ac38ae8 100644 } static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv, -@@ -640,6 +749,49 @@ static int stm32_adc_core_switches_probe(struct device *dev, +@@ -642,6 +751,49 @@ static int stm32_adc_core_switches_probe(struct device *dev, return 0; } @@ -1014,19 +1224,19 @@ index c088cb990..77ac38ae8 100644 static int stm32_adc_probe(struct platform_device *pdev) { struct stm32_adc_priv *priv; -@@ -657,8 +809,11 @@ static int stm32_adc_probe(struct platform_device *pdev) +@@ -659,8 +811,11 @@ static int stm32_adc_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, &priv->common); + priv->dev = dev; -+ priv->nb_adc_max = STM32_ADC_MAX_ADCS; priv->cfg = (const struct stm32_adc_priv_cfg *) of_match_device(dev->driver->of_match_table, dev)->data; ++ priv->nb_adc_max = priv->cfg->num_adcs; + spin_lock_init(&priv->common.lock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->common.base = devm_ioremap_resource(&pdev->dev, res); -@@ -700,6 +855,10 @@ static int stm32_adc_probe(struct platform_device *pdev) +@@ -702,6 +857,10 @@ static int stm32_adc_probe(struct platform_device *pdev) if (ret) goto err_pm_stop; @@ -1037,29 +1247,25 @@ index c088cb990..77ac38ae8 100644 ret = regulator_get_voltage(priv->vref); if (ret < 0) { dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret); -@@ -809,11 +968,20 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { - static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { - .regs = &stm32h7_adc_common_regs, +@@ -815,8 +974,16 @@ static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { .clk_sel = stm32h7_adc_clk_sel, -- .max_clk_rate_hz = 40000000, -+ .max_clk_rate_hz = 36000000, + .max_clk_rate_hz = 36000000, .has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD, + .ipid = STM32MP15_IPIDR_NUMBER, .num_irqs = 2, - }; - +- .num_adcs = 2, ++}; ++ +static const struct stm32_adc_priv_cfg stm32mp13_adc_priv_cfg = { + .regs = &stm32mp13_adc_common_regs, + .clk_sel = stm32h7_adc_clk_sel, + .max_clk_rate_hz = 75000000, + .ipid = STM32MP13_IPIDR_NUMBER, + .num_irqs = 1, -+}; -+ + }; + static const struct of_device_id stm32_adc_of_match[] = { - { - .compatible = "st,stm32f4-adc-core", -@@ -824,6 +992,9 @@ static const struct of_device_id stm32_adc_of_match[] = { +@@ -829,6 +996,9 @@ static const struct of_device_id stm32_adc_of_match[] = { }, { .compatible = "st,stm32mp1-adc-core", .data = (void *)&stm32mp1_adc_priv_cfg @@ -1070,7 +1276,7 @@ index c088cb990..77ac38ae8 100644 }, }; diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h -index 2322809bf..e94c3df10 100644 +index 2322809bfd2f..850d98949827 100644 --- a/drivers/iio/adc/stm32-adc-core.h +++ b/drivers/iio/adc/stm32-adc-core.h @@ -24,6 +24,7 @@ @@ -1081,7 +1287,15 @@ index 2322809bf..e94c3df10 100644 #define STM32_ADC_MAX_ADCS 3 #define STM32_ADC_OFFSET 0x100 #define STM32_ADCX_COMN_OFFSET 0x300 -@@ -102,6 +103,12 @@ +@@ -90,6 +91,7 @@ + #define STM32H7_ADC_IER 0x04 + #define STM32H7_ADC_CR 0x08 + #define STM32H7_ADC_CFGR 0x0C ++#define STM32H7_ADC_CFGR2 0x10 + #define STM32H7_ADC_SMPR1 0x14 + #define STM32H7_ADC_SMPR2 0x18 + #define STM32H7_ADC_PCSEL 0x1C +@@ -102,6 +104,12 @@ #define STM32H7_ADC_CALFACT 0xC4 #define STM32H7_ADC_CALFACT2 0xC8 @@ -1094,7 +1308,7 @@ index 2322809bf..e94c3df10 100644 /* STM32H7 - common registers for all ADC instances */ #define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00) #define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08) -@@ -127,6 +134,7 @@ +@@ -127,6 +135,7 @@ #define STM32H7_LINCALRDYW3 BIT(24) #define STM32H7_LINCALRDYW2 BIT(23) #define STM32H7_LINCALRDYW1 BIT(22) @@ -1102,7 +1316,22 @@ index 2322809bf..e94c3df10 100644 #define STM32H7_ADCALLIN BIT(16) #define STM32H7_BOOST BIT(8) #define STM32H7_ADSTP BIT(4) -@@ -151,6 +159,10 @@ enum stm32h7_adc_dmngt { +@@ -144,6 +153,14 @@ + #define STM32H7_DMNGT_SHIFT 0 + #define STM32H7_DMNGT_MASK GENMASK(1, 0) + ++/* STM32H7_ADC_CFGR2 bit fields */ ++#define STM32H7_OVSR_SHIFT 16 /* Correspond to OSVR field in datasheet */ ++#define STM32H7_OVSR_MASK GENMASK(25, 16) ++#define STM32H7_OVSR_BITS 10 ++#define STM32H7_OVSS_SHIFT 5 ++#define STM32H7_OVSS_MASK GENMASK(8, 5) ++#define STM32H7_ROVSE BIT(0) ++ + enum stm32h7_adc_dmngt { + STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */ + STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */ +@@ -151,6 +168,10 @@ enum stm32h7_adc_dmngt { STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */ }; @@ -1113,7 +1342,7 @@ index 2322809bf..e94c3df10 100644 /* STM32H7_ADC_CALFACT - bit fields */ #define STM32H7_CALFACT_D_SHIFT 16 #define STM32H7_CALFACT_D_MASK GENMASK(26, 16) -@@ -168,23 +180,83 @@ enum stm32h7_adc_dmngt { +@@ -168,23 +189,92 @@ enum stm32h7_adc_dmngt { #define STM32H7_EOC_MST BIT(2) /* STM32H7_ADC_CCR - bit fields */ @@ -1142,6 +1371,13 @@ index 2322809bf..e94c3df10 100644 +#define STM32MP13_RES_SHIFT 3 +#define STM32MP13_RES_MASK GENMASK(4, 3) + ++/* STM32MP13_ADC_CFGR2 bit fields */ ++#define STM32MP13_OVSR_SHIFT 2 ++#define STM32MP13_OVSR_MASK GENMASK(4, 2) ++#define STM32MP13_OVSR_BITS 3 ++#define STM32MP13_OVSS_SHIFT 5 ++#define STM32MP13_OVSS_MASK GENMASK(8, 5) ++ +/* STM32MP13_ADC_DIFSEL - bit fields */ +#define STM32MP13_DIFSEL_SHIFT 0 +#define STM32MP13_DIFSEL_MASK GENMASK(18, 0) @@ -1153,7 +1389,9 @@ index 2322809bf..e94c3df10 100644 +#define STM32MP13_CALFACT_S_MASK GENMASK(6, 0) + +/* STM32MP13_ADC2_OR - bit fields */ -+#define STM32MP13_VDDCOREEN BIT(0) ++#define STM32MP13_OP2 BIT(2) ++#define STM32MP13_OP1 BIT(1) ++#define STM32MP13_OP0 BIT(0) + +/* STM32MP13_ADC_HWCFGR0 - bit fields */ +#define STM32MP13_ADCNUM_SHIFT 0 @@ -1198,18 +1436,26 @@ index 2322809bf..e94c3df10 100644 #endif diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c -index e3e75413b..d4492ce0d 100644 +index ef5b54ed9661..d05e081e1009 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c -@@ -7,6 +7,7 @@ +@@ -6,12 +6,15 @@ + * Author: Fabrice Gasnier . */ ++#include #include +#include #include #include #include -@@ -21,6 +22,7 @@ + #include + #include ++#include + #include + #include + #include +@@ -21,10 +24,12 @@ #include #include #include @@ -1217,7 +1463,12 @@ index e3e75413b..d4492ce0d 100644 #include #include #include -@@ -35,12 +37,13 @@ + #include ++#include + + #include "stm32-adc-core.h" + +@@ -35,12 +40,13 @@ #define STM32H7_BOOST_CLKRATE 20000000UL #define STM32_ADC_CH_MAX 20 /* max number of channels */ @@ -1232,13 +1483,15 @@ index e3e75413b..d4492ce0d 100644 #define STM32_DMA_BUFFER_SIZE PAGE_SIZE -@@ -77,6 +80,30 @@ enum stm32_adc_extsel { +@@ -77,6 +83,34 @@ enum stm32_adc_extsel { STM32_EXT20, }; +enum stm32_adc_int_ch { + STM32_ADC_INT_CH_NONE = -1, + STM32_ADC_INT_CH_VDDCORE, ++ STM32_ADC_INT_CH_VDDCPU, ++ STM32_ADC_INT_CH_VDDQ_DDR, + STM32_ADC_INT_CH_VREFINT, + STM32_ADC_INT_CH_VBAT, + STM32_ADC_INT_CH_NB, @@ -1256,6 +1509,8 @@ index e3e75413b..d4492ce0d 100644 + +static const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = { + { "vddcore", STM32_ADC_INT_CH_VDDCORE }, ++ { "vddcpu", STM32_ADC_INT_CH_VDDCPU }, ++ { "vddq_ddr", STM32_ADC_INT_CH_VDDQ_DDR }, + { "vrefint", STM32_ADC_INT_CH_VREFINT }, + { "vbat", STM32_ADC_INT_CH_VBAT }, +}; @@ -1263,7 +1518,7 @@ index e3e75413b..d4492ce0d 100644 /** * struct stm32_adc_trig_info - ADC trigger info * @name: name of the trigger, corresponding to its source -@@ -89,16 +116,12 @@ struct stm32_adc_trig_info { +@@ -89,16 +123,12 @@ struct stm32_adc_trig_info { /** * struct stm32_adc_calib - optional adc calibration data @@ -1282,7 +1537,7 @@ index e3e75413b..d4492ce0d 100644 }; /** -@@ -113,6 +136,16 @@ struct stm32_adc_regs { +@@ -113,6 +143,16 @@ struct stm32_adc_regs { int shift; }; @@ -1299,67 +1554,75 @@ index e3e75413b..d4492ce0d 100644 /** * struct stm32_adc_regspec - stm32 registers definition * @dr: data register offset -@@ -124,8 +157,12 @@ struct stm32_adc_regs { +@@ -124,8 +164,14 @@ struct stm32_adc_regs { * @exten: trigger control register & bitfield * @extsel: trigger selection register & bitfield * @res: resolution selection register & bitfield + * @difsel: differential mode selection register & bitfield * @smpr: smpr1 & smpr2 registers offset array * @smp_bits: smpr1 & smpr2 index and bitfields -+ * @or_vdd: option register & vddcore bitfield ++ * @or_vddcore: option register & vddcore bitfield ++ * @or_vddcpu: option register & vddcpu bitfield ++ * @or_vddq_ddr: option register & vddq_ddr bitfield + * @ccr_vbat: common register & vbat bitfield + * @ccr_vref: common register & vrefint bitfield */ struct stm32_adc_regspec { const u32 dr; -@@ -137,8 +174,12 @@ struct stm32_adc_regspec { +@@ -137,8 +183,14 @@ struct stm32_adc_regspec { const struct stm32_adc_regs exten; const struct stm32_adc_regs extsel; const struct stm32_adc_regs res; + const struct stm32_adc_regs difsel; const u32 smpr[2]; const struct stm32_adc_regs *smp_bits; -+ const struct stm32_adc_regs or_vdd; ++ const struct stm32_adc_regs or_vddcore; ++ const struct stm32_adc_regs or_vddcpu; ++ const struct stm32_adc_regs or_vddq_ddr; + const struct stm32_adc_regs ccr_vbat; + const struct stm32_adc_regs ccr_vref; }; struct stm32_adc; -@@ -150,12 +191,16 @@ struct stm32_adc; +@@ -150,12 +202,18 @@ struct stm32_adc; * @trigs: external trigger sources * @clk_required: clock is required * @has_vregready: vregready status flag presence + * @has_boostmode: boost mode support flag + * @has_linearcal: linear calibration support flag + * @has_presel: channel preselection support flag ++ * @has_oversampling: oversampling support flag * @prepare: optional prepare routine (power-up, enable) * @start_conv: routine to start conversions * @stop_conv: routine to stop conversions * @unprepare: optional unprepare routine (disable, power-down) * @irq_clear: routine to clear irqs ++ * @set_ovs: routine to set oversampling configuration * @smp_cycles: programmable sampling time (ADC clock cycles) -+ * @ts_vrefint_ns: vrefint minimum sampling time in ns ++ * @ts_int_ch: pointer to array of internal channels minimum sampling time in ns */ struct stm32_adc_cfg { const struct stm32_adc_regspec *regs; -@@ -163,12 +208,16 @@ struct stm32_adc_cfg { +@@ -163,12 +221,18 @@ struct stm32_adc_cfg { struct stm32_adc_trig_info *trigs; bool clk_required; bool has_vregready; + bool has_boostmode; + bool has_linearcal; + bool has_presel; ++ bool has_oversampling; int (*prepare)(struct iio_dev *); void (*start_conv)(struct iio_dev *, bool dma); void (*stop_conv)(struct iio_dev *); void (*unprepare)(struct iio_dev *); void (*irq_clear)(struct iio_dev *indio_dev, u32 msk); ++ void (*set_ovs)(struct iio_dev *indio_dev, u32 ovs_idx); const unsigned int *smp_cycles; -+ const unsigned int ts_vrefint_ns; ++ const unsigned int *ts_int_ch; }; /** -@@ -193,7 +242,10 @@ struct stm32_adc_cfg { +@@ -193,7 +257,11 @@ struct stm32_adc_cfg { * @pcsel: bitmask to preselect channels on some devices * @smpr_val: sampling time settings (e.g. smpr1 / smpr2) * @cal: optional calibration data on some devices @@ -1367,10 +1630,11 @@ index e3e75413b..d4492ce0d 100644 * @chan_name: channel name array + * @num_diff: number of differential channels + * @int_ch: internal channel indexes array ++ * @ovs_idx: current oversampling ratio index (in oversampling array) */ struct stm32_adc { struct stm32_adc_common *common; -@@ -216,7 +268,10 @@ struct stm32_adc { +@@ -216,7 +284,11 @@ struct stm32_adc { u32 pcsel; u32 smpr_val[2]; struct stm32_adc_calib cal; @@ -1378,32 +1642,63 @@ index e3e75413b..d4492ce0d 100644 char chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ]; + u32 num_diff; + int int_ch[STM32_ADC_INT_CH_NB]; ++ int ovs_idx; }; struct stm32_adc_diff_channel { -@@ -260,6 +315,13 @@ static const struct stm32_adc_info stm32h7_adc_info = { - .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), +@@ -228,12 +300,24 @@ struct stm32_adc_diff_channel { + * struct stm32_adc_info - stm32 ADC, per instance config data + * @max_channels: Number of channels + * @resolutions: available resolutions ++ * @oversampling: available oversampling ratios + * @num_res: number of available resolutions ++ * @num_ovs: number of available oversampling ratios + */ + struct stm32_adc_info { + int max_channels; + const unsigned int *resolutions; ++ const unsigned int *oversampling; + const unsigned int num_res; ++ const unsigned int num_ovs; ++}; ++ ++static const unsigned int stm32h7_adc_oversampling_avail[] = { ++1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ++}; ++ ++static const unsigned int stm32mp13_adc_oversampling_avail[] = { ++1, 2, 4, 8, 16, 32, 64, 128, 256 }; + static const unsigned int stm32f4_adc_resolutions[] = { +@@ -257,7 +341,18 @@ static const unsigned int stm32h7_adc_resolutions[] = { + static const struct stm32_adc_info stm32h7_adc_info = { + .max_channels = STM32_ADC_CH_MAX, + .resolutions = stm32h7_adc_resolutions, ++ .oversampling = stm32h7_adc_oversampling_avail, + .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), ++ .num_ovs = ARRAY_SIZE(stm32h7_adc_oversampling_avail), ++}; ++ +/* stm32mp13 can have up to 19 channels */ +static const struct stm32_adc_info stm32mp13_adc_info = { + .max_channels = 19, + .resolutions = stm32f4_adc_resolutions, ++ .oversampling = stm32mp13_adc_oversampling_avail, + .num_res = ARRAY_SIZE(stm32f4_adc_resolutions), -+}; -+ ++ .num_ovs = ARRAY_SIZE(stm32mp13_adc_oversampling_avail), + }; + /* - * stm32f4_sq - describe regular sequence registers - * - L: sequence len (register & bit field) -@@ -445,8 +507,52 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = { +@@ -445,10 +540,56 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = { .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, STM32H7_EXTSEL_SHIFT }, .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT }, + .difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK}, -+ .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 }, -+ .smp_bits = stm32h7_smp_bits, -+}; -+ + .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 }, + .smp_bits = stm32h7_smp_bits, + }; + +/* STM32MP13 programmable sampling time (ADC clock cycles, rounded down) */ +static const unsigned int stm32mp13_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { + 2, 6, 12, 24, 47, 92, 247, 640, @@ -1423,7 +1718,9 @@ index e3e75413b..d4492ce0d 100644 + .difsel = { STM32MP13_ADC_DIFSEL, STM32MP13_DIFSEL_MASK}, + .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 }, + .smp_bits = stm32h7_smp_bits, -+ .or_vdd = { STM32MP13_ADC2_OR, STM32MP13_VDDCOREEN }, ++ .or_vddcore = { STM32MP13_ADC2_OR, STM32MP13_OP0 }, ++ .or_vddcpu = { STM32MP13_ADC2_OR, STM32MP13_OP1 }, ++ .or_vddq_ddr = { STM32MP13_ADC2_OR, STM32MP13_OP2 }, + .ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN }, + .ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN }, +}; @@ -1440,15 +1737,17 @@ index e3e75413b..d4492ce0d 100644 + STM32H7_EXTSEL_SHIFT }, + .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT }, + .difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK}, - .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 }, - .smp_bits = stm32h7_smp_bits, -+ .or_vdd = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN }, ++ .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 }, ++ .smp_bits = stm32h7_smp_bits, ++ .or_vddcore = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN }, + .ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN }, + .ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN }, - }; - ++}; ++ /* -@@ -487,6 +593,14 @@ static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits) + * STM32 ADC registers access routines + * @adc: stm32 adc instance +@@ -487,6 +628,14 @@ static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits) spin_unlock_irqrestore(&adc->lock, flags); } @@ -1463,7 +1762,7 @@ index e3e75413b..d4492ce0d 100644 static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits) { unsigned long flags; -@@ -496,6 +610,14 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits) +@@ -496,6 +645,14 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits) spin_unlock_irqrestore(&adc->lock, flags); } @@ -1478,7 +1777,7 @@ index e3e75413b..d4492ce0d 100644 /** * stm32_adc_conv_irq_enable() - Enable end of conversion interrupt * @adc: stm32 adc instance -@@ -577,6 +699,60 @@ static int stm32_adc_hw_start(struct device *dev) +@@ -577,6 +734,78 @@ static int stm32_adc_hw_start(struct device *dev) return ret; } @@ -1494,8 +1793,18 @@ index e3e75413b..d4492ce0d 100644 + switch (i) { + case STM32_ADC_INT_CH_VDDCORE: + dev_dbg(&indio_dev->dev, "Enable VDDCore\n"); -+ stm32_adc_set_bits(adc, adc->cfg->regs->or_vdd.reg, -+ adc->cfg->regs->or_vdd.mask); ++ stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcore.reg, ++ adc->cfg->regs->or_vddcore.mask); ++ break; ++ case STM32_ADC_INT_CH_VDDCPU: ++ dev_dbg(&indio_dev->dev, "Enable VDDCPU\n"); ++ stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcpu.reg, ++ adc->cfg->regs->or_vddcpu.mask); ++ break; ++ case STM32_ADC_INT_CH_VDDQ_DDR: ++ dev_dbg(&indio_dev->dev, "Enable VDDQ_DDR\n"); ++ stm32_adc_set_bits(adc, adc->cfg->regs->or_vddq_ddr.reg, ++ adc->cfg->regs->or_vddq_ddr.mask); + break; + case STM32_ADC_INT_CH_VREFINT: + dev_dbg(&indio_dev->dev, "Enable VREFInt\n"); @@ -1521,8 +1830,16 @@ index e3e75413b..d4492ce0d 100644 + + switch (i) { + case STM32_ADC_INT_CH_VDDCORE: -+ stm32_adc_clr_bits(adc, adc->cfg->regs->or_vdd.reg, -+ adc->cfg->regs->or_vdd.mask); ++ stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcore.reg, ++ adc->cfg->regs->or_vddcore.mask); ++ break; ++ case STM32_ADC_INT_CH_VDDCPU: ++ stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcpu.reg, ++ adc->cfg->regs->or_vddcpu.mask); ++ break; ++ case STM32_ADC_INT_CH_VDDQ_DDR: ++ stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddq_ddr.reg, ++ adc->cfg->regs->or_vddq_ddr.mask); + break; + case STM32_ADC_INT_CH_VREFINT: + stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vref.reg, @@ -1539,7 +1856,7 @@ index e3e75413b..d4492ce0d 100644 /** * stm32f4_adc_start_conv() - Start conversions for regular channels. * @indio_dev: IIO device instance -@@ -661,6 +837,7 @@ static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev) +@@ -661,6 +890,7 @@ static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev) if (ret) dev_warn(&indio_dev->dev, "stop failed\n"); @@ -1547,7 +1864,7 @@ index e3e75413b..d4492ce0d 100644 stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK); } -@@ -671,6 +848,17 @@ static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk) +@@ -671,6 +901,55 @@ static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk) stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk); } @@ -1561,11 +1878,49 @@ index e3e75413b..d4492ce0d 100644 + + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART); +} ++ ++static void stm32h7_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx) ++{ ++ struct stm32_adc *adc = iio_priv(indio_dev); ++ u32 ovsr_bits, bits, msk = STM32H7_ROVSE; ++ ++ msk |= STM32H7_OVSR_MASK | STM32H7_OVSS_MASK; ++ stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk); ++ ++ if (!ovs_idx) ++ return; ++ ++ bits = STM32H7_ROVSE; ++ ovsr_bits = (1 << ovs_idx) - 1; ++ bits |= ovsr_bits << STM32H7_OVSR_SHIFT; ++ bits |= ovs_idx << STM32H7_OVSS_SHIFT; ++ ++ stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk); ++} ++ ++static void stm32mp13_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx) ++{ ++ struct stm32_adc *adc = iio_priv(indio_dev); ++ u32 bits, msk = STM32H7_ROVSE; ++ ++ msk |= STM32MP13_OVSR_MASK | STM32MP13_OVSS_MASK; ++ stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk); ++ ++ if (!ovs_idx) ++ return; ++ ++ bits = STM32H7_ROVSE; ++ if (ovs_idx - 1) ++ bits |= (ovs_idx - 1) << STM32MP13_OVSR_SHIFT; ++ bits |= ovs_idx << STM32MP13_OVSS_SHIFT; ++ ++ stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk); ++} + static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) { struct stm32_adc *adc = iio_priv(indio_dev); -@@ -681,7 +869,8 @@ static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) +@@ -681,7 +960,8 @@ static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD); stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN); @@ -1575,7 +1930,7 @@ index e3e75413b..d4492ce0d 100644 stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST); /* Wait for startup time */ -@@ -703,7 +892,8 @@ static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) +@@ -703,7 +983,8 @@ static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc) { @@ -1585,7 +1940,7 @@ index e3e75413b..d4492ce0d 100644 /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD); -@@ -738,6 +928,9 @@ static void stm32h7_adc_disable(struct iio_dev *indio_dev) +@@ -738,6 +1019,9 @@ static void stm32h7_adc_disable(struct iio_dev *indio_dev) int ret; u32 val; @@ -1595,7 +1950,7 @@ index e3e75413b..d4492ce0d 100644 /* Disable ADC and wait until it's effectively disabled */ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS); ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, -@@ -779,14 +972,7 @@ static int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev) +@@ -779,14 +1063,7 @@ static int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev) lincalrdyw_mask >>= 1; } @@ -1611,7 +1966,7 @@ index e3e75413b..d4492ce0d 100644 return 0; } -@@ -802,10 +988,6 @@ static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev) +@@ -802,10 +1079,6 @@ static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev) int i, ret; u32 lincalrdyw_mask, val; @@ -1622,7 +1977,7 @@ index e3e75413b..d4492ce0d 100644 lincalrdyw_mask = STM32H7_LINCALRDYW6; for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { /* -@@ -867,24 +1049,30 @@ static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev) +@@ -867,24 +1140,30 @@ static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev) /** * stm32h7_adc_selfcalib() - Procedure to calibrate ADC * @indio_dev: IIO device instance @@ -1659,7 +2014,7 @@ index e3e75413b..d4492ce0d 100644 /* Start calibration, then wait for completion */ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL); -@@ -892,7 +1080,7 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev) +@@ -892,7 +1171,7 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev) !(val & STM32H7_ADCAL), 100, STM32H7_ADC_CALIB_TIMEOUT_US); if (ret) { @@ -1668,7 +2023,7 @@ index e3e75413b..d4492ce0d 100644 goto out; } -@@ -902,24 +1090,50 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev) +@@ -902,24 +1181,50 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev) * - Linearity calibration (needs to be done only once for single/diff) * will run simultaneously with offset calibration. */ @@ -1724,7 +2079,7 @@ index e3e75413b..d4492ce0d 100644 /** * stm32h7_adc_prepare() - Leave power down mode to enable ADC. * @indio_dev: IIO device instance -@@ -934,37 +1148,48 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev) +@@ -934,37 +1239,48 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev) static int stm32h7_adc_prepare(struct iio_dev *indio_dev) { struct stm32_adc *adc = iio_priv(indio_dev); @@ -1786,7 +2141,7 @@ index e3e75413b..d4492ce0d 100644 pwr_dwn: stm32h7_adc_enter_pwr_down(adc); -@@ -975,8 +1200,10 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) +@@ -975,8 +1291,10 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) { struct stm32_adc *adc = iio_priv(indio_dev); @@ -1798,7 +2153,79 @@ index e3e75413b..d4492ce0d 100644 stm32h7_adc_enter_pwr_down(adc); } -@@ -1213,6 +1440,7 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, +@@ -1204,6 +1522,71 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, + return ret; + } + ++static int stm32_adc_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, ++ int val, int val2, long mask) ++{ ++ struct stm32_adc *adc = iio_priv(indio_dev); ++ struct device *dev = indio_dev->dev.parent; ++ int nb = adc->cfg->adc_info->num_ovs; ++ u32 idx; ++ int ret; ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ++ ret = iio_device_claim_direct_mode(indio_dev); ++ if (ret) ++ return ret; ++ ++ if (val2) { ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ for (idx = 0; idx < nb; idx++) ++ if (adc->cfg->adc_info->oversampling[idx] == val) ++ break; ++ ++ if (idx >= nb) { ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ ret = pm_runtime_resume_and_get(dev); ++ if (ret < 0) ++ goto err; ++ ++ adc->cfg->set_ovs(indio_dev, idx); ++ ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_put_autosuspend(dev); ++ ++ adc->ovs_idx = idx; ++ ++err: ++ iio_device_release_direct_mode(indio_dev); ++ ++ return ret; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int stm32_adc_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, ++ const int **vals, int *type, int *length, long m) ++{ ++ struct stm32_adc *adc = iio_priv(indio_dev); ++ ++ switch (m) { ++ case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ++ *type = IIO_VAL_INT; ++ *length = adc->cfg->adc_info->num_ovs; ++ *vals = adc->cfg->adc_info->oversampling; ++ return IIO_AVAIL_LIST; ++ default: ++ return -EINVAL; ++ } ++} ++ + static int stm32_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +@@ -1213,6 +1596,7 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: @@ -1806,7 +2233,7 @@ index e3e75413b..d4492ce0d 100644 ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; -@@ -1220,6 +1448,10 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, +@@ -1220,6 +1604,10 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, ret = stm32_adc_single_conv(indio_dev, chan, val); else ret = -EINVAL; @@ -1817,38 +2244,27 @@ index e3e75413b..d4492ce0d 100644 iio_device_release_direct_mode(indio_dev); return ret; -@@ -1259,7 +1491,6 @@ static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) - struct stm32_adc *adc = iio_priv(indio_dev); - const struct stm32_adc_regspec *regs = adc->cfg->regs; - u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); -- u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg); +@@ -1241,6 +1629,10 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, + *val = 0; + return IIO_VAL_INT; - /* Check ovr status right now, as ovr mask should be already disabled */ - if (status & regs->isr_ovr.mask) { -@@ -1274,11 +1505,6 @@ static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) - return IRQ_HANDLED; ++ case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ++ *val = adc->cfg->adc_info->oversampling[adc->ovs_idx]; ++ return IIO_VAL_INT; ++ + default: + return -EINVAL; } +@@ -1417,6 +1809,8 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev, -- if (!(status & mask)) -- dev_err_ratelimited(&indio_dev->dev, -- "Unexpected IRQ: IER=0x%08x, ISR=0x%08x\n", -- mask, status); -- - return IRQ_NONE; - } - -@@ -1288,10 +1514,6 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) - struct stm32_adc *adc = iio_priv(indio_dev); - const struct stm32_adc_regspec *regs = adc->cfg->regs; - u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); -- u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg); -- -- if (!(status & mask)) -- return IRQ_WAKE_THREAD; - - if (status & regs->isr_ovr.mask) { - /* -@@ -1628,6 +1850,23 @@ static const struct iio_chan_spec_ext_info stm32_adc_ext_info[] = { + static const struct iio_info stm32_adc_iio_info = { + .read_raw = stm32_adc_read_raw, ++ .write_raw = stm32_adc_write_raw, ++ .read_avail = stm32_adc_read_avail, + .validate_trigger = stm32_adc_validate_trigger, + .hwfifo_set_watermark = stm32_adc_set_watermark, + .update_scan_mode = stm32_adc_update_scan_mode, +@@ -1618,6 +2012,23 @@ static const struct iio_chan_spec_ext_info stm32_adc_ext_info[] = { {}, }; @@ -1872,21 +2288,24 @@ index e3e75413b..d4492ce0d 100644 static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev) { struct device_node *node = indio_dev->dev.of_node; -@@ -1658,6 +1897,13 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns) +@@ -1646,7 +2057,15 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns) + { + const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel]; u32 period_ns, shift = smpr->shift, mask = smpr->mask; - unsigned int smp, r = smpr->reg; - +- unsigned int smp, r = smpr->reg; ++ unsigned int i, smp, r = smpr->reg; ++ + /* -+ * For vrefint channel, ensure that the sampling time cannot ++ * For internal channels, ensure that the sampling time cannot + * be lower than the one specified in the datasheet + */ -+ if (channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT]) -+ smp_ns = max(smp_ns, adc->cfg->ts_vrefint_ns); -+ ++ for (i = 0; i < STM32_ADC_INT_CH_NB; i++) ++ if (channel == adc->int_ch[i] && adc->int_ch[i] != STM32_ADC_INT_CH_NONE) ++ smp_ns = max(smp_ns, adc->cfg->ts_int_ch[i]); + /* Determine sampling time (ADC clock cycles) */ period_ns = NSEC_PER_SEC / adc->common->rate; - for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++) -@@ -1689,7 +1935,10 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, +@@ -1679,9 +2098,16 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, chan->datasheet_name = name; chan->scan_index = scan_index; chan->indexed = 1; @@ -1897,8 +2316,14 @@ index e3e75413b..d4492ce0d 100644 + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET); ++ if (adc->cfg->has_oversampling) { ++ chan->info_mask_shared_by_all |= BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); ++ chan->info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); ++ } chan->scan_type.sign = 'u'; -@@ -1701,23 +1950,17 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, + chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res]; + chan->scan_type.storagebits = 16; +@@ -1691,23 +2117,17 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, adc->pcsel |= BIT(chan->channel); if (differential) { /* pre-build diff channels mask */ @@ -1925,7 +2350,7 @@ index e3e75413b..d4492ce0d 100644 ret = of_property_count_u32_elems(node, "st,adc-channels"); if (ret > adc_info->max_channels) { -@@ -1728,24 +1971,13 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) +@@ -1718,24 +2138,13 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) } ret = of_property_count_elems_of_size(node, "st,adc-diff-channels", @@ -1952,7 +2377,7 @@ index e3e75413b..d4492ce0d 100644 } /* Optional sample time is provided either for each, or all channels */ -@@ -1755,13 +1987,45 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) +@@ -1745,13 +2154,45 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) return -EINVAL; } @@ -2004,7 +2429,7 @@ index e3e75413b..d4492ce0d 100644 of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) { if (val >= adc_info->max_channels) { -@@ -1772,8 +2036,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) +@@ -1762,8 +2203,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) /* Channel can't be configured both as single-ended & diff */ for (i = 0; i < num_diff; i++) { if (val == diff[i].vinp) { @@ -2014,7 +2439,7 @@ index e3e75413b..d4492ce0d 100644 return -EINVAL; } } -@@ -1782,19 +2045,6 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) +@@ -1772,19 +2212,6 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) scan_index++; } @@ -2034,7 +2459,7 @@ index e3e75413b..d4492ce0d 100644 for (i = 0; i < scan_index; i++) { /* * Using of_property_read_u32_index(), smp value will only be -@@ -1802,12 +2052,185 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) +@@ -1792,12 +2219,215 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) * get either no value, 1 shared value for all indexes, or one * value per channel. */ @@ -2058,6 +2483,35 @@ index e3e75413b..d4492ce0d 100644 + + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { + if (!strncmp(stm32_adc_ic[i].name, ch_name, STM32_ADC_CH_SZ)) { ++ /* Check internal channel availability */ ++ switch (i) { ++ case STM32_ADC_INT_CH_VDDCORE: ++ if (!adc->cfg->regs->or_vddcore.reg) ++ dev_warn(&indio_dev->dev, ++ "%s channel not available\n", ch_name); ++ break; ++ case STM32_ADC_INT_CH_VDDCPU: ++ if (!adc->cfg->regs->or_vddcpu.reg) ++ dev_warn(&indio_dev->dev, ++ "%s channel not available\n", ch_name); ++ break; ++ case STM32_ADC_INT_CH_VDDQ_DDR: ++ if (!adc->cfg->regs->or_vddq_ddr.reg) ++ dev_warn(&indio_dev->dev, ++ "%s channel not available\n", ch_name); ++ break; ++ case STM32_ADC_INT_CH_VREFINT: ++ if (!adc->cfg->regs->ccr_vref.reg) ++ dev_warn(&indio_dev->dev, ++ "%s channel not available\n", ch_name); ++ break; ++ case STM32_ADC_INT_CH_VBAT: ++ if (!adc->cfg->regs->ccr_vbat.reg) ++ dev_warn(&indio_dev->dev, ++ "%s channel not available\n", ch_name); ++ break; ++ } ++ + if (stm32_adc_ic[i].idx != STM32_ADC_INT_CH_VREFINT) { + adc->int_ch[i] = chan; + break; @@ -2146,18 +2600,19 @@ index e3e75413b..d4492ce0d 100644 + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val, + vin[1], scan_index, differential); + ++ val = 0; + ret = of_property_read_u32(child, "st,min-sample-time-ns", &val); + /* st,min-sample-time-ns is optional */ -+ if (!ret) { -+ stm32_adc_smpr_init(adc, channels[scan_index].channel, val); -+ if (differential) -+ stm32_adc_smpr_init(adc, vin[1], val); -+ } else if (ret != -EINVAL) { ++ if (ret && ret != -EINVAL) { + dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n", + ret); + goto err; + } + ++ stm32_adc_smpr_init(adc, channels[scan_index].channel, val); ++ if (differential) ++ stm32_adc_smpr_init(adc, vin[1], val); ++ + scan_index++; + } + @@ -2222,7 +2677,7 @@ index e3e75413b..d4492ce0d 100644 if (timestamping) { struct iio_chan_spec *timestamp = &channels[scan_index]; -@@ -1982,6 +2405,9 @@ static int stm32_adc_probe(struct platform_device *pdev) +@@ -1972,6 +2602,9 @@ static int stm32_adc_probe(struct platform_device *pdev) pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -2232,7 +2687,7 @@ index e3e75413b..d4492ce0d 100644 return 0; err_hw_stop: -@@ -2010,6 +2436,7 @@ static int stm32_adc_remove(struct platform_device *pdev) +@@ -2000,6 +2633,7 @@ static int stm32_adc_remove(struct platform_device *pdev) struct stm32_adc *adc = iio_priv(indio_dev); pm_runtime_get_sync(&pdev->dev); @@ -2240,19 +2695,34 @@ index e3e75413b..d4492ce0d 100644 iio_device_unregister(indio_dev); stm32_adc_hw_stop(&pdev->dev); pm_runtime_disable(&pdev->dev); -@@ -2091,6 +2518,9 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { +@@ -2077,35 +2711,72 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = { + .irq_clear = stm32f4_adc_irq_clear, + }; + ++const unsigned int stm32_adc_min_ts_h7[] = { 0, 0, 0, 4300, 9000 }; ++static_assert(ARRAY_SIZE(stm32_adc_min_ts_h7) == STM32_ADC_INT_CH_NB); ++ + static const struct stm32_adc_cfg stm32h7_adc_cfg = { .regs = &stm32h7_adc_regspec, .adc_info = &stm32h7_adc_info, .trigs = stm32h7_adc_trigs, + .has_boostmode = true, + .has_linearcal = true, + .has_presel = true, ++ .has_oversampling = true, .start_conv = stm32h7_adc_start_conv, .stop_conv = stm32h7_adc_stop_conv, .prepare = stm32h7_adc_prepare, -@@ -2100,22 +2530,40 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { + .unprepare = stm32h7_adc_unprepare, + .smp_cycles = stm32h7_adc_smp_cycles, + .irq_clear = stm32h7_adc_irq_clear, ++ .set_ovs = stm32h7_adc_set_ovs, ++ .ts_int_ch = stm32_adc_min_ts_h7, }; ++const unsigned int stm32_adc_min_ts_mp1[] = { 100, 100, 100, 4300, 9800 }; ++static_assert(ARRAY_SIZE(stm32_adc_min_ts_mp1) == STM32_ADC_INT_CH_NB); ++ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { - .regs = &stm32h7_adc_regspec, + .regs = &stm32mp1_adc_regspec, @@ -2262,38 +2732,45 @@ index e3e75413b..d4492ce0d 100644 + .has_boostmode = true, + .has_linearcal = true, + .has_presel = true, ++ .has_oversampling = true, .start_conv = stm32h7_adc_start_conv, .stop_conv = stm32h7_adc_stop_conv, .prepare = stm32h7_adc_prepare, .unprepare = stm32h7_adc_unprepare, .smp_cycles = stm32h7_adc_smp_cycles, .irq_clear = stm32h7_adc_irq_clear, -+ .ts_vrefint_ns = 4300, ++ .set_ovs = stm32h7_adc_set_ovs, ++ .ts_int_ch = stm32_adc_min_ts_mp1, +}; + ++const unsigned int stm32_adc_min_ts_mp13[] = { 100, 0, 0, 4300, 9800 }; ++static_assert(ARRAY_SIZE(stm32_adc_min_ts_mp13) == STM32_ADC_INT_CH_NB); ++ +static const struct stm32_adc_cfg stm32mp13_adc_cfg = { + .regs = &stm32mp13_adc_regspec, + .adc_info = &stm32mp13_adc_info, + .trigs = stm32h7_adc_trigs, ++ .has_oversampling = true, + .start_conv = stm32mp13_adc_start_conv, + .stop_conv = stm32h7_adc_stop_conv, + .prepare = stm32h7_adc_prepare, + .unprepare = stm32h7_adc_unprepare, + .smp_cycles = stm32mp13_adc_smp_cycles, + .irq_clear = stm32h7_adc_irq_clear, ++ .set_ovs = stm32mp13_adc_set_ovs, ++ .ts_int_ch = stm32_adc_min_ts_mp13, }; static const struct of_device_id stm32_adc_of_match[] = { { .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg }, { .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg }, { .compatible = "st,stm32mp1-adc", .data = (void *)&stm32mp1_adc_cfg }, -+ { .compatible = "st,stm32mp13-adc", -+ .data = (void *)&stm32mp13_adc_cfg }, ++ { .compatible = "st,stm32mp13-adc", .data = (void *)&stm32mp13_adc_cfg }, {}, }; MODULE_DEVICE_TABLE(of, stm32_adc_of_match); diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c -index 1cfefb3b5..997f1f387 100644 +index 1cfefb3b5e56..997f1f387a04 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -10,6 +10,7 @@ @@ -2483,7 +2960,7 @@ index 1cfefb3b5..997f1f387 100644 static int stm32_dfsdm_adc_probe(struct platform_device *pdev) { diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c -index a627af9a8..65c01d522 100644 +index a627af9a825e..65c01d522ce3 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -6,6 +6,7 @@ @@ -2627,7 +3104,7 @@ index a627af9a8..65c01d522 100644 ret = stm32_dfsdm_clk_prepare_enable(dfsdm); diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h -index 4afc1f528..4f230e2a7 100644 +index 4afc1f528b78..4f230e2a7692 100644 --- a/drivers/iio/adc/stm32-dfsdm.h +++ b/drivers/iio/adc/stm32-dfsdm.h @@ -13,25 +13,28 @@ @@ -2714,10 +3191,91 @@ index 4afc1f528..4f230e2a7 100644 enum stm32_dfsdm_sinc_order { DFSDM_FASTSINC_ORDER, /* FastSinc filter type */ diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c -index 33c76710f..d99d4b4b0 100644 +index 33c76710f845..78bc38d1f5a9 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c -@@ -132,7 +132,6 @@ static const struct stm32_exti_drv_data stm32h7xx_drv_data = { +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -34,21 +35,15 @@ struct stm32_exti_bank { + u32 swier_ofst; + u32 rpr_ofst; + u32 fpr_ofst; ++ u32 trg_ofst; + }; + + #define UNDEF_REG ~0 + +-struct stm32_desc_irq { +- u32 exti; +- u32 irq_parent; +- struct irq_chip *chip; +-}; +- + struct stm32_exti_drv_data { + const struct stm32_exti_bank **exti_banks; +- const struct stm32_desc_irq *desc_irqs; ++ const u8 *desc_irqs; + u32 bank_nr; +- u32 irq_nr; + }; + + struct stm32_exti_chip_data { +@@ -62,13 +57,15 @@ struct stm32_exti_chip_data { + }; + + struct stm32_exti_host_data { ++ struct list_head lh; + void __iomem *base; + struct stm32_exti_chip_data *chips_data; + const struct stm32_exti_drv_data *drv_data; + struct hwspinlock *hwlock; ++ struct device_node *irq_map_node; + }; + +-static struct stm32_exti_host_data *stm32_host_data; ++static LIST_HEAD(stm32_host_data_list); + + static const struct stm32_exti_bank stm32f4xx_exti_b1 = { + .imr_ofst = 0x00, +@@ -78,6 +75,7 @@ static const struct stm32_exti_bank stm32f4xx_exti_b1 = { + .swier_ofst = 0x10, + .rpr_ofst = 0x14, + .fpr_ofst = UNDEF_REG, ++ .trg_ofst = UNDEF_REG, + }; + + static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = { +@@ -97,6 +95,7 @@ static const struct stm32_exti_bank stm32h7xx_exti_b1 = { + .swier_ofst = 0x08, + .rpr_ofst = 0x88, + .fpr_ofst = UNDEF_REG, ++ .trg_ofst = UNDEF_REG, + }; + + static const struct stm32_exti_bank stm32h7xx_exti_b2 = { +@@ -107,6 +106,7 @@ static const struct stm32_exti_bank stm32h7xx_exti_b2 = { + .swier_ofst = 0x28, + .rpr_ofst = 0x98, + .fpr_ofst = UNDEF_REG, ++ .trg_ofst = UNDEF_REG, + }; + + static const struct stm32_exti_bank stm32h7xx_exti_b3 = { +@@ -117,6 +117,7 @@ static const struct stm32_exti_bank stm32h7xx_exti_b3 = { + .swier_ofst = 0x48, + .rpr_ofst = 0xA8, + .fpr_ofst = UNDEF_REG, ++ .trg_ofst = UNDEF_REG, + }; + + static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = { +@@ -132,32 +133,32 @@ static const struct stm32_exti_drv_data stm32h7xx_drv_data = { static const struct stm32_exti_bank stm32mp1_exti_b1 = { .imr_ofst = 0x80, @@ -2725,7 +3283,10 @@ index 33c76710f..d99d4b4b0 100644 .rtsr_ofst = 0x00, .ftsr_ofst = 0x04, .swier_ofst = 0x08, -@@ -142,7 +141,6 @@ static const struct stm32_exti_bank stm32mp1_exti_b1 = { + .rpr_ofst = 0x0C, + .fpr_ofst = 0x10, ++ .trg_ofst = 0x3EC, + }; static const struct stm32_exti_bank stm32mp1_exti_b2 = { .imr_ofst = 0x90, @@ -2733,7 +3294,10 @@ index 33c76710f..d99d4b4b0 100644 .rtsr_ofst = 0x20, .ftsr_ofst = 0x24, .swier_ofst = 0x28, -@@ -152,7 +150,6 @@ static const struct stm32_exti_bank stm32mp1_exti_b2 = { + .rpr_ofst = 0x2C, + .fpr_ofst = 0x30, ++ .trg_ofst = 0x3E8, + }; static const struct stm32_exti_bank stm32mp1_exti_b3 = { .imr_ofst = 0xA0, @@ -2741,79 +3305,191 @@ index 33c76710f..d99d4b4b0 100644 .rtsr_ofst = 0x40, .ftsr_ofst = 0x44, .swier_ofst = 0x48, -@@ -201,6 +198,8 @@ static const struct stm32_desc_irq stm32mp1_desc_irq[] = { - { .exti = 31, .irq_parent = 53, .chip = &stm32_exti_h_chip_direct }, - { .exti = 32, .irq_parent = 82, .chip = &stm32_exti_h_chip_direct }, - { .exti = 33, .irq_parent = 83, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 43, .irq_parent = 75, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 44, .irq_parent = 98, .chip = &stm32_exti_h_chip_direct }, - { .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, - { .exti = 48, .irq_parent = 138, .chip = &stm32_exti_h_chip_direct }, - { .exti = 50, .irq_parent = 139, .chip = &stm32_exti_h_chip_direct }, -@@ -214,6 +213,48 @@ static const struct stm32_desc_irq stm32mp1_desc_irq[] = { - { .exti = 73, .irq_parent = 129, .chip = &stm32_exti_h_chip }, + .rpr_ofst = 0x4C, + .fpr_ofst = 0x50, ++ .trg_ofst = 0x3E4, }; -+static const struct stm32_desc_irq stm32mp13_desc_irq[] = { -+ { .exti = 0, .irq_parent = 6, .chip = &stm32_exti_h_chip }, -+ { .exti = 1, .irq_parent = 7, .chip = &stm32_exti_h_chip }, -+ { .exti = 2, .irq_parent = 8, .chip = &stm32_exti_h_chip }, -+ { .exti = 3, .irq_parent = 9, .chip = &stm32_exti_h_chip }, -+ { .exti = 4, .irq_parent = 10, .chip = &stm32_exti_h_chip }, -+ { .exti = 5, .irq_parent = 24, .chip = &stm32_exti_h_chip }, -+ { .exti = 6, .irq_parent = 65, .chip = &stm32_exti_h_chip }, -+ { .exti = 7, .irq_parent = 66, .chip = &stm32_exti_h_chip }, -+ { .exti = 8, .irq_parent = 67, .chip = &stm32_exti_h_chip }, -+ { .exti = 9, .irq_parent = 68, .chip = &stm32_exti_h_chip }, -+ { .exti = 10, .irq_parent = 41, .chip = &stm32_exti_h_chip }, -+ { .exti = 11, .irq_parent = 43, .chip = &stm32_exti_h_chip }, -+ { .exti = 12, .irq_parent = 77, .chip = &stm32_exti_h_chip }, -+ { .exti = 13, .irq_parent = 78, .chip = &stm32_exti_h_chip }, -+ { .exti = 14, .irq_parent = 106, .chip = &stm32_exti_h_chip }, -+ { .exti = 15, .irq_parent = 109, .chip = &stm32_exti_h_chip }, -+ { .exti = 16, .irq_parent = 1, .chip = &stm32_exti_h_chip }, -+ { .exti = 19, .irq_parent = 3, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 21, .irq_parent = 32, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 22, .irq_parent = 34, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 23, .irq_parent = 73, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 24, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 25, .irq_parent = 114, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 26, .irq_parent = 38, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 27, .irq_parent = 39, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 28, .irq_parent = 40, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 29, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 30, .irq_parent = 53, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 31, .irq_parent = 54, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 32, .irq_parent = 83, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 33, .irq_parent = 84, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 44, .irq_parent = 96, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 47, .irq_parent = 92, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 48, .irq_parent = 116, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 50, .irq_parent = 117, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 52, .irq_parent = 118, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 53, .irq_parent = 119, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 68, .irq_parent = 63, .chip = &stm32_exti_h_chip_direct }, -+ { .exti = 70, .irq_parent = 98, .chip = &stm32_exti_h_chip_direct }, + static const struct stm32_exti_bank *stm32mp1_exti_banks[] = { +@@ -169,76 +170,115 @@ static const struct stm32_exti_bank *stm32mp1_exti_banks[] = { + static struct irq_chip stm32_exti_h_chip; + static struct irq_chip stm32_exti_h_chip_direct; + +-static const struct stm32_desc_irq stm32mp1_desc_irq[] = { +- { .exti = 0, .irq_parent = 6, .chip = &stm32_exti_h_chip }, +- { .exti = 1, .irq_parent = 7, .chip = &stm32_exti_h_chip }, +- { .exti = 2, .irq_parent = 8, .chip = &stm32_exti_h_chip }, +- { .exti = 3, .irq_parent = 9, .chip = &stm32_exti_h_chip }, +- { .exti = 4, .irq_parent = 10, .chip = &stm32_exti_h_chip }, +- { .exti = 5, .irq_parent = 23, .chip = &stm32_exti_h_chip }, +- { .exti = 6, .irq_parent = 64, .chip = &stm32_exti_h_chip }, +- { .exti = 7, .irq_parent = 65, .chip = &stm32_exti_h_chip }, +- { .exti = 8, .irq_parent = 66, .chip = &stm32_exti_h_chip }, +- { .exti = 9, .irq_parent = 67, .chip = &stm32_exti_h_chip }, +- { .exti = 10, .irq_parent = 40, .chip = &stm32_exti_h_chip }, +- { .exti = 11, .irq_parent = 42, .chip = &stm32_exti_h_chip }, +- { .exti = 12, .irq_parent = 76, .chip = &stm32_exti_h_chip }, +- { .exti = 13, .irq_parent = 77, .chip = &stm32_exti_h_chip }, +- { .exti = 14, .irq_parent = 121, .chip = &stm32_exti_h_chip }, +- { .exti = 15, .irq_parent = 127, .chip = &stm32_exti_h_chip }, +- { .exti = 16, .irq_parent = 1, .chip = &stm32_exti_h_chip }, +- { .exti = 19, .irq_parent = 3, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 21, .irq_parent = 31, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 22, .irq_parent = 33, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 23, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 24, .irq_parent = 95, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 25, .irq_parent = 107, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 26, .irq_parent = 37, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 27, .irq_parent = 38, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 28, .irq_parent = 39, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 29, .irq_parent = 71, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 30, .irq_parent = 52, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 31, .irq_parent = 53, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 32, .irq_parent = 82, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 33, .irq_parent = 83, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 48, .irq_parent = 138, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 50, .irq_parent = 139, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 52, .irq_parent = 140, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 53, .irq_parent = 141, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 54, .irq_parent = 135, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 61, .irq_parent = 100, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 65, .irq_parent = 144, .chip = &stm32_exti_h_chip }, +- { .exti = 68, .irq_parent = 143, .chip = &stm32_exti_h_chip }, +- { .exti = 70, .irq_parent = 62, .chip = &stm32_exti_h_chip_direct }, +- { .exti = 73, .irq_parent = 129, .chip = &stm32_exti_h_chip }, ++#define EXTI_INVALID_IRQ U8_MAX ++#define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_BANK) ++ ++static const u8 stm32mp1_desc_irq[] = { ++ /* default value */ ++ [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, ++ ++ [0] = 6, ++ [1] = 7, ++ [2] = 8, ++ [3] = 9, ++ [4] = 10, ++ [5] = 23, ++ [6] = 64, ++ [7] = 65, ++ [8] = 66, ++ [9] = 67, ++ [10] = 40, ++ [11] = 42, ++ [12] = 76, ++ [13] = 77, ++ [14] = 121, ++ [15] = 127, ++ [16] = 1, ++ [19] = 3, ++ [21] = 31, ++ [22] = 33, ++ [23] = 72, ++ [24] = 95, ++ [25] = 107, ++ [26] = 37, ++ [27] = 38, ++ [28] = 39, ++ [29] = 71, ++ [30] = 52, ++ [31] = 53, ++ [32] = 82, ++ [33] = 83, ++ [43] = 75, ++ [44] = 98, ++ [47] = 93, ++ [48] = 138, ++ [50] = 139, ++ [52] = 140, ++ [53] = 141, ++ [54] = 135, ++ [61] = 100, ++ [65] = 144, ++ [68] = 143, ++ [70] = 62, ++ [73] = 129, +}; + ++static const u8 stm32mp13_desc_irq[] = { ++ /* default value */ ++ [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, ++ ++ [0] = 6, ++ [1] = 7, ++ [2] = 8, ++ [3] = 9, ++ [4] = 10, ++ [5] = 24, ++ [6] = 65, ++ [7] = 66, ++ [8] = 67, ++ [9] = 68, ++ [10] = 41, ++ [11] = 43, ++ [12] = 77, ++ [13] = 78, ++ [14] = 106, ++ [15] = 109, ++ [16] = 1, ++ [19] = 3, ++ [21] = 32, ++ [22] = 34, ++ [23] = 73, ++ [24] = 93, ++ [25] = 114, ++ [26] = 38, ++ [27] = 39, ++ [28] = 40, ++ [29] = 72, ++ [30] = 53, ++ [31] = 54, ++ [32] = 83, ++ [33] = 84, ++ [44] = 96, ++ [47] = 92, ++ [48] = 116, ++ [50] = 117, ++ [52] = 118, ++ [53] = 119, ++ [68] = 63, ++ [70] = 98, + }; + static const struct stm32_exti_drv_data stm32mp1_drv_data = { .exti_banks = stm32mp1_exti_banks, .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), -@@ -221,6 +262,13 @@ static const struct stm32_exti_drv_data stm32mp1_drv_data = { - .irq_nr = ARRAY_SIZE(stm32mp1_desc_irq), + .desc_irqs = stm32mp1_desc_irq, +- .irq_nr = ARRAY_SIZE(stm32mp1_desc_irq), }; +-static const struct +-stm32_desc_irq *stm32_exti_get_desc(const struct stm32_exti_drv_data *drv_data, +- irq_hw_number_t hwirq) +-{ +- const struct stm32_desc_irq *desc = NULL; +- int i; +- +- if (!drv_data->desc_irqs) +- return NULL; +- +- for (i = 0; i < drv_data->irq_nr; i++) { +- desc = &drv_data->desc_irqs[i]; +- if (desc->exti == hwirq) +- break; +- } +- +- return desc; +-} +static const struct stm32_exti_drv_data stm32mp13_drv_data = { + .exti_banks = stm32mp1_exti_banks, + .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), + .desc_irqs = stm32mp13_desc_irq, -+ .irq_nr = ARRAY_SIZE(stm32mp13_desc_irq), +}; -+ - static const struct - stm32_desc_irq *stm32_exti_get_desc(const struct stm32_exti_drv_data *drv_data, - irq_hw_number_t hwirq) -@@ -504,6 +552,16 @@ static void stm32_exti_h_unmask(struct irq_data *d) + + static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) + { +@@ -504,6 +544,16 @@ static void stm32_exti_h_unmask(struct irq_data *d) irq_chip_unmask_parent(d); } @@ -2830,7 +3506,7 @@ index 33c76710f..d99d4b4b0 100644 static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) { struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); -@@ -539,6 +597,9 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) +@@ -539,6 +589,9 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) unlock: raw_spin_unlock(&chip_data->rlock); @@ -2840,7 +3516,7 @@ index 33c76710f..d99d4b4b0 100644 return err; } -@@ -556,6 +617,9 @@ static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on) +@@ -556,6 +609,9 @@ static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on) raw_spin_unlock(&chip_data->rlock); @@ -2850,22 +3526,101 @@ index 33c76710f..d99d4b4b0 100644 return 0; } -@@ -565,7 +629,13 @@ static int stm32_exti_h_set_affinity(struct irq_data *d, +@@ -565,53 +621,74 @@ static int stm32_exti_h_set_affinity(struct irq_data *d, if (d->parent_data->chip) return irq_chip_set_affinity_parent(d, dest, force); - return -EINVAL; + return IRQ_SET_MASK_OK_DONE; -+} -+ + } + +-static int __maybe_unused stm32_exti_h_suspend(void) +static void stm32_exti_h_ack(struct irq_data *d) +{ + if (d->parent_data->chip) + irq_chip_ack_parent(d); ++} ++ ++static int stm32_exti_h_suspend(void) + { + struct stm32_exti_chip_data *chip_data; ++ struct stm32_exti_host_data *host_data; + int i; + +- for (i = 0; i < stm32_host_data->drv_data->bank_nr; i++) { +- chip_data = &stm32_host_data->chips_data[i]; +- raw_spin_lock(&chip_data->rlock); +- stm32_chip_suspend(chip_data, chip_data->wake_active); +- raw_spin_unlock(&chip_data->rlock); ++ list_for_each_entry(host_data, &stm32_host_data_list, lh) { ++ for (i = 0; i < host_data->drv_data->bank_nr; i++) { ++ chip_data = &host_data->chips_data[i]; ++ raw_spin_lock(&chip_data->rlock); ++ stm32_chip_suspend(chip_data, chip_data->wake_active); ++ raw_spin_unlock(&chip_data->rlock); ++ } + } + + return 0; } - static int __maybe_unused stm32_exti_h_suspend(void) -@@ -629,8 +699,11 @@ static int stm32_exti_h_retrigger(struct irq_data *d) +-static void __maybe_unused stm32_exti_h_resume(void) ++static void stm32_exti_h_resume(void) + { + struct stm32_exti_chip_data *chip_data; ++ struct stm32_exti_host_data *host_data; + int i; + +- for (i = 0; i < stm32_host_data->drv_data->bank_nr; i++) { +- chip_data = &stm32_host_data->chips_data[i]; +- raw_spin_lock(&chip_data->rlock); +- stm32_chip_resume(chip_data, chip_data->mask_cache); +- raw_spin_unlock(&chip_data->rlock); ++ list_for_each_entry(host_data, &stm32_host_data_list, lh) { ++ for (i = 0; i < host_data->drv_data->bank_nr; i++) { ++ chip_data = &host_data->chips_data[i]; ++ raw_spin_lock(&chip_data->rlock); ++ stm32_chip_resume(chip_data, chip_data->mask_cache); ++ raw_spin_unlock(&chip_data->rlock); ++ } + } + } + + static struct syscore_ops stm32_exti_h_syscore_ops = { +-#ifdef CONFIG_PM_SLEEP + .suspend = stm32_exti_h_suspend, + .resume = stm32_exti_h_resume, +-#endif + }; + + static void stm32_exti_h_syscore_init(struct stm32_exti_host_data *host_data) + { +- stm32_host_data = host_data; +- register_syscore_ops(&stm32_exti_h_syscore_ops); ++ if (IS_ENABLED(CONFIG_PM_SLEEP)) { ++ if (list_empty(&stm32_host_data_list)) ++ register_syscore_ops(&stm32_exti_h_syscore_ops); ++ ++ list_add_tail(&host_data->lh, &stm32_host_data_list); ++ } + } + +-static void stm32_exti_h_syscore_deinit(void) ++static void stm32_exti_h_syscore_deinit(struct platform_device *pdev) + { +- unregister_syscore_ops(&stm32_exti_h_syscore_ops); ++ struct stm32_exti_host_data *host_data = platform_get_drvdata(pdev); ++ ++ if (IS_ENABLED(CONFIG_PM_SLEEP)) { ++ list_del(&host_data->lh); ++ ++ if (list_empty(&stm32_host_data_list)) ++ unregister_syscore_ops(&stm32_exti_h_syscore_ops); ++ } + } + + static int stm32_exti_h_retrigger(struct irq_data *d) +@@ -629,8 +706,11 @@ static int stm32_exti_h_retrigger(struct irq_data *d) static struct irq_chip stm32_exti_h_chip = { .name = "stm32-exti-h", .irq_eoi = stm32_exti_h_eoi, @@ -2877,7 +3632,7 @@ index 33c76710f..d99d4b4b0 100644 .irq_retrigger = stm32_exti_h_retrigger, .irq_set_type = stm32_exti_h_set_type, .irq_set_wake = stm32_exti_h_set_wake, -@@ -642,8 +715,10 @@ static struct irq_chip stm32_exti_h_chip_direct = { +@@ -642,8 +722,10 @@ static struct irq_chip stm32_exti_h_chip_direct = { .name = "stm32-exti-h-direct", .irq_eoi = irq_chip_eoi_parent, .irq_ack = irq_chip_ack_parent, @@ -2890,41 +3645,134 @@ index 33c76710f..d99d4b4b0 100644 .irq_retrigger = irq_chip_retrigger_hierarchy, .irq_set_type = irq_chip_set_type_parent, .irq_set_wake = stm32_exti_h_set_wake, -@@ -674,14 +749,28 @@ static int stm32_exti_h_domain_alloc(struct irq_domain *dm, +@@ -651,34 +733,109 @@ static struct irq_chip stm32_exti_h_chip_direct = { + .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL, + }; - irq_domain_set_hwirq_and_chip(dm, virq, hwirq, desc->chip, - chip_data); ++static int stm32_exti_h_domain_match(struct irq_domain *dm, ++ struct device_node *node, ++ enum irq_domain_bus_token bus_token) ++{ ++ struct stm32_exti_host_data *host_data = dm->host_data; ++ ++ if (!node || ++ (bus_token != DOMAIN_BUS_ANY && dm->bus_token != bus_token)) ++ return 0; ++ ++ if (!host_data->irq_map_node) ++ return (to_of_node(dm->fwnode) == node); ++ ++ if (node != host_data->irq_map_node->parent) ++ return 0; ++ ++ return (to_of_node(dm->parent->fwnode) == of_irq_find_parent(host_data->irq_map_node->parent)); ++} ++ ++static int stm32_exti_h_domain_select(struct irq_domain *dm, ++ struct irq_fwspec *fwspec, ++ enum irq_domain_bus_token bus_token) ++{ ++ struct fwnode_handle *fwnode = fwspec->fwnode; ++ struct stm32_exti_host_data *host_data = dm->host_data; ++ struct of_phandle_args out_irq; ++ int ret; ++ ++ if (!fwnode || ++ (bus_token != DOMAIN_BUS_ANY && dm->bus_token != bus_token)) ++ return 0; ++ ++ if (!host_data->irq_map_node) ++ return (dm->fwnode == fwnode); ++ ++ if (fwnode != of_node_to_fwnode(host_data->irq_map_node->parent)) ++ return 0; ++ ++ out_irq.np = host_data->irq_map_node; ++ out_irq.args_count = 2; ++ out_irq.args[0] = fwspec->param[0]; ++ out_irq.args[1] = fwspec->param[1]; ++ ++ ret = of_irq_parse_raw(NULL, &out_irq); ++ if (ret) ++ return ret; ++ ++ return (dm->parent->fwnode == of_node_to_fwnode(out_irq.np)); ++} ++ + static int stm32_exti_h_domain_alloc(struct irq_domain *dm, + unsigned int virq, + unsigned int nr_irqs, void *data) + { + struct stm32_exti_host_data *host_data = dm->host_data; + struct stm32_exti_chip_data *chip_data; +- const struct stm32_desc_irq *desc; ++ u8 desc_irq; + struct irq_fwspec *fwspec = data; + struct irq_fwspec p_fwspec; ++ struct of_phandle_args out_irq; + irq_hw_number_t hwirq; +- int bank; ++ int bank, ret; ++ u32 event_trg; ++ struct irq_chip *chip; + + hwirq = fwspec->param[0]; ++ if (hwirq >= host_data->drv_data->bank_nr * IRQS_PER_BANK) ++ return -EINVAL; ++ + bank = hwirq / IRQS_PER_BANK; + chip_data = &host_data->chips_data[bank]; + ++ event_trg = readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst); ++ chip = (event_trg & BIT(hwirq % IRQS_PER_BANK)) ? ++ &stm32_exti_h_chip : &stm32_exti_h_chip_direct; ++ ++ irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data); ++ ++ if (host_data->irq_map_node) { ++ out_irq.np = host_data->irq_map_node; ++ out_irq.args_count = 2; ++ out_irq.args[0] = fwspec->param[0]; ++ out_irq.args[1] = fwspec->param[1]; ++ ++ ret = of_irq_parse_raw(NULL, &out_irq); ++ if (ret) ++ return ret; ++ ++ of_phandle_args_to_fwspec(out_irq.np, out_irq.args, ++ out_irq.args_count, &p_fwspec); ++ ++ return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); ++ } + +- desc = stm32_exti_get_desc(host_data->drv_data, hwirq); +- if (!desc) ++ if (!host_data->drv_data || !host_data->drv_data->desc_irqs) + return -EINVAL; + +- irq_domain_set_hwirq_and_chip(dm, virq, hwirq, desc->chip, +- chip_data); - if (desc->irq_parent) { -+ /* -+ * EXTI 55 to 60 are mapped to PWR interrupt controller. -+ * The hwirq translation is done diferently than for GIC. -+ */ -+ if (hwirq >= 55 && hwirq <= 60) { ++ desc_irq = host_data->drv_data->desc_irqs[hwirq]; ++ if (desc_irq != EXTI_INVALID_IRQ) { p_fwspec.fwnode = dm->parent->fwnode; -- p_fwspec.param_count = 3; -- p_fwspec.param[0] = GIC_SPI; + p_fwspec.param_count = 3; + p_fwspec.param[0] = GIC_SPI; - p_fwspec.param[1] = desc->irq_parent; -- p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; -+ p_fwspec.param_count = 2; -+ p_fwspec.param[0] = hwirq - 55; -+ p_fwspec.param[1] = fwspec->param[1]; ++ p_fwspec.param[1] = desc_irq; + p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); -+ } else { -+ if (desc->irq_parent) { -+ p_fwspec.fwnode = dm->parent->fwnode; -+ p_fwspec.param_count = 3; -+ p_fwspec.param[0] = GIC_SPI; -+ p_fwspec.param[1] = desc->irq_parent; -+ p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; -+ -+ return irq_domain_alloc_irqs_parent(dm, virq, 1, -+ &p_fwspec); -+ } +@@ -710,8 +867,6 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd, + goto free_chips_data; } - return 0; -@@ -743,7 +832,8 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data, +- stm32_host_data = host_data; +- + return host_data; + + free_chips_data: +@@ -743,7 +898,8 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data, * clear registers to avoid residue */ writel_relaxed(0, base + stm32_bank->imr_ofst); @@ -2934,48 +3782,99 @@ index 33c76710f..d99d4b4b0 100644 pr_info("%pOF: bank%d\n", node, bank_idx); -@@ -846,11 +936,12 @@ static int stm32_exti_probe(struct platform_device *pdev) +@@ -824,6 +980,8 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data, + } + + static const struct irq_domain_ops stm32_exti_h_domain_ops = { ++ .match = stm32_exti_h_domain_match, ++ .select = stm32_exti_h_domain_select, + .alloc = stm32_exti_h_domain_alloc, + .free = irq_domain_free_irqs_common, + .xlate = irq_domain_xlate_twocell, +@@ -832,13 +990,17 @@ static const struct irq_domain_ops stm32_exti_h_domain_ops = { + static void stm32_exti_remove_irq(void *data) + { + struct irq_domain *domain = data; ++ struct fwnode_handle *fwnode = domain->fwnode; + + irq_domain_remove(domain); ++ ++ if (is_fwnode_irqchip(fwnode)) ++ irq_domain_free_fwnode(fwnode); + } + + static int stm32_exti_remove(struct platform_device *pdev) + { +- stm32_exti_h_syscore_deinit(); ++ stm32_exti_h_syscore_deinit(pdev); + return 0; + } + +@@ -846,16 +1008,20 @@ static int stm32_exti_probe(struct platform_device *pdev) { int ret, i; struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; -+ struct device_node *child, *np = dev->of_node; - struct irq_domain *parent_domain, *domain; +- struct irq_domain *parent_domain, *domain; ++ struct device_node *child, *np = dev->of_node, *wakeup_np; ++ struct irq_domain *parent_domain, *domain, *wakeup_domain; ++ struct fwnode_handle *fwnode; struct stm32_exti_host_data *host_data; const struct stm32_exti_drv_data *drv_data; struct resource *res; -+ u32 nirqs; ++ char *name; host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); if (!host_data) -@@ -916,6 +1007,34 @@ static int stm32_exti_probe(struct platform_device *pdev) + return -ENOMEM; + ++ platform_set_drvdata(pdev, host_data); ++ + /* check for optional hwspinlock which may be not available yet */ + ret = of_hwspin_lock_get_id(np, 0); + if (ret == -EPROBE_DEFER) +@@ -916,6 +1082,48 @@ static int stm32_exti_probe(struct platform_device *pdev) if (ret) return ret; -+ for_each_child_of_node(np, child) { -+ parent_domain = irq_find_host(of_irq_find_parent(child)); -+ if (!parent_domain) { -+ dev_err(dev, "child interrupt-parent not found\n"); -+ return -EINVAL; -+ } ++ child = of_get_child_by_name(np, "exti-interrupt-map"); ++ if (child && of_property_read_bool(child, "interrupt-map")) ++ host_data->irq_map_node = child; + -+ ret = of_property_read_u32(child, "st,irq-number", &nirqs); -+ if (ret || !nirqs) { -+ dev_err(dev, "Missing or bad irq-number property\n"); -+ return -EINVAL; -+ } ++ wakeup_np = of_parse_phandle(np, "wakeup-parent", 0); ++ if (wakeup_np && !host_data->irq_map_node) { ++ dev_warn(dev, "wakeup-parent ignored due to missing interrupt-map nexus node"); ++ of_node_put(wakeup_np); ++ wakeup_np = NULL; ++ } ++ if (wakeup_np) { ++ wakeup_domain = irq_find_host(wakeup_np); ++ of_node_put(wakeup_np); ++ if (!wakeup_domain) ++ return -EPROBE_DEFER; + -+ domain = irq_domain_add_hierarchy(parent_domain, 0, nirqs, -+ child, -+ &stm32_exti_h_domain_ops, -+ host_data); ++ /* as in __irq_domain_add() */ ++ name = kasprintf(GFP_KERNEL, "%pOF-wakeup", np); ++ if (!name) ++ return -ENOMEM; ++ strreplace(name, '/', ':'); ++ ++ fwnode = irq_domain_alloc_named_fwnode(name); ++ kfree(name); ++ if (!fwnode) ++ return -ENOMEM; ++ ++ domain = irq_domain_create_hierarchy(wakeup_domain, 0, ++ drv_data->bank_nr * IRQS_PER_BANK, ++ fwnode, &stm32_exti_h_domain_ops, ++ host_data); + if (!domain) { + dev_err(dev, "Could not register exti domain\n"); ++ irq_domain_free_fwnode(fwnode); + return -ENOMEM; + } + -+ ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, -+ domain); ++ ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain); + if (ret) + return ret; + } @@ -2983,7 +3882,7 @@ index 33c76710f..d99d4b4b0 100644 stm32_exti_h_syscore_init(host_data); return 0; -@@ -924,6 +1043,7 @@ static int stm32_exti_probe(struct platform_device *pdev) +@@ -924,6 +1132,7 @@ static int stm32_exti_probe(struct platform_device *pdev) /* platform driver only for MP1 */ static const struct of_device_id stm32_exti_ids[] = { { .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data}, @@ -2991,6 +3890,45 @@ index 33c76710f..d99d4b4b0 100644 {}, }; MODULE_DEVICE_TABLE(of, stm32_exti_ids); +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index 9ee238ad29ce..553da4899f55 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -64,6 +64,10 @@ struct irq_fwspec { + u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS]; + }; + ++/* Conversion function from of_phandle_args fields to fwspec */ ++void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, ++ unsigned int count, struct irq_fwspec *fwspec); ++ + /* + * Should several domains have the same device node, but serve + * different purposes (for example one domain is for PCI/MSI, and the +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 035e3038c4de..5c74ebb13a77 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -744,9 +744,8 @@ static int irq_domain_translate(struct irq_domain *d, + return 0; + } + +-static void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, +- unsigned int count, +- struct irq_fwspec *fwspec) ++void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, ++ unsigned int count, struct irq_fwspec *fwspec) + { + int i; + +@@ -756,6 +755,7 @@ static void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, + for (i = 0; i < count; i++) + fwspec->param[i] = args[i]; + } ++EXPORT_SYMBOL_GPL(of_phandle_args_to_fwspec); + + unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) + { -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0009-ARM-5.15.24-stm32mp1-r1-REMOTEPROC-RPMSG.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0010-v5.15-stm32mp-r2-REMOTEPROC-RPMSG.patch similarity index 82% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0009-ARM-5.15.24-stm32mp1-r1-REMOTEPROC-RPMSG.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0010-v5.15-stm32mp-r2-REMOTEPROC-RPMSG.patch index 2d2a8c2..c22cce9 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0009-ARM-5.15.24-stm32mp1-r1-REMOTEPROC-RPMSG.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0010-v5.15-stm32mp-r2-REMOTEPROC-RPMSG.patch @@ -1,9 +1,9 @@ -From 3ecc5f791e1309ffaa44d17987a9f322599241ff Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:56:46 +0200 -Subject: [PATCH 09/22] ARM-5.15.24-stm32mp1-r1-REMOTEPROC-RPMSG +From 2af007b9996146b7357a9b3952bc16940da1ee58 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:40:22 +0100 +Subject: [PATCH 10/22] v5.15-stm32mp-r2 REMOTEPROC-RPMSG -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../bindings/remoteproc/rproc-srm.txt | 58 ++ .../bindings/remoteproc/st,stm32-rproc.yaml | 25 +- @@ -17,42 +17,50 @@ Signed-off-by: Christophe Priouzeau drivers/remoteproc/rproc_srm_dev.c | 744 ++++++++++++++++ drivers/remoteproc/stm32_rproc.c | 324 ++++--- drivers/remoteproc/tee_remoteproc.c | 378 ++++++++ - drivers/rpmsg/rpmsg_core.c | 21 + - drivers/rpmsg/rpmsg_internal.h | 2 + - drivers/rpmsg/virtio_rpmsg_bus.c | 10 + + drivers/rpmsg/Kconfig | 8 + + drivers/rpmsg/Makefile | 1 + + drivers/rpmsg/qcom_glink_native.c | 2 +- + drivers/rpmsg/qcom_smd.c | 2 +- + drivers/rpmsg/rpmsg_char.c | 229 ++--- + drivers/rpmsg/rpmsg_char.h | 46 + + drivers/rpmsg/rpmsg_core.c | 36 +- + drivers/rpmsg/rpmsg_ctrl.c | 243 ++++++ + drivers/rpmsg/rpmsg_internal.h | 12 +- + drivers/rpmsg/virtio_rpmsg_bus.c | 12 +- drivers/tee/amdtee/amdtee_private.h | 8 +- drivers/tee/amdtee/core.c | 22 +- drivers/tee/optee/Makefile | 2 + drivers/tee/optee/call.c | 814 ++++++++++++++---- drivers/tee/optee/call_queue.c | 86 ++ - drivers/tee/optee/core.c | 335 ++++++- + drivers/tee/optee/core.c | 463 +++++++++- drivers/tee/optee/notif.c | 125 +++ drivers/tee/optee/optee_msg.h | 160 +++- - drivers/tee/optee/optee_private.h | 177 +++- + drivers/tee/optee/optee_private.h | 180 +++- drivers/tee/optee/optee_rpc_cmd.h | 31 +- - drivers/tee/optee/optee_smc.h | 78 +- + drivers/tee/optee/optee_smc.h | 94 +- drivers/tee/optee/rpc.c | 99 +-- - drivers/tee/tee_core.c | 79 +- + drivers/tee/tee_core.c | 73 +- drivers/tee/tee_shm.c | 13 +- - drivers/tty/rpmsg_tty.c | 287 ++++++ include/linux/rpmsg.h | 10 + - include/linux/tee_drv.h | 31 +- + include/linux/tee_drv.h | 17 +- include/linux/tee_remoteproc.h | 101 +++ + include/uapi/linux/rpmsg.h | 10 + include/uapi/linux/tee.h | 36 +- - 34 files changed, 4104 insertions(+), 445 deletions(-) + 41 files changed, 4358 insertions(+), 599 deletions(-) create mode 100644 Documentation/devicetree/bindings/remoteproc/rproc-srm.txt create mode 100644 drivers/remoteproc/rproc_srm_core.c create mode 100644 drivers/remoteproc/rproc_srm_core.h create mode 100644 drivers/remoteproc/rproc_srm_dev.c create mode 100644 drivers/remoteproc/tee_remoteproc.c + create mode 100644 drivers/rpmsg/rpmsg_char.h + create mode 100644 drivers/rpmsg/rpmsg_ctrl.c create mode 100644 drivers/tee/optee/call_queue.c create mode 100644 drivers/tee/optee/notif.c - create mode 100644 drivers/tty/rpmsg_tty.c create mode 100644 include/linux/tee_remoteproc.h diff --git a/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt new file mode 100644 -index 000000000..baa6e8e13 +index 000000000000..baa6e8e135e1 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/rproc-srm.txt @@ -0,0 +1,58 @@ @@ -115,7 +123,7 @@ index 000000000..baa6e8e13 + }; + }; diff --git a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml -index 1e6225677..93c27e3ec 100644 +index 1e6225677e00..93c27e3ecd85 100644 --- a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml @@ -25,21 +25,12 @@ properties: @@ -167,7 +175,7 @@ index 1e6225677..93c27e3ec 100644 st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; }; diff --git a/Documentation/staging/remoteproc.rst b/Documentation/staging/remoteproc.rst -index 9cccd3dd6..c2367e3c0 100644 +index 9cccd3dd6a4b..c2367e3c0b19 100644 --- a/Documentation/staging/remoteproc.rst +++ b/Documentation/staging/remoteproc.rst @@ -357,3 +357,25 @@ Of course, RSC_VDEV resource entries are only good enough for static @@ -197,7 +205,7 @@ index 9cccd3dd6..c2367e3c0 100644 +The resources handled by the SRM are defined in the DeviceTree: please read +Documentation/devicetree/bindings/remoteproc/rproc-srm.txt for details. diff --git a/Documentation/staging/tee.rst b/Documentation/staging/tee.rst -index 4d4b5f889..3c63d8dcd 100644 +index 4d4b5f889603..3c63d8dcd61e 100644 --- a/Documentation/staging/tee.rst +++ b/Documentation/staging/tee.rst @@ -184,6 +184,36 @@ order to support device enumeration. In other words, OP-TEE driver invokes this @@ -238,7 +246,7 @@ index 4d4b5f889..3c63d8dcd 100644 ============== diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig -index 9a6eedc39..33e96dd61 100644 +index 9a6eedc3994a..33e96dd612cf 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -23,6 +23,25 @@ config REMOTEPROC_CDEV @@ -292,7 +300,7 @@ index 9a6eedc39..33e96dd61 100644 endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile -index bb26c9e4e..521dd3384 100644 +index bb26c9e4ef9c..521dd3384fba 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -11,6 +11,9 @@ remoteproc-y += remoteproc_sysfs.o @@ -306,7 +314,7 @@ index bb26c9e4e..521dd3384 100644 obj-$(CONFIG_INGENIC_VPU_RPROC) += ingenic_rproc.o obj-$(CONFIG_MTK_SCP) += mtk_scp.o mtk_scp_ipi.o diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c -index 775df165e..df31b9222 100644 +index 775df165eb45..df31b9222b38 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -38,6 +38,7 @@ @@ -340,7 +348,7 @@ index 775df165e..df31b9222 100644 diff --git a/drivers/remoteproc/rproc_srm_core.c b/drivers/remoteproc/rproc_srm_core.c new file mode 100644 -index 000000000..fc61e8b35 +index 000000000000..fc61e8b35686 --- /dev/null +++ b/drivers/remoteproc/rproc_srm_core.c @@ -0,0 +1,303 @@ @@ -649,7 +657,7 @@ index 000000000..fc61e8b35 +MODULE_LICENSE("GPL v2"); diff --git a/drivers/remoteproc/rproc_srm_core.h b/drivers/remoteproc/rproc_srm_core.h new file mode 100644 -index 000000000..7dffdb38f +index 000000000000..7dffdb38f4d4 --- /dev/null +++ b/drivers/remoteproc/rproc_srm_core.h @@ -0,0 +1,98 @@ @@ -753,7 +761,7 @@ index 000000000..7dffdb38f +#endif diff --git a/drivers/remoteproc/rproc_srm_dev.c b/drivers/remoteproc/rproc_srm_dev.c new file mode 100644 -index 000000000..e47654af3 +index 000000000000..e47654af3e3a --- /dev/null +++ b/drivers/remoteproc/rproc_srm_dev.c @@ -0,0 +1,744 @@ @@ -1502,7 +1510,7 @@ index 000000000..e47654af3 +MODULE_DESCRIPTION("Remoteproc System Resource Manager driver - dev"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c -index b643efcf9..4b713b74a 100644 +index b643efcf995a..4b713b74ad44 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -20,13 +20,11 @@ @@ -1990,7 +1998,7 @@ index b643efcf9..4b713b74a 100644 .pm = &stm32_rproc_pm_ops, diff --git a/drivers/remoteproc/tee_remoteproc.c b/drivers/remoteproc/tee_remoteproc.c new file mode 100644 -index 000000000..da95273a3 +index 000000000000..da95273a30ac --- /dev/null +++ b/drivers/remoteproc/tee_remoteproc.c @@ -0,0 +1,378 @@ @@ -2372,11 +2380,519 @@ index 000000000..da95273a3 +MODULE_DESCRIPTION("secure remote processor control driver"); +MODULE_AUTHOR("Arnaud Pouliquen "); +MODULE_LICENSE("GPL v2"); +diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig +index 0b4407abdf13..d3795860f5c0 100644 +--- a/drivers/rpmsg/Kconfig ++++ b/drivers/rpmsg/Kconfig +@@ -15,6 +15,14 @@ config RPMSG_CHAR + in /dev. They make it possible for user-space programs to send and + receive rpmsg packets. + ++config RPMSG_CTRL ++ tristate "RPMSG control interface" ++ depends on RPMSG && ( RPMSG_CHAR || RPMSG_CHAR=n ) ++ help ++ Say Y here to enable the support of the /dev/rpmsg_ctrlX API. This API ++ allows user-space programs to create endpoints with specific service name, ++ source and destination addresses. ++ + config RPMSG_NS + tristate "RPMSG name service announcement" + depends on RPMSG +diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile +index 8d452656f0ee..58e3b382e316 100644 +--- a/drivers/rpmsg/Makefile ++++ b/drivers/rpmsg/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_RPMSG) += rpmsg_core.o + obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o ++obj-$(CONFIG_RPMSG_CTRL) += rpmsg_ctrl.o + obj-$(CONFIG_RPMSG_NS) += rpmsg_ns.o + obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o + qcom_glink-objs := qcom_glink_native.o qcom_glink_ssr.o +diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c +index 05533c71b10e..7d7e809800ec 100644 +--- a/drivers/rpmsg/qcom_glink_native.c ++++ b/drivers/rpmsg/qcom_glink_native.c +@@ -1642,7 +1642,7 @@ static int qcom_glink_create_chrdev(struct qcom_glink *glink) + rpdev->dev.parent = glink->dev; + rpdev->dev.release = qcom_glink_device_release; + +- return rpmsg_chrdev_register_device(rpdev); ++ return rpmsg_ctrldev_register_device(rpdev); + } + + struct qcom_glink *qcom_glink_native_probe(struct device *dev, +diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c +index c1c07ff39a79..b2cd71c350ee 100644 +--- a/drivers/rpmsg/qcom_smd.c ++++ b/drivers/rpmsg/qcom_smd.c +@@ -1113,7 +1113,7 @@ static int qcom_smd_create_chrdev(struct qcom_smd_edge *edge) + qsdev->rpdev.dev.parent = &edge->dev; + qsdev->rpdev.dev.release = qcom_smd_release_device; + +- return rpmsg_chrdev_register_device(&qsdev->rpdev); ++ return rpmsg_ctrldev_register_device(&qsdev->rpdev); + } + + /* +diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c +index 88c985f9e73a..29a814eb16f0 100644 +--- a/drivers/rpmsg/rpmsg_char.c ++++ b/drivers/rpmsg/rpmsg_char.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* ++ * Copyright (C) 2022, STMicroelectronics + * Copyright (c) 2016, Linaro Ltd. + * Copyright (c) 2012, Michal Simek + * Copyright (c) 2012, PetaLogix +@@ -22,35 +23,19 @@ + #include + #include + ++#include "rpmsg_char.h" + #include "rpmsg_internal.h" + + #define RPMSG_DEV_MAX (MINORMASK + 1) + + static dev_t rpmsg_major; +-static struct class *rpmsg_class; + +-static DEFINE_IDA(rpmsg_ctrl_ida); + static DEFINE_IDA(rpmsg_ept_ida); + static DEFINE_IDA(rpmsg_minor_ida); + + #define dev_to_eptdev(dev) container_of(dev, struct rpmsg_eptdev, dev) + #define cdev_to_eptdev(i_cdev) container_of(i_cdev, struct rpmsg_eptdev, cdev) + +-#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev) +-#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev) +- +-/** +- * struct rpmsg_ctrldev - control device for instantiating endpoint devices +- * @rpdev: underlaying rpmsg device +- * @cdev: cdev for the ctrl device +- * @dev: device for the ctrl device +- */ +-struct rpmsg_ctrldev { +- struct rpmsg_device *rpdev; +- struct cdev cdev; +- struct device dev; +-}; +- + /** + * struct rpmsg_eptdev - endpoint device context + * @dev: endpoint device +@@ -62,6 +47,8 @@ struct rpmsg_ctrldev { + * @queue_lock: synchronization of @queue operations + * @queue: incoming message queue + * @readq: wait object for incoming queue ++ * @default_ept: set to channel default endpoint if the default endpoint should be re-used ++ * on device open to prevent endpoint address update. + */ + struct rpmsg_eptdev { + struct device dev; +@@ -72,13 +59,15 @@ struct rpmsg_eptdev { + + struct mutex ept_lock; + struct rpmsg_endpoint *ept; ++ struct rpmsg_endpoint *default_ept; + + spinlock_t queue_lock; + struct sk_buff_head queue; + wait_queue_head_t readq; ++ + }; + +-static int rpmsg_eptdev_destroy(struct device *dev, void *data) ++int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data) + { + struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev); + +@@ -97,6 +86,7 @@ static int rpmsg_eptdev_destroy(struct device *dev, void *data) + + return 0; + } ++EXPORT_SYMBOL(rpmsg_chrdev_eptdev_destroy); + + static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len, + void *priv, u32 addr) +@@ -135,7 +125,15 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) + + get_device(dev); + +- ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo); ++ /* ++ * If the default_ept is set, the rpmsg device default endpoint is used. ++ * Else a new endpoint is created on open that will be destroyed on release. ++ */ ++ if (eptdev->default_ept) ++ ept = eptdev->default_ept; ++ else ++ ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo); ++ + if (!ept) { + dev_err(dev, "failed to open %s\n", eptdev->chinfo.name); + put_device(dev); +@@ -158,7 +156,8 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp) + /* Close the endpoint, if it's not already destroyed by the parent */ + mutex_lock(&eptdev->ept_lock); + if (eptdev->ept) { +- rpmsg_destroy_ept(eptdev->ept); ++ if (!eptdev->default_ept) ++ rpmsg_destroy_ept(eptdev->ept); + eptdev->ept = NULL; + } + mutex_unlock(&eptdev->ept_lock); +@@ -285,7 +284,11 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd, + if (cmd != RPMSG_DESTROY_EPT_IOCTL) + return -EINVAL; + +- return rpmsg_eptdev_destroy(&eptdev->dev, NULL); ++ /* Don't allow to destroy a default endpoint. */ ++ if (eptdev->default_ept) ++ return -EINVAL; ++ ++ return rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL); + } + + static const struct file_operations rpmsg_eptdev_fops = { +@@ -343,21 +346,18 @@ static void rpmsg_eptdev_release_device(struct device *dev) + kfree(eptdev); + } + +-static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev, +- struct rpmsg_channel_info chinfo) ++static struct rpmsg_eptdev *rpmsg_chrdev_eptdev_alloc(struct rpmsg_device *rpdev, ++ struct device *parent) + { +- struct rpmsg_device *rpdev = ctrldev->rpdev; + struct rpmsg_eptdev *eptdev; + struct device *dev; +- int ret; + + eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL); + if (!eptdev) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + + dev = &eptdev->dev; + eptdev->rpdev = rpdev; +- eptdev->chinfo = chinfo; + + mutex_init(&eptdev->ept_lock); + spin_lock_init(&eptdev->queue_lock); +@@ -366,13 +366,23 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev, + + device_initialize(dev); + dev->class = rpmsg_class; +- dev->parent = &ctrldev->dev; ++ dev->parent = parent; + dev->groups = rpmsg_eptdev_groups; + dev_set_drvdata(dev, eptdev); + + cdev_init(&eptdev->cdev, &rpmsg_eptdev_fops); + eptdev->cdev.owner = THIS_MODULE; + ++ return eptdev; ++} ++ ++static int rpmsg_chrdev_eptdev_add(struct rpmsg_eptdev *eptdev, struct rpmsg_channel_info chinfo) ++{ ++ struct device *dev = &eptdev->dev; ++ int ret; ++ ++ eptdev->chinfo = chinfo; ++ + ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL); + if (ret < 0) + goto free_eptdev; +@@ -404,163 +414,91 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev, + return ret; + } + +-static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp) +-{ +- struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev); +- +- get_device(&ctrldev->dev); +- filp->private_data = ctrldev; +- +- return 0; +-} +- +-static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp) +-{ +- struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev); +- +- put_device(&ctrldev->dev); +- +- return 0; +-} +- +-static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd, +- unsigned long arg) ++int rpmsg_chrdev_eptdev_create(struct rpmsg_device *rpdev, struct device *parent, ++ struct rpmsg_channel_info chinfo) + { +- struct rpmsg_ctrldev *ctrldev = fp->private_data; +- void __user *argp = (void __user *)arg; +- struct rpmsg_endpoint_info eptinfo; +- struct rpmsg_channel_info chinfo; +- +- if (cmd != RPMSG_CREATE_EPT_IOCTL) +- return -EINVAL; +- +- if (copy_from_user(&eptinfo, argp, sizeof(eptinfo))) +- return -EFAULT; +- +- memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE); +- chinfo.name[RPMSG_NAME_SIZE-1] = '\0'; +- chinfo.src = eptinfo.src; +- chinfo.dst = eptinfo.dst; +- +- return rpmsg_eptdev_create(ctrldev, chinfo); +-}; ++ struct rpmsg_eptdev *eptdev; ++ int ret; + +-static const struct file_operations rpmsg_ctrldev_fops = { +- .owner = THIS_MODULE, +- .open = rpmsg_ctrldev_open, +- .release = rpmsg_ctrldev_release, +- .unlocked_ioctl = rpmsg_ctrldev_ioctl, +- .compat_ioctl = compat_ptr_ioctl, +-}; ++ eptdev = rpmsg_chrdev_eptdev_alloc(rpdev, parent); ++ if (IS_ERR(eptdev)) ++ return PTR_ERR(eptdev); + +-static void rpmsg_ctrldev_release_device(struct device *dev) +-{ +- struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev); ++ ret = rpmsg_chrdev_eptdev_add(eptdev, chinfo); + +- ida_simple_remove(&rpmsg_ctrl_ida, dev->id); +- ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); +- kfree(ctrldev); ++ return ret; + } ++EXPORT_SYMBOL(rpmsg_chrdev_eptdev_create); + + static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev) + { +- struct rpmsg_ctrldev *ctrldev; +- struct device *dev; +- int ret; +- +- ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL); +- if (!ctrldev) +- return -ENOMEM; +- +- ctrldev->rpdev = rpdev; +- +- dev = &ctrldev->dev; +- device_initialize(dev); +- dev->parent = &rpdev->dev; +- dev->class = rpmsg_class; +- +- cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops); +- ctrldev->cdev.owner = THIS_MODULE; +- +- ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL); +- if (ret < 0) +- goto free_ctrldev; +- dev->devt = MKDEV(MAJOR(rpmsg_major), ret); +- +- ret = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL); +- if (ret < 0) +- goto free_minor_ida; +- dev->id = ret; +- dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret); ++ struct rpmsg_channel_info chinfo; ++ struct rpmsg_eptdev *eptdev; ++ struct device *dev = &rpdev->dev; + +- ret = cdev_device_add(&ctrldev->cdev, &ctrldev->dev); +- if (ret) +- goto free_ctrl_ida; ++ memcpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); ++ chinfo.src = rpdev->src; ++ chinfo.dst = rpdev->dst; + +- /* We can now rely on the release function for cleanup */ +- dev->release = rpmsg_ctrldev_release_device; ++ eptdev = rpmsg_chrdev_eptdev_alloc(rpdev, dev); ++ if (IS_ERR(eptdev)) ++ return PTR_ERR(eptdev); + +- dev_set_drvdata(&rpdev->dev, ctrldev); ++ /* Set the default_ept to the rpmsg device endpoint */ ++ eptdev->default_ept = rpdev->ept; + +- return ret; ++ /* ++ * The rpmsg_ept_cb uses *priv parameter to get its rpmsg_eptdev context. ++ * Storedit in default_ept *priv field. ++ */ ++ eptdev->default_ept->priv = eptdev; + +-free_ctrl_ida: +- ida_simple_remove(&rpmsg_ctrl_ida, dev->id); +-free_minor_ida: +- ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); +-free_ctrldev: +- put_device(dev); +- kfree(ctrldev); +- +- return ret; ++ return rpmsg_chrdev_eptdev_add(eptdev, chinfo); + } + + static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev) + { +- struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev); + int ret; + +- /* Destroy all endpoints */ +- ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_eptdev_destroy); ++ ret = device_for_each_child(&rpdev->dev, NULL, rpmsg_chrdev_eptdev_destroy); + if (ret) +- dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret); +- +- cdev_device_del(&ctrldev->cdev, &ctrldev->dev); +- put_device(&ctrldev->dev); ++ dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret); + } + ++static struct rpmsg_device_id rpmsg_chrdev_id_table[] = { ++ { .name = "rpmsg-raw" }, ++ { }, ++}; ++ + static struct rpmsg_driver rpmsg_chrdev_driver = { + .probe = rpmsg_chrdev_probe, + .remove = rpmsg_chrdev_remove, +- .drv = { +- .name = "rpmsg_chrdev", +- }, ++ .callback = rpmsg_ept_cb, ++ .id_table = rpmsg_chrdev_id_table, ++ .drv.name = "rpmsg_chrdev", + }; + + static int rpmsg_chrdev_init(void) + { + int ret; + +- ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg"); ++ ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char"); + if (ret < 0) { + pr_err("rpmsg: failed to allocate char dev region\n"); + return ret; + } + +- rpmsg_class = class_create(THIS_MODULE, "rpmsg"); +- if (IS_ERR(rpmsg_class)) { +- pr_err("failed to create rpmsg class\n"); +- unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); +- return PTR_ERR(rpmsg_class); +- } +- + ret = register_rpmsg_driver(&rpmsg_chrdev_driver); + if (ret < 0) { +- pr_err("rpmsgchr: failed to register rpmsg driver\n"); +- class_destroy(rpmsg_class); +- unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); ++ pr_err("rpmsg: failed to register rpmsg raw driver\n"); ++ goto free_region; + } + ++ return 0; ++ ++free_region: ++ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); ++ + return ret; + } + postcore_initcall(rpmsg_chrdev_init); +@@ -568,7 +506,6 @@ postcore_initcall(rpmsg_chrdev_init); + static void rpmsg_chrdev_exit(void) + { + unregister_rpmsg_driver(&rpmsg_chrdev_driver); +- class_destroy(rpmsg_class); + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); + } + module_exit(rpmsg_chrdev_exit); +diff --git a/drivers/rpmsg/rpmsg_char.h b/drivers/rpmsg/rpmsg_char.h +new file mode 100644 +index 000000000000..117d9cbc52f0 +--- /dev/null ++++ b/drivers/rpmsg/rpmsg_char.h +@@ -0,0 +1,46 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022, STMicroelectronics ++ */ ++ ++#ifndef __RPMSG_CHRDEV_H__ ++#define __RPMSG_CHRDEV_H__ ++ ++#if IS_ENABLED(CONFIG_RPMSG_CHAR) ++/** ++ * rpmsg_chrdev_eptdev_create() - register char device based on an endpoint ++ * @rpdev: prepared rpdev to be used for creating endpoints ++ * @parent: parent device ++ * @chinfo: associated endpoint channel information. ++ * ++ * This function create a new rpmsg char endpoint device to instantiate a new ++ * endpoint based on chinfo information. ++ */ ++int rpmsg_chrdev_eptdev_create(struct rpmsg_device *rpdev, struct device *parent, ++ struct rpmsg_channel_info chinfo); ++ ++/** ++ * rpmsg_chrdev_eptdev_destroy() - destroy created char device endpoint. ++ * @data: private data associated to the endpoint device ++ * ++ * This function destroys a rpmsg char endpoint device created by the RPMSG_DESTROY_EPT_IOCTL ++ * control. ++ */ ++int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data); ++ ++#else /*IS_ENABLED(CONFIG_RPMSG_CHAR) */ ++ ++static inline int rpmsg_chrdev_eptdev_create(struct rpmsg_device *rpdev, struct device *parent, ++ struct rpmsg_channel_info chinfo) ++{ ++ return -ENXIO; ++} ++ ++static inline int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data) ++{ ++ return -ENXIO; ++} ++ ++#endif /*IS_ENABLED(CONFIG_RPMSG_CHAR) */ ++ ++#endif /*__RPMSG_CHRDEV_H__ */ diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c -index a71de08ac..4c6b4a587 100644 +index a71de08acc7b..41648ad9f8a6 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c -@@ -327,6 +327,27 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, +@@ -20,6 +20,9 @@ + + #include "rpmsg_internal.h" + ++struct class *rpmsg_class; ++EXPORT_SYMBOL(rpmsg_class); ++ + /** + * rpmsg_create_channel() - create a new rpmsg channel + * using its name and address info. +@@ -327,6 +330,27 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, } EXPORT_SYMBOL(rpmsg_trysend_offchannel); @@ -2404,11 +2920,297 @@ index a71de08ac..4c6b4a587 100644 /* * match a rpmsg channel with a channel info struct. * this is used to make sure we're not creating rpmsg devices for channels +@@ -641,10 +665,17 @@ static int __init rpmsg_init(void) + { + int ret; + ++ rpmsg_class = class_create(THIS_MODULE, "rpmsg"); ++ if (IS_ERR(rpmsg_class)) { ++ pr_err("failed to create rpmsg class\n"); ++ return PTR_ERR(rpmsg_class); ++ } ++ + ret = bus_register(&rpmsg_bus); +- if (ret) ++ if (ret) { + pr_err("failed to register rpmsg bus: %d\n", ret); +- ++ class_destroy(rpmsg_class); ++ } + return ret; + } + postcore_initcall(rpmsg_init); +@@ -652,6 +683,7 @@ postcore_initcall(rpmsg_init); + static void __exit rpmsg_fini(void) + { + bus_unregister(&rpmsg_bus); ++ class_destroy(rpmsg_class); + } + module_exit(rpmsg_fini); + +diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c +new file mode 100644 +index 000000000000..107da70fdbaa +--- /dev/null ++++ b/drivers/rpmsg/rpmsg_ctrl.c +@@ -0,0 +1,243 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022, STMicroelectronics ++ * Copyright (c) 2016, Linaro Ltd. ++ * Copyright (c) 2012, Michal Simek ++ * Copyright (c) 2012, PetaLogix ++ * Copyright (c) 2011, Texas Instruments, Inc. ++ * Copyright (c) 2011, Google, Inc. ++ * ++ * Based on rpmsg performance statistics driver by Michal Simek, which in turn ++ * was based on TI & Google OMX rpmsg driver. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rpmsg_char.h" ++#include "rpmsg_internal.h" ++ ++#define RPMSG_DEV_MAX (MINORMASK + 1) ++ ++static dev_t rpmsg_major; ++ ++static DEFINE_IDA(rpmsg_ctrl_ida); ++static DEFINE_IDA(rpmsg_minor_ida); ++ ++#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev) ++#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev) ++ ++/** ++ * struct rpmsg_ctrldev - control device for instantiating endpoint devices ++ * @rpdev: underlaying rpmsg device ++ * @cdev: cdev for the ctrl device ++ * @dev: device for the ctrl device ++ * @ctrl_lock: serialize the ioctrls. ++ */ ++struct rpmsg_ctrldev { ++ struct rpmsg_device *rpdev; ++ struct cdev cdev; ++ struct device dev; ++ struct mutex ctrl_lock; ++}; ++ ++static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp) ++{ ++ struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev); ++ ++ get_device(&ctrldev->dev); ++ filp->private_data = ctrldev; ++ ++ return 0; ++} ++ ++static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp) ++{ ++ struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev); ++ ++ put_device(&ctrldev->dev); ++ ++ return 0; ++} ++ ++static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct rpmsg_ctrldev *ctrldev = fp->private_data; ++ void __user *argp = (void __user *)arg; ++ struct rpmsg_endpoint_info eptinfo; ++ struct rpmsg_channel_info chinfo; ++ struct rpmsg_device *rpdev; ++ int ret = 0; ++ ++ if (copy_from_user(&eptinfo, argp, sizeof(eptinfo))) ++ return -EFAULT; ++ ++ memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE); ++ chinfo.name[RPMSG_NAME_SIZE - 1] = '\0'; ++ chinfo.src = eptinfo.src; ++ chinfo.dst = eptinfo.dst; ++ ++ mutex_lock(&ctrldev->ctrl_lock); ++ switch (cmd) { ++ case RPMSG_CREATE_EPT_IOCTL: ++ ret = rpmsg_chrdev_eptdev_create(ctrldev->rpdev, &ctrldev->dev, chinfo); ++ break; ++ ++ case RPMSG_CREATE_DEV_IOCTL: ++ rpdev = rpmsg_create_channel(ctrldev->rpdev, &chinfo); ++ if (!rpdev) { ++ dev_err(&ctrldev->dev, "failed to create %s channel\n", chinfo.name); ++ ret = -ENXIO; ++ } ++ break; ++ ++ case RPMSG_RELEASE_DEV_IOCTL: ++ ret = rpmsg_release_channel(ctrldev->rpdev, &chinfo); ++ if (ret) ++ dev_err(&ctrldev->dev, "failed to release %s channel (%d)\n", ++ chinfo.name, ret); ++ break; ++ ++ default: ++ ret = -EINVAL; ++ } ++ mutex_unlock(&ctrldev->ctrl_lock); ++ ++ return ret; ++}; ++ ++static const struct file_operations rpmsg_ctrldev_fops = { ++ .owner = THIS_MODULE, ++ .open = rpmsg_ctrldev_open, ++ .release = rpmsg_ctrldev_release, ++ .unlocked_ioctl = rpmsg_ctrldev_ioctl, ++ .compat_ioctl = compat_ptr_ioctl, ++}; ++ ++static void rpmsg_ctrldev_release_device(struct device *dev) ++{ ++ struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev); ++ ++ ida_simple_remove(&rpmsg_ctrl_ida, dev->id); ++ ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); ++ kfree(ctrldev); ++} ++ ++static int rpmsg_ctrldev_probe(struct rpmsg_device *rpdev) ++{ ++ struct rpmsg_ctrldev *ctrldev; ++ struct device *dev; ++ int ret; ++ ++ ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL); ++ if (!ctrldev) ++ return -ENOMEM; ++ ++ ctrldev->rpdev = rpdev; ++ ++ dev = &ctrldev->dev; ++ device_initialize(dev); ++ dev->parent = &rpdev->dev; ++ dev->class = rpmsg_class; ++ ++ mutex_init(&ctrldev->ctrl_lock); ++ cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops); ++ ctrldev->cdev.owner = THIS_MODULE; ++ ++ ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL); ++ if (ret < 0) ++ goto free_ctrldev; ++ dev->devt = MKDEV(MAJOR(rpmsg_major), ret); ++ ++ ret = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL); ++ if (ret < 0) ++ goto free_minor_ida; ++ dev->id = ret; ++ dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret); ++ ++ ret = cdev_device_add(&ctrldev->cdev, &ctrldev->dev); ++ if (ret) ++ goto free_ctrl_ida; ++ ++ /* We can now rely on the release function for cleanup */ ++ dev->release = rpmsg_ctrldev_release_device; ++ ++ dev_set_drvdata(&rpdev->dev, ctrldev); ++ ++ return ret; ++ ++free_ctrl_ida: ++ ida_simple_remove(&rpmsg_ctrl_ida, dev->id); ++free_minor_ida: ++ ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); ++free_ctrldev: ++ put_device(dev); ++ kfree(ctrldev); ++ ++ return ret; ++} ++ ++static void rpmsg_ctrldev_remove(struct rpmsg_device *rpdev) ++{ ++ struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev); ++ int ret; ++ ++ /* Destroy all endpoints */ ++ ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_eptdev_destroy); ++ if (ret) ++ dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret); ++ ++ cdev_device_del(&ctrldev->cdev, &ctrldev->dev); ++ put_device(&ctrldev->dev); ++} ++ ++static struct rpmsg_driver rpmsg_ctrldev_driver = { ++ .probe = rpmsg_ctrldev_probe, ++ .remove = rpmsg_ctrldev_remove, ++ .drv = { ++ .name = "rpmsg_ctrl", ++ }, ++}; ++ ++static int rpmsg_ctrldev_init(void) ++{ ++ int ret; ++ ++ ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_ctrl"); ++ if (ret < 0) { ++ pr_err("failed to allocate char dev region\n"); ++ return ret; ++ } ++ ++ ret = register_rpmsg_driver(&rpmsg_ctrldev_driver); ++ if (ret < 0) { ++ pr_err("failed to register rpmsg driver\n"); ++ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); ++ } ++ ++ return ret; ++} ++postcore_initcall(rpmsg_ctrldev_init); ++ ++static void rpmsg_ctrldev_exit(void) ++{ ++ unregister_rpmsg_driver(&rpmsg_ctrldev_driver); ++ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); ++} ++module_exit(rpmsg_ctrldev_exit); ++ ++MODULE_DESCRIPTION("rpmsg control interface"); ++MODULE_ALIAS("rpmsg:" KBUILD_MODNAME); ++MODULE_LICENSE("GPL v2"); diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h -index a76c34425..b1245d3ed 100644 +index a76c344253bf..d4b23fd019a8 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h -@@ -53,6 +53,7 @@ struct rpmsg_device_ops { +@@ -18,6 +18,8 @@ + #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev) + #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) + ++extern struct class *rpmsg_class; ++ + /** + * struct rpmsg_device_ops - indirection table for the rpmsg_device operations + * @create_channel: create backend-specific channel, optional +@@ -53,6 +55,7 @@ struct rpmsg_device_ops { * @trysendto: see @rpmsg_trysendto(), optional * @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional * @poll: see @rpmsg_poll(), optional @@ -2416,7 +3218,7 @@ index a76c34425..b1245d3ed 100644 * * Indirection table for the operations that a rpmsg backend should implement. * In addition to @destroy_ept, the backend must at least implement @send and -@@ -72,6 +73,7 @@ struct rpmsg_endpoint_ops { +@@ -72,6 +75,7 @@ struct rpmsg_endpoint_ops { void *data, int len); __poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait); @@ -2424,8 +3226,29 @@ index a76c34425..b1245d3ed 100644 }; struct device *rpmsg_find_device(struct device *parent, +@@ -82,16 +86,16 @@ struct rpmsg_device *rpmsg_create_channel(struct rpmsg_device *rpdev, + int rpmsg_release_channel(struct rpmsg_device *rpdev, + struct rpmsg_channel_info *chinfo); + /** +- * rpmsg_chrdev_register_device() - register chrdev device based on rpdev ++ * rpmsg_ctrldev_register_device() - register a char device for control based on rpdev + * @rpdev: prepared rpdev to be used for creating endpoints + * + * This function wraps rpmsg_register_device() preparing the rpdev for use as + * basis for the rpmsg chrdev. + */ +-static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev) ++static inline int rpmsg_ctrldev_register_device(struct rpmsg_device *rpdev) + { +- strcpy(rpdev->id.name, "rpmsg_chrdev"); +- rpdev->driver_override = "rpmsg_chrdev"; ++ strcpy(rpdev->id.name, "rpmsg_ctrl"); ++ rpdev->driver_override = "rpmsg_ctrl"; + + return rpmsg_register_device(rpdev); + } diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c -index 8e49a3bac..05fd06fc6 100644 +index b03e7404212f..1c54fe2fac5b 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -149,6 +149,7 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, @@ -2459,8 +3282,17 @@ index 8e49a3bac..05fd06fc6 100644 static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, struct rpmsg_hdr *msg, unsigned int len) { +@@ -840,7 +850,7 @@ static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev + rpdev_ctrl->dev.release = virtio_rpmsg_release_device; + rpdev_ctrl->little_endian = virtio_is_little_endian(vrp->vdev); + +- err = rpmsg_chrdev_register_device(rpdev_ctrl); ++ err = rpmsg_ctrldev_register_device(rpdev_ctrl); + if (err) { + /* vch will be free in virtio_rpmsg_release_device() */ + return ERR_PTR(err); diff --git a/drivers/tee/amdtee/amdtee_private.h b/drivers/tee/amdtee/amdtee_private.h -index 6d0f7062b..73c183510 100644 +index 6d0f7062bb87..73c183510c26 100644 --- a/drivers/tee/amdtee/amdtee_private.h +++ b/drivers/tee/amdtee/amdtee_private.h @@ -135,13 +135,17 @@ static inline u32 get_session_index(u32 session) @@ -2484,7 +3316,7 @@ index 6d0f7062b..73c183510 100644 int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session); diff --git a/drivers/tee/amdtee/core.c b/drivers/tee/amdtee/core.c -index 297dc62bc..e6f1e331d 100644 +index 297dc62bca29..e6f1e331d3c3 100644 --- a/drivers/tee/amdtee/core.c +++ b/drivers/tee/amdtee/core.c @@ -230,7 +230,9 @@ static void destroy_session(struct kref *ref) @@ -2550,7 +3382,7 @@ index 297dc62bc..e6f1e331d 100644 return 0; } diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile -index 3aa33ea9e..446d65dc8 100644 +index 3aa33ea9e6a6..446d65dc83b8 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -1,7 +1,9 @@ @@ -2564,7 +3396,7 @@ index 3aa33ea9e..446d65dc8 100644 optee-objs += supp.o optee-objs += shm_pool.o diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c -index 945f03da0..f2b495ee8 100644 +index 945f03da0223..f2b495ee8c8f 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -17,126 +17,289 @@ @@ -3547,7 +4379,7 @@ index 945f03da0..f2b495ee8 100644 diff --git a/drivers/tee/optee/call_queue.c b/drivers/tee/optee/call_queue.c new file mode 100644 -index 000000000..70922c040 +index 000000000000..70922c040fc6 --- /dev/null +++ b/drivers/tee/optee/call_queue.c @@ -0,0 +1,86 @@ @@ -3638,7 +4470,7 @@ index 000000000..70922c040 + mutex_unlock(&cq->mutex); +} diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c -index 5363ebebf..b7681d24d 100644 +index 50c0d839fe75..ab3e5d65e946 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -8,17 +8,22 @@ @@ -3696,7 +4528,7 @@ index 5363ebebf..b7681d24d 100644 kfree(ctxdata); if (!IS_ERR(shm)) -@@ -355,6 +362,230 @@ static const struct tee_desc optee_supp_desc = { +@@ -355,6 +362,345 @@ static const struct tee_desc optee_supp_desc = { .flags = TEE_DESC_PRIVILEGED, }; @@ -3717,6 +4549,119 @@ index 5363ebebf..b7681d24d 100644 + return 0; +} + ++static u32 get_it_value(optee_invoke_fn *invoke_fn, bool *value_valid, ++ bool *value_pending) ++{ ++ struct arm_smccc_res res; ++ ++ invoke_fn(OPTEE_SMC_GET_IT_NOTIF_VALUE, 0, 0, 0, 0, 0, 0, 0, &res); ++ ++ if (res.a0) ++ return 0; ++ *value_valid = (res.a2 & OPTEE_SMC_IT_NOTIF_VALUE_VALID); ++ *value_pending = (res.a2 & OPTEE_SMC_IT_NOTIF_VALUE_PENDING); ++ return res.a1; ++} ++ ++static u32 set_it_mask(optee_invoke_fn *invoke_fn, u32 it_value, bool mask) ++{ ++ struct arm_smccc_res res; ++ ++ invoke_fn(OPTEE_SMC_SET_IT_NOTIF_MASK, it_value, mask, 0, 0, 0, 0, 0, &res); ++ ++ if (res.a0) ++ return 0; ++ ++ return res.a1; ++} ++ ++static int handle_optee_it(struct optee *optee) ++{ ++ bool value_valid; ++ bool value_pending; ++ u32 it; ++ ++ do { ++ struct irq_desc *desc; ++ ++ it = get_it_value(optee->invoke_fn, &value_valid, ++ &value_pending); ++ if (!value_valid) ++ break; ++ ++ desc = irq_to_desc(irq_find_mapping(optee->domain, it)); ++ if (!desc) { ++ pr_err("no desc for optee IT:%d\n", it); ++ return -EIO; ++ } ++ ++ handle_simple_irq(desc); ++ ++ } while (value_pending); ++ ++ return 0; ++} ++ ++static void optee_it_irq_mask(struct irq_data *d) ++{ ++ struct optee *optee = d->domain->host_data; ++ ++ set_it_mask(optee->invoke_fn, d->hwirq, true); ++} ++ ++static void optee_it_irq_unmask(struct irq_data *d) ++{ ++ struct optee *optee = d->domain->host_data; ++ ++ set_it_mask(optee->invoke_fn, d->hwirq, false); ++} ++ ++static struct irq_chip optee_it_irq_chip = { ++ .name = "optee-it", ++ .irq_disable = optee_it_irq_mask, ++ .irq_enable = optee_it_irq_unmask, ++ .flags = IRQCHIP_SKIP_SET_WAKE, ++}; ++ ++static int optee_it_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_hwirq_and_chip(d, virq, hwirq, &optee_it_irq_chip, d->host_data); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops optee_it_irq_domain_ops = { ++ .alloc = optee_it_alloc, ++ .free = irq_domain_free_irqs_common, ++}; ++ ++static int optee_irq_domain_init(struct platform_device *pdev, struct optee *optee) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ ++ optee->domain = irq_domain_add_linear(np, OPTEE_MAX_IT, ++ &optee_it_irq_domain_ops, ++ optee); ++ if (!optee->domain) { ++ pr_err("Unable to add irq domain!\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static void optee_irq_domain_uninit(struct optee *optee) ++{ ++ irq_domain_remove(optee->domain); ++} ++ +static int optee_smc_do_bottom_half(struct tee_context *ctx) +{ + return simple_call_with_arg(ctx, OPTEE_MSG_CMD_DO_BOTTOM_HALF); @@ -3765,6 +4710,8 @@ index 5363ebebf..b7681d24d 100644 + + if (value == OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF) + do_bottom_half = true; ++ else if (value == OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_IT) ++ handle_optee_it(optee); + else + optee_notif_send(optee, value); + } while (value_pending); @@ -3927,7 +4874,7 @@ index 5363ebebf..b7681d24d 100644 static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn) { struct arm_smccc_res res; -@@ -404,7 +635,7 @@ static bool optee_msg_api_revision_is_compatible(optee_invoke_fn *invoke_fn) +@@ -404,7 +750,7 @@ static bool optee_msg_api_revision_is_compatible(optee_invoke_fn *invoke_fn) } static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, @@ -3936,7 +4883,7 @@ index 5363ebebf..b7681d24d 100644 { union { struct arm_smccc_res smccc; -@@ -427,6 +658,12 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, +@@ -427,6 +773,12 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, return false; *sec_caps = res.result.capabilities; @@ -3949,25 +4896,18 @@ index 5363ebebf..b7681d24d 100644 return true; } -@@ -588,6 +825,8 @@ static int optee_remove(struct platform_device *pdev) - /* Unregister OP-TEE specific client devices on TEE bus */ - optee_unregister_devices(); - -+ optee_notif_uninit(optee); -+ - /* - * Ask OP-TEE to free all cached shared memory objects to decrease - * reference counters and also avoid wild pointers in secure world -@@ -595,6 +834,8 @@ static int optee_remove(struct platform_device *pdev) +@@ -596,6 +948,10 @@ static int optee_remove(struct platform_device *pdev) */ optee_disable_shm_cache(optee); ++ optee_irq_domain_uninit(optee); ++ + optee_smc_notif_uninit_irq(optee); + /* * The two devices have to be unregistered before we can free the * other resources. -@@ -605,7 +846,6 @@ static int optee_remove(struct platform_device *pdev) +@@ -606,7 +962,6 @@ static int optee_remove(struct platform_device *pdev) tee_shm_pool_free(optee->pool); if (optee->memremaped_shm) memunmap(optee->memremaped_shm); @@ -3975,15 +4915,15 @@ index 5363ebebf..b7681d24d 100644 optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); -@@ -633,6 +873,7 @@ static int optee_probe(struct platform_device *pdev) - struct optee *optee = NULL; +@@ -635,6 +990,7 @@ static int optee_probe(struct platform_device *pdev) void *memremaped_shm = NULL; struct tee_device *teedev; + struct tee_context *ctx; + u32 max_notif_value; u32 sec_caps; int rc; -@@ -662,7 +903,8 @@ static int optee_probe(struct platform_device *pdev) +@@ -664,7 +1020,8 @@ static int optee_probe(struct platform_device *pdev) return -EINVAL; } @@ -3993,7 +4933,7 @@ index 5363ebebf..b7681d24d 100644 pr_warn("capabilities mismatch\n"); return -EINVAL; } -@@ -685,7 +927,7 @@ static int optee_probe(struct platform_device *pdev) +@@ -687,7 +1044,7 @@ static int optee_probe(struct platform_device *pdev) optee = kzalloc(sizeof(*optee), GFP_KERNEL); if (!optee) { rc = -ENOMEM; @@ -4002,7 +4942,7 @@ index 5363ebebf..b7681d24d 100644 } optee->invoke_fn = invoke_fn; -@@ -694,32 +936,59 @@ static int optee_probe(struct platform_device *pdev) +@@ -696,38 +1053,73 @@ static int optee_probe(struct platform_device *pdev) teedev = tee_device_alloc(&optee_desc, NULL, pool, optee); if (IS_ERR(teedev)) { rc = PTR_ERR(teedev); @@ -4035,11 +4975,19 @@ index 5363ebebf..b7681d24d 100644 optee_supp_init(&optee->supp); optee->memremaped_shm = memremaped_shm; optee->pool = pool; ++ + ctx = teedev_open(optee->teedev); + if (IS_ERR(ctx)) { + rc = PTR_ERR(ctx); +- goto err; ++ goto err_supp_uninit; + } + optee->ctx = ctx; + platform_set_drvdata(pdev, optee); + rc = optee_notif_init(optee, max_notif_value); + if (rc) -+ goto err_supp_uninit; ++ goto err_close_ctx; + + if (sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) { + unsigned int irq; @@ -4060,6 +5008,13 @@ index 5363ebebf..b7681d24d 100644 + irq_dispose_mapping(irq); + goto err_notif_uninit; + } ++ ++ rc = optee_irq_domain_init(pdev, optee); ++ if (rc) { ++ irq_dispose_mapping(irq); ++ goto err_notif_uninit; ++ } ++ + enable_async_notif(optee->invoke_fn); + pr_info("Asynchronous notifications enabled\n"); + } @@ -4067,7 +5022,7 @@ index 5363ebebf..b7681d24d 100644 /* * Ensure that there are no pre-existing shm objects before enabling * the shm cache so that there's no chance of receiving an invalid -@@ -734,31 +1003,33 @@ static int optee_probe(struct platform_device *pdev) +@@ -742,31 +1134,36 @@ static int optee_probe(struct platform_device *pdev) if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) pr_info("dynamic shared memory is enabled\n"); @@ -4101,8 +5056,11 @@ index 5363ebebf..b7681d24d 100644 + optee_disable_shm_cache(optee); + optee_smc_notif_uninit_irq(optee); + optee_unregister_devices(); ++ optee_irq_domain_uninit(optee); +err_notif_uninit: + optee_notif_uninit(optee); ++err_close_ctx: ++ teedev_close_context(optee->ctx); +err_supp_uninit: + optee_supp_uninit(&optee->supp); + mutex_destroy(&optee->call_queue.mutex); @@ -4122,7 +5080,7 @@ index 5363ebebf..b7681d24d 100644 diff --git a/drivers/tee/optee/notif.c b/drivers/tee/optee/notif.c new file mode 100644 -index 000000000..a28fa03dc +index 000000000000..a28fa03dcd0e --- /dev/null +++ b/drivers/tee/optee/notif.c @@ -0,0 +1,125 @@ @@ -4252,7 +5210,7 @@ index 000000000..a28fa03dc + kfree(optee->notif.bitmap); +} diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h -index e3d72d09c..e247cbce8 100644 +index e3d72d09c484..e247cbce8710 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -12,9 +12,11 @@ @@ -4446,10 +5404,10 @@ index e3d72d09c..e247cbce8 100644 + #endif /* _OPTEE_MSG_H */ diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h -index f6bb4a763..e66b5fcdb 100644 +index ea09533e30cd..37ab55cc104e 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h -@@ -16,14 +16,23 @@ +@@ -16,14 +16,25 @@ /* Some Global Platform error codes used in this driver */ #define TEEC_SUCCESS 0x00000000 @@ -4469,11 +5427,13 @@ index f6bb4a763..e66b5fcdb 100644 + * are usually not even close to 255 so we should be safe for now. + */ +#define OPTEE_DEFAULT_MAX_NOTIF_VALUE 255 ++ ++#define OPTEE_MAX_IT 32 + typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, -@@ -35,10 +44,13 @@ struct optee_call_queue { +@@ -35,10 +46,13 @@ struct optee_call_queue { struct list_head waiters; }; @@ -4490,8 +5450,8 @@ index f6bb4a763..e66b5fcdb 100644 }; /** -@@ -72,8 +84,7 @@ struct optee_supp { - * @teedev: client device +@@ -73,8 +87,7 @@ struct optee_supp { + * @ctx: driver internal TEE context * @invoke_fn: function to issue smc or hvc * @call_queue: queue of threads waiting to call @invoke_fn - * @wait_queue: queue of threads from secure world waiting for a @@ -4500,7 +5460,7 @@ index f6bb4a763..e66b5fcdb 100644 * @supp: supplicant synchronization struct for RPC to supplicant * @pool: shared memory pool * @memremaped_shm virtual address of memory in shared memory pool -@@ -82,13 +93,16 @@ struct optee_supp { +@@ -83,6 +96,9 @@ struct optee_supp { * @scan_bus_done flag if device registation was already done. * @scan_bus_wq workqueue to scan optee bus and register optee drivers * @scan_bus_work workq to scan optee bus and register optee drivers @@ -4510,15 +5470,16 @@ index f6bb4a763..e66b5fcdb 100644 */ struct optee { struct tee_device *supp_teedev; - struct tee_device *teedev; +@@ -90,7 +106,7 @@ struct optee { optee_invoke_fn *invoke_fn; + struct tee_context *ctx; struct optee_call_queue call_queue; - struct optee_wait_queue wait_queue; + struct optee_notif notif; struct optee_supp supp; struct tee_shm_pool *pool; void *memremaped_shm; -@@ -96,17 +110,80 @@ struct optee { +@@ -98,17 +114,81 @@ struct optee { bool scan_bus_done; struct workqueue_struct *scan_bus_wq; struct work_struct scan_bus_work; @@ -4527,6 +5488,7 @@ index f6bb4a763..e66b5fcdb 100644 + struct optee_pcpu __percpu *optee_pcpu; + struct workqueue_struct *notif_pcpu_wq; + struct work_struct notif_pcpu_work; ++ struct irq_domain *domain; +}; + +struct optee_call_waiter { @@ -4599,7 +5561,7 @@ index f6bb4a763..e66b5fcdb 100644 }; struct optee_rpc_param { -@@ -120,19 +197,40 @@ struct optee_rpc_param { +@@ -122,19 +202,40 @@ struct optee_rpc_param { u32 a7; }; @@ -4648,7 +5610,7 @@ index f6bb4a763..e66b5fcdb 100644 u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, struct tee_param *param); -@@ -148,15 +246,40 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params, +@@ -150,15 +251,40 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params, int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params, struct tee_param *param); @@ -4691,7 +5653,7 @@ index f6bb4a763..e66b5fcdb 100644 void optee_enable_shm_cache(struct optee *optee); void optee_disable_shm_cache(struct optee *optee); void optee_disable_unmapped_shm_cache(struct optee *optee); -@@ -171,21 +294,43 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, +@@ -173,21 +299,43 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, unsigned long start); int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm); @@ -4736,7 +5698,7 @@ index f6bb4a763..e66b5fcdb 100644 * Small helpers */ diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h -index b8275140c..f3f06e099 100644 +index b8275140cef8..f3f06e0994a7 100644 --- a/drivers/tee/optee/optee_rpc_cmd.h +++ b/drivers/tee/optee/optee_rpc_cmd.h @@ -28,24 +28,27 @@ @@ -4782,7 +5744,7 @@ index b8275140c..f3f06e099 100644 /* * Suspend execution diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h -index 80eb763a8..f1e9af0ce 100644 +index 80eb763a8a80..6fd5c2cd88a6 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -107,6 +107,12 @@ struct optee_smc_call_get_os_revision_result { @@ -4830,7 +5792,7 @@ index 80eb763a8..f1e9af0ce 100644 }; /* -@@ -319,6 +331,68 @@ struct optee_smc_disable_shm_cache_result { +@@ -319,6 +331,84 @@ struct optee_smc_disable_shm_cache_result { #define OPTEE_SMC_GET_THREAD_COUNT \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_THREAD_COUNT) @@ -4895,12 +5857,28 @@ index 80eb763a8..f1e9af0ce 100644 +#define OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE 17 +#define OPTEE_SMC_GET_ASYNC_NOTIF_VALUE \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE) ++ ++#define OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_IT 1 ++ ++#define OPTEE_SMC_IT_NOTIF_VALUE_VALID BIT(0) ++#define OPTEE_SMC_IT_NOTIF_VALUE_PENDING BIT(1) ++ ++/* ++ * Notification that OP-TEE generates and interruption. ++ */ ++#define OPTEE_SMC_FUNCID_GET_IT_NOTIF_VALUE 53 ++#define OPTEE_SMC_GET_IT_NOTIF_VALUE \ ++ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_IT_NOTIF_VALUE) ++ ++#define OPTEE_SMC_FUNCID_SET_IT_NOTIF_MASK 54 ++#define OPTEE_SMC_SET_IT_NOTIF_MASK \ ++ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_SET_IT_NOTIF_MASK) + /* * Resume from RPC (for example after processing a foreign interrupt) * diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c -index efbaff7ad..bcf5a6faa 100644 +index 456833d82007..ae41f4e640ab 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -14,23 +14,6 @@ @@ -4994,7 +5972,7 @@ index efbaff7ad..bcf5a6faa 100644 break; default: goto bad; -@@ -463,7 +406,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, +@@ -465,7 +408,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, case OPTEE_RPC_CMD_GET_TIME: handle_rpc_func_cmd_get_time(arg); break; @@ -5003,7 +5981,7 @@ index efbaff7ad..bcf5a6faa 100644 handle_rpc_func_cmd_wq(optee, arg); break; case OPTEE_RPC_CMD_SUSPEND: -@@ -539,3 +482,31 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, +@@ -541,3 +484,31 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC; } @@ -5036,43 +6014,10 @@ index efbaff7ad..bcf5a6faa 100644 + return false; +} diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c -index 85102d12d..705bb4e53 100644 +index 3fc426dad2df..705bb4e53301 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c -@@ -43,7 +43,7 @@ static DEFINE_SPINLOCK(driver_lock); - static struct class *tee_class; - static dev_t tee_devt; - --static struct tee_context *teedev_open(struct tee_device *teedev) -+struct tee_context *teedev_open(struct tee_device *teedev) - { - int rc; - struct tee_context *ctx; -@@ -70,6 +70,7 @@ static struct tee_context *teedev_open(struct tee_device *teedev) - return ERR_PTR(rc); - - } -+EXPORT_SYMBOL_GPL(teedev_open); - - void teedev_ctx_get(struct tee_context *ctx) - { -@@ -96,13 +97,14 @@ void teedev_ctx_put(struct tee_context *ctx) - kref_put(&ctx->refcount, teedev_ctx_release); - } - --static void teedev_close_context(struct tee_context *ctx) -+void teedev_close_context(struct tee_context *ctx) - { - struct tee_device *teedev = ctx->teedev; - - teedev_ctx_put(ctx); - tee_device_put(teedev); - } -+EXPORT_SYMBOL_GPL(teedev_close_context); - - static int tee_open(struct inode *inode, struct file *filp) - { -@@ -354,6 +356,14 @@ tee_ioctl_shm_register(struct tee_context *ctx, +@@ -356,6 +356,14 @@ tee_ioctl_shm_register(struct tee_context *ctx, return ret; } @@ -5087,7 +6032,7 @@ index 85102d12d..705bb4e53 100644 static int params_from_user(struct tee_context *ctx, struct tee_param *params, size_t num_params, struct tee_ioctl_param __user *uparams) -@@ -462,6 +472,33 @@ static int params_to_user(struct tee_ioctl_param __user *uparams, +@@ -464,6 +472,33 @@ static int params_to_user(struct tee_ioctl_param __user *uparams, return 0; } @@ -5121,7 +6066,7 @@ index 85102d12d..705bb4e53 100644 static int tee_ioctl_open_session(struct tee_context *ctx, struct tee_ioctl_buf_data __user *ubuf) { -@@ -509,7 +546,9 @@ static int tee_ioctl_open_session(struct tee_context *ctx, +@@ -511,7 +546,9 @@ static int tee_ioctl_open_session(struct tee_context *ctx, goto out; } @@ -5132,7 +6077,7 @@ index 85102d12d..705bb4e53 100644 if (rc) goto out; have_session = true; -@@ -580,7 +619,9 @@ static int tee_ioctl_invoke(struct tee_context *ctx, +@@ -582,7 +619,9 @@ static int tee_ioctl_invoke(struct tee_context *ctx, goto out; } @@ -5143,7 +6088,7 @@ index 85102d12d..705bb4e53 100644 if (rc) goto out; -@@ -1157,9 +1198,22 @@ int tee_client_open_session(struct tee_context *ctx, +@@ -1159,9 +1198,22 @@ int tee_client_open_session(struct tee_context *ctx, struct tee_ioctl_open_session_arg *arg, struct tee_param *param) { @@ -5167,7 +6112,7 @@ index 85102d12d..705bb4e53 100644 } EXPORT_SYMBOL_GPL(tee_client_open_session); -@@ -1175,9 +1229,22 @@ int tee_client_invoke_func(struct tee_context *ctx, +@@ -1177,9 +1229,22 @@ int tee_client_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_param *param) { @@ -5192,7 +6137,7 @@ index 85102d12d..705bb4e53 100644 EXPORT_SYMBOL_GPL(tee_client_invoke_func); diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c -index 499fccba3..4fd4161cb 100644 +index 6e662fb131d5..94282f2bb154 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -157,7 +157,8 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, @@ -5205,7 +6150,7 @@ index 499fccba3..4fd4161cb 100644 return ERR_PTR(-ENOTSUPP); if (!tee_device_get(teedev)) -@@ -431,6 +432,16 @@ struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id) +@@ -434,6 +435,16 @@ struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id) } EXPORT_SYMBOL_GPL(tee_shm_get_from_id); @@ -5222,301 +6167,8 @@ index 499fccba3..4fd4161cb 100644 /** * tee_shm_put() - Decrease reference count on a shared memory handle * @shm: Shared memory handle -diff --git a/drivers/tty/rpmsg_tty.c b/drivers/tty/rpmsg_tty.c -new file mode 100644 -index 000000000..29db413bb ---- /dev/null -+++ b/drivers/tty/rpmsg_tty.c -@@ -0,0 +1,287 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2021 STMicroelectronics - All Rights Reserved -+ * -+ * The rpmsg tty driver implements serial communication on the RPMsg bus to makes -+ * possible for user-space programs to send and receive rpmsg messages as a standard -+ * tty protocol. -+ * -+ * The remote processor can instantiate a new tty by requesting a "rpmsg-tty" RPMsg service. -+ * The "rpmsg-tty" service is directly used for data exchange. No flow control is implemented yet. -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define RPMSG_TTY_NAME "ttyRPMSG" -+#define MAX_TTY_RPMSG 32 -+ -+static DEFINE_IDR(tty_idr); /* tty instance id */ -+static DEFINE_MUTEX(idr_lock); /* protects tty_idr */ -+ -+static struct tty_driver *rpmsg_tty_driver; -+ -+struct rpmsg_tty_port { -+ struct tty_port port; /* TTY port data */ -+ int id; /* TTY rpmsg index */ -+ struct rpmsg_device *rpdev; /* rpmsg device */ -+}; -+ -+static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 src) -+{ -+ struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev); -+ int copied; -+ -+ if (!len) -+ return -EINVAL; -+ copied = tty_insert_flip_string(&cport->port, data, len); -+ if (copied != len) -+ dev_err_ratelimited(&rpdev->dev, "Trunc buffer: available space is %d\n", copied); -+ tty_flip_buffer_push(&cport->port); -+ -+ return 0; -+} -+ -+static int rpmsg_tty_install(struct tty_driver *driver, struct tty_struct *tty) -+{ -+ struct rpmsg_tty_port *cport = idr_find(&tty_idr, tty->index); -+ struct tty_port *port; -+ -+ tty->driver_data = cport; -+ -+ port = tty_port_get(&cport->port); -+ return tty_port_install(port, driver, tty); -+} -+ -+static void rpmsg_tty_cleanup(struct tty_struct *tty) -+{ -+ tty_port_put(tty->port); -+} -+ -+static int rpmsg_tty_open(struct tty_struct *tty, struct file *filp) -+{ -+ return tty_port_open(tty->port, tty, filp); -+} -+ -+static void rpmsg_tty_close(struct tty_struct *tty, struct file *filp) -+{ -+ return tty_port_close(tty->port, tty, filp); -+} -+ -+static int rpmsg_tty_write(struct tty_struct *tty, const u8 *buf, int len) -+{ -+ struct rpmsg_tty_port *cport = tty->driver_data; -+ struct rpmsg_device *rpdev; -+ int msg_max_size, msg_size; -+ int ret; -+ -+ rpdev = cport->rpdev; -+ -+ msg_max_size = rpmsg_get_mtu(rpdev->ept); -+ if (msg_max_size < 0) -+ return msg_max_size; -+ -+ msg_size = min(len, msg_max_size); -+ -+ /* -+ * Use rpmsg_trysend instead of rpmsg_send to send the message so the caller is not -+ * hung until a rpmsg buffer is available. In such case rpmsg_trysend returns -ENOMEM. -+ */ -+ ret = rpmsg_trysend(rpdev->ept, (void *)buf, msg_size); -+ if (ret) { -+ dev_dbg_ratelimited(&rpdev->dev, "rpmsg_send failed: %d\n", ret); -+ return ret; -+ } -+ -+ return msg_size; -+} -+ -+static unsigned int rpmsg_tty_write_room(struct tty_struct *tty) -+{ -+ struct rpmsg_tty_port *cport = tty->driver_data; -+ int size; -+ -+ size = rpmsg_get_mtu(cport->rpdev->ept); -+ if (size < 0) -+ return 0; -+ -+ return size; -+} -+ -+static void rpmsg_tty_hangup(struct tty_struct *tty) -+{ -+ tty_port_hangup(tty->port); -+} -+ -+static const struct tty_operations rpmsg_tty_ops = { -+ .install = rpmsg_tty_install, -+ .open = rpmsg_tty_open, -+ .close = rpmsg_tty_close, -+ .write = rpmsg_tty_write, -+ .write_room = rpmsg_tty_write_room, -+ .hangup = rpmsg_tty_hangup, -+ .cleanup = rpmsg_tty_cleanup, -+}; -+ -+static struct rpmsg_tty_port *rpmsg_tty_alloc_cport(void) -+{ -+ struct rpmsg_tty_port *cport; -+ int ret; -+ -+ cport = kzalloc(sizeof(*cport), GFP_KERNEL); -+ if (!cport) -+ return ERR_PTR(-ENOMEM); -+ -+ mutex_lock(&idr_lock); -+ ret = idr_alloc(&tty_idr, cport, 0, MAX_TTY_RPMSG, GFP_KERNEL); -+ mutex_unlock(&idr_lock); -+ -+ if (ret < 0) { -+ kfree(cport); -+ return ERR_PTR(ret); -+ } -+ -+ cport->id = ret; -+ -+ return cport; -+} -+ -+static void rpmsg_tty_destruct_port(struct tty_port *port) -+{ -+ struct rpmsg_tty_port *cport = container_of(port, struct rpmsg_tty_port, port); -+ -+ mutex_lock(&idr_lock); -+ idr_remove(&tty_idr, cport->id); -+ mutex_unlock(&idr_lock); -+ -+ kfree(cport); -+} -+ -+static const struct tty_port_operations rpmsg_tty_port_ops = { -+ .destruct = rpmsg_tty_destruct_port, -+}; -+ -+ -+static int rpmsg_tty_probe(struct rpmsg_device *rpdev) -+{ -+ struct rpmsg_tty_port *cport; -+ struct device *dev = &rpdev->dev; -+ struct device *tty_dev; -+ int ret; -+ -+ cport = rpmsg_tty_alloc_cport(); -+ if (IS_ERR(cport)) -+ return dev_err_probe(dev, PTR_ERR(cport), "Failed to alloc tty port\n"); -+ -+ tty_port_init(&cport->port); -+ cport->port.ops = &rpmsg_tty_port_ops; -+ -+ tty_dev = tty_port_register_device(&cport->port, rpmsg_tty_driver, -+ cport->id, dev); -+ if (IS_ERR(tty_dev)) { -+ ret = dev_err_probe(dev, PTR_ERR(tty_dev), "Failed to register tty port\n"); -+ tty_port_put(&cport->port); -+ return ret; -+ } -+ -+ cport->rpdev = rpdev; -+ -+ dev_set_drvdata(dev, cport); -+ -+ dev_dbg(dev, "New channel: 0x%x -> 0x%x: " RPMSG_TTY_NAME "%d\n", -+ rpdev->src, rpdev->dst, cport->id); -+ -+ return 0; -+} -+ -+static void rpmsg_tty_remove(struct rpmsg_device *rpdev) -+{ -+ struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev); -+ -+ dev_dbg(&rpdev->dev, "Removing rpmsg tty device %d\n", cport->id); -+ -+ /* User hang up to release the tty */ -+ tty_port_tty_hangup(&cport->port, false); -+ -+ tty_unregister_device(rpmsg_tty_driver, cport->id); -+ -+ tty_port_put(&cport->port); -+} -+ -+static struct rpmsg_device_id rpmsg_driver_tty_id_table[] = { -+ { .name = "rpmsg-tty" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_tty_id_table); -+ -+static struct rpmsg_driver rpmsg_tty_rpmsg_drv = { -+ .drv.name = KBUILD_MODNAME, -+ .id_table = rpmsg_driver_tty_id_table, -+ .probe = rpmsg_tty_probe, -+ .callback = rpmsg_tty_cb, -+ .remove = rpmsg_tty_remove, -+}; -+ -+static int __init rpmsg_tty_init(void) -+{ -+ int ret; -+ -+ rpmsg_tty_driver = tty_alloc_driver(MAX_TTY_RPMSG, TTY_DRIVER_REAL_RAW | -+ TTY_DRIVER_DYNAMIC_DEV); -+ if (IS_ERR(rpmsg_tty_driver)) -+ return PTR_ERR(rpmsg_tty_driver); -+ -+ rpmsg_tty_driver->driver_name = "rpmsg_tty"; -+ rpmsg_tty_driver->name = RPMSG_TTY_NAME; -+ rpmsg_tty_driver->major = 0; -+ rpmsg_tty_driver->type = TTY_DRIVER_TYPE_CONSOLE; -+ -+ /* Disable unused mode by default */ -+ rpmsg_tty_driver->init_termios = tty_std_termios; -+ rpmsg_tty_driver->init_termios.c_lflag &= ~(ECHO | ICANON); -+ rpmsg_tty_driver->init_termios.c_oflag &= ~(OPOST | ONLCR); -+ -+ tty_set_operations(rpmsg_tty_driver, &rpmsg_tty_ops); -+ -+ ret = tty_register_driver(rpmsg_tty_driver); -+ if (ret < 0) { -+ pr_err("Couldn't install driver: %d\n", ret); -+ goto error_put; -+ } -+ -+ ret = register_rpmsg_driver(&rpmsg_tty_rpmsg_drv); -+ if (ret < 0) { -+ pr_err("Couldn't register driver: %d\n", ret); -+ goto error_unregister; -+ } -+ -+ return 0; -+ -+error_unregister: -+ tty_unregister_driver(rpmsg_tty_driver); -+ -+error_put: -+ tty_driver_kref_put(rpmsg_tty_driver); -+ -+ return ret; -+} -+ -+static void __exit rpmsg_tty_exit(void) -+{ -+ unregister_rpmsg_driver(&rpmsg_tty_rpmsg_drv); -+ tty_unregister_driver(rpmsg_tty_driver); -+ tty_driver_kref_put(rpmsg_tty_driver); -+ idr_destroy(&tty_idr); -+} -+ -+module_init(rpmsg_tty_init); -+module_exit(rpmsg_tty_exit); -+ -+MODULE_AUTHOR("Arnaud Pouliquen "); -+MODULE_DESCRIPTION("remote processor messaging tty driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h -index a8dcf8a9a..02fa9116c 100644 +index a8dcf8a9ae88..02fa9116cd60 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -186,6 +186,8 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, @@ -5544,7 +6196,7 @@ index a8dcf8a9a..02fa9116c 100644 /* use a macro to avoid include chaining to get THIS_MODULE */ diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h -index feda1dc7f..7501b9bf6 100644 +index 38b701b7af4c..7501b9bf6d61 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -50,6 +50,8 @@ struct tee_shm_pool; @@ -5595,28 +6247,9 @@ index feda1dc7f..7501b9bf6 100644 /** * tee_shm_put() - Decrease reference count on a shared memory handle * @shm: Shared memory handle -@@ -582,4 +595,18 @@ struct tee_client_driver { - #define to_tee_client_driver(d) \ - container_of(d, struct tee_client_driver, driver) - -+/** -+ * teedev_open() - Open a struct tee_device -+ * @teedev: Device to open -+ * -+ * @return a pointer to struct tee_context on success or an ERR_PTR on failure. -+ */ -+struct tee_context *teedev_open(struct tee_device *teedev); -+ -+/** -+ * teedev_close_context() - closes a struct tee_context -+ * @ctx: The struct tee_context to close -+ */ -+void teedev_close_context(struct tee_context *ctx); -+ - #endif /*__TEE_DRV_H*/ diff --git a/include/linux/tee_remoteproc.h b/include/linux/tee_remoteproc.h new file mode 100644 -index 000000000..5ba0b6116 +index 000000000000..5ba0b611679c --- /dev/null +++ b/include/linux/tee_remoteproc.h @@ -0,0 +1,101 @@ @@ -5721,8 +6354,27 @@ index 000000000..5ba0b6116 + +#endif /* CONFIG_TEE_REMOTEPROC */ +#endif /* TEE_REMOTEPROC_H */ +diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h +index f5ca8740f3fb..1637e68177d9 100644 +--- a/include/uapi/linux/rpmsg.h ++++ b/include/uapi/linux/rpmsg.h +@@ -33,4 +33,14 @@ struct rpmsg_endpoint_info { + */ + #define RPMSG_DESTROY_EPT_IOCTL _IO(0xb5, 0x2) + ++/** ++ * Instantiate a new local rpmsg service device. ++ */ ++#define RPMSG_CREATE_DEV_IOCTL _IOW(0xb5, 0x3, struct rpmsg_endpoint_info) ++ ++/** ++ * Release a local rpmsg device. ++ */ ++#define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info) ++ + #endif diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h -index 25a6c534b..157ec3dbd 100644 +index 25a6c534beb1..157ec3dbd8b8 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -52,6 +52,7 @@ @@ -5785,5 +6437,5 @@ index 25a6c534b..157ec3dbd 100644 * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted * Application -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0010-ARM-5.15.24-stm32mp1-r1-MISC-MEDIA-SOC-THERMAL.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0011-v5.15-stm32mp-r2-MISC-MEDIA-SOC-THERMAL.patch similarity index 89% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0010-ARM-5.15.24-stm32mp1-r1-MISC-MEDIA-SOC-THERMAL.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0011-v5.15-stm32mp-r2-MISC-MEDIA-SOC-THERMAL.patch index 1b76ea6..1bf0c90 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0010-ARM-5.15.24-stm32mp1-r1-MISC-MEDIA-SOC-THERMAL.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0011-v5.15-stm32mp-r2-MISC-MEDIA-SOC-THERMAL.patch @@ -1,38 +1,39 @@ -From 34da0da73b83e12132610e47ee7638ad5e429ba4 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:59:07 +0200 -Subject: [PATCH 10/22] ARM-5.15.24-stm32mp1-r1-MISC-MEDIA-SOC-THERMAL +From ba945334e6168553846f1fcc73a59a463a276255 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:54:37 +0100 +Subject: [PATCH 11/22] v5.15-stm32mp-r2 MISC-MEDIA-SOC-THERMAL -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- - .../bindings/media/i2c/galaxycore,gc2145.yaml | 115 ++ + CONTRIBUTING.md | 30 + + .../bindings/media/i2c/galaxycore,gc2145.yaml | 115 + + .../bindings/media/st,stm32-dcmipp.yaml | 96 + .../bindings/soc/stm32/st,stm32mp1-hslv.yaml | 44 + .../bindings/soc/stm32/stm32_hdp.txt | 39 + - MAINTAINERS | 8 + - drivers/char/hw_random/stm32-rng.c | 182 +- + MAINTAINERS | 17 + + SECURITY.md | 8 + + drivers/char/hw_random/stm32-rng.c | 229 +- drivers/firmware/Kconfig | 2 +- + drivers/gpio/gpiolib.c | 20 +- drivers/input/touchscreen/edt-ft5x06.c | 20 + drivers/input/touchscreen/goodix.c | 39 +- drivers/media/i2c/Kconfig | 12 + drivers/media/i2c/Makefile | 1 + - drivers/media/i2c/gc2145.c | 1754 +++++++++++++++++ - drivers/media/i2c/ov5640.c | 459 +++-- + drivers/media/i2c/gc2145.c | 1949 +++++++++++++++++ + drivers/media/i2c/ov5640.c | 459 +++- drivers/media/i2c/st-mipid02.c | 10 +- drivers/media/platform/Kconfig | 13 + drivers/media/platform/stm32/Makefile | 1 + drivers/media/platform/stm32/stm32-dcmi.c | 129 +- .../platform/stm32/stm32-dcmipp/Makefile | 5 + - .../stm32/stm32-dcmipp/dcmipp-bytecap.c | 1109 +++++++++++ - .../stm32/stm32-dcmipp/dcmipp-byteproc.c | 737 +++++++ - .../stm32/stm32-dcmipp/dcmipp-common.c | 116 ++ - .../stm32/stm32-dcmipp/dcmipp-common.h | 235 +++ - .../platform/stm32/stm32-dcmipp/dcmipp-core.c | 688 +++++++ - .../stm32/stm32-dcmipp/dcmipp-parallel.c | 494 +++++ + .../stm32/stm32-dcmipp/dcmipp-bytecap.c | 1112 ++++++++++ + .../stm32/stm32-dcmipp/dcmipp-byteproc.c | 790 +++++++ + .../stm32/stm32-dcmipp/dcmipp-common.c | 116 + + .../stm32/stm32-dcmipp/dcmipp-common.h | 240 ++ + .../platform/stm32/stm32-dcmipp/dcmipp-core.c | 682 ++++++ + .../stm32/stm32-dcmipp/dcmipp-parallel.c | 497 +++++ drivers/media/v4l2-core/v4l2-fwnode.c | 3 + - drivers/mtd/mtdcore.c | 2 + - drivers/mtd/nand/raw/stm32_fmc2_nand.c | 40 +- - drivers/nvmem/core.c | 2 +- - drivers/nvmem/stm32-romem.c | 498 ++++- + drivers/nvmem/stm32-romem.c | 642 +++++- drivers/of/platform.c | 4 + drivers/pwm/pwm-stm32-lp.c | 4 +- drivers/pwm/pwm-stm32.c | 4 + @@ -41,18 +42,21 @@ Signed-off-by: Christophe Priouzeau drivers/soc/st/Kconfig | 25 + drivers/soc/st/Makefile | 3 + drivers/soc/st/stm32-hslv.c | 157 ++ - drivers/soc/st/stm32_hdp.c | 242 +++ + drivers/soc/st/stm32_hdp.c | 242 ++ drivers/soc/st/stm32_pm_domain.c | 212 ++ drivers/thermal/st/stm_thermal.c | 30 +- include/dt-bindings/soc/stm32-hdp.h | 108 + include/dt-bindings/soc/stm32mp13-hdp.h | 133 ++ - include/linux/nvmem-provider.h | 4 +- + include/linux/smscphy.h | 20 + include/media/mipi-csi2.h | 45 + include/media/v4l2-fwnode.h | 2 + - 44 files changed, 7483 insertions(+), 249 deletions(-) + 45 files changed, 8058 insertions(+), 253 deletions(-) + create mode 100644 CONTRIBUTING.md create mode 100644 Documentation/devicetree/bindings/media/i2c/galaxycore,gc2145.yaml + create mode 100644 Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml create mode 100644 Documentation/devicetree/bindings/soc/stm32/st,stm32mp1-hslv.yaml create mode 100644 Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt + create mode 100644 SECURITY.md create mode 100644 drivers/media/i2c/gc2145.c create mode 100644 drivers/media/platform/stm32/stm32-dcmipp/Makefile create mode 100644 drivers/media/platform/stm32/stm32-dcmipp/dcmipp-bytecap.c @@ -70,9 +74,45 @@ Signed-off-by: Christophe Priouzeau create mode 100644 include/dt-bindings/soc/stm32mp13-hdp.h create mode 100644 include/media/mipi-csi2.h +diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md +new file mode 100644 +index 000000000000..3d1bacd78a54 +--- /dev/null ++++ b/CONTRIBUTING.md +@@ -0,0 +1,30 @@ ++# Contributing guide ++ ++This document serves as a checklist before contributing to this repository. It includes links to read up on if topics are unclear to you. ++ ++This guide mainly focuses on the proper use of Git. ++ ++## 1. Issues ++ ++STM32MPU projects do not activate "Github issues" feature for the time being. If you need to report an issue or question about this project deliverables, you can report them using [ ST Support Center ](https://my.st.com/ols#/ols/newrequest) or [ ST Community MPU Forum ](https://community.st.com/s/topic/0TO0X0000003u2AWAQ/stm32-mpus). ++ ++## 2. Pull Requests ++ ++STMicrolectronics is happy to receive contributions from the community, based on an initial Contributor License Agreement (CLA) procedure. ++ ++* If you are an individual writing original source code and you are sure **you own the intellectual property**, then you need to sign an Individual CLA (https://cla.st.com). ++* If you work for a company that wants also to allow you to contribute with your work, your company needs to provide a Corporate CLA (https://cla.st.com) mentioning your GitHub account name. ++* If you are not sure that a CLA (Individual or Corporate) has been signed for your GitHub account you can check here (https://cla.st.com). ++ ++Please note that: ++* The Corporate CLA will always take precedence over the Individual CLA. ++* One CLA submission is sufficient, for any project proposed by STMicroelectronics. ++ ++__How to proceed__ ++ ++* We recommend to fork the project in your GitHub account to further develop your contribution. Please use the latest commit version. ++* Please, submit one Pull Request for one new feature or proposal. This will ease the analysis and final merge if accepted. ++ ++__Note__ ++ ++Merge will not be done directly in GitHub but it will need first to follow internal integration process before public deliver in a standard release. The Pull request will stay open until it is merged and delivered. diff --git a/Documentation/devicetree/bindings/media/i2c/galaxycore,gc2145.yaml b/Documentation/devicetree/bindings/media/i2c/galaxycore,gc2145.yaml new file mode 100644 -index 000000000..af07250ce +index 000000000000..af07250ceadb --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/galaxycore,gc2145.yaml @@ -0,0 +1,115 @@ @@ -191,9 +231,111 @@ index 000000000..af07250ce + }; + +... +diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml +new file mode 100644 +index 000000000000..70631046017d +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml +@@ -0,0 +1,96 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/st,stm32-dcmipp.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: STMicroelectronics STM32 DCMIPP Digital Camera Memory Interface Pixel Processor binding ++ ++maintainers: ++ - Hugues Fruchet ++ - Alain Volmat ++ ++properties: ++ compatible: ++ const: st,stm32mp13-dcmipp ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ clock-names: ++ items: ++ - const: kclk ++ ++ resets: ++ maxItems: 1 ++ ++ port: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ unevaluatedProperties: false ++ description: ++ DCMIPP supports a single port node with parallel bus. ++ ++ properties: ++ endpoint: ++ $ref: video-interfaces.yaml# ++ unevaluatedProperties: false ++ ++ properties: ++ bus-type: ++ enum: [5, 6] ++ default: 5 ++ ++ bus-width: ++ enum: [8, 10, 12, 14] ++ default: 8 ++ ++ pclk-sample: true ++ hsync-active: true ++ vsync-active: true ++ ++ required: ++ - pclk-sample ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ - resets ++ - port ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ dcmipp: dcmipp@5a000000 { ++ compatible = "st,stm32mp13-dcmipp"; ++ reg = <0x5a000000 0x400>; ++ interrupts = ; ++ resets = <&rcc DCMIPP_R>; ++ clocks = <&rcc DCMIPP_K>; ++ clock-names = "kclk"; ++ ++ port { ++ dcmipp_0: endpoint { ++ remote-endpoint = <&mipid02_2>; ++ bus-width = <8>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ pclk-sample = <0>; ++ pclk-max-frequency = <120000000>; ++ }; ++ }; ++ }; ++ ++... diff --git a/Documentation/devicetree/bindings/soc/stm32/st,stm32mp1-hslv.yaml b/Documentation/devicetree/bindings/soc/stm32/st,stm32mp1-hslv.yaml new file mode 100644 -index 000000000..a228a5b26 +index 000000000000..a228a5b262d3 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/stm32/st,stm32mp1-hslv.yaml @@ -0,0 +1,44 @@ @@ -243,7 +385,7 @@ index 000000000..a228a5b26 +... diff --git a/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt b/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt new file mode 100644 -index 000000000..e2bd82f49 +index 000000000000..e2bd82f4980e --- /dev/null +++ b/Documentation/devicetree/bindings/soc/stm32/stm32_hdp.txt @@ -0,0 +1,39 @@ @@ -287,10 +429,10 @@ index 000000000..e2bd82f49 + STM32_HDP(7, HDP7_GPOVAL_7))>; +}; diff --git a/MAINTAINERS b/MAINTAINERS -index 3b79fd441..d95abb753 100644 +index edc32575828b..29e2729008d9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -7748,6 +7748,14 @@ F: kernel/futex.c +@@ -7753,6 +7753,14 @@ F: kernel/futex.c F: tools/perf/bench/futex* F: tools/testing/selftests/futex/ @@ -305,11 +447,41 @@ index 3b79fd441..d95abb753 100644 GATEWORKS SYSTEM CONTROLLER (GSC) DRIVER M: Tim Harvey M: Robert Jones +@@ -11732,6 +11740,15 @@ T: git git://linuxtv.org/media_tree.git + F: Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml + F: drivers/media/platform/stm32/stm32-dcmi.c + ++MEDIA DRIVERS FOR STM32 - DCMIPP ++M: Hugues Fruchet ++M: Alain Volmat ++L: linux-media@vger.kernel.org ++S: Supported ++T: git git://linuxtv.org/media_tree.git ++F: Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml ++F: drivers/media/platform/stm32/stm32-dcmipp/* ++ + MEDIA INPUT INFRASTRUCTURE (V4L/DVB) + M: Mauro Carvalho Chehab + L: linux-media@vger.kernel.org +diff --git a/SECURITY.md b/SECURITY.md +new file mode 100644 +index 000000000000..4b3e4e6ba5e1 +--- /dev/null ++++ b/SECURITY.md +@@ -0,0 +1,8 @@ ++# Report potential product security vulnerabilities ++ST places a high priority on security, and our Product Security Incident Response Team (PSIRT) is committed to rapidly addressing potential security vulnerabilities affecting our products. PSIRT's long history and vast experience in security allows ST to perform clear analyses and provide appropriate guidance on mitigations and solutions when applicable. ++If you wish to report potential security vulnerabilities regarding our products, **please do not report them through public GitHub issues.** Instead, we encourage you to report them to our ST PSIRT following the process described at: **https://www.st.com/content/st_com/en/security/report-vulnerabilities.html** ++ ++### IMPORTANT - READ CAREFULLY: ++STMicroelectronics International N.V., on behalf of itself, its affiliates and subsidiaries, (collectively “ST”) takes all potential security vulnerability reports or other related communications (“Report(s)”) seriously. In order to review Your Report (the terms “You” and “Yours” include your employer, and all affiliates, subsidiaries and related persons or entities) and take actions as deemed appropriate, ST requires that we have the rights and Your permission to do so. ++As such, by submitting Your Report to ST, You agree that You have the right to do so, and You grant to ST the rights to use the Report for purposes related to security vulnerability analysis, testing, correction, patching, reporting and any other related purpose or function. ++By submitting Your Report, You agree that ST’s [Privacy Policy](https://www.st.com/content/st_com/en/common/privacy-portal.html) applies to all related communications. diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c -index bc22178f8..f88f9ce2f 100644 +index bc22178f83e8..e0a8025b45db 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c -@@ -16,22 +16,33 @@ +@@ -16,22 +16,36 @@ #include #include @@ -338,6 +510,8 @@ index bc22178f8..f88f9ce2f 100644 +#define RNG_NIST_CONFIG_B 0x1801000 +#define RNG_NIST_CONFIG_MASK GENMASK(25, 8) + ++#define RNG_MAX_NOISE_CLK_FREQ 3000000 ++ +struct stm32_rng_data { + bool has_cond_reset; +}; @@ -348,10 +522,38 @@ index bc22178f8..f88f9ce2f 100644 struct clk *clk; struct reset_control *rst; + const struct stm32_rng_data *data; ++ u32 pm_cr; bool ced; }; -@@ -84,34 +95,119 @@ static int stm32_rng_init(struct hwrng *rng) +@@ -79,39 +93,168 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) + return retval || !wait ? retval : -EIO; + } + ++static uint stm32_rng_clock_freq_restrain(struct hwrng *rng) ++{ ++ struct stm32_rng_private *priv = ++ container_of(rng, struct stm32_rng_private, rng); ++ unsigned long clock_rate = 0; ++ uint clock_div = 0; ++ ++ clock_rate = clk_get_rate(priv->clk); ++ ++ /* ++ * Get the exponent to apply on the CLKDIV field in RNG_CR register ++ * No need to handle the case when clock-div > 0xF as it is physically ++ * impossible ++ */ ++ while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ) ++ clock_div++; ++ ++ pr_debug("RNG clk rate : %lu\n", clk_get_rate(priv->clk) >> clock_div); ++ ++ return clock_div; ++} ++ + static int stm32_rng_init(struct hwrng *rng) + { struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); int err; @@ -368,23 +570,25 @@ index bc22178f8..f88f9ce2f 100644 - priv->base + RNG_CR); + reg = readl_relaxed(priv->base + RNG_CR); + -+ if (!priv->ced) { ++ if (!priv->ced) + reg |= RNG_CR_CED; -+ if (priv->data->has_cond_reset) { -+ reg &= ~RNG_NIST_CONFIG_MASK; -+ reg |= RNG_CR_CONDRST | RNG_NIST_CONFIG_B; -+ writel_relaxed(reg, priv->base + RNG_CR); -+ reg &= ~RNG_CR_CONDRST; -+ reg |= RNG_CR_CONFLOCK; -+ writel_relaxed(reg, priv->base + RNG_CR); -+ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, -+ reg, (!(reg & RNG_CR_CONDRST)), -+ 10, 50000); -+ if (err) { -+ dev_err((struct device *)priv->rng.priv, -+ "%s: timeout %x!\n", __func__, reg); -+ return -EINVAL; -+ } ++ ++ if (priv->data->has_cond_reset) { ++ uint clock_div = stm32_rng_clock_freq_restrain(rng); ++ ++ reg &= ~RNG_NIST_CONFIG_MASK; ++ reg |= RNG_CR_CONDRST | RNG_NIST_CONFIG_B | clock_div; ++ writel_relaxed(reg, priv->base + RNG_CR); ++ reg &= ~RNG_CR_CONDRST; ++ reg |= RNG_CR_CONFLOCK; ++ writel_relaxed(reg, priv->base + RNG_CR); ++ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg, ++ (!(reg & RNG_CR_CONDRST)), ++ 10, 50000); ++ if (err) { ++ dev_err((struct device *)priv->rng.priv, ++ "%s: timeout %x!\n", __func__, reg); ++ return -EINVAL; + } + } @@ -413,8 +617,7 @@ index bc22178f8..f88f9ce2f 100644 - struct stm32_rng_private *priv = - container_of(rng, struct stm32_rng_private, rng); + pm_runtime_disable(&ofdev->dev); - -- writel_relaxed(0, priv->base + RNG_CR); ++ + return 0; +} + @@ -423,27 +626,48 @@ index bc22178f8..f88f9ce2f 100644 +{ + u32 reg; + struct stm32_rng_private *priv = dev_get_drvdata(dev); -+ + +- writel_relaxed(0, priv->base + RNG_CR); + reg = readl_relaxed(priv->base + RNG_CR); + reg &= ~RNG_CR_RNGEN; ++ priv->pm_cr = reg; + writel_relaxed(reg, priv->base + RNG_CR); clk_disable_unprepare(priv->clk); + + return 0; -+} -+ + } + +static int stm32_rng_runtime_resume(struct device *dev) +{ + u32 reg; + struct stm32_rng_private *priv = dev_get_drvdata(dev); + + clk_prepare_enable(priv->clk); -+ reg = readl_relaxed(priv->base + RNG_CR); -+ reg |= RNG_CR_RNGEN; -+ writel_relaxed(reg, priv->base + RNG_CR); ++ ++ /* Clean error indications */ ++ writel_relaxed(0, priv->base + RNG_SR); ++ ++ if (priv->data->has_cond_reset) { ++ /* ++ * Correct configuration in bits [29:4] must be set in the same ++ * access that set RNG_CR_CONDRST bit. Else config setting is ++ * not taken into account. CONFIGLOCK bit must also be unset but ++ * it is not handled at the moment. ++ */ ++ writel_relaxed(priv->pm_cr | RNG_CR_CONDRST, priv->base + RNG_CR); ++ ++ reg = readl_relaxed(priv->base + RNG_CR); ++ reg |= RNG_CR_RNGEN; ++ reg &= ~RNG_CR_CONDRST; ++ writel_relaxed(reg, priv->base + RNG_CR); ++ } else { ++ reg = readl_relaxed(priv->base + RNG_CR); ++ reg |= RNG_CR_RNGEN; ++ writel_relaxed(reg, priv->base + RNG_CR); ++ } + + return 0; - } ++} +#endif + +static const struct dev_pm_ops stm32_rng_pm_ops = { @@ -473,14 +697,14 @@ index bc22178f8..f88f9ce2f 100644 + {}, +}; +MODULE_DEVICE_TABLE(of, stm32_rng_match); - ++ static int stm32_rng_probe(struct platform_device *ofdev) { + const struct of_device_id *match; struct device *dev = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; struct stm32_rng_private *priv; -@@ -143,13 +239,18 @@ static int stm32_rng_probe(struct platform_device *ofdev) +@@ -143,13 +286,18 @@ static int stm32_rng_probe(struct platform_device *ofdev) priv->ced = of_property_read_bool(np, "clock-error-detect"); @@ -502,7 +726,7 @@ index bc22178f8..f88f9ce2f 100644 priv->rng.read = stm32_rng_read; priv->rng.priv = (unsigned long) dev; priv->rng.quality = 900; -@@ -161,47 +262,6 @@ static int stm32_rng_probe(struct platform_device *ofdev) +@@ -161,47 +309,6 @@ static int stm32_rng_probe(struct platform_device *ofdev) return devm_hwrng_register(dev, &priv->rng); } @@ -551,7 +775,7 @@ index bc22178f8..f88f9ce2f 100644 .driver = { .name = "stm32-rng", diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig -index cda7d7162..dd44afd6a 100644 +index 97ce31e667fc..b54bfd332613 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -11,7 +11,7 @@ source "drivers/firmware/arm_scmi/Kconfig" @@ -563,8 +787,47 @@ index cda7d7162..dd44afd6a 100644 help System Control and Power Interface (SCPI) Message Protocol is defined for the purpose of communication between the Application +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 320baed949ee..db4ad34fcac4 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -422,8 +422,16 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip) + if (count > chip->ngpio) + count = chip->ngpio; + +- for (i = 0; i < count; i++) +- gdev->descs[i].name = names[chip->offset + i]; ++ for (i = 0; i < count; i++) { ++ /* ++ * Allow overriding "fixed" names provided by the GPIO ++ * provider. The "fixed" names are more often than not ++ * generic and less informative than the names given in ++ * device properties. ++ */ ++ if (names[chip->offset + i] && names[chip->offset + i][0]) ++ gdev->descs[i].name = names[chip->offset + i]; ++ } + + kfree(names); + +@@ -708,10 +716,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + INIT_LIST_HEAD(&gdev->pin_ranges); + #endif + +- if (gc->names) ++ if (gc->names) { + ret = gpiochip_set_desc_names(gc); +- else +- ret = devprop_gpiochip_set_names(gc); ++ if (ret) ++ goto err_remove_from_list; ++ } ++ ret = devprop_gpiochip_set_names(gc); + if (ret) + goto err_remove_from_list; + diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c -index bb2e1cbff..918d81e6e 100644 +index bb2e1cbffba7..918d81e6ebac 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -30,6 +30,8 @@ @@ -616,18 +879,18 @@ index bb2e1cbff..918d81e6e 100644 dev_dbg(&client->dev, diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c -index 5051a1766..f96979543 100644 +index 3667f7e51fde..890cc8270c6a 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c -@@ -21,6 +21,7 @@ - #include +@@ -16,6 +16,7 @@ + #include #include #include +#include #include #include - #include -@@ -310,7 +311,7 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) + #include +@@ -248,7 +249,7 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) error = goodix_i2c_read(ts->client, addr, data, header_contact_keycode_size); if (error) { @@ -636,7 +899,7 @@ index 5051a1766..f96979543 100644 error); return error; } -@@ -438,7 +439,7 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) +@@ -376,7 +377,7 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) goodix_process_events(ts); if (goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0) < 0) @@ -645,7 +908,7 @@ index 5051a1766..f96979543 100644 return IRQ_HANDLED; } -@@ -1157,6 +1158,8 @@ static int goodix_ts_probe(struct i2c_client *client, +@@ -1135,6 +1136,8 @@ static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct goodix_ts_data *ts; @@ -654,10 +917,10 @@ index 5051a1766..f96979543 100644 int error; dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr); -@@ -1210,6 +1213,26 @@ static int goodix_ts_probe(struct i2c_client *client, - dev_err(&client->dev, "Controller reset failed.\n"); +@@ -1186,6 +1189,26 @@ static int goodix_ts_probe(struct i2c_client *client, + error = goodix_reset(ts); + if (error) return error; - } + } else { + /* reset the controller */ + if (ts->gpiod_rst) { @@ -681,7 +944,7 @@ index 5051a1766..f96979543 100644 } error = goodix_i2c_test(client); -@@ -1256,6 +1279,17 @@ static int goodix_ts_probe(struct i2c_client *client, +@@ -1232,6 +1255,17 @@ static int goodix_ts_probe(struct i2c_client *client, return error; } @@ -699,7 +962,7 @@ index 5051a1766..f96979543 100644 return 0; } -@@ -1311,6 +1345,7 @@ static int __maybe_unused goodix_suspend(struct device *dev) +@@ -1287,6 +1321,7 @@ static int __maybe_unused goodix_suspend(struct device *dev) * sooner, delay 58ms here. */ msleep(58); @@ -708,7 +971,7 @@ index 5051a1766..f96979543 100644 } diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig -index 6157e73ee..9343c680b 100644 +index 6157e73eef24..9343c680b87c 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -730,6 +730,18 @@ config VIDEO_APTINA_PLL @@ -731,7 +994,7 @@ index 6157e73ee..9343c680b 100644 tristate "Hynix Hi-556 sensor support" depends on I2C && VIDEO_V4L2 diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile -index 83268f20a..3916c2818 100644 +index 83268f20aa3a..3916c2818522 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -133,4 +133,5 @@ obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o @@ -742,10 +1005,10 @@ index 83268f20a..3916c2818 100644 obj-$(CONFIG_SDR_MAX2175) += max2175.o diff --git a/drivers/media/i2c/gc2145.c b/drivers/media/i2c/gc2145.c new file mode 100644 -index 000000000..f0c7a8ad7 +index 000000000000..f892f18dc19b --- /dev/null +++ b/drivers/media/i2c/gc2145.c -@@ -0,0 +1,1754 @@ +@@ -0,0 +1,1949 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * A V4L2 driver for Galaxycore GC2145 camera. @@ -771,7 +1034,10 @@ index 000000000..f0c7a8ad7 + +/* Chip ID */ +/* Page 0 */ ++#define GC2145_REG_ANALOG_MODE1 0x17 +#define GC2145_REG_OUTPUT_FMT 0x84 ++#define GC2145_REG_DEBUG_MODE2 0x8c ++#define GC2145_REG_DEBUG_MODE3 0x8d +#define GC2145_REG_CHIP_ID 0xf0 +#define GC2145_REG_PAGE_SELECT 0xfe +/* Page 3 */ @@ -1688,6 +1954,14 @@ index 000000000..f0c7a8ad7 + }, +}; + ++struct gc2145_ctrls { ++ struct v4l2_ctrl_handler handler; ++ struct v4l2_ctrl *pixel_rate; ++ struct v4l2_ctrl *test_pattern; ++ struct v4l2_ctrl *hflip; ++ struct v4l2_ctrl *vflip; ++}; ++ +struct gc2145 { + struct v4l2_subdev sd; + struct media_pad pad; @@ -1700,9 +1974,8 @@ index 000000000..f0c7a8ad7 + struct gpio_desc *powerdown_gpio; + struct regulator_bulk_data supplies[GC2145_NUM_SUPPLIES]; + -+ struct v4l2_ctrl_handler ctrl_handler; -+ /* V4L2 Controls */ -+ struct v4l2_ctrl *pixel_rate; ++ /* V4L2 controls */ ++ struct gc2145_ctrls ctrls; + + /* Current mode */ + const struct gc2145_mode *mode; @@ -1722,6 +1995,12 @@ index 000000000..f0c7a8ad7 + return container_of(_sd, struct gc2145, sd); +} + ++static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct gc2145, ++ ctrls.handler)->sd; ++} ++ +static int gc2145_read_reg(struct gc2145 *gc2145, u8 addr, u8 *data, int data_size) +{ + struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd); @@ -1774,6 +2053,22 @@ index 000000000..f0c7a8ad7 + return 0; +} + ++static int gc2145_mod_reg(struct gc2145 *gc2145, u16 reg, u8 mask, u8 val) ++{ ++ u8 readval; ++ int ret; ++ ++ ret = gc2145_read_reg(gc2145, reg, &readval, 1); ++ if (ret) ++ return ret; ++ ++ readval &= ~mask; ++ val &= mask; ++ val |= readval; ++ ++ return gc2145_write_reg(gc2145, reg, val); ++} ++ +/* Write a list of registers */ +static int gc2145_write_regs(struct gc2145 *gc2145, const struct gc2145_reg *regs, u32 len) +{ @@ -1877,6 +2172,36 @@ index 000000000..f0c7a8ad7 + return 0; +} + ++static int gc2145_enum_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_frame_interval_enum *fie) ++{ ++ struct gc2145 *gc2145 = to_gc2145(sd); ++ const struct gc2145_format *gc2145_format; ++ u32 code, i; ++ ++ /* The driver currently only support a unique framerate per resolution */ ++ if (fie->index > 0) ++ return -EINVAL; ++ ++ gc2145_format = gc2145_get_format_code(gc2145, fie->code); ++ code = gc2145_format->code; ++ if (fie->code != code) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(supported_modes); i++) ++ if (supported_modes[i].width == fie->width && ++ supported_modes[i].height == fie->height) ++ break; ++ ++ if (i >= ARRAY_SIZE(supported_modes)) ++ return -EINVAL; ++ ++ fie->interval.numerator = supported_modes[i].frame_interval.numerator; ++ fie->interval.denominator = supported_modes[i].frame_interval.denominator; ++ ++ return 0; ++} ++ +static void gc2145_reset_colorspace(struct v4l2_mbus_framefmt *fmt) +{ + fmt->colorspace = V4L2_COLORSPACE_SRGB; @@ -1930,6 +2255,7 @@ index 000000000..f0c7a8ad7 + const struct gc2145_mode *mode; + const struct gc2145_format *gc2145_fmt; + struct v4l2_mbus_framefmt *framefmt; ++ struct gc2145_ctrls *ctrls = &gc2145->ctrls; + + mutex_lock(&gc2145->mutex); + @@ -1952,7 +2278,7 @@ index 000000000..f0c7a8ad7 + gc2145->fmt = fmt->format; + gc2145->mode = mode; + /* Update pixel_rate based on the mode */ -+ __v4l2_ctrl_s_ctrl_int64(gc2145->pixel_rate, mode->pixel_rate); ++ __v4l2_ctrl_s_ctrl_int64(ctrls->pixel_rate, mode->pixel_rate); + } + + mutex_unlock(&gc2145->mutex); @@ -2062,8 +2388,13 @@ index 000000000..f0c7a8ad7 + if (ret) + return ret; + ++ /* Come back on page 0 by default */ ++ ret = gc2145_write_reg(gc2145, GC2145_REG_PAGE_SELECT, 0x00); ++ if (ret) ++ return ret; ++ + /* Apply customized values from user */ -+ ret = __v4l2_ctrl_handler_setup(gc2145->sd.ctrl_handler); ++ ret = __v4l2_ctrl_handler_setup(&gc2145->ctrls.handler); + if (ret) + goto err_rpm_put; + @@ -2245,6 +2576,42 @@ index 000000000..f0c7a8ad7 + return 0; +} + ++static const char * const test_pattern_menu[] = { ++ "Disabled", ++ "Colored patterns", ++ "Uniform white", ++ "Uniform yellow", ++ "Uniform cyan", ++ "Uniform green", ++ "Uniform magenta", ++ "Uniform red", ++ "Uniform black", ++}; ++ ++#define GC2145_TEST_PATTERN_ENABLE BIT(0) ++#define GC2145_TEST_PATTERN_UXGA BIT(3) ++ ++#define GC2145_TEST_UNIFORM BIT(3) ++#define GC2145_TEST_WHITE (4 << 4) ++#define GC2145_TEST_YELLOW (8 << 4) ++#define GC2145_TEST_CYAN (9 << 4) ++#define GC2145_TEST_GREEN (6 << 4) ++#define GC2145_TEST_MAGENTA (10 << 4) ++#define GC2145_TEST_RED (5 << 4) ++#define GC2145_TEST_BLACK (0) ++ ++static const u8 test_pattern_val[] = { ++ 0, ++ GC2145_TEST_PATTERN_ENABLE, ++ GC2145_TEST_UNIFORM | GC2145_TEST_WHITE, ++ GC2145_TEST_UNIFORM | GC2145_TEST_YELLOW, ++ GC2145_TEST_UNIFORM | GC2145_TEST_CYAN, ++ GC2145_TEST_UNIFORM | GC2145_TEST_GREEN, ++ GC2145_TEST_UNIFORM | GC2145_TEST_MAGENTA, ++ GC2145_TEST_UNIFORM | GC2145_TEST_RED, ++ GC2145_TEST_UNIFORM | GC2145_TEST_BLACK, ++}; ++ +static const struct v4l2_subdev_core_ops gc2145_core_ops = { + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, @@ -2265,6 +2632,7 @@ index 000000000..f0c7a8ad7 + .get_fmt = gc2145_get_pad_format, + .set_fmt = gc2145_set_pad_format, + .enum_frame_size = gc2145_enum_frame_size, ++ .enum_frame_interval = gc2145_enum_frame_interval, +}; + +static const struct v4l2_subdev_ops gc2145_subdev_ops = { @@ -2277,38 +2645,124 @@ index 000000000..f0c7a8ad7 + .open = gc2145_open, +}; + ++static int gc2145_set_ctrl_test_pattern(struct gc2145 *gc2145, int value) ++{ ++ int ret; ++ ++ if (!value) { ++ /* Disable test pattern */ ++ ret = gc2145_write_reg(gc2145, GC2145_REG_DEBUG_MODE2, 0); ++ if (ret) ++ return ret; ++ ++ return gc2145_write_reg(gc2145, GC2145_REG_DEBUG_MODE3, 0); ++ } ++ ++ /* Enable test pattern, colored or uniform */ ++ ret = gc2145_write_reg(gc2145, GC2145_REG_DEBUG_MODE2, ++ GC2145_TEST_PATTERN_ENABLE | ++ GC2145_TEST_PATTERN_UXGA); ++ if (ret) ++ return ret; ++ ++ if (!(test_pattern_val[value] & GC2145_TEST_UNIFORM)) ++ return gc2145_write_reg(gc2145, GC2145_REG_DEBUG_MODE3, 0); ++ ++ /* Uniform */ ++ return gc2145_write_reg(gc2145, GC2145_REG_DEBUG_MODE3, ++ test_pattern_val[value]); ++} ++ ++static int gc2145_set_ctrl_hflip(struct gc2145 *gc2145, int value) ++{ ++ return gc2145_mod_reg(gc2145, GC2145_REG_ANALOG_MODE1, ++ BIT(0), (value ? BIT(0) : 0)); ++} ++ ++static int gc2145_set_ctrl_vflip(struct gc2145 *gc2145, int value) ++{ ++ return gc2145_mod_reg(gc2145, GC2145_REG_ANALOG_MODE1, ++ BIT(1), (value ? BIT(1) : 0)); ++} ++ ++static int gc2145_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = ctrl_to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gc2145 *gc2145 = to_gc2145(sd); ++ int ret; ++ ++ /* v4l2_ctrl_lock() locks our own mutex */ ++ ++ ret = pm_runtime_resume_and_get(&client->dev); ++ if (ret < 0) ++ return ret; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_TEST_PATTERN: ++ ret = gc2145_set_ctrl_test_pattern(gc2145, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = gc2145_set_ctrl_hflip(gc2145, ctrl->val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = gc2145_set_ctrl_vflip(gc2145, ctrl->val); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ pm_runtime_put(&client->dev); ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops gc2145_ctrl_ops = { ++ .s_ctrl = gc2145_s_ctrl, ++}; ++ +/* Initialize control handlers */ +static int gc2145_init_controls(struct gc2145 *gc2145) +{ + struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd); -+ struct v4l2_ctrl_handler *ctrl_hdlr; ++ const struct v4l2_ctrl_ops *ops = &gc2145_ctrl_ops; ++ struct gc2145_ctrls *ctrls = &gc2145->ctrls; ++ struct v4l2_ctrl_handler *hdl = &ctrls->handler; + int ret; + -+ ctrl_hdlr = &gc2145->ctrl_handler; -+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); ++ ret = v4l2_ctrl_handler_init(hdl, 12); + if (ret) + return ret; + -+ mutex_init(&gc2145->mutex); -+ ctrl_hdlr->lock = &gc2145->mutex; ++ hdl->lock = &gc2145->mutex; + + /* By default, PIXEL_RATE is read only */ -+ gc2145->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_PIXEL_RATE, 0, INT_MAX, 1, -+ GC2145_640_480_PIXELRATE); -+ gc2145->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE, ++ 0, INT_MAX, 1, ++ GC2145_640_480_PIXELRATE); ++ ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY; + -+ if (ctrl_hdlr->error) { -+ ret = ctrl_hdlr->error; ++ ctrls->test_pattern = ++ v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN, ++ ARRAY_SIZE(test_pattern_menu) - 1, ++ 0, 0, test_pattern_menu); ++ ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, ++ 0, 1, 1, 0); ++ ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, ++ 0, 1, 1, 0); ++ ++ if (hdl->error) { ++ ret = hdl->error; + dev_err(&client->dev, "control init failed (%d)\n", ret); + goto error; + } + -+ gc2145->sd.ctrl_handler = ctrl_hdlr; ++ gc2145->sd.ctrl_handler = hdl; + + return 0; + +error: -+ v4l2_ctrl_handler_free(ctrl_hdlr); ++ v4l2_ctrl_handler_free(hdl); + mutex_destroy(&gc2145->mutex); + + return ret; @@ -2316,8 +2770,7 @@ index 000000000..f0c7a8ad7 + +static void gc2145_free_controls(struct gc2145 *gc2145) +{ -+ v4l2_ctrl_handler_free(gc2145->sd.ctrl_handler); -+ mutex_destroy(&gc2145->mutex); ++ v4l2_ctrl_handler_free(&gc2145->ctrls.handler); +} + +static int gc2145_check_hwcfg(struct device *dev) @@ -2404,6 +2857,8 @@ index 000000000..f0c7a8ad7 + if (ret) + return ret; + ++ mutex_init(&gc2145->mutex); ++ + ret = gc2145_identify_module(gc2145); + if (ret) + goto error_power_off; @@ -2453,6 +2908,7 @@ index 000000000..f0c7a8ad7 + +error_power_off: + gc2145_power_off(dev); ++ mutex_destroy(&gc2145->mutex); + + return ret; +} @@ -2471,6 +2927,8 @@ index 000000000..f0c7a8ad7 + gc2145_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + ++ mutex_destroy(&gc2145->mutex); ++ + return 0; +} + @@ -2501,7 +2959,7 @@ index 000000000..f0c7a8ad7 +MODULE_DESCRIPTION("GalaxyCore GC2145 sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c -index ddbd71394..551075a64 100644 +index db5a19babe67..df2b1fc1a4eb 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -65,6 +65,7 @@ @@ -3174,8 +3632,8 @@ index ddbd71394..551075a64 100644 struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) @@ -2325,8 +2528,14 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd, - if (mbus_fmt->code != sensor->fmt.code) - sensor->pending_fmt_change = true; + /* update format even if code is unchanged, resolution might change */ + sensor->fmt = *mbus_fmt; - __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, - ov5640_calc_pixel_rate(sensor)); @@ -3279,7 +3737,7 @@ index ddbd71394..551075a64 100644 sensor->xclk = devm_clk_get(dev, "xclk"); if (IS_ERR(sensor->xclk)) { diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c -index f630b88cb..b69e5baaf 100644 +index f630b88cbfaa..b69e5baafb2e 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -50,6 +50,7 @@ @@ -3330,7 +3788,7 @@ index f630b88cb..b69e5baaf 100644 return 0; } diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 80321e038..94a4ba771 100644 +index 80321e03809a..94a4ba771a7f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -138,6 +138,19 @@ config VIDEO_STM32_DCMI @@ -3354,7 +3812,7 @@ index 80321e038..94a4ba771 100644 tristate "Renesas Capture Engine Unit (CEU) driver" depends on VIDEO_DEV && VIDEO_V4L2 diff --git a/drivers/media/platform/stm32/Makefile b/drivers/media/platform/stm32/Makefile -index 48b36db2c..a37eee4bf 100644 +index 48b36db2c2e2..a37eee4bfad7 100644 --- a/drivers/media/platform/stm32/Makefile +++ b/drivers/media/platform/stm32/Makefile @@ -1,2 +1,3 @@ @@ -3362,7 +3820,7 @@ index 48b36db2c..a37eee4bf 100644 obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32-dcmi.o +obj-$(CONFIG_VIDEO_STM32_DCMIPP) += stm32-dcmipp/ diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c -index 611071864..c6d58e3ec 100644 +index 6110718645a4..c6d58e3ecd41 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -95,6 +95,9 @@ enum state { @@ -3645,7 +4103,7 @@ index 611071864..c6d58e3ec 100644 media_device_cleanup(&dcmi->mdev); diff --git a/drivers/media/platform/stm32/stm32-dcmipp/Makefile b/drivers/media/platform/stm32/stm32-dcmipp/Makefile new file mode 100644 -index 000000000..cbddc9814 +index 000000000000..cbddc98141a4 --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmipp/Makefile @@ -0,0 +1,5 @@ @@ -3656,10 +4114,10 @@ index 000000000..cbddc9814 +obj-$(CONFIG_VIDEO_STM32_DCMIPP) += dcmipp-parallel.o dcmipp-byteproc.o dcmipp-bytecap.o diff --git a/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-bytecap.c b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-bytecap.c new file mode 100644 -index 000000000..415766c08 +index 000000000000..01b1fb6ce488 --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-bytecap.c -@@ -0,0 +1,1109 @@ +@@ -0,0 +1,1112 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for STM32 Digital Camera Memory Interface Pixel Processor @@ -3825,7 +4283,10 @@ index 000000000..415766c08 + .height = DCMIPP_FMT_HEIGHT_DEFAULT, + .pixelformat = V4L2_PIX_FMT_RGB565, + .field = V4L2_FIELD_NONE, -+ .colorspace = V4L2_COLORSPACE_DEFAULT, ++ .colorspace = DCMIPP_COLORSPACE_DEFAULT, ++ .ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT, ++ .quantization = DCMIPP_QUANTIZATION_DEFAULT, ++ .xfer_func = DCMIPP_XFER_FUNC_DEFAULT, +}; + +static inline int frame_size(u32 width, u32 height, u32 format) @@ -4771,10 +5232,10 @@ index 000000000..415766c08 +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-byteproc.c b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-byteproc.c new file mode 100644 -index 000000000..703843601 +index 000000000000..62e55987cc17 --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-byteproc.c -@@ -0,0 +1,737 @@ +@@ -0,0 +1,790 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for STM32 Digital Camera Memory Interface Pixel Processor @@ -4818,6 +5279,7 @@ index 000000000..703843601 +#define DCMIPP_P0PPCR_BSM_MASK GENMASK(8, 7) +#define DCMIPP_P0PPCR_BSM_SHIFT 0x7 +#define DCMIPP_P0PPCR_LSM BIT(10) ++#define DCMIPP_P0PPCR_OELS BIT(11) + +#define IS_SINK(pad) (!(pad)) +#define IS_SRC(pad) ((pad)) @@ -4898,7 +5360,10 @@ index 000000000..703843601 + .height = DCMIPP_FMT_HEIGHT_DEFAULT, + .code = BYTEPROC_MEDIA_BUS_FMT_DEFAULT, + .field = V4L2_FIELD_NONE, -+ .colorspace = V4L2_COLORSPACE_DEFAULT, ++ .colorspace = DCMIPP_COLORSPACE_DEFAULT, ++ .ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT, ++ .quantization = DCMIPP_QUANTIZATION_DEFAULT, ++ .xfer_func = DCMIPP_XFER_FUNC_DEFAULT, +}; + +static const struct v4l2_rect crop_min = { @@ -4932,12 +5397,13 @@ index 000000000..703843601 +static void dcmipp_byteproc_adjust_compose(struct v4l2_rect *r, + const struct v4l2_mbus_framefmt *fmt) +{ -+ r->top = r->left = 0; ++ r->top = 0; ++ r->left = 0; + + /* Compose is not possible for JPEG or Bayer formats */ -+ if ((fmt->code == MEDIA_BUS_FMT_JPEG_1X8) || -+ (fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8) || (fmt->code == MEDIA_BUS_FMT_SGBRG8_1X8) || -+ (fmt->code == MEDIA_BUS_FMT_SGRBG8_1X8) || (fmt->code == MEDIA_BUS_FMT_SRGGB8_1X8)) { ++ if (fmt->code == MEDIA_BUS_FMT_JPEG_1X8 || ++ fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 || fmt->code == MEDIA_BUS_FMT_SGBRG8_1X8 || ++ fmt->code == MEDIA_BUS_FMT_SGRBG8_1X8 || fmt->code == MEDIA_BUS_FMT_SRGGB8_1X8) { + r->width = fmt->width; + r->height = fmt->height; + return; @@ -4950,7 +5416,7 @@ index 000000000..703843601 + r->height = fmt->height; + + /* Adjust width - /2 or /4 for 8bits formats and /2 for 16bits formats */ -+ if ((fmt->code == MEDIA_BUS_FMT_Y8_1X8) && (r->width <= (fmt->width / 4))) ++ if (fmt->code == MEDIA_BUS_FMT_Y8_1X8 && r->width <= (fmt->width / 4)) + r->width = fmt->width / 4; + else if (r->width <= (fmt->width / 2)) + r->width = fmt->width / 2; @@ -4995,7 +5461,8 @@ index 000000000..703843601 + else + r = v4l2_subdev_get_try_crop(sd, sd_state, i); + -+ r->top = r->left = 0; ++ r->top = 0; ++ r->left = 0; + r->width = DCMIPP_FMT_WIDTH_DEFAULT; + r->height = DCMIPP_FMT_HEIGHT_DEFAULT; + } @@ -5099,9 +5566,11 @@ index 000000000..703843601 + fmt->format.height = crop->height; + } else { + dcmipp_byteproc_adjust_fmt(&fmt->format); -+ crop->top = crop->left = compose->top = compose->left = 0; -+ crop->width = compose->width = fmt->format.width; -+ crop->height = compose->height = fmt->format.height; ++ crop->top = 0; ++ crop->left = 0; ++ crop->width = fmt->format.width; ++ crop->height = fmt->format.height; ++ *compose = *crop; + *sink_fmt = fmt->format; + } + @@ -5124,14 +5593,14 @@ index 000000000..703843601 + * Compose is done on the sink pad + * Crop is done on the src pad + */ -+ if (((s->target == V4L2_SEL_TGT_CROP) || -+ (s->target == V4L2_SEL_TGT_CROP_BOUNDS) || -+ (s->target == V4L2_SEL_TGT_CROP_DEFAULT)) && IS_SINK(s->pad)) ++ if ((s->target == V4L2_SEL_TGT_CROP || ++ s->target == V4L2_SEL_TGT_CROP_BOUNDS || ++ s->target == V4L2_SEL_TGT_CROP_DEFAULT) && IS_SINK(s->pad)) + return -EINVAL; + -+ if (((s->target == V4L2_SEL_TGT_COMPOSE) || -+ (s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS) || -+ (s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT)) && IS_SRC(s->pad)) ++ if ((s->target == V4L2_SEL_TGT_COMPOSE || ++ s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS || ++ s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT) && IS_SRC(s->pad)) + return -EINVAL; + + if (s->which == V4L2_SUBDEV_FORMAT_ACTIVE) { @@ -5159,7 +5628,8 @@ index 000000000..703843601 + s->r = dcmipp_byteproc_get_compose_bound(sink_fmt); + break; + case V4L2_SEL_TGT_COMPOSE_DEFAULT: -+ s->r.top = s->r.left = 0; ++ s->r.top = 0; ++ s->r.left = 0; + s->r.width = sink_fmt->width; + s->r.height = sink_fmt->height; + break; @@ -5183,14 +5653,14 @@ index 000000000..703843601 + * Compose is done on the sink pad + * Crop is done on the src pad + */ -+ if (((s->target == V4L2_SEL_TGT_CROP) || -+ (s->target == V4L2_SEL_TGT_CROP_BOUNDS) || -+ (s->target == V4L2_SEL_TGT_CROP_DEFAULT)) && IS_SINK(s->pad)) ++ if ((s->target == V4L2_SEL_TGT_CROP || ++ s->target == V4L2_SEL_TGT_CROP_BOUNDS || ++ s->target == V4L2_SEL_TGT_CROP_DEFAULT) && IS_SINK(s->pad)) + return -EINVAL; + -+ if (((s->target == V4L2_SEL_TGT_COMPOSE) || -+ (s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS) || -+ (s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT)) && IS_SRC(s->pad)) ++ if ((s->target == V4L2_SEL_TGT_COMPOSE || ++ s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS || ++ s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT) && IS_SRC(s->pad)) + return -EINVAL; + + if (s->which == V4L2_SUBDEV_FORMAT_ACTIVE) { @@ -5227,10 +5697,46 @@ index 000000000..703843601 + return 0; +} + ++static const unsigned int dcmipp_frates[] = {1, 2, 4, 8}; ++ ++static int dcmipp_byteproc_enum_frame_interval ++ (struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_frame_interval_enum *fie) ++{ ++ struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd); ++ struct v4l2_fract *sink_interval = &byteproc->sink_interval; ++ unsigned int ratio; ++ int ret = 0; ++ ++ if (fie->pad > 1 || ++ fie->index >= (IS_SRC(fie->pad) ? ARRAY_SIZE(dcmipp_frates) : 1) || ++ fie->width > DCMIPP_FRAME_MAX_WIDTH || ++ fie->height > DCMIPP_FRAME_MAX_HEIGHT) ++ return -EINVAL; ++ ++ mutex_lock(&byteproc->lock); ++ ++ if (IS_SINK(fie->pad)) { ++ fie->interval = *sink_interval; ++ goto out; ++ } ++ ++ ratio = dcmipp_frates[fie->index]; ++ ++ fie->interval.numerator = sink_interval->numerator * ratio; ++ fie->interval.denominator = sink_interval->denominator; ++ ++out: ++ mutex_unlock(&byteproc->lock); ++ return ret; ++} ++ +static const struct v4l2_subdev_pad_ops dcmipp_byteproc_pad_ops = { + .init_cfg = dcmipp_byteproc_init_cfg, + .enum_mbus_code = dcmipp_byteproc_enum_mbus_code, + .enum_frame_size = dcmipp_byteproc_enum_frame_size, ++ .enum_frame_interval = dcmipp_byteproc_enum_frame_interval, + .get_fmt = dcmipp_byteproc_get_fmt, + .set_fmt = dcmipp_byteproc_set_fmt, + .get_selection = dcmipp_byteproc_get_selection, @@ -5271,7 +5777,7 @@ index 000000000..703843601 + + vprediv = byteproc->sink_fmt.height / byteproc->compose.height; + if (vprediv == 2) -+ val |= DCMIPP_P0PPCR_LSM; /* one line out of two */ ++ val |= DCMIPP_P0PPCR_LSM | DCMIPP_P0PPCR_OELS; + + /* decimate using bytes and lines skipping */ + if (val) { @@ -5328,19 +5834,25 @@ index 000000000..703843601 + return -EBUSY; + } + ++ if (fi->interval.numerator == 0 || fi->interval.denominator == 0) ++ fi->interval = byteproc->sink_interval; ++ + if (IS_SINK(fi->pad)) { -+ byteproc->sink_interval = fi->interval; + /* + * Setting sink frame interval resets frame skipping. + * Sink frame interval is propagated to src. + */ + byteproc->frate = 0; ++ byteproc->sink_interval = fi->interval; + byteproc->src_interval = byteproc->sink_interval; + } else { + unsigned int ratio; ++ + /* Normalize ratio */ -+ ratio = (byteproc->sink_interval.denominator * fi->interval.numerator) / -+ (byteproc->sink_interval.numerator * fi->interval.denominator); ++ ratio = (byteproc->sink_interval.denominator * ++ fi->interval.numerator) / ++ (byteproc->sink_interval.numerator * ++ fi->interval.denominator); + + /* Hardware can skip 1 frame over 2, 4 or 8 */ + byteproc->frate = ratio >= 8 ? 3 : @@ -5348,10 +5860,10 @@ index 000000000..703843601 + ratio >= 2 ? 1 : 0; + + /* Adjust src frame interval to what hardware can really do */ -+ byteproc->src_interval.numerator = 1; ++ byteproc->src_interval.numerator = ++ byteproc->sink_interval.numerator * ratio; + byteproc->src_interval.denominator = -+ (byteproc->sink_interval.denominator / byteproc->sink_interval.numerator) / -+ (1 << byteproc->frate); ++ byteproc->sink_interval.denominator; + } + + mutex_unlock(&byteproc->lock); @@ -5465,8 +5977,10 @@ index 000000000..703843601 + + /* Initialize the frame format */ + byteproc->sink_fmt = fmt_default; -+ byteproc->compose = byteproc->crop = r; -+ byteproc->sink_interval = byteproc->src_interval = interval; ++ byteproc->crop = r; ++ byteproc->compose = r; ++ byteproc->src_interval = interval; ++ byteproc->sink_interval = interval; + + return 0; +} @@ -5514,7 +6028,7 @@ index 000000000..703843601 +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-common.c b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-common.c new file mode 100644 -index 000000000..2a566bacc +index 000000000000..2a566bacc80e --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-common.c @@ -0,0 +1,116 @@ @@ -5636,10 +6150,10 @@ index 000000000..2a566bacc +EXPORT_SYMBOL_GPL(dcmipp_ent_sd_unregister); diff --git a/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-common.h b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-common.h new file mode 100644 -index 000000000..5cfd08595 +index 000000000000..50108fd4563b --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-common.h -@@ -0,0 +1,235 @@ +@@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Driver for STM32 Digital Camera Memory Interface Pixel Processor @@ -5677,6 +6191,11 @@ index 000000000..5cfd08595 +#define DCMIPP_FRAME_INDEX(lin, col, width, bpp) \ + (((lin) * (width) + (col)) * (bpp)) + ++#define DCMIPP_COLORSPACE_DEFAULT V4L2_COLORSPACE_REC709 ++#define DCMIPP_YCBCR_ENC_DEFAULT V4L2_YCBCR_ENC_DEFAULT ++#define DCMIPP_QUANTIZATION_DEFAULT V4L2_QUANTIZATION_DEFAULT ++#define DCMIPP_XFER_FUNC_DEFAULT V4L2_XFER_FUNC_DEFAULT ++ +/** + * struct dcmipp_colorimetry_clamp - Adjust colorimetry parameters + * @@ -5690,17 +6209,17 @@ index 000000000..5cfd08595 +do { \ + if ((fmt)->colorspace == V4L2_COLORSPACE_DEFAULT || \ + (fmt)->colorspace > V4L2_COLORSPACE_DCI_P3) { \ -+ (fmt)->colorspace = V4L2_COLORSPACE_DEFAULT; \ -+ (fmt)->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; \ -+ (fmt)->quantization = V4L2_QUANTIZATION_DEFAULT; \ -+ (fmt)->xfer_func = V4L2_XFER_FUNC_DEFAULT; \ ++ (fmt)->colorspace = DCMIPP_COLORSPACE_DEFAULT; \ ++ (fmt)->ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT; \ ++ (fmt)->quantization = DCMIPP_QUANTIZATION_DEFAULT; \ ++ (fmt)->xfer_func = DCMIPP_XFER_FUNC_DEFAULT; \ + } \ + if ((fmt)->ycbcr_enc > V4L2_YCBCR_ENC_SMPTE240M) \ -+ (fmt)->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; \ ++ (fmt)->ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT; \ + if ((fmt)->quantization > V4L2_QUANTIZATION_LIM_RANGE) \ -+ (fmt)->quantization = V4L2_QUANTIZATION_DEFAULT; \ ++ (fmt)->quantization = DCMIPP_QUANTIZATION_DEFAULT; \ + if ((fmt)->xfer_func > V4L2_XFER_FUNC_SMPTE2084) \ -+ (fmt)->xfer_func = V4L2_XFER_FUNC_DEFAULT; \ ++ (fmt)->xfer_func = DCMIPP_XFER_FUNC_DEFAULT; \ +} while (0) + +/** @@ -5877,10 +6396,10 @@ index 000000000..5cfd08595 + diff --git a/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-core.c b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-core.c new file mode 100644 -index 000000000..38b6eaaf1 +index 000000000000..7935ee3ead71 --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-core.c -@@ -0,0 +1,688 @@ +@@ -0,0 +1,682 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for STM32 Digital Camera Memory Interface Pixel Processor @@ -5931,7 +6450,6 @@ index 000000000..38b6eaaf1 + /* Hardware resources */ + struct reset_control *rstc; + void __iomem *regs; -+ struct clk *mclk; + struct clk *kclk; + + /* The pipeline configuration */ @@ -6504,7 +7022,6 @@ index 000000000..38b6eaaf1 + struct dcmipp_device *dcmipp = dev_get_drvdata(dev); + + clk_disable_unprepare(dcmipp->kclk); -+ clk_disable_unprepare(dcmipp->mclk); + + return 0; +} @@ -6514,10 +7031,6 @@ index 000000000..38b6eaaf1 + struct dcmipp_device *dcmipp = dev_get_drvdata(dev); + int ret; + -+ ret = clk_prepare_enable(dcmipp->mclk); -+ if (ret) -+ dev_err(dev, "%s: Failed to prepare_enable clock\n", __func__); -+ + ret = clk_prepare_enable(dcmipp->kclk); + if (ret) + dev_err(dev, "%s: Failed to prepare_enable k clock\n", __func__); @@ -6571,10 +7084,10 @@ index 000000000..38b6eaaf1 +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-parallel.c b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-parallel.c new file mode 100644 -index 000000000..d123f64e9 +index 000000000000..e737a48cfd66 --- /dev/null +++ b/drivers/media/platform/stm32/stm32-dcmipp/dcmipp-parallel.c -@@ -0,0 +1,494 @@ +@@ -0,0 +1,497 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for STM32 Digital Camera Memory Interface Pixel Processor @@ -6729,7 +7242,10 @@ index 000000000..d123f64e9 + .height = DCMIPP_FMT_HEIGHT_DEFAULT, + .code = PAR_MEDIA_BUS_FMT_DEFAULT, + .field = V4L2_FIELD_NONE, -+ .colorspace = V4L2_COLORSPACE_DEFAULT, ++ .colorspace = DCMIPP_COLORSPACE_DEFAULT, ++ .ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT, ++ .quantization = DCMIPP_QUANTIZATION_DEFAULT, ++ .xfer_func = DCMIPP_XFER_FUNC_DEFAULT, +}; + +static int dcmipp_par_init_cfg(struct v4l2_subdev *sd, @@ -6811,7 +7327,7 @@ index 000000000..d123f64e9 + fmt->code = fmt_default.code; + + /* Exclude JPEG if BT656 bus is selected */ -+ if (vpix->code_sink == MEDIA_BUS_FMT_JPEG_1X8 && ++ if (vpix && vpix->code_sink == MEDIA_BUS_FMT_JPEG_1X8 && + par->ved.bus_type == V4L2_MBUS_BT656) + fmt->code = fmt_default.code; + @@ -7070,7 +7586,7 @@ index 000000000..d123f64e9 +MODULE_DESCRIPTION("STMicroelectronics STM32 Digital Camera Memory Interface with Pixel Processor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c -index 843259c30..1259d094a 100644 +index 843259c304bb..1259d094a61b 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -345,6 +345,9 @@ v4l2_fwnode_endpoint_parse_parallel_bus(struct fwnode_handle *fwnode, @@ -7083,153 +7599,8 @@ index 843259c30..1259d094a 100644 switch (bus_type) { default: bus->flags = flags; -diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c -index 54df9cfd5..61f236e03 100644 ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -546,6 +546,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd) - config.stride = 1; - config.read_only = true; - config.root_only = true; -+ config.ignore_wp = true; - config.no_of_node = !of_device_is_compatible(node, "nvmem-cells"); - config.priv = mtd; - -@@ -830,6 +831,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, - config.owner = THIS_MODULE; - config.type = NVMEM_TYPE_OTP; - config.root_only = true; -+ config.ignore_wp = true; - config.reg_read = reg_read; - config.size = size; - config.of_node = np; -diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c -index 1c277fbb9..733f9857e 100644 ---- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c -+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -231,6 +232,7 @@ struct stm32_fmc2_timings { - - struct stm32_fmc2_nand { - struct nand_chip chip; -+ struct gpio_desc *wp_gpio; - struct stm32_fmc2_timings timings; - int ncs; - int cs_used[FMC2_MAX_CE]; -@@ -1747,6 +1749,18 @@ static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = { - .setup_interface = stm32_fmc2_nfc_setup_interface, - }; - -+static void stm32_fmc2_nfc_wp_enable(struct stm32_fmc2_nand *nand) -+{ -+ if (nand->wp_gpio) -+ gpiod_set_value(nand->wp_gpio, 1); -+} -+ -+static void stm32_fmc2_nfc_wp_disable(struct stm32_fmc2_nand *nand) -+{ -+ if (nand->wp_gpio) -+ gpiod_set_value(nand->wp_gpio, 0); -+} -+ - static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, - struct device_node *dn) - { -@@ -1785,6 +1799,18 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, - nand->cs_used[i] = cs; - } - -+ nand->wp_gpio = devm_gpiod_get_from_of_node(nfc->dev, dn, -+ "wp-gpios", 0, -+ GPIOD_OUT_HIGH, "wp"); -+ if (IS_ERR(nand->wp_gpio)) { -+ ret = PTR_ERR(nand->wp_gpio); -+ if (ret != -ENOENT) -+ return dev_err_probe(nfc->dev, ret, -+ "failed to request WP GPIO\n"); -+ -+ nand->wp_gpio = NULL; -+ } -+ - nand_set_flash_node(&nand->chip, dn); - - return 0; -@@ -1960,10 +1986,12 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) - chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE | - NAND_USES_DMA; - -+ stm32_fmc2_nfc_wp_disable(nand); -+ - /* Scan to find existence of the device */ - ret = nand_scan(chip, nand->ncs); - if (ret) -- goto err_release_dma; -+ goto err_wp_enable; - - ret = mtd_device_register(mtd, NULL, 0); - if (ret) -@@ -1976,6 +2004,9 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) - err_nand_cleanup: - nand_cleanup(chip); - -+err_wp_enable: -+ stm32_fmc2_nfc_wp_enable(nand); -+ - err_release_dma: - if (nfc->dma_ecc_ch) - dma_release_channel(nfc->dma_ecc_ch); -@@ -2016,15 +2047,20 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev) - - clk_disable_unprepare(nfc->clk); - -+ stm32_fmc2_nfc_wp_enable(nand); -+ - return 0; - } - - static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev) - { - struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev); -+ struct stm32_fmc2_nand *nand = &nfc->nand; - - clk_disable_unprepare(nfc->clk); - -+ stm32_fmc2_nfc_wp_enable(nand); -+ - pinctrl_pm_select_sleep_state(dev); - - return 0; -@@ -2046,6 +2082,8 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev) - - stm32_fmc2_nfc_init(nfc); - -+ stm32_fmc2_nfc_wp_disable(nand); -+ - for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) { - if (!(nfc->cs_assigned & BIT(chip_cs))) - continue; -diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c -index 9aecb8302..fb7840c73 100644 ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -768,7 +768,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) - - if (config->wp_gpio) - nvmem->wp_gpio = config->wp_gpio; -- else -+ else if (!config->ignore_wp) - nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp", - GPIOD_OUT_HIGH); - if (IS_ERR(nvmem->wp_gpio)) { diff --git a/drivers/nvmem/stm32-romem.c b/drivers/nvmem/stm32-romem.c -index 354be5268..36b38add8 100644 +index 354be526897f..bb1d52988179 100644 --- a/drivers/nvmem/stm32-romem.c +++ b/drivers/nvmem/stm32-romem.c @@ -2,15 +2,18 @@ @@ -7252,11 +7623,12 @@ index 354be5268..36b38add8 100644 /* BSEC secure service access from non-secure */ #define STM32_SMC_BSEC 0x82001003 -@@ -22,28 +25,51 @@ +@@ -22,28 +25,54 @@ /* shadow registers offest */ #define STM32MP15_BSEC_DATA0 0x200 -/* 32 (x 32-bits) lower shadow registers */ +-#define STM32MP15_BSEC_NUM_LOWER 32 +/* + * BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) + * - Lower: 1K bits, 2:1 redundancy, incremental bit programming @@ -7264,12 +7636,12 @@ index 354be5268..36b38add8 100644 + * - Upper: 2K bits, ECC protection, word programming only + * => 64 (x 32-bits) = words 32 to 95 + */ - #define STM32MP15_BSEC_NUM_LOWER 32 - -+#define STM32_ROMEM_AUTOSUSPEND_DELAY_MS 50 + ++#define STM32_ROMEM_AUTOSUSPEND_DELAY_MS 50 + struct stm32_romem_cfg { int size; ++ u8 lower; + bool ta; }; @@ -7278,11 +7650,14 @@ index 354be5268..36b38add8 100644 struct nvmem_config cfg; + struct clk *clk; + struct device *ta; ++ u8 lower; }; +struct device *stm32_bsec_pta_find(struct device *dev); +static int stm32_bsec_pta_read(void *context, unsigned int offset, void *buf, + size_t bytes); ++static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf, ++ size_t bytes); + static int stm32_romem_read(void *context, unsigned int offset, void *buf, size_t bytes) @@ -7306,7 +7681,7 @@ index 354be5268..36b38add8 100644 return 0; } -@@ -65,6 +91,17 @@ static int stm32_bsec_smc(u8 op, u32 otp, u32 data, u32 *result) +@@ -65,6 +94,17 @@ static int stm32_bsec_smc(u8 op, u32 otp, u32 data, u32 *result) #endif } @@ -7324,7 +7699,7 @@ index 354be5268..36b38add8 100644 static int stm32_bsec_read(void *context, unsigned int offset, void *buf, size_t bytes) { -@@ -74,13 +111,19 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf, +@@ -74,18 +114,24 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf, u8 *buf8 = buf, *val8 = (u8 *)&val; int i, j = 0, ret, skip_bytes, size; @@ -7346,7 +7721,13 @@ index 354be5268..36b38add8 100644 for (i = roffset; (i < roffset + rbytes); i += 4) { u32 otp = i >> 2; -@@ -95,7 +138,7 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf, + +- if (otp < STM32MP15_BSEC_NUM_LOWER) { ++ if (otp < priv->lower) { + /* read lower data from shadow registers */ + val = readl_relaxed( + priv->base + STM32MP15_BSEC_DATA0 + i); +@@ -95,7 +141,7 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf, if (ret) { dev_err(dev, "Can't read data%d (%d)\n", otp, ret); @@ -7355,7 +7736,7 @@ index 354be5268..36b38add8 100644 } } /* skip first bytes in case of unaligned read */ -@@ -109,7 +152,11 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf, +@@ -109,7 +155,11 @@ static int stm32_bsec_read(void *context, unsigned int offset, void *buf, skip_bytes = 0; } @@ -7368,7 +7749,7 @@ index 354be5268..36b38add8 100644 } static int stm32_bsec_write(void *context, unsigned int offset, void *buf, -@@ -120,20 +167,61 @@ static int stm32_bsec_write(void *context, unsigned int offset, void *buf, +@@ -120,20 +170,61 @@ static int stm32_bsec_write(void *context, unsigned int offset, void *buf, u32 *buf32 = buf; int ret, i; @@ -7395,7 +7776,7 @@ index 354be5268..36b38add8 100644 } - return 0; -+ if (offset + bytes >= STM32MP15_BSEC_NUM_LOWER * 4) ++ if (offset + bytes >= priv->lower * 4) + dev_warn(dev, "Update of upper OTPs with ECC protection (word programming, only once)\n"); + +end_write: @@ -7434,7 +7815,7 @@ index 354be5268..36b38add8 100644 } static int stm32_romem_probe(struct platform_device *pdev) -@@ -142,6 +230,8 @@ static int stm32_romem_probe(struct platform_device *pdev) +@@ -142,6 +233,8 @@ static int stm32_romem_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct stm32_romem_priv *priv; struct resource *res; @@ -7443,33 +7824,35 @@ index 354be5268..36b38add8 100644 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) -@@ -158,6 +248,7 @@ static int stm32_romem_probe(struct platform_device *pdev) +@@ -158,6 +251,9 @@ static int stm32_romem_probe(struct platform_device *pdev) priv->cfg.dev = dev; priv->cfg.priv = priv; priv->cfg.owner = THIS_MODULE; + priv->cfg.type = NVMEM_TYPE_OTP; ++ ++ priv->lower = 0; cfg = (const struct stm32_romem_cfg *) of_match_device(dev->driver->of_match_table, dev)->data; -@@ -167,15 +258,108 @@ static int stm32_romem_probe(struct platform_device *pdev) +@@ -167,15 +263,110 @@ static int stm32_romem_probe(struct platform_device *pdev) priv->cfg.reg_read = stm32_romem_read; } else { priv->cfg.size = cfg->size; - priv->cfg.reg_read = stm32_bsec_read; - priv->cfg.reg_write = stm32_bsec_write; ++ priv->lower = cfg->lower; + if (cfg->ta || optee_presence_check()) { + priv->ta = stm32_bsec_pta_find(dev); + /* wait for OP-TEE client driver to be up and ready */ + if (!priv->ta) { + /* BSEC PTA is required or SMC not ready */ -+ if (cfg->ta || !stm32_bsec_check()) { ++ if (cfg->ta || !stm32_bsec_check()) + return -EPROBE_DEFER; -+ } + } + } + if (priv->ta) { -+ priv->cfg.read_only = true; + priv->cfg.reg_read = stm32_bsec_pta_read; ++ priv->cfg.reg_write = stm32_bsec_pta_write; + } else { + priv->cfg.reg_read = stm32_bsec_read; + priv->cfg.reg_write = stm32_bsec_write; @@ -7488,7 +7871,7 @@ index 354be5268..36b38add8 100644 + if (priv->clk) { + ret = clk_prepare_enable(priv->clk); + if (ret) -+ return dev_err_probe(dev, ret,"failed to enable clock\n"); ++ return dev_err_probe(dev, ret, "failed to enable clock\n"); + } + + pm_runtime_set_autosuspend_delay(dev, STM32_ROMEM_AUTOSUSPEND_DELAY_MS); @@ -7502,9 +7885,8 @@ index 354be5268..36b38add8 100644 + if (ret) + return dev_err_probe(dev, ret, + "unable to register cleanup action\n"); - } - -- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); ++ } ++ + nvmem = devm_nvmem_register(dev, &priv->cfg); + + return PTR_ERR_OR_ZERO(nvmem); @@ -7540,8 +7922,9 @@ index 354be5268..36b38add8 100644 + "Failed to prepare_enable clock (%d)\n", ret); + return ret; + } -+ } -+ + } + +- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); + return 0; } @@ -7554,16 +7937,18 @@ index 354be5268..36b38add8 100644 + static const struct stm32_romem_cfg stm32mp15_bsec_cfg = { .size = 384, /* 96 x 32-bits data words */ ++ .lower = 32, /* 32 word with incremental bit programming */ + .ta = false, +}; + +static const struct stm32_romem_cfg stm32mp13_bsec_cfg = { -+ .size = 384, /* 96 x 32-bits data words */ ++ .size = 384, /* 96 x 32-bits data words */ ++ .lower = 32, /* 32 word with incremental bit programming */ + .ta = true, }; static const struct of_device_id stm32_romem_of_match[] = { -@@ -183,6 +367,8 @@ static const struct of_device_id stm32_romem_of_match[] = { +@@ -183,6 +374,8 @@ static const struct of_device_id stm32_romem_of_match[] = { .compatible = "st,stm32mp15-bsec", .data = (void *)&stm32mp15_bsec_cfg, }, { @@ -7572,7 +7957,7 @@ index 354be5268..36b38add8 100644 }, }; MODULE_DEVICE_TABLE(of, stm32_romem_of_match); -@@ -191,10 +377,292 @@ static struct platform_driver stm32_romem_driver = { +@@ -191,10 +384,425 @@ static struct platform_driver stm32_romem_driver = { .probe = stm32_romem_probe, .driver = { .name = "stm32-romem", @@ -7586,16 +7971,15 @@ index 354be5268..36b38add8 100644 +/************************************************************************* + * BSEC PTA : OP-TEE client driver to pseudo trusted application + *************************************************************************/ ++ +/* + * Read OTP memory + * -+ * [in] value a: OTP start offset in byte -+ * b: access type -+ * 0 to read from shadow -+ * 1 to read from fuse -+ * 2 to read lock status -+ * [out] memref buffer: Output buffer to store read values -+ * size: Size of OTP to be read ++ * [in] value[0].a OTP start offset in byte ++ * [in] value[0].b Access type (0 : shadow, ++ * 1 : fuse, 2 : lock) ++ * [out] memref[1].buffer Output buffer to store read values ++ * [out] memref[1].size Size of OTP to be read + * + * Return codes: + * TEE_SUCCESS - Invoke command success @@ -7603,11 +7987,29 @@ index 354be5268..36b38add8 100644 + */ +#define PTA_BSEC_READ_MEM 0x0 /* Read OTP */ + ++/* ++ * Write OTP memory ++ * ++ * [in] value[0].a OTP start offset in byte ++ * [in] value[0].b Access type (0 : shadow, ++ * 1 : fuse, 2 : lock) ++ * [in] memref[1].buffer Input buffer to read values ++ * [in] memref[1].size Size of OTP to be written ++ * ++ * Return codes: ++ * TEE_SUCCESS - Invoke command success ++ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param ++ */ ++#define PTA_BSEC_WRITE_MEM 0x1 /* Write OTP */ ++ +/* value of PTA_BSEC access type = value[in] b */ +#define SHADOW_ACCESS 0 +#define FUSE_ACCESS 1 +#define LOCK_ACCESS 2 + ++/* Bitfield definition for LOCK status */ ++#define LOCK_PERM BIT(30) ++ +/** + * struct stm32_bsec_pta_priv - OP-TEE BSEC TA private data + * @ctx: OP-TEE context handler. @@ -7782,6 +8184,113 @@ index 354be5268..36b38add8 100644 + return ret; +} + ++/** ++ * stm32_bsec_pta_write() - nvmem write access using PTA client driver ++ * @context: nvmem context => romem privdate data ++ * @offset: nvmem offset ++ * @buf: buffer with nvem values ++ * @bytes: number of bytes to write ++ * ++ * Return: ++ * On success, 0. On failure, -errno. ++ */ ++static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ struct stm32_romem_priv *romem_priv = context; ++ struct device *dev; ++ struct stm32_bsec_pta_priv *priv; ++ struct tee_shm *shm; ++ struct tee_ioctl_invoke_arg arg; ++ struct tee_param param[2]; ++ u8 *shm_buf; ++ int ret; ++ ++ dev = romem_priv->ta; ++ if (!dev) { ++ pr_err("TA_BSEC invoke with driver\n"); ++ return -ENXIO; ++ } ++ ++ /* Allow only writing complete 32-bits aligned words */ ++ if ((bytes % 4) || (offset % 4)) ++ return -EINVAL; ++ ++ priv = dev_get_drvdata(dev); ++ ++ memset(&arg, 0, sizeof(arg)); ++ memset(¶m, 0, sizeof(param)); ++ ++ arg.func = PTA_BSEC_WRITE_MEM; ++ arg.session = priv->session_id; ++ arg.num_params = 2; ++ ++ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; ++ param[0].u.value.a = offset; ++ param[0].u.value.b = FUSE_ACCESS; ++ ++ shm = tee_shm_alloc(priv->ctx, bytes, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); ++ if (IS_ERR(shm)) ++ return PTR_ERR(shm); ++ ++ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; ++ param[1].u.memref.shm = shm; ++ param[1].u.memref.size = bytes; ++ ++ shm_buf = tee_shm_get_va(shm, 0); ++ if (IS_ERR(shm_buf)) { ++ dev_err(dev, "tee_shm_get_va failed for transmit\n"); ++ return PTR_ERR(shm_buf); ++ } ++ ++ memcpy(shm_buf, buf, bytes); ++ ++ ret = tee_client_invoke_func(priv->ctx, &arg, param); ++ if (ret < 0 || arg.ret != 0) { ++ dev_err(dev, "TA_BSEC invoke failed TEE err: %x, ret:%x\n", ++ arg.ret, ret); ++ if (!ret) ++ ret = -EIO; ++ } ++ dev_dbg(dev, "Write OTPs %d to %d, ret=%d\n", ++ offset / 4, (offset + bytes) / 4, ret); ++ ++ /* Lock the upper OTPs with ECC protection, word programming only */ ++ if (!ret && ((offset + bytes) >= (romem_priv->lower * 4))) { ++ u32 start, nb_lock; ++ u32 *lock = (u32 *)shm_buf; ++ int i; ++ ++ /* ++ * don't lock the lower OTPs, no ECC protection and incremental ++ * bit programming, a second write is allowed ++ */ ++ start = max_t(u32, offset, romem_priv->lower * 4); ++ nb_lock = (offset + bytes - start) / 4; ++ ++ param[0].u.value.a = start; ++ param[0].u.value.b = LOCK_ACCESS; ++ param[1].u.memref.size = nb_lock * 4; ++ ++ for (i = 0; i < nb_lock; i++) ++ lock[i] = LOCK_PERM; ++ ++ ret = tee_client_invoke_func(priv->ctx, &arg, param); ++ if (ret < 0 || arg.ret != 0) { ++ dev_err(dev, "TA_BSEC invoke failed TEE err: %x, ret:%x\n", ++ arg.ret, ret); ++ if (!ret) ++ ret = -EIO; ++ } ++ dev_dbg(dev, "Lock upper OTPs %d to %d, ret=%d\n", ++ start / 4, start / 4 + nb_lock, ret); ++ } ++ ++ tee_shm_free(shm); ++ ++ return ret; ++} ++ +static const struct tee_client_device_id stm32_bsec_id_table[] = { + { + UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5, @@ -7830,6 +8339,15 @@ index 354be5268..36b38add8 100644 + + return -ENXIO; +} ++ ++static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ pr_debug("%s: TA BSEC request without OPTEE support\n", __func__); ++ ++ return -ENXIO; ++} ++ +struct device *stm32_bsec_pta_find(struct device *dev) +{ + pr_debug("%s: TA BSEC request without OPTEE support\n", __func__); @@ -7867,7 +8385,7 @@ index 354be5268..36b38add8 100644 MODULE_AUTHOR("Fabrice Gasnier "); MODULE_DESCRIPTION("STMicroelectronics STM32 RO-MEM"); diff --git a/drivers/of/platform.c b/drivers/of/platform.c -index 74afbb7a4..654ca9e98 100644 +index 74afbb7a4f5e..654ca9e9808c 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -537,6 +537,10 @@ static int __init of_platform_default_populate_init(void) @@ -7882,7 +8400,7 @@ index 74afbb7a4..654ca9e98 100644 of_platform_default_populate(NULL, NULL, NULL); diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c -index 3115abb3f..917428242 100644 +index 3115abb3f52a..917428242775 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c @@ -58,7 +58,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, @@ -7904,7 +8422,7 @@ index 3115abb3f..917428242 100644 if (!cstate.enabled) { /* enable clock to drive PWM counter */ diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c -index 794ca5b02..24aab0450 100644 +index 794ca5b02968..24aab0450c78 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -207,6 +207,10 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, @@ -7919,7 +8437,7 @@ index 794ca5b02..24aab0450 100644 regmap_update_bits(priv->regmap, pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig -index e8a30c4c5..c73f79a37 100644 +index e8a30c4c5aec..c73f79a3799a 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -17,6 +17,7 @@ source "drivers/soc/renesas/Kconfig" @@ -7931,7 +8449,7 @@ index e8a30c4c5..c73f79a37 100644 source "drivers/soc/tegra/Kconfig" source "drivers/soc/ti/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile -index a05e9fbcd..e4909f646 100644 +index a05e9fbcd3e0..e4909f6467f9 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -23,6 +23,7 @@ obj-y += renesas/ @@ -7944,7 +8462,7 @@ index a05e9fbcd..e4909f646 100644 obj-y += ti/ diff --git a/drivers/soc/st/Kconfig b/drivers/soc/st/Kconfig new file mode 100644 -index 000000000..8fde9d232 +index 000000000000..8fde9d232291 --- /dev/null +++ b/drivers/soc/st/Kconfig @@ -0,0 +1,25 @@ @@ -7975,7 +8493,7 @@ index 000000000..8fde9d232 +endif # ARCH_STM32 diff --git a/drivers/soc/st/Makefile b/drivers/soc/st/Makefile new file mode 100644 -index 000000000..b57d95080 +index 000000000000..b57d9508021f --- /dev/null +++ b/drivers/soc/st/Makefile @@ -0,0 +1,3 @@ @@ -7984,7 +8502,7 @@ index 000000000..b57d95080 +obj-$(CONFIG_STM32_PM_DOMAINS) += stm32_pm_domain.o diff --git a/drivers/soc/st/stm32-hslv.c b/drivers/soc/st/stm32-hslv.c new file mode 100644 -index 000000000..224b0cbd8 +index 000000000000..224b0cbd84de --- /dev/null +++ b/drivers/soc/st/stm32-hslv.c @@ -0,0 +1,157 @@ @@ -8147,7 +8665,7 @@ index 000000000..224b0cbd8 +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/st/stm32_hdp.c b/drivers/soc/st/stm32_hdp.c new file mode 100644 -index 000000000..47687ebd1 +index 000000000000..47687ebd1ffd --- /dev/null +++ b/drivers/soc/st/stm32_hdp.c @@ -0,0 +1,242 @@ @@ -8395,7 +8913,7 @@ index 000000000..47687ebd1 +module_platform_driver(hdp_driver); diff --git a/drivers/soc/st/stm32_pm_domain.c b/drivers/soc/st/stm32_pm_domain.c new file mode 100644 -index 000000000..0386624c2 +index 000000000000..0386624c20f2 --- /dev/null +++ b/drivers/soc/st/stm32_pm_domain.c @@ -0,0 +1,212 @@ @@ -8612,7 +9130,7 @@ index 000000000..0386624c2 +} +core_initcall(stm32_pm_domains_init); diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c -index 5fd3fb891..1e065a332 100644 +index 5fd3fb8912a6..1e065a3323f9 100644 --- a/drivers/thermal/st/stm_thermal.c +++ b/drivers/thermal/st/stm_thermal.c @@ -82,8 +82,7 @@ @@ -8696,7 +9214,7 @@ index 5fd3fb891..1e065a332 100644 diff --git a/include/dt-bindings/soc/stm32-hdp.h b/include/dt-bindings/soc/stm32-hdp.h new file mode 100644 -index 000000000..d98665327 +index 000000000000..d98665327281 --- /dev/null +++ b/include/dt-bindings/soc/stm32-hdp.h @@ -0,0 +1,108 @@ @@ -8810,7 +9328,7 @@ index 000000000..d98665327 +#endif /* _DT_BINDINGS_STM32_HDP_H */ diff --git a/include/dt-bindings/soc/stm32mp13-hdp.h b/include/dt-bindings/soc/stm32mp13-hdp.h new file mode 100644 -index 000000000..091c1c835 +index 000000000000..091c1c83587a --- /dev/null +++ b/include/dt-bindings/soc/stm32mp13-hdp.h @@ -0,0 +1,133 @@ @@ -8947,31 +9465,45 @@ index 000000000..091c1c835 +#define HDP7_GPOVAL_7 15 + +#endif /* _DT_BINDINGS_STM32_HDP_H */ -diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h -index 104505e90..87932bdb2 100644 ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -66,7 +66,8 @@ struct nvmem_keepout { - * @word_size: Minimum read/write access granularity. - * @stride: Minimum read/write access stride. - * @priv: User context passed to read/write callbacks. -- * @wp-gpio: Write protect pin -+ * @wp-gpio: Write protect pin -+ * @ignore_wp: Write Protect pin is managed by the provider. - * - * Note: A default "nvmem" name will be assigned to the device if - * no name is specified in its configuration. In such case "" is -@@ -88,6 +89,7 @@ struct nvmem_config { - enum nvmem_type type; - bool read_only; - bool root_only; -+ bool ignore_wp; - struct device_node *of_node; - bool no_of_node; - nvmem_reg_read_t reg_read; +diff --git a/include/linux/smscphy.h b/include/linux/smscphy.h +index 1a136271ba6a..00884908e509 100644 +--- a/include/linux/smscphy.h ++++ b/include/linux/smscphy.h +@@ -14,6 +14,7 @@ + #define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */ + #define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */ + #define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */ ++#define MII_LAN83C185_ISF_INT8 (1<<8) /* Wake on LAN */ + + #define MII_LAN83C185_ISF_INT_ALL (0x0e) + +@@ -28,4 +29,23 @@ + #define MII_LAN83C185_MODE_POWERDOWN 0xC0 /* Power Down mode */ + #define MII_LAN83C185_MODE_ALL 0xE0 /* All capable mode */ + ++/* MMD 3 Registers */ ++#define LAN8742_MMD3_WAKEUP_CTRL (32784) ++#define LAN8742_MMD3_WUCSR_LED2_AS_NPME BIT(12) ++#define LAN8742_MMD3_WUCSR_WOL BIT(8) ++#define LAN8742_MMD3_WUCSR_PFDA_FR BIT(7) ++#define LAN8742_MMD3_WUCSR_WUFR BIT(6) ++#define LAN8742_MMD3_WUCSR_MPR BIT(5) ++#define LAN8742_MMD3_WUCSR_BCAST_FR BIT(4) ++#define LAN8742_MMD3_WUCSR_MPEN BIT(1) ++ ++#define LAN8742_MMD3_WAKEUP_FILTER (32785) ++#define LAN8742_MMD3_WUF_CFGA_FE BIT(15) ++#define LAN8742_MMD3_WUF_CFGA_AME BIT(10) ++ ++#define LAN8742_MMD3_MAC_ADDRA (32865) ++#define LAN8742_MMD3_MAC_ADDRB (32866) ++#define LAN8742_MMD3_MAC_ADDRC (32867) ++#define LAN8742_MMD3_PME_ASSERT_DELAY (32868) ++ + #endif /* __LINUX_SMSCPHY_H__ */ diff --git a/include/media/mipi-csi2.h b/include/media/mipi-csi2.h new file mode 100644 -index 000000000..392794e5b +index 000000000000..392794e5badd --- /dev/null +++ b/include/media/mipi-csi2.h @@ -0,0 +1,45 @@ @@ -9021,7 +9553,7 @@ index 000000000..392794e5b + +#endif /* _MEDIA_MIPI_CSI2_H */ diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h -index 7ab033b81..065ce8d26 100644 +index 7ab033b819eb..065ce8d26fa6 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h @@ -49,11 +49,13 @@ struct v4l2_fwnode_bus_mipi_csi2 { @@ -9039,5 +9571,5 @@ index 7ab033b81..065ce8d26 100644 /** -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0011-ARM-5.15.24-stm32mp1-r1-MFD.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0012-v5.15-stm32mp-r2-MFD.patch similarity index 96% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0011-ARM-5.15.24-stm32mp1-r1-MFD.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0012-v5.15-stm32mp-r2-MFD.patch index 7df339c..8e6e68c 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0011-ARM-5.15.24-stm32mp1-r1-MFD.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0012-v5.15-stm32mp-r2-MFD.patch @@ -1,9 +1,9 @@ -From d88b31f16b525087c38623bda52699ff7859dcf6 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 11:59:44 +0200 -Subject: [PATCH 11/22] ARM-5.15.24-stm32mp1-r1-MFD +From 69ed3aa4864f05afff66ffd7596de3b45d739360 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:55:56 +0100 +Subject: [PATCH 12/22] v5.15-stm32mp-r2 MFD -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../bindings/mfd/st,stm32-lptimer.yaml | 3 + .../bindings/mfd/st,stm32mp1-pwr.txt | 57 +++ @@ -19,7 +19,7 @@ Signed-off-by: Christophe Priouzeau create mode 100644 drivers/mfd/stm32-pwr.c diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml -index 8bcea8dd7..6e518ae12 100644 +index 8bcea8dd7d90..6e518ae12e7f 100644 --- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml +++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml @@ -44,6 +44,9 @@ properties: @@ -34,7 +34,7 @@ index 8bcea8dd7..6e518ae12 100644 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 000000000..b5f414a19 +index 000000000000..b5f414a19120 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/st,stm32mp1-pwr.txt @@ -0,0 +1,57 @@ @@ -96,7 +96,7 @@ index 000000000..b5f414a19 +}; + diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index d2f345245..181730a69 100644 +index d2f345245538..181730a693a1 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2042,6 +2042,16 @@ config MFD_STPMIC1 @@ -117,7 +117,7 @@ index d2f345245..181730a69 100644 tristate "Support for STMicroelectronics Multi-Function eXpander (STMFX)" depends on I2C diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 2ba6646e8..68201ea8e 100644 +index 2ba6646e874c..68201ea8e037 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -255,6 +255,7 @@ obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o @@ -130,7 +130,7 @@ index 2ba6646e8..68201ea8e 100644 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 000000000..c06e2fb6c +index 000000000000..c06e2fb6c0eb --- /dev/null +++ b/drivers/mfd/stm32-pwr.c @@ -0,0 +1,423 @@ @@ -558,7 +558,7 @@ index 000000000..c06e2fb6c +arch_initcall(stm32_pwr_init); +module_exit(stm32_pwr_exit); diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c -index e095a3930..b411d2958 100644 +index e095a3930142..b411d2958c18 100644 --- a/drivers/mfd/stmfx.c +++ b/drivers/mfd/stmfx.c @@ -81,13 +81,11 @@ static struct mfd_cell stmfx_cells[] = { @@ -576,7 +576,7 @@ index e095a3930..b411d2958 100644 .resources = stmfx_ts_resources, .num_resources = ARRAY_SIZE(stmfx_ts_resources), diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c -index eb3da558c..40eef5d18 100644 +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) @@ -600,7 +600,7 @@ index eb3da558c..40eef5d18 100644 return 0; diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c -index 7b1d27072..e2c98c66b 100644 +index 7b1d270722ba..e2c98c66bf9f 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -185,6 +185,12 @@ static int wm8994_resume(struct device *dev) @@ -617,7 +617,7 @@ index 7b1d27072..e2c98c66b 100644 wm8994->supplies); if (ret != 0) { diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h -index f8db83aed..f48f04dc4 100644 +index f8db83aedb2b..f48f04dc4187 100644 --- a/include/linux/mfd/stm32-timers.h +++ b/include/linux/mfd/stm32-timers.h @@ -31,6 +31,7 @@ @@ -629,5 +629,5 @@ index f8db83aed..f48f04dc4 100644 #define TIM_CR1_CEN BIT(0) /* Counter Enable */ #define TIM_CR1_DIR BIT(4) /* Counter Direction */ -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0013-v5.15-stm32mp-r2-MMC.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0013-v5.15-stm32mp-r2-MMC.patch new file mode 100644 index 0000000..4f5d0f5 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0013-v5.15-stm32mp-r2-MMC.patch @@ -0,0 +1,341 @@ +From 99e2eb7f37c25b7e9a5e0b18af405d8bae95df12 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:56:26 +0100 +Subject: [PATCH 13/22] v5.15-stm32mp-r2 MMC + +Signed-off-by: Romuald JEANNE +--- + .../devicetree/bindings/mmc/arm,pl18x.yaml | 6 ++ + drivers/mmc/host/mmci.c | 7 +- + drivers/mmc/host/mmci_stm32_sdmmc.c | 93 +++++++++++++++---- + drivers/mtd/nand/raw/stm32_fmc2_nand.c | 40 +++++++- + 4 files changed, 125 insertions(+), 21 deletions(-) + +diff --git a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml +index 47595cb483be..eed54bee7665 100644 +--- a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml ++++ b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml +@@ -53,6 +53,12 @@ properties: + items: + - const: arm,pl18x + - const: arm,primecell ++ - description: Entry for STMicroelectronics variant of PL18x. ++ This dedicated compatible is used by bootloaders. ++ items: ++ - const: st,stm32-sdmmc2 ++ - const: arm,pl18x ++ - const: arm,primecell + + clocks: + description: One or two clocks, the "apb_pclk" and the "MCLK" +diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c +index 3765e2f4ad98..3d416c4edc7c 100644 +--- a/drivers/mmc/host/mmci.c ++++ b/drivers/mmc/host/mmci.c +@@ -280,7 +280,7 @@ static struct variant_data variant_stm32_sdmmc = { + static struct variant_data variant_stm32_sdmmcv2 = { + .fifosize = 16 * 4, + .fifohalfsize = 8 * 4, +- .f_max = 208000000, ++ .f_max = 267000000, + .stm32_clkdiv = true, + .cmdreg_cpsm_enable = MCI_CPSM_STM32_ENABLE, + .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC, +@@ -2431,6 +2431,11 @@ static const struct amba_id mmci_ids[] = { + .mask = 0xf0ffffff, + .data = &variant_stm32_sdmmcv2, + }, ++ { ++ .id = 0x20253180, ++ .mask = 0xf0ffffff, ++ .data = &variant_stm32_sdmmcv2, ++ }, + /* Qualcomm variants */ + { + .id = 0x00051180, +diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c +index 4cceb9bab036..60bca78a72b1 100644 +--- a/drivers/mmc/host/mmci_stm32_sdmmc.c ++++ b/drivers/mmc/host/mmci_stm32_sdmmc.c +@@ -43,6 +43,9 @@ struct sdmmc_lli_desc { + struct sdmmc_idma { + dma_addr_t sg_dma; + void *sg_cpu; ++ dma_addr_t bounce_dma_addr; ++ void *bounce_buf; ++ bool use_bounce_buffer; + }; + + struct sdmmc_dlyb { +@@ -54,6 +57,8 @@ struct sdmmc_dlyb { + static int sdmmc_idma_validate_data(struct mmci_host *host, + struct mmc_data *data) + { ++ struct sdmmc_idma *idma = host->dma_priv; ++ struct device *dev = mmc_dev(host->mmc); + struct scatterlist *sg; + int i; + +@@ -61,41 +66,69 @@ static int sdmmc_idma_validate_data(struct mmci_host *host, + * idma has constraints on idmabase & idmasize for each element + * excepted the last element which has no constraint on idmasize + */ ++ idma->use_bounce_buffer = false; + for_each_sg(data->sg, sg, data->sg_len - 1, i) { + if (!IS_ALIGNED(sg->offset, sizeof(u32)) || + !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) { +- dev_err(mmc_dev(host->mmc), ++ dev_dbg(mmc_dev(host->mmc), + "unaligned scatterlist: ofst:%x length:%d\n", + data->sg->offset, data->sg->length); +- return -EINVAL; ++ goto use_bounce_buffer; + } + } + + if (!IS_ALIGNED(sg->offset, sizeof(u32))) { +- dev_err(mmc_dev(host->mmc), ++ dev_dbg(mmc_dev(host->mmc), + "unaligned last scatterlist: ofst:%x length:%d\n", + data->sg->offset, data->sg->length); +- return -EINVAL; ++ goto use_bounce_buffer; + } + ++ return 0; ++ ++use_bounce_buffer: ++ if (!idma->bounce_buf) { ++ idma->bounce_buf = dmam_alloc_coherent(dev, ++ host->mmc->max_req_size, ++ &idma->bounce_dma_addr, ++ GFP_KERNEL); ++ if (!idma->bounce_buf) { ++ dev_err(dev, "Unable to map allocate DMA bounce buffer.\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ idma->use_bounce_buffer = true; ++ + return 0; + } + + static int _sdmmc_idma_prep_data(struct mmci_host *host, + struct mmc_data *data) + { +- int n_elem; ++ struct sdmmc_idma *idma = host->dma_priv; + +- n_elem = dma_map_sg(mmc_dev(host->mmc), +- data->sg, +- data->sg_len, +- mmc_get_dma_dir(data)); ++ if (idma->use_bounce_buffer) { ++ if (data->flags & MMC_DATA_WRITE) { ++ unsigned int xfer_bytes = data->blksz * data->blocks; + +- if (!n_elem) { +- dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n"); +- return -EINVAL; +- } ++ sg_copy_to_buffer(data->sg, data->sg_len, ++ idma->bounce_buf, xfer_bytes); ++ dma_wmb(); ++ } ++ } else { ++ int n_elem; ++ ++ n_elem = dma_map_sg(mmc_dev(host->mmc), ++ data->sg, ++ data->sg_len, ++ mmc_get_dma_dir(data)); + ++ if (!n_elem) { ++ dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n"); ++ return -EINVAL; ++ } ++ } + return 0; + } + +@@ -112,8 +145,19 @@ static int sdmmc_idma_prep_data(struct mmci_host *host, + static void sdmmc_idma_unprep_data(struct mmci_host *host, + struct mmc_data *data, int err) + { +- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, +- mmc_get_dma_dir(data)); ++ struct sdmmc_idma *idma = host->dma_priv; ++ ++ if (idma->use_bounce_buffer) { ++ if (data->flags & MMC_DATA_READ) { ++ unsigned int xfer_bytes = data->blksz * data->blocks; ++ ++ sg_copy_from_buffer(data->sg, data->sg_len, ++ idma->bounce_buf, xfer_bytes); ++ } ++ } else { ++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ mmc_get_dma_dir(data)); ++ } + } + + static int sdmmc_idma_setup(struct mmci_host *host) +@@ -137,6 +181,8 @@ static int sdmmc_idma_setup(struct mmci_host *host) + host->mmc->max_segs = SDMMC_LLI_BUF_LEN / + sizeof(struct sdmmc_lli_desc); + host->mmc->max_seg_size = host->variant->stm32_idmabsize_mask; ++ ++ host->mmc->max_req_size = SZ_1M; + } else { + host->mmc->max_segs = 1; + host->mmc->max_seg_size = host->mmc->max_req_size; +@@ -154,8 +200,16 @@ static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl) + struct scatterlist *sg; + int i; + +- if (!host->variant->dma_lli || data->sg_len == 1) { +- writel_relaxed(sg_dma_address(data->sg), ++ if (!host->variant->dma_lli || data->sg_len == 1 || ++ idma->use_bounce_buffer) { ++ u32 dma_addr; ++ ++ if (idma->use_bounce_buffer) ++ dma_addr = idma->bounce_dma_addr; ++ else ++ dma_addr = sg_dma_address(data->sg); ++ ++ writel_relaxed(dma_addr, + host->base + MMCI_STM32_IDMABASE0R); + writel_relaxed(MMCI_STM32_IDMAEN, + host->base + MMCI_STM32_IDMACTRLR); +@@ -241,11 +295,12 @@ static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired) + + /* + * SDMMC_FBCK is selected when an external Delay Block is needed +- * with SDR104. ++ * with SDR104 or HS200. + */ + if (host->mmc->ios.timing >= MMC_TIMING_UHS_SDR50) { + clk |= MCI_STM32_CLK_BUSSPEED; +- if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104) { ++ if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 || ++ host->mmc->ios.timing == MMC_TIMING_MMC_HS200) { + clk &= ~MCI_STM32_CLK_SEL_MSK; + clk |= MCI_STM32_CLK_SELFBCK; + } +diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c +index 1c277fbb91f2..733f9857e801 100644 +--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c ++++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -231,6 +232,7 @@ struct stm32_fmc2_timings { + + struct stm32_fmc2_nand { + struct nand_chip chip; ++ struct gpio_desc *wp_gpio; + struct stm32_fmc2_timings timings; + int ncs; + int cs_used[FMC2_MAX_CE]; +@@ -1747,6 +1749,18 @@ static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = { + .setup_interface = stm32_fmc2_nfc_setup_interface, + }; + ++static void stm32_fmc2_nfc_wp_enable(struct stm32_fmc2_nand *nand) ++{ ++ if (nand->wp_gpio) ++ gpiod_set_value(nand->wp_gpio, 1); ++} ++ ++static void stm32_fmc2_nfc_wp_disable(struct stm32_fmc2_nand *nand) ++{ ++ if (nand->wp_gpio) ++ gpiod_set_value(nand->wp_gpio, 0); ++} ++ + static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, + struct device_node *dn) + { +@@ -1785,6 +1799,18 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, + nand->cs_used[i] = cs; + } + ++ nand->wp_gpio = devm_gpiod_get_from_of_node(nfc->dev, dn, ++ "wp-gpios", 0, ++ GPIOD_OUT_HIGH, "wp"); ++ if (IS_ERR(nand->wp_gpio)) { ++ ret = PTR_ERR(nand->wp_gpio); ++ if (ret != -ENOENT) ++ return dev_err_probe(nfc->dev, ret, ++ "failed to request WP GPIO\n"); ++ ++ nand->wp_gpio = NULL; ++ } ++ + nand_set_flash_node(&nand->chip, dn); + + return 0; +@@ -1960,10 +1986,12 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) + chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE | + NAND_USES_DMA; + ++ stm32_fmc2_nfc_wp_disable(nand); ++ + /* Scan to find existence of the device */ + ret = nand_scan(chip, nand->ncs); + if (ret) +- goto err_release_dma; ++ goto err_wp_enable; + + ret = mtd_device_register(mtd, NULL, 0); + if (ret) +@@ -1976,6 +2004,9 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) + err_nand_cleanup: + nand_cleanup(chip); + ++err_wp_enable: ++ stm32_fmc2_nfc_wp_enable(nand); ++ + err_release_dma: + if (nfc->dma_ecc_ch) + dma_release_channel(nfc->dma_ecc_ch); +@@ -2016,15 +2047,20 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev) + + clk_disable_unprepare(nfc->clk); + ++ stm32_fmc2_nfc_wp_enable(nand); ++ + return 0; + } + + static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev) + { + struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev); ++ struct stm32_fmc2_nand *nand = &nfc->nand; + + clk_disable_unprepare(nfc->clk); + ++ stm32_fmc2_nfc_wp_enable(nand); ++ + pinctrl_pm_select_sleep_state(dev); + + return 0; +@@ -2046,6 +2082,8 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev) + + stm32_fmc2_nfc_init(nfc); + ++ stm32_fmc2_nfc_wp_disable(nand); ++ + for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) { + if (!(nfc->cs_assigned & BIT(chip_cs))) + continue; +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0013-ARM-5.15.24-stm32mp1-r1-NET-TTY.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0014-v5.15-stm32mp-r2-NET-TTY.patch similarity index 73% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0013-ARM-5.15.24-stm32mp1-r1-NET-TTY.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0014-v5.15-stm32mp-r2-NET-TTY.patch index f4add29..17e26e6 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0013-ARM-5.15.24-stm32mp1-r1-NET-TTY.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0014-v5.15-stm32mp-r2-NET-TTY.patch @@ -1,25 +1,30 @@ -From edb75d8544f2a81271e24ce887c07fda229bd30b Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:00:39 +0200 -Subject: [PATCH 13/22] ARM-5.15.24-stm32mp1-r1-NET-TTY +From 24528431ff2487e385cb19c78b1708b356b82c2f Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:57:48 +0100 +Subject: [PATCH 14/22] v5.15-stm32mp-r2 NET-TTY -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../net/ethernet/stmicro/stmmac/dwmac-stm32.c | 231 ++++-- + drivers/net/phy/phy_device.c | 2 +- drivers/net/phy/realtek.c | 12 +- - drivers/net/phy/smsc.c | 27 + + drivers/net/phy/smsc.c | 102 +++ + .../broadcom/brcm80211/brcmfmac/bcmsdh.c | 39 +- drivers/tty/Kconfig | 12 + drivers/tty/Makefile | 1 + + drivers/tty/rpmsg_tty.c | 287 +++++++ + drivers/tty/serial/Kconfig | 1 + drivers/tty/serial/serial_core.c | 10 + drivers/tty/serial/serial_mctrl_gpio.c | 38 + drivers/tty/serial/serial_mctrl_gpio.h | 18 + - drivers/tty/serial/stm32-usart.c | 758 ++++++++++++++---- + drivers/tty/serial/stm32-usart.c | 759 ++++++++++++++---- drivers/tty/serial/stm32-usart.h | 18 +- include/uapi/linux/serial.h | 4 +- - 11 files changed, 892 insertions(+), 237 deletions(-) + 15 files changed, 1278 insertions(+), 256 deletions(-) + create mode 100644 drivers/tty/rpmsg_tty.c diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c -index 2b38a499a..f0849cf42 100644 +index 2b38a499a404..f0849cf4266f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c @@ -15,6 +15,7 @@ @@ -446,8 +451,21 @@ index 2b38a499a..f0849cf42 100644 { } }; MODULE_DEVICE_TABLE(of, stm32_dwmac_match); +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index b616f55ea222..891fc76fe4c5 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -319,7 +319,7 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev) + * PHY_HALTED nor PHY_READY this is an indication that something went wrong + * and we should most likely be using MAC managed PM and we are not. + */ +- WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY); ++// WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY); + + ret = phy_init_hw(phydev); + if (ret < 0) diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c -index 11be60333..c61c37294 100644 +index 11be60333fa8..c61c37294c67 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -336,14 +336,10 @@ static int rtl8211f_config_init(struct phy_device *phydev) @@ -470,15 +488,139 @@ index 11be60333..c61c37294 100644 switch (phydev->interface) { case PHY_INTERFACE_MODE_RGMII: diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c -index d8cac02a7..b7d65470b 100644 +index 636b0907a598..634dd7f85274 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c -@@ -481,6 +481,32 @@ static struct phy_driver smsc_phy_driver[] = { - .get_strings = smsc_get_strings, - .get_stats = smsc_get_stats, +@@ -45,6 +45,7 @@ static struct smsc_hw_stat smsc_hw_stats[] = { -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, + struct smsc_phy_priv { + bool energy_enable; ++ bool wakeup_enable; + struct clk *refclk; + }; + +@@ -69,6 +70,8 @@ static int smsc_phy_config_intr(struct phy_device *phydev) + intmask = MII_LAN83C185_ISF_INT4 | MII_LAN83C185_ISF_INT6; + if (priv->energy_enable) + intmask |= MII_LAN83C185_ISF_INT7; ++ if (priv->wakeup_enable) ++ intmask |= MII_LAN83C185_ISF_INT8; + rc = phy_write(phydev, MII_LAN83C185_IM, intmask); + } else { + rc = phy_write(phydev, MII_LAN83C185_IM, intmask); +@@ -105,11 +108,52 @@ static irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev) + return IRQ_HANDLED; + } + ++static int smsc_phy_config_wol(struct phy_device *phydev) ++{ ++ int i, wol_ctrl, wol_filter; ++ u16 pwd[3] = {0, 0, 0}; ++ ++ /* Write @MAC in LAN8742_MMD3_MAC_ADDRA/B/C registers */ ++ u8 *mac_addr = phydev->attached_dev->dev_addr; ++ /* Store the device address for the magic packet */ ++ for (i = 0; i < ARRAY_SIZE(pwd); i++) ++ pwd[i] = mac_addr[5 - i * 2] << 8 | mac_addr[5 - (i * 2 + 1)]; ++ ++ phy_write_mmd(phydev, 3, LAN8742_MMD3_MAC_ADDRA, ++ pwd[0]); ++ ++ phy_write_mmd(phydev, 3, LAN8742_MMD3_MAC_ADDRB, ++ pwd[1]); ++ ++ phy_write_mmd(phydev, 3, LAN8742_MMD3_MAC_ADDRC, ++ pwd[2]); ++ ++ /* Configure WoL */ ++ wol_ctrl = phy_read_mmd(phydev, 3, LAN8742_MMD3_WAKEUP_CTRL); ++ ++ /* Configure LED2 functions as nPME, WoL Configured, Magic Packet Enable */ ++ wol_ctrl |= (LAN8742_MMD3_WUCSR_LED2_AS_NPME | LAN8742_MMD3_WUCSR_WOL | LAN8742_MMD3_WUCSR_MPEN); ++ phy_write_mmd(phydev, 3, LAN8742_MMD3_WAKEUP_CTRL, ++ wol_ctrl); ++ ++ wol_filter = phy_read_mmd(phydev, 3, LAN8742_MMD3_WAKEUP_FILTER); ++ ++ /* Configure Filter enabled, Address Match Enable */ ++ wol_filter |= (LAN8742_MMD3_WUF_CFGA_FE | LAN8742_MMD3_WUF_CFGA_AME); ++ phy_write_mmd(phydev, 3, LAN8742_MMD3_WAKEUP_FILTER, ++ wol_filter); ++ ++ return 0; ++} ++ + static int smsc_phy_config_init(struct phy_device *phydev) + { + struct smsc_phy_priv *priv = phydev->priv; + int rc; + ++ if (priv->wakeup_enable) ++ smsc_phy_config_wol(phydev); ++ + if (!priv->energy_enable || phydev->irq != PHY_POLL) + return 0; + +@@ -146,6 +190,17 @@ static int smsc_phy_reset(struct phy_device *phydev) + return genphy_soft_reset(phydev); + } + ++static int smsc_phy_suspend(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ ++ /* do not power down PHY when PHY enable power/wakeup */ ++ if (!device_may_wakeup(dev)) ++ return genphy_suspend(phydev); ++ ++ return 0; ++} ++ + static int lan911x_config_init(struct phy_device *phydev) + { + return smsc_phy_ack_interrupt(phydev); +@@ -251,6 +306,20 @@ static int lan87xx_read_status(struct phy_device *phydev) + return rc; + } + ++ if (priv->wakeup_enable) { ++ /* Check status of WUCSR bits 7:4 : Perfect DA Frame, Remote Wakeup ++ * Frame, Magic Packet, Broadcast Frame Received, if one of these bits ++ * are 1, clearing them*/ ++ int wol_ctrl = phy_read_mmd(phydev, 3, LAN8742_MMD3_WAKEUP_CTRL); ++ ++ if ((wol_ctrl & (LAN8742_MMD3_WUCSR_PFDA_FR | LAN8742_MMD3_WUCSR_WUFR | ++ LAN8742_MMD3_WUCSR_MPR | LAN8742_MMD3_WUCSR_BCAST_FR)) > 0) { ++ wol_ctrl |= (LAN8742_MMD3_WUCSR_PFDA_FR | LAN8742_MMD3_WUCSR_WUFR | ++ LAN8742_MMD3_WUCSR_MPR | LAN8742_MMD3_WUCSR_BCAST_FR); ++ phy_write_mmd(phydev, 3, LAN8742_MMD3_WAKEUP_CTRL, ++ wol_ctrl); ++ } ++ } + return err; + } + +@@ -313,10 +382,16 @@ static int smsc_phy_probe(struct phy_device *phydev) + return -ENOMEM; + + priv->energy_enable = true; ++ priv->wakeup_enable = false; + + if (of_property_read_bool(of_node, "smsc,disable-energy-detect")) + priv->energy_enable = false; + ++ if (of_property_read_bool(of_node, "wakeup-source")) { ++ device_set_wakeup_capable(dev, true); ++ priv->wakeup_enable = true; ++ } ++ + phydev->priv = priv; + + /* Make clk optional to keep DTB backward compatibility. */ +@@ -485,6 +560,32 @@ static struct phy_driver smsc_phy_driver[] = { + + .suspend = genphy_suspend, + .resume = genphy_resume, +}, { + .phy_id = 0x0007c130, + .phy_id_mask = 0xfffffff0, @@ -503,10 +645,12 @@ index d8cac02a7..b7d65470b 100644 + .get_strings = smsc_get_strings, + .get_stats = smsc_get_stats, + - .suspend = genphy_suspend, - .resume = genphy_resume, ++ .suspend = smsc_phy_suspend, ++ .resume = genphy_resume, } }; -@@ -498,6 +524,7 @@ static struct mdio_device_id __maybe_unused smsc_tbl[] = { + + module_phy_driver(smsc_phy_driver); +@@ -500,6 +601,7 @@ static struct mdio_device_id __maybe_unused smsc_tbl[] = { { 0x0007c0d0, 0xfffffff0 }, { 0x0007c0f0, 0xfffffff0 }, { 0x0007c110, 0xfffffff0 }, @@ -514,8 +658,95 @@ index d8cac02a7..b7d65470b 100644 { } }; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +index ac02244a6fdf..9c598ea97499 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -1119,9 +1119,21 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled) + { + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(sdiodev->func1); + +- brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled); +- sdiodev->wowl_enabled = enabled; ++ /* Power must be preserved to be able to support WOWL. */ ++ if (!(pm_caps & MMC_PM_KEEP_POWER)) ++ goto notsup; ++ ++ if (sdiodev->settings->bus.sdio.oob_irq_supported || ++ pm_caps & MMC_PM_WAKE_SDIO_IRQ) { ++ sdiodev->wowl_enabled = enabled; ++ brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled); ++ return; ++ } ++ ++notsup: ++ brcmf_dbg(SDIO, "WOWL not supported\n"); + } + + #ifdef CONFIG_PM_SLEEP +@@ -1130,7 +1142,7 @@ static int brcmf_ops_sdio_suspend(struct device *dev) + struct sdio_func *func; + struct brcmf_bus *bus_if; + struct brcmf_sdio_dev *sdiodev; +- mmc_pm_flag_t pm_caps, sdio_flags; ++ mmc_pm_flag_t sdio_flags; + int ret = 0; + + func = container_of(dev, struct sdio_func, dev); +@@ -1142,20 +1154,15 @@ static int brcmf_ops_sdio_suspend(struct device *dev) + bus_if = dev_get_drvdata(dev); + sdiodev = bus_if->bus_priv.sdio; + +- pm_caps = sdio_get_host_pm_caps(func); +- +- if (pm_caps & MMC_PM_KEEP_POWER) { +- /* preserve card power during suspend */ ++ if (sdiodev->wowl_enabled) { + brcmf_sdiod_freezer_on(sdiodev); + brcmf_sdio_wd_timer(sdiodev->bus, 0); + + sdio_flags = MMC_PM_KEEP_POWER; +- if (sdiodev->wowl_enabled) { +- if (sdiodev->settings->bus.sdio.oob_irq_supported) +- enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); +- else +- sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; +- } ++ if (sdiodev->settings->bus.sdio.oob_irq_supported) ++ enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); ++ else ++ sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; + + if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags)) + brcmf_err("Failed to set pm_flags %x\n", sdio_flags); +@@ -1176,21 +1183,19 @@ static int brcmf_ops_sdio_resume(struct device *dev) + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct sdio_func *func = container_of(dev, struct sdio_func, dev); +- mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(func); + int ret = 0; + + brcmf_dbg(SDIO, "Enter: F%d\n", func->num); + if (func->num != 2) + return 0; + +- if (!(pm_caps & MMC_PM_KEEP_POWER)) { ++ if (!sdiodev->wowl_enabled) { + /* bus was powered off and device removed, probe again */ + ret = brcmf_sdiod_probe(sdiodev); + if (ret) + brcmf_err("Failed to probe device on resume\n"); + } else { +- if (sdiodev->wowl_enabled && +- sdiodev->settings->bus.sdio.oob_irq_supported) ++ if (sdiodev->settings->bus.sdio.oob_irq_supported) + disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); + + brcmf_sdiod_freezer_off(sdiodev); diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig -index 23cc988c6..cc30ff93e 100644 +index 23cc988c68a4..cc30ff93e2e4 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -368,6 +368,18 @@ config VCC @@ -538,7 +769,7 @@ index 23cc988c6..cc30ff93e 100644 source "drivers/tty/serdev/Kconfig" diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile -index a2bd75fba..07aca5184 100644 +index a2bd75fbaaa4..07aca5184a55 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -26,5 +26,6 @@ obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o @@ -548,11 +779,316 @@ index a2bd75fba..07aca5184 100644 +obj-$(CONFIG_RPMSG_TTY) += rpmsg_tty.o obj-y += ipwireless/ +diff --git a/drivers/tty/rpmsg_tty.c b/drivers/tty/rpmsg_tty.c +new file mode 100644 +index 000000000000..29db413bbc03 +--- /dev/null ++++ b/drivers/tty/rpmsg_tty.c +@@ -0,0 +1,287 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2021 STMicroelectronics - All Rights Reserved ++ * ++ * The rpmsg tty driver implements serial communication on the RPMsg bus to makes ++ * possible for user-space programs to send and receive rpmsg messages as a standard ++ * tty protocol. ++ * ++ * The remote processor can instantiate a new tty by requesting a "rpmsg-tty" RPMsg service. ++ * The "rpmsg-tty" service is directly used for data exchange. No flow control is implemented yet. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define RPMSG_TTY_NAME "ttyRPMSG" ++#define MAX_TTY_RPMSG 32 ++ ++static DEFINE_IDR(tty_idr); /* tty instance id */ ++static DEFINE_MUTEX(idr_lock); /* protects tty_idr */ ++ ++static struct tty_driver *rpmsg_tty_driver; ++ ++struct rpmsg_tty_port { ++ struct tty_port port; /* TTY port data */ ++ int id; /* TTY rpmsg index */ ++ struct rpmsg_device *rpdev; /* rpmsg device */ ++}; ++ ++static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 src) ++{ ++ struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev); ++ int copied; ++ ++ if (!len) ++ return -EINVAL; ++ copied = tty_insert_flip_string(&cport->port, data, len); ++ if (copied != len) ++ dev_err_ratelimited(&rpdev->dev, "Trunc buffer: available space is %d\n", copied); ++ tty_flip_buffer_push(&cport->port); ++ ++ return 0; ++} ++ ++static int rpmsg_tty_install(struct tty_driver *driver, struct tty_struct *tty) ++{ ++ struct rpmsg_tty_port *cport = idr_find(&tty_idr, tty->index); ++ struct tty_port *port; ++ ++ tty->driver_data = cport; ++ ++ port = tty_port_get(&cport->port); ++ return tty_port_install(port, driver, tty); ++} ++ ++static void rpmsg_tty_cleanup(struct tty_struct *tty) ++{ ++ tty_port_put(tty->port); ++} ++ ++static int rpmsg_tty_open(struct tty_struct *tty, struct file *filp) ++{ ++ return tty_port_open(tty->port, tty, filp); ++} ++ ++static void rpmsg_tty_close(struct tty_struct *tty, struct file *filp) ++{ ++ return tty_port_close(tty->port, tty, filp); ++} ++ ++static int rpmsg_tty_write(struct tty_struct *tty, const u8 *buf, int len) ++{ ++ struct rpmsg_tty_port *cport = tty->driver_data; ++ struct rpmsg_device *rpdev; ++ int msg_max_size, msg_size; ++ int ret; ++ ++ rpdev = cport->rpdev; ++ ++ msg_max_size = rpmsg_get_mtu(rpdev->ept); ++ if (msg_max_size < 0) ++ return msg_max_size; ++ ++ msg_size = min(len, msg_max_size); ++ ++ /* ++ * Use rpmsg_trysend instead of rpmsg_send to send the message so the caller is not ++ * hung until a rpmsg buffer is available. In such case rpmsg_trysend returns -ENOMEM. ++ */ ++ ret = rpmsg_trysend(rpdev->ept, (void *)buf, msg_size); ++ if (ret) { ++ dev_dbg_ratelimited(&rpdev->dev, "rpmsg_send failed: %d\n", ret); ++ return ret; ++ } ++ ++ return msg_size; ++} ++ ++static unsigned int rpmsg_tty_write_room(struct tty_struct *tty) ++{ ++ struct rpmsg_tty_port *cport = tty->driver_data; ++ int size; ++ ++ size = rpmsg_get_mtu(cport->rpdev->ept); ++ if (size < 0) ++ return 0; ++ ++ return size; ++} ++ ++static void rpmsg_tty_hangup(struct tty_struct *tty) ++{ ++ tty_port_hangup(tty->port); ++} ++ ++static const struct tty_operations rpmsg_tty_ops = { ++ .install = rpmsg_tty_install, ++ .open = rpmsg_tty_open, ++ .close = rpmsg_tty_close, ++ .write = rpmsg_tty_write, ++ .write_room = rpmsg_tty_write_room, ++ .hangup = rpmsg_tty_hangup, ++ .cleanup = rpmsg_tty_cleanup, ++}; ++ ++static struct rpmsg_tty_port *rpmsg_tty_alloc_cport(void) ++{ ++ struct rpmsg_tty_port *cport; ++ int ret; ++ ++ cport = kzalloc(sizeof(*cport), GFP_KERNEL); ++ if (!cport) ++ return ERR_PTR(-ENOMEM); ++ ++ mutex_lock(&idr_lock); ++ ret = idr_alloc(&tty_idr, cport, 0, MAX_TTY_RPMSG, GFP_KERNEL); ++ mutex_unlock(&idr_lock); ++ ++ if (ret < 0) { ++ kfree(cport); ++ return ERR_PTR(ret); ++ } ++ ++ cport->id = ret; ++ ++ return cport; ++} ++ ++static void rpmsg_tty_destruct_port(struct tty_port *port) ++{ ++ struct rpmsg_tty_port *cport = container_of(port, struct rpmsg_tty_port, port); ++ ++ mutex_lock(&idr_lock); ++ idr_remove(&tty_idr, cport->id); ++ mutex_unlock(&idr_lock); ++ ++ kfree(cport); ++} ++ ++static const struct tty_port_operations rpmsg_tty_port_ops = { ++ .destruct = rpmsg_tty_destruct_port, ++}; ++ ++ ++static int rpmsg_tty_probe(struct rpmsg_device *rpdev) ++{ ++ struct rpmsg_tty_port *cport; ++ struct device *dev = &rpdev->dev; ++ struct device *tty_dev; ++ int ret; ++ ++ cport = rpmsg_tty_alloc_cport(); ++ if (IS_ERR(cport)) ++ return dev_err_probe(dev, PTR_ERR(cport), "Failed to alloc tty port\n"); ++ ++ tty_port_init(&cport->port); ++ cport->port.ops = &rpmsg_tty_port_ops; ++ ++ tty_dev = tty_port_register_device(&cport->port, rpmsg_tty_driver, ++ cport->id, dev); ++ if (IS_ERR(tty_dev)) { ++ ret = dev_err_probe(dev, PTR_ERR(tty_dev), "Failed to register tty port\n"); ++ tty_port_put(&cport->port); ++ return ret; ++ } ++ ++ cport->rpdev = rpdev; ++ ++ dev_set_drvdata(dev, cport); ++ ++ dev_dbg(dev, "New channel: 0x%x -> 0x%x: " RPMSG_TTY_NAME "%d\n", ++ rpdev->src, rpdev->dst, cport->id); ++ ++ return 0; ++} ++ ++static void rpmsg_tty_remove(struct rpmsg_device *rpdev) ++{ ++ struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev); ++ ++ dev_dbg(&rpdev->dev, "Removing rpmsg tty device %d\n", cport->id); ++ ++ /* User hang up to release the tty */ ++ tty_port_tty_hangup(&cport->port, false); ++ ++ tty_unregister_device(rpmsg_tty_driver, cport->id); ++ ++ tty_port_put(&cport->port); ++} ++ ++static struct rpmsg_device_id rpmsg_driver_tty_id_table[] = { ++ { .name = "rpmsg-tty" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_tty_id_table); ++ ++static struct rpmsg_driver rpmsg_tty_rpmsg_drv = { ++ .drv.name = KBUILD_MODNAME, ++ .id_table = rpmsg_driver_tty_id_table, ++ .probe = rpmsg_tty_probe, ++ .callback = rpmsg_tty_cb, ++ .remove = rpmsg_tty_remove, ++}; ++ ++static int __init rpmsg_tty_init(void) ++{ ++ int ret; ++ ++ rpmsg_tty_driver = tty_alloc_driver(MAX_TTY_RPMSG, TTY_DRIVER_REAL_RAW | ++ TTY_DRIVER_DYNAMIC_DEV); ++ if (IS_ERR(rpmsg_tty_driver)) ++ return PTR_ERR(rpmsg_tty_driver); ++ ++ rpmsg_tty_driver->driver_name = "rpmsg_tty"; ++ rpmsg_tty_driver->name = RPMSG_TTY_NAME; ++ rpmsg_tty_driver->major = 0; ++ rpmsg_tty_driver->type = TTY_DRIVER_TYPE_CONSOLE; ++ ++ /* Disable unused mode by default */ ++ rpmsg_tty_driver->init_termios = tty_std_termios; ++ rpmsg_tty_driver->init_termios.c_lflag &= ~(ECHO | ICANON); ++ rpmsg_tty_driver->init_termios.c_oflag &= ~(OPOST | ONLCR); ++ ++ tty_set_operations(rpmsg_tty_driver, &rpmsg_tty_ops); ++ ++ ret = tty_register_driver(rpmsg_tty_driver); ++ if (ret < 0) { ++ pr_err("Couldn't install driver: %d\n", ret); ++ goto error_put; ++ } ++ ++ ret = register_rpmsg_driver(&rpmsg_tty_rpmsg_drv); ++ if (ret < 0) { ++ pr_err("Couldn't register driver: %d\n", ret); ++ goto error_unregister; ++ } ++ ++ return 0; ++ ++error_unregister: ++ tty_unregister_driver(rpmsg_tty_driver); ++ ++error_put: ++ tty_driver_kref_put(rpmsg_tty_driver); ++ ++ return ret; ++} ++ ++static void __exit rpmsg_tty_exit(void) ++{ ++ unregister_rpmsg_driver(&rpmsg_tty_rpmsg_drv); ++ tty_unregister_driver(rpmsg_tty_driver); ++ tty_driver_kref_put(rpmsg_tty_driver); ++ idr_destroy(&tty_idr); ++} ++ ++module_init(rpmsg_tty_init); ++module_exit(rpmsg_tty_exit); ++ ++MODULE_AUTHOR("Arnaud Pouliquen "); ++MODULE_DESCRIPTION("remote processor messaging tty driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig +index 131a6a587acd..a1dea5888110 100644 +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -1440,6 +1440,7 @@ config SERIAL_STM32_CONSOLE + bool "Support for console on STM32" + depends on SERIAL_STM32=y + select SERIAL_CORE_CONSOLE ++ select SERIAL_EARLYCON + + config SERIAL_MVEBU_UART + bool "Marvell EBU serial port support" diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c -index dc6129dde..bde6c62e6 100644 +index 82ddbb92d07d..596e76f49c60 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c -@@ -3238,6 +3238,16 @@ int uart_get_rs485_mode(struct uart_port *port) +@@ -3237,6 +3237,16 @@ int uart_get_rs485_mode(struct uart_port *port) u32 rs485_delay[2]; int ret; @@ -570,7 +1106,7 @@ index dc6129dde..bde6c62e6 100644 rs485_delay, 2); if (!ret) { diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c -index c41d8911c..1663b3afc 100644 +index c41d8911ce95..1663b3afc3a0 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -299,4 +299,42 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) @@ -617,7 +1153,7 @@ index c41d8911c..1663b3afc 100644 + MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h -index b134a0ffc..fc76910fb 100644 +index b134a0ffc894..fc76910fb105 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -91,6 +91,16 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios); @@ -653,10 +1189,10 @@ index b134a0ffc..fc76910fb 100644 #endif diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c -index 200cd293d..f8c048443 100644 +index fc166cc2c856..4d7a316649c1 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c -@@ -61,38 +61,65 @@ static void stm32_usart_clr_bits(struct uart_port *port, u32 reg, u32 bits) +@@ -61,40 +61,67 @@ static void stm32_usart_clr_bits(struct uart_port *port, u32 reg, u32 bits) writel_relaxed(val, port->membase + reg); } @@ -712,6 +1248,8 @@ index 200cd293d..f8c048443 100644 *cr3 |= USART_CR3_DEM; over8 = *cr1 & USART_CR1_OVER8; + *cr1 &= ~(USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK); + - if (over8) - rs485_deat_dedt = delay_ADE * baud * 8; - else @@ -745,7 +1283,7 @@ index 200cd293d..f8c048443 100644 *cr1 |= rs485_deat_dedt; } -@@ -123,10 +150,7 @@ static int stm32_usart_config_rs485(struct uart_port *port, +@@ -125,10 +152,7 @@ static int stm32_usart_config_rs485(struct uart_port *port, << USART_BRR_04_R_SHIFT; baud = DIV_ROUND_CLOSEST(port->uartclk, usartdiv); @@ -757,7 +1295,7 @@ index 200cd293d..f8c048443 100644 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; -@@ -165,63 +189,103 @@ static int stm32_usart_init_rs485(struct uart_port *port, +@@ -167,63 +191,103 @@ static int stm32_usart_init_rs485(struct uart_port *port, return uart_get_rs485_mode(port); } @@ -894,7 +1432,7 @@ index 200cd293d..f8c048443 100644 sr |= USART_SR_DUMMY_RX; flag = TTY_NORMAL; -@@ -240,8 +304,9 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded) +@@ -242,8 +306,9 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded) writel_relaxed(sr & USART_SR_ERR_MASK, port->membase + ofs->icr); @@ -905,7 +1443,7 @@ index 200cd293d..f8c048443 100644 if (sr & USART_SR_ERR_MASK) { if (sr & USART_SR_ORE) { port->icount.overrun++; -@@ -275,21 +340,208 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded) +@@ -277,21 +342,208 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded) uart_insert_char(port, sr, USART_SR_ORE, c, flag); } @@ -921,8 +1459,7 @@ index 200cd293d..f8c048443 100644 + int dma_count, i; + + dma_start = stm32_port->rx_buf + (RX_BUF_L - stm32_port->last_res); - -- tty_flip_buffer_push(tport); ++ + /* + * Apply rdr_mask on buffer in order to mask parity bit. + * This loop is useless in cs8 mode because DMA copies only @@ -1008,7 +1545,8 @@ index 200cd293d..f8c048443 100644 + struct tty_port *tport = &port->state->port; + unsigned int size; + unsigned long flags; -+ + +- tty_flip_buffer_push(tport); + spin_lock_irqsave(&port->lock, flags); + size = stm32_usart_receive_chars(port, false); + uart_unlock_and_check_sysrq_irqrestore(port, flags); @@ -1120,7 +1658,7 @@ index 200cd293d..f8c048443 100644 /* Let's see if we have pending data to send */ spin_lock_irqsave(&port->lock, flags); -@@ -329,11 +581,6 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) +@@ -331,11 +583,6 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct circ_buf *xmit = &port->state->xmit; @@ -1132,7 +1670,7 @@ index 200cd293d..f8c048443 100644 while (!uart_circ_empty(xmit)) { /* Check that TDR is empty before filling FIFO */ if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) -@@ -353,15 +600,17 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) +@@ -355,15 +602,17 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) static void stm32_usart_transmit_chars_dma(struct uart_port *port) { struct stm32_port *stm32port = to_stm32_port(port); @@ -1155,7 +1693,7 @@ index 200cd293d..f8c048443 100644 count = uart_circ_chars_pending(xmit); -@@ -392,28 +641,35 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) +@@ -394,28 +643,35 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) if (!desc) goto fallback_err; @@ -1198,28 +1736,18 @@ index 200cd293d..f8c048443 100644 } static void stm32_usart_transmit_chars(struct uart_port *port) -@@ -421,15 +677,28 @@ static void stm32_usart_transmit_chars(struct uart_port *port) - struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - struct circ_buf *xmit = &port->state->xmit; -+ u32 isr; -+ int ret; +@@ -427,8 +683,8 @@ static void stm32_usart_transmit_chars(struct uart_port *port) + int ret; if (port->x_char) { - if (stm32_port->tx_dma_busy) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + /* dma terminate may have been called in case of dma pause failure */ + stm32_usart_tx_dma_pause(stm32_port); -+ -+ /* Check that TDR is empty before filling FIFO */ -+ ret = -+ readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, -+ isr, -+ (isr & USART_SR_TXE), -+ 10, 1000); -+ if (ret) -+ dev_warn(port->dev, "1 character may be erased\n"); -+ + + /* Check that TDR is empty before filling FIFO */ + ret = +@@ -442,8 +698,9 @@ static void stm32_usart_transmit_chars(struct uart_port *port) writel_relaxed(port->x_char, port->membase + ofs->tdr); port->x_char = 0; port->icount.tx++; @@ -1231,7 +1759,7 @@ index 200cd293d..f8c048443 100644 return; } -@@ -462,6 +731,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) +@@ -476,6 +733,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; u32 sr; @@ -1239,7 +1767,7 @@ index 200cd293d..f8c048443 100644 sr = readl_relaxed(port->membase + ofs->isr); -@@ -478,8 +748,20 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) +@@ -492,8 +750,20 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) pm_wakeup_event(tport->tty->dev, 0); } @@ -1262,7 +1790,7 @@ index 200cd293d..f8c048443 100644 if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) { spin_lock(&port->lock); -@@ -487,7 +769,8 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) +@@ -501,7 +771,8 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) spin_unlock(&port->lock); } @@ -1272,7 +1800,7 @@ index 200cd293d..f8c048443 100644 return IRQ_WAKE_THREAD; else return IRQ_HANDLED; -@@ -496,10 +779,16 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) +@@ -510,10 +781,16 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; @@ -1292,7 +1820,7 @@ index 200cd293d..f8c048443 100644 return IRQ_HANDLED; } -@@ -557,6 +846,9 @@ static void stm32_usart_stop_tx(struct uart_port *port) +@@ -571,6 +848,9 @@ static void stm32_usart_stop_tx(struct uart_port *port) stm32_usart_tx_interrupt_disable(port); @@ -1302,7 +1830,7 @@ index 200cd293d..f8c048443 100644 if (rs485conf->flags & SER_RS485_ENABLED) { if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { mctrl_gpio_set(stm32_port->gpios, -@@ -595,13 +887,9 @@ static void stm32_usart_start_tx(struct uart_port *port) +@@ -609,13 +889,9 @@ static void stm32_usart_start_tx(struct uart_port *port) static void stm32_usart_flush_buffer(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); @@ -1318,7 +1846,7 @@ index 200cd293d..f8c048443 100644 } /* Throttle the remote when input buffer is about to overflow. */ -@@ -612,10 +900,18 @@ static void stm32_usart_throttle(struct uart_port *port) +@@ -626,10 +902,18 @@ static void stm32_usart_throttle(struct uart_port *port) unsigned long flags; spin_lock_irqsave(&port->lock, flags); @@ -1337,7 +1865,7 @@ index 200cd293d..f8c048443 100644 spin_unlock_irqrestore(&port->lock, flags); } -@@ -631,6 +927,15 @@ static void stm32_usart_unthrottle(struct uart_port *port) +@@ -645,6 +929,15 @@ static void stm32_usart_unthrottle(struct uart_port *port) if (stm32_port->cr3_irq) stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq); @@ -1353,7 +1881,7 @@ index 200cd293d..f8c048443 100644 spin_unlock_irqrestore(&port->lock, flags); } -@@ -640,6 +945,9 @@ static void stm32_usart_stop_rx(struct uart_port *port) +@@ -654,14 +947,28 @@ static void stm32_usart_stop_rx(struct uart_port *port) struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; @@ -1363,7 +1891,27 @@ index 200cd293d..f8c048443 100644 stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); if (stm32_port->cr3_irq) stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); -@@ -676,6 +984,14 @@ static int stm32_usart_startup(struct uart_port *port) + } + +-/* Handle breaks - ignored by us */ + static void stm32_usart_break_ctl(struct uart_port *port, int break_state) + { ++ struct stm32_port *stm32_port = to_stm32_port(port); ++ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&port->lock, flags); ++ ++ if (break_state) ++ stm32_usart_set_bits(port, ofs->rqr, USART_RQR_SBKRQ); ++ else ++ stm32_usart_clr_bits(port, ofs->rqr, USART_RQR_SBKRQ); ++ ++ spin_unlock_irqrestore(&port->lock, flags); + } + + static int stm32_usart_startup(struct uart_port *port) +@@ -690,6 +997,14 @@ static int stm32_usart_startup(struct uart_port *port) if (ofs->rqr != UNDEF_REG) writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr); @@ -1378,7 +1926,7 @@ index 200cd293d..f8c048443 100644 /* RX enabling */ val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit); stm32_usart_set_bits(port, ofs->cr1, val); -@@ -691,10 +1007,11 @@ static void stm32_usart_shutdown(struct uart_port *port) +@@ -705,10 +1020,11 @@ static void stm32_usart_shutdown(struct uart_port *port) u32 val, isr; int ret; @@ -1393,7 +1941,7 @@ index 200cd293d..f8c048443 100644 /* Disable modem control interrupts */ stm32_usart_disable_ms(port); -@@ -713,6 +1030,12 @@ static void stm32_usart_shutdown(struct uart_port *port) +@@ -727,6 +1043,12 @@ static void stm32_usart_shutdown(struct uart_port *port) if (ret) dev_err(port->dev, "Transmission is not complete\n"); @@ -1406,7 +1954,7 @@ index 200cd293d..f8c048443 100644 /* flush RX & TX FIFO */ if (ofs->rqr != UNDEF_REG) writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ, -@@ -815,9 +1138,11 @@ static void stm32_usart_set_termios(struct uart_port *port, +@@ -838,9 +1160,11 @@ static void stm32_usart_set_termios(struct uart_port *port, stm32_port->cr1_irq = USART_CR1_RTOIE; writel_relaxed(bits, port->membase + ofs->rtor); cr2 |= USART_CR2_RTOEN; @@ -1421,7 +1969,7 @@ index 200cd293d..f8c048443 100644 } cr1 |= stm32_port->cr1_irq; -@@ -880,14 +1205,22 @@ static void stm32_usart_set_termios(struct uart_port *port, +@@ -903,14 +1227,22 @@ static void stm32_usart_set_termios(struct uart_port *port, if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= USART_SR_DUMMY_RX; @@ -1449,7 +1997,7 @@ index 200cd293d..f8c048443 100644 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; -@@ -970,6 +1303,40 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state, +@@ -993,6 +1325,40 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state, } } @@ -1490,7 +2038,7 @@ index 200cd293d..f8c048443 100644 static const struct uart_ops stm32_uart_ops = { .tx_empty = stm32_usart_tx_empty, .set_mctrl = stm32_usart_set_mctrl, -@@ -991,6 +1358,12 @@ static const struct uart_ops stm32_uart_ops = { +@@ -1014,6 +1380,12 @@ static const struct uart_ops stm32_uart_ops = { .request_port = stm32_usart_request_port, .config_port = stm32_usart_config_port, .verify_port = stm32_usart_verify_port, @@ -1503,7 +2051,7 @@ index 200cd293d..f8c048443 100644 }; /* -@@ -1171,7 +1544,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, +@@ -1194,7 +1566,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, struct uart_port *port = &stm32port->port; struct device *dev = &pdev->dev; struct dma_slave_config config; @@ -1511,7 +2059,7 @@ index 200cd293d..f8c048443 100644 int ret; /* -@@ -1199,32 +1571,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, +@@ -1222,32 +1593,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, return ret; } @@ -1544,7 +2092,7 @@ index 200cd293d..f8c048443 100644 return 0; } -@@ -1245,8 +1591,6 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, +@@ -1268,8 +1613,6 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, struct dma_slave_config config; int ret; @@ -1553,7 +2101,7 @@ index 200cd293d..f8c048443 100644 stm32port->tx_buf = dma_alloc_coherent(dev, TX_BUF_L, &stm32port->tx_dma_buf, GFP_KERNEL); -@@ -1377,6 +1721,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) +@@ -1400,6 +1743,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; int err; @@ -1561,7 +2109,7 @@ index 200cd293d..f8c048443 100644 pm_runtime_get_sync(&pdev->dev); err = uart_remove_one_port(&stm32_usart_driver, port); -@@ -1387,7 +1732,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) +@@ -1410,7 +1754,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); @@ -1570,7 +2118,7 @@ index 200cd293d..f8c048443 100644 if (stm32_port->tx_ch) { stm32_usart_of_dma_tx_remove(stm32_port, pdev); -@@ -1395,12 +1740,16 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) +@@ -1418,12 +1762,16 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) } if (stm32_port->rx_ch) { @@ -1589,7 +2137,7 @@ index 200cd293d..f8c048443 100644 if (stm32_port->wakeup_src) { dev_pm_clear_wake_irq(&pdev->dev); -@@ -1412,18 +1761,24 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) +@@ -1435,18 +1783,24 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) return 0; } @@ -1619,7 +2167,7 @@ index 200cd293d..f8c048443 100644 static void stm32_usart_console_write(struct console *co, const char *s, unsigned int cnt) { -@@ -1499,6 +1854,57 @@ static struct console stm32_console = { +@@ -1522,6 +1876,57 @@ static struct console stm32_console = { #define STM32_SERIAL_CONSOLE NULL #endif /* CONFIG_SERIAL_STM32_CONSOLE */ @@ -1677,7 +2225,7 @@ index 200cd293d..f8c048443 100644 static struct uart_driver stm32_usart_driver = { .driver_name = DRIVER_NAME, .dev_name = STM32_SERIAL_NAME, -@@ -1508,14 +1914,18 @@ static struct uart_driver stm32_usart_driver = { +@@ -1531,14 +1936,18 @@ static struct uart_driver stm32_usart_driver = { .cons = STM32_SERIAL_CONSOLE, }; @@ -1700,7 +2248,7 @@ index 200cd293d..f8c048443 100644 /* * Enable low-power wake-up and wake-up irq if argument is set to -@@ -1524,20 +1934,52 @@ static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, +@@ -1547,20 +1956,52 @@ static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, if (enable) { stm32_usart_set_bits(port, ofs->cr1, USART_CR1_UESM); stm32_usart_set_bits(port, ofs->cr3, USART_CR3_WUFIE); @@ -1755,7 +2303,7 @@ index 200cd293d..f8c048443 100644 /* * When "no_console_suspend" is enabled, keep the pinctrl default state -@@ -1558,11 +2000,15 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev) +@@ -1581,11 +2022,15 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev) static int __maybe_unused stm32_usart_serial_resume(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); @@ -1774,7 +2322,7 @@ index 200cd293d..f8c048443 100644 return uart_resume_port(&stm32_usart_driver, port); } diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h -index 07ac29132..9c7ddb906 100644 +index 07ac291328cd..9c7ddb906d3c 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -109,7 +109,7 @@ struct stm32_usart_info stm32h7_info = { @@ -1831,7 +2379,7 @@ index 07ac29132..9c7ddb906 100644 static struct stm32_port stm32_ports[STM32_MAX_PORTS]; diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h -index fa6b16e5f..e79080578 100644 +index fa6b16e5fdd8..e79080578bd8 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -128,7 +128,9 @@ struct serial_rs485 { @@ -1846,5 +2394,5 @@ index fa6b16e5f..e79080578 100644 }; -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0014-ARM-5.15.24-stm32mp1-r1-PERF.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0015-v5.15-stm32mp-r2-PERF.patch similarity index 97% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0014-ARM-5.15.24-stm32mp1-r1-PERF.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0015-v5.15-stm32mp-r2-PERF.patch index eb4cdee..0b5ade8 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0014-ARM-5.15.24-stm32mp1-r1-PERF.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0015-v5.15-stm32mp-r2-PERF.patch @@ -1,9 +1,9 @@ -From 004f2714f71a2ebf3f233b3fae5a3e0e14b5e68e Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:01:13 +0200 -Subject: [PATCH 14/22] ARM-5.15.24-stm32mp1-r1-PERF +From df5b54b2fc266fd51fff7130ee8707027e2aa3ea Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:58:41 +0100 +Subject: [PATCH 15/22] v5.15-stm32mp-r2 PERF -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- Documentation/admin-guide/perf/index.rst | 1 + .../admin-guide/perf/stm32-ddr-pmu.rst | 44 ++ @@ -17,7 +17,7 @@ Signed-off-by: Christophe Priouzeau create mode 100644 drivers/perf/stm32_ddr_pmu.c diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst -index 5a8f2529a..9f68f68be 100644 +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 @@ -30,7 +30,7 @@ index 5a8f2529a..9f68f68be 100644 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 000000000..db647fc1a +index 000000000000..db647fc1acad --- /dev/null +++ b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst @@ -0,0 +1,44 @@ @@ -80,7 +80,7 @@ index 000000000..db647fc1a + diff --git a/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.yaml new file mode 100644 -index 000000000..085f2886e +index 000000000000..085f2886e580 --- /dev/null +++ b/Documentation/devicetree/bindings/perf/stm32-ddr-pmu.yaml @@ -0,0 +1,44 @@ @@ -129,7 +129,7 @@ index 000000000..085f2886e + }; +... diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig -index 77522e5ef..fb55e0bbf 100644 +index 77522e5efe11..fb55e0bbfb90 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -106,6 +106,13 @@ config QCOM_L3_PMU @@ -147,7 +147,7 @@ index 77522e5ef..fb55e0bbf 100644 tristate "Cavium ThunderX2 SoC PMU UNCORE" depends on ARCH_THUNDER2 && ARM64 && ACPI && NUMA diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile -index 5260b116c..f1d363307 100644 +index 5260b116c7da..f1d3633075b7 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o @@ -160,7 +160,7 @@ index 5260b116c..f1d363307 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 000000000..c0082109a +index 000000000000..c0082109aa16 --- /dev/null +++ b/drivers/perf/stm32_ddr_pmu.c @@ -0,0 +1,439 @@ @@ -604,5 +604,5 @@ index 000000000..c0082109a +MODULE_AUTHOR("Gerald Baeza "); +MODULE_LICENSE("GPL v2"); -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0015-ARM-5.15.24-stm32mp1-r1-PHY-USB.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0016-v5.15-stm32mp-r2-PHY-USB.patch similarity index 92% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0015-ARM-5.15.24-stm32mp1-r1-PHY-USB.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0016-v5.15-stm32mp-r2-PHY-USB.patch index 9200e08..c36da5c 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0015-ARM-5.15.24-stm32mp1-r1-PHY-USB.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0016-v5.15-stm32mp-r2-PHY-USB.patch @@ -1,24 +1,24 @@ -From 36353ea45646109b55656e806ea70c10fce2453b Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:04:31 +0200 -Subject: [PATCH 15/22] ARM-5.15.24-stm32mp1-r1-PHY-USB +From f593955537b76035054bfc42586146cd974c9ae3 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 15:59:56 +0100 +Subject: [PATCH 16/22] v5.15-stm32mp-r2 PHY-USB -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../bindings/phy/phy-stm32-usbphyc.yaml | 133 +++ .../devicetree/bindings/usb/dwc2.yaml | 33 +- .../devicetree/bindings/usb/generic-ehci.yaml | 5 + .../devicetree/bindings/usb/generic-ohci.yaml | 5 + .../bindings/usb/st,typec-stm32g0.yaml | 83 ++ - drivers/phy/st/phy-stm32-usbphyc.c | 232 ++++- + drivers/phy/st/phy-stm32-usbphyc.c | 233 +++++- drivers/usb/core/hcd.c | 9 +- drivers/usb/core/phy.c | 22 +- drivers/usb/core/phy.h | 6 +- - drivers/usb/dwc2/core.h | 24 +- + drivers/usb/dwc2/core.h | 22 +- drivers/usb/dwc2/core_intr.c | 3 +- drivers/usb/dwc2/debugfs.c | 4 +- - drivers/usb/dwc2/drd.c | 85 +- - drivers/usb/dwc2/gadget.c | 5 +- + drivers/usb/dwc2/drd.c | 79 +- + drivers/usb/dwc2/gadget.c | 2 +- drivers/usb/dwc2/hcd.c | 61 +- drivers/usb/dwc2/params.c | 75 +- drivers/usb/dwc2/platform.c | 82 +- @@ -26,15 +26,15 @@ Signed-off-by: Christophe Priouzeau drivers/usb/host/ohci-platform.c | 14 +- drivers/usb/typec/ucsi/Kconfig | 10 + drivers/usb/typec/ucsi/Makefile | 1 + - drivers/usb/typec/ucsi/ucsi.c | 42 +- + drivers/usb/typec/ucsi/ucsi.c | 49 +- drivers/usb/typec/ucsi/ucsi.h | 2 + - drivers/usb/typec/ucsi/ucsi_stm32g0.c | 801 ++++++++++++++++++ - 24 files changed, 1584 insertions(+), 169 deletions(-) + drivers/usb/typec/ucsi/ucsi_stm32g0.c | 770 ++++++++++++++++++ + 24 files changed, 1551 insertions(+), 168 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/st,typec-stm32g0.yaml create mode 100644 drivers/usb/typec/ucsi/ucsi_stm32g0.c diff --git a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml -index 3329f1d33..750ce7074 100644 +index 3329f1d33a4f..750ce7074648 100644 --- a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml +++ b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml @@ -74,6 +74,10 @@ patternProperties: @@ -199,7 +199,7 @@ index 3329f1d33..750ce7074 100644 }; ... diff --git a/Documentation/devicetree/bindings/usb/dwc2.yaml b/Documentation/devicetree/bindings/usb/dwc2.yaml -index 10c7d9b6c..882a2f1e0 100644 +index 10c7d9b6cc53..882a2f1e0738 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.yaml +++ b/Documentation/devicetree/bindings/usb/dwc2.yaml @@ -9,6 +9,9 @@ title: DesignWare HS OTG USB 2.0 controller Bindings @@ -258,10 +258,10 @@ index 10c7d9b6c..882a2f1e0 100644 - compatible - reg diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml -index 891349762..c134aabec 100644 +index cb5da1df8d40..0b12acf804ec 100644 --- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml +++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml -@@ -148,6 +148,11 @@ properties: +@@ -149,6 +149,11 @@ properties: - host - otg @@ -274,10 +274,10 @@ index 891349762..c134aabec 100644 - compatible - reg diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml -index acbf94fa5..1efa1eed9 100644 +index d5fd3aa53ed2..ef237675a83a 100644 --- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml +++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml -@@ -115,6 +115,11 @@ properties: +@@ -116,6 +116,11 @@ properties: - host - otg @@ -291,7 +291,7 @@ index acbf94fa5..1efa1eed9 100644 - reg diff --git a/Documentation/devicetree/bindings/usb/st,typec-stm32g0.yaml b/Documentation/devicetree/bindings/usb/st,typec-stm32g0.yaml new file mode 100644 -index 000000000..b2729bd01 +index 000000000000..b2729bd015a1 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/st,typec-stm32g0.yaml @@ -0,0 +1,83 @@ @@ -379,7 +379,7 @@ index 000000000..b2729bd01 + }; +... diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c -index da05642d3..d3d1235b9 100644 +index cd0747ab6267..af198f7c3f09 100644 --- a/drivers/phy/st/phy-stm32-usbphyc.c +++ b/drivers/phy/st/phy-stm32-usbphyc.c @@ -12,6 +12,7 @@ @@ -493,7 +493,7 @@ index da05642d3..d3d1235b9 100644 }; struct stm32_usbphyc { -@@ -295,6 +376,12 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) +@@ -297,6 +378,12 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) static int stm32_usbphyc_phy_power_on(struct phy *phy) { struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); @@ -506,7 +506,7 @@ index da05642d3..d3d1235b9 100644 if (usbphyc_phy->vbus) return regulator_enable(usbphyc_phy->vbus); -@@ -305,6 +392,12 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy) +@@ -307,6 +394,12 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy) static int stm32_usbphyc_phy_power_off(struct phy *phy) { struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); @@ -519,7 +519,7 @@ index da05642d3..d3d1235b9 100644 if (usbphyc_phy->vbus) return regulator_disable(usbphyc_phy->vbus); -@@ -375,6 +468,107 @@ static int stm32_usbphyc_clk48_register(struct stm32_usbphyc *usbphyc) +@@ -377,6 +470,107 @@ static int stm32_usbphyc_clk48_register(struct stm32_usbphyc *usbphyc) return ret; } @@ -627,7 +627,7 @@ index da05642d3..d3d1235b9 100644 static void stm32_usbphyc_switch_setup(struct stm32_usbphyc *usbphyc, u32 utmi_switch) { -@@ -492,17 +686,15 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) +@@ -494,17 +688,15 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) usbphyc->vdda1v1 = devm_regulator_get(dev, "vdda1v1"); if (IS_ERR(usbphyc->vdda1v1)) { @@ -649,14 +649,15 @@ index da05642d3..d3d1235b9 100644 goto clk_disable; } -@@ -550,6 +742,14 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) +@@ -552,6 +744,15 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) usbphyc->phys[port]->vbus = NULL; } + /* Get optional wakeup interrupt */ -+ usbphyc->phys[port]->wakeirq = of_irq_get(child, 0); -+ if (usbphyc->phys[port]->wakeirq == -EPROBE_DEFER) ++ ret = of_irq_get(child, 0); ++ if (ret == -EPROBE_DEFER) + goto put_child; ++ usbphyc->phys[port]->wakeirq = ret; + + /* Configure phy tuning */ + stm32_usbphyc_phy_tuning(usbphyc, child, index); @@ -664,7 +665,7 @@ index da05642d3..d3d1235b9 100644 port++; } -@@ -598,6 +798,25 @@ static int stm32_usbphyc_remove(struct platform_device *pdev) +@@ -600,6 +801,25 @@ static int stm32_usbphyc_remove(struct platform_device *pdev) return 0; } @@ -690,7 +691,7 @@ index da05642d3..d3d1235b9 100644 static const struct of_device_id stm32_usbphyc_of_match[] = { { .compatible = "st,stm32mp1-usbphyc", }, { }, -@@ -610,6 +829,7 @@ static struct platform_driver stm32_usbphyc_driver = { +@@ -612,6 +832,7 @@ static struct platform_driver stm32_usbphyc_driver = { .driver = { .of_match_table = stm32_usbphyc_of_match, .name = "stm32-usbphyc", @@ -699,10 +700,10 @@ index da05642d3..d3d1235b9 100644 }; module_platform_driver(stm32_usbphyc_driver); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c -index dd3c288fa..9c4fef396 100644 +index 6c5934dbe9b3..ee16e33b431e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c -@@ -2292,7 +2292,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) +@@ -2295,7 +2295,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) if (!PMSG_IS_AUTO(msg)) usb_phy_roothub_suspend(hcd->self.sysdev, @@ -712,7 +713,7 @@ index dd3c288fa..9c4fef396 100644 /* Did we race with a root-hub wakeup event? */ if (rhdev->do_remote_wakeup) { -@@ -2333,7 +2334,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) +@@ -2336,7 +2337,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) if (!PMSG_IS_AUTO(msg)) { status = usb_phy_roothub_resume(hcd->self.sysdev, @@ -722,7 +723,7 @@ index dd3c288fa..9c4fef396 100644 if (status) return status; } -@@ -2378,7 +2380,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) +@@ -2381,7 +2383,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) } } else { hcd->state = old_state; @@ -733,7 +734,7 @@ index dd3c288fa..9c4fef396 100644 "resume", status); if (status != -ESHUTDOWN) diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c -index fb1588e7c..746615aa1 100644 +index fb1588e7c282..746615aa1b2d 100644 --- a/drivers/usb/core/phy.c +++ b/drivers/usb/core/phy.c @@ -212,34 +212,36 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub) @@ -784,7 +785,7 @@ index fb1588e7c..746615aa1 100644 return err; diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h -index 20a267cd9..3df4ddbb6 100644 +index 20a267cd986b..3df4ddbb6046 100644 --- a/drivers/usb/core/phy.h +++ b/drivers/usb/core/phy.h @@ -23,8 +23,10 @@ int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub); @@ -801,7 +802,7 @@ index 20a267cd9..3df4ddbb6 100644 #endif /* __USB_CORE_PHY_H_ */ diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h -index cb9059a84..255fca4e8 100644 +index 71e62b3081db..255fca4e8346 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -238,11 +238,14 @@ enum dwc2_ep0_state { @@ -854,24 +855,8 @@ index cb9059a84..255fca4e8 100644 unsigned int hcd_enabled:1; unsigned int gadget_enabled:1; unsigned int ll_hw_enabled:1; -@@ -1417,6 +1419,7 @@ void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); - void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); - int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); - #define dwc2_is_device_connected(hsotg) (hsotg->connected) -+#define dwc2_is_device_enabled(hsotg) (hsotg->enabled) - int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg); - int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup); - int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg); -@@ -1453,6 +1456,7 @@ static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, - int testmode) - { return 0; } - #define dwc2_is_device_connected(hsotg) (0) -+#define dwc2_is_device_enabled(hsotg) (0) - static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) - { return 0; } - static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c -index a5c52b237..c786560fb 100644 +index a5c52b237e72..c786560fb54e 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -433,13 +433,14 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) @@ -891,7 +876,7 @@ index a5c52b237..c786560fb 100644 /* Change to L0 state */ hsotg->lx_state = DWC2_L0; diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c -index f13eed423..1d72ece9c 100644 +index f13eed4231e1..1d72ece9cfe4 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c @@ -670,7 +670,9 @@ static int params_show(struct seq_file *seq, void *v) @@ -906,7 +891,7 @@ index f13eed423..1d72ece9c 100644 print_param(seq, p, dma_desc_fs_enable); print_param(seq, p, speed); diff --git a/drivers/usb/dwc2/drd.c b/drivers/usb/dwc2/drd.c -index aa6eb76f6..c64701307 100644 +index 36f2c38416e5..c64701307ccc 100644 --- a/drivers/usb/dwc2/drd.c +++ b/drivers/usb/dwc2/drd.c @@ -13,6 +13,10 @@ @@ -967,7 +952,7 @@ index aa6eb76f6..c64701307 100644 gotgctl &= ~GOTGCTL_AVALOVAL; if (valid) gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL; -@@ -105,12 +118,22 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) +@@ -105,6 +118,14 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) spin_lock_irqsave(&hsotg->lock, flags); @@ -982,17 +967,7 @@ index aa6eb76f6..c64701307 100644 if (role == USB_ROLE_HOST) { already = dwc2_ovr_avalid(hsotg, true); } else if (role == USB_ROLE_DEVICE) { - already = dwc2_ovr_bvalid(hsotg, true); -- /* This clear DCTL.SFTDISCON bit */ -- dwc2_hsotg_core_connect(hsotg); -+ if (dwc2_is_device_enabled(hsotg)) { -+ /* This clear DCTL.SFTDISCON bit */ -+ dwc2_hsotg_core_connect(hsotg); -+ } - } else { - if (dwc2_is_device_mode(hsotg)) { - if (!dwc2_ovr_bvalid(hsotg, false)) -@@ -123,9 +146,18 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) +@@ -125,9 +146,18 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) spin_unlock_irqrestore(&hsotg->lock, flags); @@ -1012,7 +987,7 @@ index aa6eb76f6..c64701307 100644 if (!hsotg->ll_hw_enabled && hsotg->clk) clk_disable_unprepare(hsotg->clk); -@@ -141,11 +173,21 @@ int dwc2_drd_init(struct dwc2_hsotg *hsotg) +@@ -143,11 +173,21 @@ int dwc2_drd_init(struct dwc2_hsotg *hsotg) { struct usb_role_switch_desc role_sw_desc = {0}; struct usb_role_switch *role_sw; @@ -1034,7 +1009,7 @@ index aa6eb76f6..c64701307 100644 role_sw_desc.driver_data = hsotg; role_sw_desc.fwnode = dev_fwnode(hsotg->dev); role_sw_desc.set = dwc2_drd_role_sw_set; -@@ -183,6 +225,31 @@ void dwc2_drd_suspend(struct dwc2_hsotg *hsotg) +@@ -185,6 +225,31 @@ void dwc2_drd_suspend(struct dwc2_hsotg *hsotg) void dwc2_drd_resume(struct dwc2_hsotg *hsotg) { u32 gintsts, gintmsk; @@ -1067,20 +1042,10 @@ index aa6eb76f6..c64701307 100644 if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) { gintsts = dwc2_readl(hsotg, GINTSTS); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c -index 0909b088a..c96299472 100644 +index 519bb82b00e8..b171fac12585 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c -@@ -3594,7 +3594,8 @@ void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) - void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) - { - /* remove the soft-disconnect and let's go */ -- dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON); -+ if (!hsotg->role_sw || (dwc2_readl(hsotg, GOTGCTL) & GOTGCTL_BSESVLD)) -+ dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON); - } - - /** -@@ -4988,6 +4989,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg) +@@ -4988,6 +4988,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg) hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; hsotg->gadget.name = dev_name(dev); @@ -1088,7 +1053,7 @@ index 0909b088a..c96299472 100644 hsotg->remote_wakeup_allowed = 0; if (hsotg->params.lpm) -@@ -5670,7 +5672,6 @@ void dwc2_gadget_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup) +@@ -5670,7 +5671,6 @@ void dwc2_gadget_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup) } /* Change to L0 state */ @@ -1097,7 +1062,7 @@ index 0909b088a..c96299472 100644 hsotg->bus_suspended = false; } diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c -index 657dbd50f..7929af33f 100644 +index 82322696b903..c0dc708cc32a 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -138,19 +138,15 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) @@ -1255,7 +1220,7 @@ index 657dbd50f..7929af33f 100644 usleep_range(3000, 5000); spin_lock_irqsave(&hsotg->lock, flags); diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c -index 59e119345..d300ae3d9 100644 +index 59e119345994..d300ae3d9274 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -36,6 +36,7 @@ @@ -1425,7 +1390,7 @@ index 59e119345..d300ae3d9 100644 if (!valid) diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c -index c331a5128..cdfd78535 100644 +index 265d437ca0f1..d16a69355e89 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -222,20 +222,16 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) @@ -1599,7 +1564,7 @@ index c331a5128..cdfd78535 100644 if (dwc2_is_device_mode(dwc2)) ret = dwc2_hsotg_resume(dwc2); diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c -index c3dc90627..92401d01d 100644 +index c3dc906274d9..92401d01d28d 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -35,6 +35,7 @@ @@ -1661,7 +1626,7 @@ index c3dc90627..92401d01d 100644 int err = pdata->power_on(pdev); if (err < 0) diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c -index 4a8456f12..f2e0c78cc 100644 +index 4a8456f12a73..f2e0c78cc58d 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -214,7 +214,8 @@ static int ohci_platform_probe(struct platform_device *dev) @@ -1714,7 +1679,7 @@ index 4a8456f12..f2e0c78cc 100644 int err = pdata->power_on(pdev); if (err < 0) diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig -index 5e9b37b3f..8f9c4b9f3 100644 +index 5e9b37b3f25e..8f9c4b9f31f7 100644 --- a/drivers/usb/typec/ucsi/Kconfig +++ b/drivers/usb/typec/ucsi/Kconfig @@ -48,4 +48,14 @@ config UCSI_ACPI @@ -1733,7 +1698,7 @@ index 5e9b37b3f..8f9c4b9f3 100644 + endif diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile -index 8a8eb5cb8..480d533d7 100644 +index 8a8eb5cb8e0f..480d533d762f 100644 --- a/drivers/usb/typec/ucsi/Makefile +++ b/drivers/usb/typec/ucsi/Makefile @@ -17,3 +17,4 @@ endif @@ -1742,10 +1707,24 @@ index 8a8eb5cb8..480d533d7 100644 obj-$(CONFIG_UCSI_CCG) += ucsi_ccg.o +obj-$(CONFIG_UCSI_STM32G0) += ucsi_stm32g0.o diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c -index 5ef5bd0e8..3f5bd05a6 100644 +index 1f23eb543d8f..9659819ca2c9 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c -@@ -1142,12 +1142,8 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) +@@ -205,8 +205,11 @@ void ucsi_altmode_update_active(struct ucsi_connector *con) + ret = ucsi_send_command(con->ucsi, command, &cur, sizeof(cur)); + if (ret < 0) { + if (con->ucsi->version > 0x0100) { +- dev_err(con->ucsi->dev, +- "GET_CURRENT_CAM command failed\n"); ++ if (ret != -EOPNOTSUPP) ++ dev_err(con->ucsi->dev, ++ "GET_CURRENT_CAM command failed %d\n", ret); ++ else ++ dev_dbg(con->ucsi->dev, "GET_CURRENT_CAM not supported\n"); + return; + } + cur = 0xff; +@@ -1156,12 +1159,8 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) ucsi_port_psy_changed(con); } @@ -1760,7 +1739,7 @@ index 5ef5bd0e8..3f5bd05a6 100644 /* Only notify USB controller if partner supports USB data */ if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB)) -@@ -1331,7 +1327,9 @@ EXPORT_SYMBOL_GPL(ucsi_destroy); +@@ -1345,7 +1344,9 @@ EXPORT_SYMBOL_GPL(ucsi_destroy); */ int ucsi_register(struct ucsi *ucsi) { @@ -1771,7 +1750,7 @@ index 5ef5bd0e8..3f5bd05a6 100644 ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version, sizeof(ucsi->version)); -@@ -1341,6 +1339,33 @@ int ucsi_register(struct ucsi *ucsi) +@@ -1355,6 +1356,33 @@ int ucsi_register(struct ucsi *ucsi) if (!ucsi->version) return -ENODEV; @@ -1805,7 +1784,7 @@ index 5ef5bd0e8..3f5bd05a6 100644 queue_work(system_long_wq, &ucsi->work); return 0; -@@ -1374,6 +1399,9 @@ void ucsi_unregister(struct ucsi *ucsi) +@@ -1388,6 +1416,9 @@ void ucsi_unregister(struct ucsi *ucsi) } kfree(ucsi->connector); @@ -1816,7 +1795,7 @@ index 5ef5bd0e8..3f5bd05a6 100644 EXPORT_SYMBOL_GPL(ucsi_unregister); diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h -index cee666790..26572e953 100644 +index cee666790907..26572e953e9c 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -286,6 +286,8 @@ struct ucsi { @@ -1830,10 +1809,10 @@ index cee666790..26572e953 100644 diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c new file mode 100644 -index 000000000..9d7651d5c +index 000000000000..a107f2eb9129 --- /dev/null +++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c -@@ -0,0 +1,801 @@ +@@ -0,0 +1,770 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * UCSI driver for STMicroelectronics STM32G0 Type-C controller @@ -2281,8 +2260,7 @@ index 000000000..9d7651d5c +{ + struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); + struct i2c_client *client = g0->client; -+ struct power_supply *psy; -+ int i, ret; ++ int ret; + + /* Request alert interrupt */ + ret = request_threaded_irq(client->irq, NULL, ucsi_stm32g0_irq_handler, IRQF_ONESHOT, @@ -2299,27 +2277,6 @@ index 000000000..9d7651d5c + return ret; + } + -+ /* -+ * Below hack disables psy wakeup (enabled by default) to avoid limiting the low power -+ * mode that can be achieved on the platform. Another way is to let the userland -+ * enable or disable it with power/wakeup entries. -+ * So, unless stm32g0 wakeup has been explicitly enabled, also disable the power supply -+ * wakeup. Else, we're done here, so simply return. -+ */ -+ if (device_may_wakeup(g0->dev)) -+ return 0; -+ -+ /* -+ * ucsi_init() runs on system_long_wq, wait for it to complete. Then num_connectors is -+ * known and psy have been registered. -+ */ -+ flush_workqueue(system_long_wq); -+ -+ for (i = 0; i < ucsi->cap.num_connectors; i++) { -+ psy = ucsi->connector[i].psy; -+ device_wakeup_disable(&psy->dev); -+ } -+ + return 0; +} + @@ -2486,15 +2443,6 @@ index 000000000..9d7651d5c + + ucsi_set_drvdata(g0->ucsi, g0); + -+ /* -+ * When the "wakeup-source" flag is found, I2C core marks the device as wakeup capable -+ * and enables the wakeup by default. -+ * Only stick with wakeup capable here (disable wakeup), to avoid limiting the low power -+ * mode that can be achived by default (depending on the selected power domain). -+ */ -+ if (client->flags & I2C_CLIENT_WAKE) -+ device_wakeup_disable(dev); -+ + /* STM32G0 in bootloader mode communicates at reserved address 0x51 */ + g0->i2c_bl = i2c_new_dummy_device(client->adapter, STM32G0_I2C_BL_ADDR); + if (IS_ERR(g0->i2c_bl)) { @@ -2636,5 +2584,5 @@ index 000000000..9d7651d5c +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("platform:ucsi-stm32g0"); -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0017-v5.15-stm32mp-r2-PINCTRL-REGULATOR-SPI.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0017-v5.15-stm32mp-r2-PINCTRL-REGULATOR-SPI.patch new file mode 100644 index 0000000..5e5a160 --- /dev/null +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0017-v5.15-stm32mp-r2-PINCTRL-REGULATOR-SPI.patch @@ -0,0 +1,3016 @@ +From f7a7db118a4e7aa18f8038644ea143c5f1432c4d Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 16:03:16 +0100 +Subject: [PATCH 17/22] v5.15-stm32mp-r2 PINCTRL-REGULATOR-SPI + +Signed-off-by: Romuald JEANNE +--- + .../bindings/pinctrl/st,stm32-pinctrl.yaml | 8 + + .../regulator/protection-consumer.txt | 23 ++ + .../bindings/regulator/st,stm32-vrefbuf.yaml | 4 +- + .../bindings/spi/st,stm32-qspi.yaml | 8 + + .../devicetree/bindings/spi/st,stm32-spi.yaml | 23 ++ + drivers/pinctrl/stm32/pinctrl-stm32.c | 237 ++++++++--- + drivers/pinctrl/stm32/pinctrl-stm32.h | 16 +- + drivers/pinctrl/stm32/pinctrl-stm32mp135.c | 3 +- + drivers/pinctrl/stm32/pinctrl-stm32mp157.c | 2 +- + drivers/regulator/Kconfig | 11 + + drivers/regulator/Makefile | 1 + + drivers/regulator/protection-consumer.c | 137 +++++++ + drivers/regulator/scmi-regulator.c | 99 +++-- + drivers/regulator/stm32-pwr.c | 85 +++- + drivers/regulator/stm32-vrefbuf.c | 69 +++- + drivers/regulator/stpmic1_regulator.c | 182 +++++++- + drivers/spi/Kconfig | 1 + + drivers/spi/spi-mem.c | 2 +- + drivers/spi/spi-stm32-qspi.c | 151 +++++-- + drivers/spi/spi-stm32.c | 388 ++++++++++++------ + include/dt-bindings/pinctrl/stm32-pinfunc.h | 1 + + include/dt-bindings/spi/spi-stm32.h | 15 + + 22 files changed, 1188 insertions(+), 278 deletions(-) + create mode 100644 Documentation/devicetree/bindings/regulator/protection-consumer.txt + create mode 100644 drivers/regulator/protection-consumer.c + create mode 100644 include/dt-bindings/spi/spi-stm32.h + +diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +index dfee6d38a701..7348f40d49b5 100644 +--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml ++++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +@@ -140,9 +140,13 @@ patternProperties: + * ... + * 16 : Alternate Function 15 + * 17 : Analog ++ * 18 : Reserved + To simplify the usage, macro is available to generate "pinmux" field. + This macro is available here: + - include/dt-bindings/pinctrl/stm32-pinfunc.h ++ Setting the pinmux's function to the Reserved (RSVD) value is used to inform ++ the driver that it shall not apply the mux setting. This can be used to ++ reserve some pins, for example to a co-processor not running Linux. + Some examples of using macro: + /* GPIO A9 set as alernate function 2 */ + ... { +@@ -156,6 +160,10 @@ patternProperties: + ... { + pinmux = ; + }; ++ /* GPIO A9 reserved for co-processor */ ++ ... { ++ pinmux = ; ++ }; + + bias-disable: + type: boolean +diff --git a/Documentation/devicetree/bindings/regulator/protection-consumer.txt b/Documentation/devicetree/bindings/regulator/protection-consumer.txt +new file mode 100644 +index 000000000000..bf8169e008c3 +--- /dev/null ++++ b/Documentation/devicetree/bindings/regulator/protection-consumer.txt +@@ -0,0 +1,23 @@ ++regulator protection bindings ++ ++ ++Required properties: ++ compatible: "protection-consumer" ++ protection-supply: the phandle of the regulator to control ++ ++Optional properties: ++-------------------- ++ interrupt ++ ++ ++Example: ++ ++ regulator_protection { ++ compatible = "protection-consumer"; ++ protection-supply = <&vdd>; ++ status = "okay"; ++ ++ interrupts = <15 2>; ++ interrupt-parent = <&gpiof>; ++ }; ++ +diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml +index 3cd4a254e4cb..fe9c5e83c459 100644 +--- a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml ++++ b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml +@@ -19,7 +19,9 @@ allOf: + + properties: + compatible: +- const: st,stm32-vrefbuf ++ enum: ++ - st,stm32-vrefbuf ++ - st,stm32mp13-vrefbuf + + reg: + maxItems: 1 +diff --git a/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml +index 983c4e54c0be..a21246712f3f 100644 +--- a/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml ++++ b/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml +@@ -46,6 +46,14 @@ properties: + - const: tx + - const: rx + ++ st,dual-flash: ++ type: boolean ++ description: ++ Allows to use 8 data lines in case cs-gpios property is defined. ++ ++dependencies: ++ st,dual-flash: [ cs-gpios ] ++ + required: + - compatible + - reg +diff --git a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml +index 2d9af4c506bb..8962b2b4de9d 100644 +--- a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml ++++ b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml +@@ -27,8 +27,13 @@ allOf: + then: + properties: + st,spi-midi-ns: false ++ spi-slave: false ++ st,spi-slave-underrun: false + + properties: ++ "#address-cells": true ++ "#size-cells": true ++ + compatible: + enum: + - st,stm32f4-spi +@@ -59,6 +64,24 @@ properties: + - const: rx + - const: tx + ++ spi-slave: ++ description: ++ The SPI controller acts as a slave, instead of a master. ++ ++ cs-gpios: ++ description: ++ In case of spi-slave not defined, cs-gpios behave as defined in ++ spi-controller.yaml. ++ In case of spi-slave defined, if <0>, indicate that SS should be ++ detected via the dedicated HW pin ++ ++ st,spi-slave-underrun: ++ $ref: /schemas/types.yaml#/definitions/uint32-array ++ description: ++ First parameter enables and selects slave underrun reaction. ++ Refer to "dt-bindings/spi/spi-stm32.h" for the supported values. ++ Second parameter is the pattern in case of SPI_SEND_PATTERN mode. ++ + patternProperties: + "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$": + type: object +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c +index d3fa8cf0d72c..98acad49b960 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32.c ++++ b/drivers/pinctrl/stm32/pinctrl-stm32.c +@@ -43,6 +43,7 @@ + #define STM32_GPIO_LCKR 0x1c + #define STM32_GPIO_AFRL 0x20 + #define STM32_GPIO_AFRH 0x24 ++#define STM32_GPIO_SECCFGR 0x30 + + /* custom bitfield to backup pin status */ + #define STM32_GPIO_BKP_MODE_SHIFT 0 +@@ -73,6 +74,7 @@ static const char * const stm32_gpio_functions[] = { + "af8", "af9", "af10", + "af11", "af12", "af13", + "af14", "af15", "analog", ++ "reserved", + }; + + struct stm32_pinctrl_group { +@@ -94,6 +96,7 @@ struct stm32_gpio_bank { + u32 bank_ioport_nr; + u32 pin_backup[STM32_GPIO_PINS_PER_BANK]; + u8 irq_type[STM32_GPIO_PINS_PER_BANK]; ++ bool secure_control; + }; + + struct stm32_pinctrl { +@@ -197,11 +200,7 @@ static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank, + if (!value) + offset += STM32_GPIO_PINS_PER_BANK; + +- clk_enable(bank->clk); +- + writel_relaxed(BIT(offset), bank->base + STM32_GPIO_BSRR); +- +- clk_disable(bank->clk); + } + + static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset) +@@ -225,25 +224,11 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) + pinctrl_gpio_free(chip->base + offset); + } + +-static int stm32_gpio_get_noclk(struct gpio_chip *chip, unsigned int offset) +-{ +- struct stm32_gpio_bank *bank = gpiochip_get_data(chip); +- +- return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); +-} +- + static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) + { + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); +- int ret; +- +- clk_enable(bank->clk); + +- ret = stm32_gpio_get_noclk(chip, offset); +- +- clk_disable(bank->clk); +- +- return ret; ++ return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); + } + + static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +@@ -301,6 +286,33 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) + return ret; + } + ++static int stm32_gpio_init_valid_mask(struct gpio_chip *chip, ++ unsigned long *valid_mask, ++ unsigned int ngpios) ++{ ++ struct stm32_gpio_bank *bank = gpiochip_get_data(chip); ++ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); ++ unsigned int i; ++ u32 sec; ++ ++ /* All gpio are valid per default */ ++ bitmap_fill(valid_mask, ngpios); ++ ++ if (bank->secure_control) { ++ /* Tag secured pins as invalid */ ++ sec = readl_relaxed(bank->base + STM32_GPIO_SECCFGR); ++ ++ for (i = 0; i < ngpios; i++) { ++ if (sec & BIT(i)) { ++ clear_bit(i, valid_mask); ++ dev_dbg(pctl->dev, "No access to gpio %d - %d\n", bank->bank_nr, i); ++ } ++ } ++ } ++ ++ return 0; ++} ++ + static const struct gpio_chip stm32_gpio_template = { + .request = stm32_gpio_request, + .free = stm32_gpio_free, +@@ -311,6 +323,7 @@ static const struct gpio_chip stm32_gpio_template = { + .to_irq = stm32_gpio_to_irq, + .get_direction = stm32_gpio_get_direction, + .set_config = gpiochip_generic_config, ++ .init_valid_mask = stm32_gpio_init_valid_mask, + }; + + static void stm32_gpio_irq_trigger(struct irq_data *d) +@@ -323,7 +336,7 @@ static void stm32_gpio_irq_trigger(struct irq_data *d) + return; + + /* If level interrupt type then retrig */ +- level = stm32_gpio_get_noclk(&bank->gpio_chip, d->hwirq); ++ level = stm32_gpio_get(&bank->gpio_chip, d->hwirq); + if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) || + (level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH)) + irq_chip_retrigger_hierarchy(d); +@@ -365,7 +378,6 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data) + { + struct stm32_gpio_bank *bank = irq_data->domain->host_data; + struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); +- unsigned long flags; + int ret; + + ret = stm32_gpio_direction_input(&bank->gpio_chip, irq_data->hwirq); +@@ -379,10 +391,6 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data) + return ret; + } + +- flags = irqd_get_trigger_type(irq_data); +- if (flags & IRQ_TYPE_LEVEL_MASK) +- clk_enable(bank->clk); +- + return 0; + } + +@@ -390,9 +398,6 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data) + { + struct stm32_gpio_bank *bank = irq_data->domain->host_data; + +- if (bank->irq_type[irq_data->hwirq] & IRQ_TYPE_LEVEL_MASK) +- clk_disable(bank->clk); +- + gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq); + } + +@@ -533,7 +538,7 @@ stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin) + static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, + u32 pin_num, u32 fnum) + { +- int i; ++ int i, k; + + for (i = 0; i < pctl->npins; i++) { + const struct stm32_desc_pin *pin = pctl->pins + i; +@@ -542,7 +547,10 @@ static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, + if (pin->pin.number != pin_num) + continue; + +- while (func && func->name) { ++ if (fnum == STM32_PIN_RSVD) ++ return true; ++ ++ for (k = 0; k < STM32_CONFIG_NUM; k++) { + if (func->num == fnum) + return true; + func++; +@@ -769,7 +777,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, + unsigned long flags; + int err = 0; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + if (pctl->hwlock) { +@@ -798,7 +805,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, + + unlock: + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return err; + } +@@ -811,7 +817,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, + int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; + unsigned long flags; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + alt_offset); +@@ -823,7 +828,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, + *mode = val >> (pin * 2); + + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + } + + static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, +@@ -848,6 +852,11 @@ static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, + return -EINVAL; + } + ++ if (function == STM32_PIN_RSVD) { ++ dev_dbg(pctl->dev, "Reserved pins, skipping HW update.\n"); ++ return 0; ++ } ++ + bank = gpiochip_get_data(range->gc); + pin = stm32_gpio_pin(g->pin); + +@@ -867,12 +876,32 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, + return stm32_pmx_set_mode(bank, pin, !input, 0); + } + ++static int stm32_pmx_request(struct pinctrl_dev *pctldev, unsigned gpio) ++{ ++ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); ++ struct pinctrl_gpio_range *range; ++ ++ range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, gpio); ++ if (!range) { ++ dev_err(pctl->dev, "No gpio range defined.\n"); ++ return -EINVAL; ++ } ++ ++ if (!gpiochip_line_is_valid(range->gc, stm32_gpio_pin(gpio))) { ++ dev_warn(pctl->dev, "Can't access gpio %d\n", gpio); ++ return -EACCES; ++ } ++ ++ return 0; ++} ++ + static const struct pinmux_ops stm32_pmx_ops = { + .get_functions_count = stm32_pmx_get_funcs_cnt, + .get_function_name = stm32_pmx_get_func_name, + .get_function_groups = stm32_pmx_get_func_groups, + .set_mux = stm32_pmx_set_mux, + .gpio_set_direction = stm32_pmx_gpio_set_direction, ++ .request = stm32_pmx_request, + .strict = true, + }; + +@@ -886,7 +915,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, + u32 val; + int err = 0; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + if (pctl->hwlock) { +@@ -910,7 +938,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, + + unlock: + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return err; + } +@@ -921,14 +948,12 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank, + unsigned long flags; + u32 val; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_TYPER); + val &= BIT(offset); + + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return (val >> offset); + } +@@ -941,7 +966,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, + u32 val; + int err = 0; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + if (pctl->hwlock) { +@@ -965,7 +989,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, + + unlock: + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return err; + } +@@ -976,14 +999,12 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank, + unsigned long flags; + u32 val; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR); + val &= GENMASK(offset * 2 + 1, offset * 2); + + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return (val >> (offset * 2)); + } +@@ -996,7 +1017,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, + u32 val; + int err = 0; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + if (pctl->hwlock) { +@@ -1020,7 +1040,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, + + unlock: + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return err; + } +@@ -1031,14 +1050,12 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank, + unsigned long flags; + u32 val; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_PUPDR); + val &= GENMASK(offset * 2 + 1, offset * 2); + + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return (val >> (offset * 2)); + } +@@ -1049,7 +1066,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, + unsigned long flags; + u32 val; + +- clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + if (dir) +@@ -1060,7 +1076,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, + BIT(offset)); + + spin_unlock_irqrestore(&bank->lock, flags); +- clk_disable(bank->clk); + + return val; + } +@@ -1083,6 +1098,11 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, + bank = gpiochip_get_data(range->gc); + offset = stm32_gpio_pin(pin); + ++ if (!gpiochip_line_is_valid(range->gc, offset)) { ++ dev_warn(pctl->dev, "Can't access gpio %d\n", pin); ++ return -EACCES; ++ } ++ + switch (param) { + case PIN_CONFIG_DRIVE_PUSH_PULL: + ret = stm32_pconf_set_driving(bank, offset, 0); +@@ -1162,10 +1182,27 @@ static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + return 0; + } + ++static struct stm32_desc_pin * ++stm32_pconf_get_pin_desc_by_pin_number(struct stm32_pinctrl *pctl, ++ unsigned int pin_number) ++{ ++ struct stm32_desc_pin *pins = pctl->pins; ++ int i; ++ ++ for (i = 0; i < pctl->npins; i++) { ++ if (pins->pin.number == pin_number) ++ return pins; ++ pins++; ++ } ++ return NULL; ++} ++ + static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned int pin) + { ++ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); ++ const struct stm32_desc_pin *pin_desc; + struct pinctrl_gpio_range *range; + struct stm32_gpio_bank *bank; + int offset; +@@ -1185,6 +1222,11 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, + bank = gpiochip_get_data(range->gc); + offset = stm32_gpio_pin(pin); + ++ if (!gpiochip_line_is_valid(range->gc, offset)) { ++ seq_puts(s, "NO ACCESS"); ++ return; ++ } ++ + stm32_pmx_get_mode(bank, offset, &mode, &alt); + bias = stm32_pconf_get_bias(bank, offset); + +@@ -1215,7 +1257,12 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, + case 2: + drive = stm32_pconf_get_driving(bank, offset); + speed = stm32_pconf_get_speed(bank, offset); +- seq_printf(s, "%d - %s - %s - %s %s", alt, ++ pin_desc = stm32_pconf_get_pin_desc_by_pin_number(pctl, pin); ++ if (!pin_desc) ++ return; ++ ++ seq_printf(s, "%d (%s) - %s - %s - %s %s", alt, ++ pin_desc->functions[alt + 1].name, + drive ? "open drain" : "push pull", + biasing[bias], + speeds[speed], "speed"); +@@ -1234,6 +1281,28 @@ static const struct pinconf_ops stm32_pconf_ops = { + .pin_config_dbg_show = stm32_pconf_dbg_show, + }; + ++static struct stm32_desc_pin *stm32_pctrl_get_desc_pin_from_gpio(struct stm32_pinctrl *pctl, ++ struct stm32_gpio_bank *bank, ++ unsigned int offset) ++{ ++ unsigned int stm32_pin_nb = bank->bank_nr * STM32_GPIO_PINS_PER_BANK + offset; ++ struct stm32_desc_pin *pin_desc; ++ int i; ++ ++ /* With few exceptions (e.g. bank 'Z'), pin number matches with pin index in array */ ++ pin_desc = pctl->pins + stm32_pin_nb; ++ if (pin_desc->pin.number == stm32_pin_nb) ++ return pin_desc; ++ ++ /* Otherwise, loop all array to find the pin with the right number */ ++ for (i = 0; i < pctl->npins; i++) { ++ pin_desc = pctl->pins + i; ++ if (pin_desc->pin.number == stm32_pin_nb) ++ return pin_desc; ++ } ++ return NULL; ++} ++ + static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + struct device_node *np) + { +@@ -1245,6 +1314,8 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + struct resource res; + int npins = STM32_GPIO_PINS_PER_BANK; + int bank_nr, err, i = 0; ++ struct stm32_desc_pin *stm32_pin; ++ char **names; + + if (!IS_ERR(bank->rstc)) + reset_control_deassert(bank->rstc); +@@ -1256,9 +1327,9 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + if (IS_ERR(bank->base)) + return PTR_ERR(bank->base); + +- err = clk_prepare(bank->clk); ++ err = clk_prepare_enable(bank->clk); + if (err) { +- dev_err(dev, "failed to prepare clk (%d)\n", err); ++ dev_err(dev, "failed to prepare_enable clk (%d)\n", err); + return err; + } + +@@ -1297,6 +1368,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + bank->gpio_chip.parent = dev; + bank->bank_nr = bank_nr; + bank->bank_ioport_nr = bank_ioport_nr; ++ bank->secure_control = pctl->match_data->secure_control; + spin_lock_init(&bank->lock); + + if (pctl->domain) { +@@ -1307,18 +1379,35 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + bank->fwnode, &stm32_gpio_domain_ops, + bank); + +- if (!bank->domain) +- return -ENODEV; ++ if (!bank->domain) { ++ err = -ENODEV; ++ goto err_clk; ++ } ++ } ++ ++ names = devm_kcalloc(dev, npins, sizeof(char *), GFP_KERNEL); ++ for (i = 0; i < npins; i++) { ++ stm32_pin = stm32_pctrl_get_desc_pin_from_gpio(pctl, bank, i); ++ if (stm32_pin && stm32_pin->pin.name) ++ names[i] = devm_kasprintf(dev, GFP_KERNEL, "%s", stm32_pin->pin.name); ++ else ++ names[i] = NULL; + } + ++ bank->gpio_chip.names = (const char * const *)names; ++ + err = gpiochip_add_data(&bank->gpio_chip, bank); + if (err) { + dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr); +- return err; ++ goto err_clk; + } + + dev_info(dev, "%s bank added\n", bank->gpio_chip.label); + return 0; ++ ++err_clk: ++ clk_disable_unprepare(bank->clk); ++ return err; + } + + static struct irq_domain *stm32_pctrl_get_irq_domain(struct device_node *np) +@@ -1426,7 +1515,8 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, + if (pctl->pkg && !(pctl->pkg & p->pkg)) + continue; + pins->pin = p->pin; +- pins->functions = p->functions; ++ memcpy((struct stm32_desc_pin *)pins->functions, p->functions, ++ STM32_CONFIG_NUM * sizeof(struct stm32_desc_function)); + pins++; + nb_pins_available++; + } +@@ -1436,17 +1526,6 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, + return 0; + } + +-static void stm32_pctl_get_package(struct device_node *np, +- struct stm32_pinctrl *pctl) +-{ +- if (of_property_read_u32(np, "st,package", &pctl->pkg)) { +- pctl->pkg = 0; +- dev_warn(pctl->dev, "No package detected, use default one\n"); +- } else { +- dev_dbg(pctl->dev, "package detected: %x\n", pctl->pkg); +- } +-} +- + int stm32_pctl_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +@@ -1496,8 +1575,9 @@ int stm32_pctl_probe(struct platform_device *pdev) + pctl->dev = dev; + pctl->match_data = match->data; + +- /* get package information */ +- stm32_pctl_get_package(np, pctl); ++ /* get optional package information */ ++ if (!of_property_read_u32(np, "st,package", &pctl->pkg)) ++ dev_dbg(pctl->dev, "package detected: %x\n", pctl->pkg); + + pctl->pins = devm_kcalloc(pctl->dev, pctl->match_data->npins, + sizeof(*pctl->pins), GFP_KERNEL); +@@ -1589,6 +1669,10 @@ int stm32_pctl_probe(struct platform_device *pdev) + ret = stm32_gpiolib_register_bank(pctl, child); + if (ret) { + of_node_put(child); ++ ++ for (i = 0; i < pctl->nbanks; i++) ++ clk_disable_unprepare(pctl->banks[i].clk); ++ + return ret; + } + +@@ -1615,6 +1699,9 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( + if (!range) + return 0; + ++ if (!gpiochip_line_is_valid(range->gc, offset)) ++ return 0; ++ + pin_is_irq = gpiochip_line_is_irq(range->gc, offset); + + if (!desc || (!pin_is_irq && !desc->gpio_owner)) +@@ -1661,12 +1748,26 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( + return 0; + } + ++int __maybe_unused stm32_pinctrl_suspend(struct device *dev) ++{ ++ struct stm32_pinctrl *pctl = dev_get_drvdata(dev); ++ int i; ++ ++ for (i = 0; i < pctl->nbanks; i++) ++ clk_disable(pctl->banks[i].clk); ++ ++ return 0; ++} ++ + int __maybe_unused stm32_pinctrl_resume(struct device *dev) + { + struct stm32_pinctrl *pctl = dev_get_drvdata(dev); + struct stm32_pinctrl_group *g = pctl->groups; + int i; + ++ for (i = 0; i < pctl->nbanks; i++) ++ clk_enable(pctl->banks[i].clk); ++ + for (i = 0; i < pctl->ngroups; i++, g++) + stm32_pinctrl_restore_gpio_regs(pctl, g->pin); + +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h +index b0882d120765..28922c0047d8 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32.h ++++ b/drivers/pinctrl/stm32/pinctrl-stm32.h +@@ -17,6 +17,8 @@ + #define STM32_PIN_GPIO 0 + #define STM32_PIN_AF(x) ((x) + 1) + #define STM32_PIN_ANALOG (STM32_PIN_AF(15) + 1) ++#define STM32_PIN_RSVD (STM32_PIN_ANALOG + 1) ++#define STM32_CONFIG_NUM (STM32_PIN_RSVD + 1) + + /* package information */ + #define STM32MP_PKG_AA BIT(0) +@@ -31,26 +33,26 @@ struct stm32_desc_function { + + struct stm32_desc_pin { + struct pinctrl_pin_desc pin; +- const struct stm32_desc_function *functions; ++ const struct stm32_desc_function functions[STM32_CONFIG_NUM]; + const unsigned int pkg; + }; + + #define STM32_PIN(_pin, ...) \ + { \ + .pin = _pin, \ +- .functions = (struct stm32_desc_function[]){ \ +- __VA_ARGS__, { } }, \ ++ .functions = { \ ++ __VA_ARGS__}, \ + } + + #define STM32_PIN_PKG(_pin, _pkg, ...) \ + { \ + .pin = _pin, \ + .pkg = _pkg, \ +- .functions = (struct stm32_desc_function[]){ \ +- __VA_ARGS__, { } }, \ ++ .functions = { \ ++ __VA_ARGS__}, \ + } + #define STM32_FUNCTION(_num, _name) \ +- { \ ++ [_num] = { \ + .num = _num, \ + .name = _name, \ + } +@@ -58,6 +60,7 @@ struct stm32_desc_pin { + struct stm32_pinctrl_match_data { + const struct stm32_desc_pin *pins; + const unsigned int npins; ++ bool secure_control; + }; + + struct stm32_gpio_bank; +@@ -65,6 +68,7 @@ struct stm32_gpio_bank; + int stm32_pctl_probe(struct platform_device *pdev); + void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, + int pin, u32 *mode, u32 *alt); ++int stm32_pinctrl_suspend(struct device *dev); + int stm32_pinctrl_resume(struct device *dev); + + #endif /* __PINCTRL_STM32_H */ +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp135.c b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c +index 4ab03520c407..fde1df191c24 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32mp135.c ++++ b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c +@@ -1649,6 +1649,7 @@ static const struct stm32_desc_pin stm32mp135_pins[] = { + static struct stm32_pinctrl_match_data stm32mp135_match_data = { + .pins = stm32mp135_pins, + .npins = ARRAY_SIZE(stm32mp135_pins), ++ .secure_control = true, + }; + + static const struct of_device_id stm32mp135_pctrl_match[] = { +@@ -1660,7 +1661,7 @@ static const struct of_device_id stm32mp135_pctrl_match[] = { + }; + + static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = { +- SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume) ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(stm32_pinctrl_suspend, stm32_pinctrl_resume) + }; + + static struct platform_driver stm32mp135_pinctrl_driver = { +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c +index 2ccb99d64df8..91b2fc8ddbdb 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c ++++ b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c +@@ -2343,7 +2343,7 @@ static const struct of_device_id stm32mp157_pctrl_match[] = { + }; + + static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = { +- SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume) ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(stm32_pinctrl_suspend, stm32_pinctrl_resume) + }; + + static struct platform_driver stm32mp157_pinctrl_driver = { +diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig +index 4fd13b06231f..285931c185b3 100644 +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -37,6 +37,17 @@ config REGULATOR_FIXED_VOLTAGE + useful for systems which use a combination of software + managed regulators and simple non-configurable regulators. + ++config REGULATOR_PROTECTION_CONSUMER ++ tristate "Regulator protection consumer" ++ depends on OF ++ help ++ This driver handles regulator over-current detection in order to ++ protect regulators from crashing. In case of over-current event ++ or any IRQ, the protection consumer forces disable the regulator ++ that was declared as supply. ++ ++ If unsure, say no. ++ + config REGULATOR_VIRTUAL_CONSUMER + tristate "Virtual regulator consumer support" + help +diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile +index 9e382b50a5ef..543e04fa2419 100644 +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -7,6 +7,7 @@ + obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o irq_helpers.o + obj-$(CONFIG_OF) += of_regulator.o + obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o ++obj-$(CONFIG_REGULATOR_PROTECTION_CONSUMER) += protection-consumer.o + obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o + obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o + +diff --git a/drivers/regulator/protection-consumer.c b/drivers/regulator/protection-consumer.c +new file mode 100644 +index 000000000000..a4d299f8559b +--- /dev/null ++++ b/drivers/regulator/protection-consumer.c +@@ -0,0 +1,137 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (C) STMicroelectronics 2021 ++// Author: Pascal Paillet for STMicroelectronics. ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * struct protection_data - regulator driver data ++ * @reg: regulator consumer structure ++ * @nb: notifier_block structure ++ * @dev: device driver ++ */ ++struct protection_data { ++ struct regulator *reg; ++ struct notifier_block nb; ++ struct device *dev; ++}; ++ ++/** ++ * protection_irq_handler() - irq handler ++ * @irq: irq number ++ * @dev: struct protection_data ++ * ++ * force disable the regulator ++ */ ++static irqreturn_t protection_irq_handler(int irq, void *dev) ++{ ++ struct protection_data *protection = (struct protection_data *)dev; ++ ++ dev_warn(protection->dev, "Interrupt received on regulator\n"); ++ if (regulator_is_enabled(protection->reg)) ++ regulator_force_disable(protection->reg); ++ ++ return IRQ_HANDLED; ++} ++ ++/** ++ * regulator_event() - regulator framework callback ++ * @nb: notifier_block ++ * @event: regulator framework event ++ * @data: struct protection_data ++ * ++ * force disable the regulator in case of regulator event ++ * ++ * Return: 0 for successful probe else appropriate error ++ */ ++static int regulator_event(struct notifier_block *nb, unsigned long event, ++ void *data) ++{ ++ struct protection_data *protection = ++ container_of(nb, struct protection_data, nb); ++ ++ if ((event & REGULATOR_EVENT_OVER_CURRENT) || ++ (event & REGULATOR_EVENT_OVER_TEMP)) { ++ dev_warn(protection->dev, "Event received on regulator\n"); ++ if (regulator_is_enabled(protection->reg)) ++ regulator_force_disable(protection->reg); ++ } ++ ++ return 0; ++} ++ ++/** ++ * protection_probe() - probe ++ * @pdev: platform_device ++ * ++ * Return: 0 for successful probe else appropriate error ++ */ ++static int protection_probe(struct platform_device *pdev) ++{ ++ struct protection_data *protection; ++ int irq, ret; ++ ++ protection = devm_kzalloc(&pdev->dev, sizeof(struct protection_data), GFP_KERNEL); ++ if (!protection) ++ return -ENOMEM; ++ ++ protection->dev = &pdev->dev; ++ ++ protection->reg = devm_regulator_get(&pdev->dev, "protection"); ++ if (IS_ERR(protection->reg)) ++ return PTR_ERR(protection->reg); ++ ++ protection->nb.notifier_call = regulator_event; ++ ret = devm_regulator_register_notifier(protection->reg, &protection->nb); ++ if (ret != 0) { ++ dev_err(&pdev->dev, "Failed to register regulator notifier: %d\n", ret); ++ return ret; ++ } ++ ++ /* irq is optional, the driver can be used with regulator events */ ++ irq = platform_get_irq_optional(pdev, 0); ++ if (irq <= 0 && (irq != -ENXIO)) ++ return irq ? : -ENOENT; ++ ++ if (irq > 0) { ++ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, ++ protection_irq_handler, ++ IRQF_ONESHOT | IRQF_SHARED, ++ pdev->name, protection); ++ if (ret) { ++ dev_err(&pdev->dev, "Request IRQ failed\n"); ++ return ret; ++ } ++ } ++ platform_set_drvdata(pdev, protection); ++ dev_dbg(&pdev->dev, "protection probed\n"); ++ ++ return 0; ++} ++ ++static const struct of_device_id protection_dt_match[] = { ++ { .compatible = "protection-consumer" }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, protection_dt_match); ++ ++static struct platform_driver protection_driver = { ++ .driver = { ++ .name = "protection-consumer", ++ .owner = THIS_MODULE, ++ .of_match_table = protection_dt_match, ++ }, ++ .probe = protection_probe, ++}; ++ ++module_platform_driver(protection_driver); ++ ++MODULE_AUTHOR(""); ++MODULE_DESCRIPTION("protection consumer driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/regulator/scmi-regulator.c b/drivers/regulator/scmi-regulator.c +index 41ae7ac27ff6..fd884082c578 100644 +--- a/drivers/regulator/scmi-regulator.c ++++ b/drivers/regulator/scmi-regulator.c +@@ -219,10 +219,11 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) + */ + if (vinfo->negative_volts_allowed) { + dev_warn(dev, "Negative voltages NOT supported...skip %s\n", +- sreg->of_node->full_name); ++ vinfo->name); + return -EOPNOTSUPP; + } + ++ + sreg->desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", vinfo->name); + if (!sreg->desc.name) + return -ENOMEM; +@@ -230,8 +231,6 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) + sreg->desc.id = sreg->id; + sreg->desc.type = REGULATOR_VOLTAGE; + sreg->desc.owner = THIS_MODULE; +- sreg->desc.of_match_full_name = true; +- sreg->desc.of_match = sreg->of_node->full_name; + sreg->desc.regulators_node = "regulators"; + if (vinfo->segmented) + ret = scmi_config_linear_regulator_mappings(sreg, vinfo); +@@ -239,7 +238,6 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) + ret = scmi_config_discrete_regulator_mappings(sreg, vinfo); + if (ret) + return ret; +- + /* + * Using the scmi device here to have DT searched from Voltage + * protocol node down. +@@ -252,40 +250,59 @@ static int scmi_regulator_common_init(struct scmi_regulator *sreg) + return 0; + } + ++static int scmi_find_domain_from_name(struct scmi_device *sdev, ++ struct device_node *np, ++ struct scmi_regulator_info *rinfo, ++ u32 *dom) ++{ ++ const char *name = of_get_property(np, "voltd-name", NULL); ++ int d; ++ ++ if (!name) ++ return -EINVAL; ++ ++ for (d = 0; d < rinfo->num_doms; d++) { ++ struct scmi_regulator *sreg = rinfo->sregv[d]; ++ ++ if (!sreg || !sreg->desc.name || strcmp(sreg->desc.name, name)) ++ continue; ++ ++ *dom=d; ++ return 0; ++ } ++ ++ dev_warn(&sdev->dev, "scmi voltage domain %s not found\n", name); ++ return -ENODEV; ++} ++ + static int process_scmi_regulator_of_node(struct scmi_device *sdev, +- struct scmi_protocol_handle *ph, + struct device_node *np, + struct scmi_regulator_info *rinfo) + { + u32 dom, ret; + + ret = of_property_read_u32(np, "reg", &dom); +- if (ret) +- return ret; ++ if (ret == -EINVAL) { ++ ret = scmi_find_domain_from_name(sdev, np, rinfo, &dom); ++ if (ret < 0) { ++ return ret; ++ } ++ } + + if (dom >= rinfo->num_doms) + return -ENODEV; + +- if (rinfo->sregv[dom]) { +- dev_err(&sdev->dev, +- "SCMI Voltage Domain %d already in use. Skipping: %s\n", +- dom, np->full_name); +- return -EINVAL; +- } +- +- rinfo->sregv[dom] = devm_kzalloc(&sdev->dev, +- sizeof(struct scmi_regulator), +- GFP_KERNEL); + if (!rinfo->sregv[dom]) +- return -ENOMEM; ++ return -EINVAL; + + rinfo->sregv[dom]->id = dom; + rinfo->sregv[dom]->sdev = sdev; +- rinfo->sregv[dom]->ph = ph; + + /* get hold of good nodes */ + of_node_get(np); + rinfo->sregv[dom]->of_node = np; ++ rinfo->sregv[dom]->desc.of_match_full_name = true; ++ rinfo->sregv[dom]->desc.of_match = rinfo->sregv[dom]->of_node->name; + + dev_dbg(&sdev->dev, + "Found SCMI Regulator entry -- OF node [%d] -> %s\n", +@@ -338,21 +355,38 @@ static int scmi_regulator_probe(struct scmi_device *sdev) + rinfo->num_doms = num_doms; + + /* +- * Start collecting into rinfo->sregv possibly good SCMI Regulators as +- * described by a well-formed DT entry and associated with an existing +- * plausible SCMI Voltage Domain number, all belonging to this SCMI +- * platform instance node (handle->dev->of_node). ++ * Start collecting into rinfo->sregv for each regulator that we ++ * can successfully reach via SCMI. + */ +- np = of_find_node_by_name(handle->dev->of_node, "regulators"); +- for_each_child_of_node(np, child) { +- ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo); +- /* abort on any mem issue */ +- if (ret == -ENOMEM) { +- of_node_put(child); +- return ret; ++ for (d = 0; d < num_doms; d++) { ++ struct scmi_regulator *sreg; ++ ++ sreg = devm_kzalloc(&sdev->dev, sizeof(struct scmi_regulator), ++ GFP_KERNEL); ++ if (!sreg) ++ return -ENOMEM; ++ ++ sreg->sdev = sdev; ++ sreg->id = d; ++ sreg->ph = ph; ++ ++ ret = scmi_regulator_common_init(sreg); ++ if (ret) { ++ devm_kfree(&sdev->dev, sreg); ++ continue; + } ++ ++ rinfo->sregv[d] = sreg; + } + of_node_put(np); ++ /* ++ * Map each DT entry with an existing SCMI Voltage Domain number ++ * all belonging to this SCMI platform instance node (handle->dev->of_node). ++ */ ++ np = of_find_node_by_name(handle->dev->of_node, "regulators"); ++ for_each_child_of_node(np, child) ++ process_scmi_regulator_of_node(sdev, child, rinfo); ++ + /* + * Register a regulator for each valid regulator-DT-entry that we + * can successfully reach via SCMI and has a valid associated voltage +@@ -365,9 +399,8 @@ static int scmi_regulator_probe(struct scmi_device *sdev) + if (!sreg) + continue; + +- ret = scmi_regulator_common_init(sreg); +- /* Skip invalid voltage domains */ +- if (ret) ++ /* Skip if not described in the device-tree */ ++ if (!sreg->of_node) + continue; + + sreg->rdev = devm_regulator_register(&sdev->dev, &sreg->desc, +diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c +index 2a42acb7c24e..2b328b970b46 100644 +--- a/drivers/regulator/stm32-pwr.c ++++ b/drivers/regulator/stm32-pwr.c +@@ -3,12 +3,15 @@ + // Authors: Gabriel Fernandez + // Pascal Paillet . + ++#include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + #include + +@@ -24,6 +27,11 @@ + #define REG_1_1_EN BIT(30) + #define REG_1_1_RDY BIT(31) + ++#define STM32_SMC_PWR 0x82001001 ++#define STM32_WRITE 0x1 ++#define STM32_SMC_REG_SET 0x2 ++#define STM32_SMC_REG_CLEAR 0x3 ++ + /* list of supported regulators */ + enum { + PWR_REG11, +@@ -39,10 +47,18 @@ static u32 ready_mask_table[STM32PWR_REG_NUM_REGS] = { + }; + + struct stm32_pwr_reg { ++ int tzen; + void __iomem *base; + u32 ready_mask; + }; + ++#define SMC(class, op, address, val)\ ++ ({\ ++ struct arm_smccc_res res;\ ++ arm_smccc_smc(class, op, address, val,\ ++ 0, 0, 0, 0, &res);\ ++ }) ++ + static int stm32_pwr_reg_is_ready(struct regulator_dev *rdev) + { + struct stm32_pwr_reg *priv = rdev_get_drvdata(rdev); +@@ -69,9 +85,15 @@ static int stm32_pwr_reg_enable(struct regulator_dev *rdev) + int ret; + u32 val; + +- val = readl_relaxed(priv->base + REG_PWR_CR3); +- val |= rdev->desc->enable_mask; +- writel_relaxed(val, priv->base + REG_PWR_CR3); ++ if (priv->tzen) { ++ SMC(STM32_SMC_PWR, STM32_SMC_REG_SET, REG_PWR_CR3, ++ rdev->desc->enable_mask); ++ } else { ++ val = readl_relaxed(priv->base + REG_PWR_CR3); ++ val |= rdev->desc->enable_mask; ++ writel_relaxed(val, priv->base + REG_PWR_CR3); ++ } ++ + + /* use an arbitrary timeout of 20ms */ + ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, val, +@@ -88,9 +110,14 @@ static int stm32_pwr_reg_disable(struct regulator_dev *rdev) + int ret; + u32 val; + +- val = readl_relaxed(priv->base + REG_PWR_CR3); +- val &= ~rdev->desc->enable_mask; +- writel_relaxed(val, priv->base + REG_PWR_CR3); ++ if (priv->tzen) { ++ SMC(STM32_SMC_PWR, STM32_SMC_REG_CLEAR, REG_PWR_CR3, ++ rdev->desc->enable_mask); ++ } else { ++ val = readl_relaxed(priv->base + REG_PWR_CR3); ++ val &= ~rdev->desc->enable_mask; ++ writel_relaxed(val, priv->base + REG_PWR_CR3); ++ } + + /* use an arbitrary timeout of 20ms */ + ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, !val, +@@ -121,12 +148,50 @@ static const struct regulator_ops stm32_pwr_reg_ops = { + .supply_name = _supply, \ + } \ + +-static const struct regulator_desc stm32_pwr_desc[] = { ++static struct regulator_desc stm32_pwr_desc[] = { + PWR_REG(PWR_REG11, "reg11", 1100000, REG_1_1_EN, "vdd"), + PWR_REG(PWR_REG18, "reg18", 1800000, REG_1_8_EN, "vdd"), + PWR_REG(PWR_USB33, "usb33", 3300000, USB_3_3_EN, "vdd_3v3_usbfs"), + }; + ++static int is_stm32_soc_secured(struct platform_device *pdev, int *val) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct regmap *syscon; ++ u32 reg, mask; ++ int tzc_val = 0; ++ int err; ++ ++ syscon = syscon_regmap_lookup_by_phandle(np, "st,tzcr"); ++ if (IS_ERR(syscon)) { ++ if (PTR_ERR(syscon) != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "tzcr syscon required\n"); ++ return PTR_ERR(syscon); ++ } ++ ++ err = of_property_read_u32_index(np, "st,tzcr", 1, ®); ++ if (err) { ++ dev_err(&pdev->dev, "tzcr offset required !\n"); ++ return err; ++ } ++ ++ err = of_property_read_u32_index(np, "st,tzcr", 2, &mask); ++ if (err) { ++ dev_err(&pdev->dev, "tzcr mask required !\n"); ++ return err; ++ } ++ ++ err = regmap_read(syscon, reg, &tzc_val); ++ if (err) { ++ dev_err(&pdev->dev, "failed to read tzcr status !\n"); ++ return err; ++ } ++ ++ *val = tzc_val & mask; ++ ++ return 0; ++} ++ + static int stm32_pwr_regulator_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +@@ -135,6 +200,11 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) + struct regulator_dev *rdev; + struct regulator_config config = { }; + int i, ret = 0; ++ int tzen = 0; ++ ++ ret = is_stm32_soc_secured(pdev, &tzen); ++ if (ret) ++ return ret; + + base = of_iomap(np, 0); + if (!base) { +@@ -149,6 +219,7 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) + GFP_KERNEL); + if (!priv) + return -ENOMEM; ++ priv->tzen = tzen; + priv->base = base; + priv->ready_mask = ready_mask_table[i]; + config.driver_data = priv; +diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c +index 161622ea7259..d7eb7607b1b2 100644 +--- a/drivers/regulator/stm32-vrefbuf.c ++++ b/drivers/regulator/stm32-vrefbuf.c +@@ -31,6 +31,7 @@ struct stm32_vrefbuf { + void __iomem *base; + struct clk *clk; + struct device *dev; ++ u32 backup_val; + }; + + static const unsigned int stm32_vrefbuf_voltages[] = { +@@ -38,6 +39,11 @@ static const unsigned int stm32_vrefbuf_voltages[] = { + 2500000, 2048000, 1800000, 1500000, + }; + ++static const unsigned int stm32mp13_vrefbuf_voltages[] = { ++ /* Matches resp. VRS = 000b, 001b, 010b, 011b */ ++ 2500000, 2048000, 1800000, 1650000, ++}; ++ + static int stm32_vrefbuf_enable(struct regulator_dev *rdev) + { + struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); +@@ -180,11 +186,24 @@ static const struct regulator_desc stm32_vrefbuf_regu = { + .owner = THIS_MODULE, + }; + ++static const struct regulator_desc stm32mp13_vrefbuf_regu = { ++ .name = "vref", ++ .supply_name = "vdda", ++ .volt_table = stm32mp13_vrefbuf_voltages, ++ .n_voltages = ARRAY_SIZE(stm32mp13_vrefbuf_voltages), ++ .ops = &stm32_vrefbuf_volt_ops, ++ .off_on_delay = 1000, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ + static int stm32_vrefbuf_probe(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; + struct stm32_vrefbuf *priv; + struct regulator_config config = { }; + struct regulator_dev *rdev; ++ const struct regulator_desc *desc; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +@@ -213,14 +232,19 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) + goto err_pm_stop; + } + ++ desc = (const struct regulator_desc *) ++ of_match_device(dev->driver->of_match_table, dev)->data; ++ if (!desc) ++ return -EINVAL; ++ + config.dev = &pdev->dev; + config.driver_data = priv; + config.of_node = pdev->dev.of_node; + config.init_data = of_get_regulator_init_data(&pdev->dev, + pdev->dev.of_node, +- &stm32_vrefbuf_regu); ++ desc); + +- rdev = regulator_register(&stm32_vrefbuf_regu, &config); ++ rdev = regulator_register(desc, &config); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(&pdev->dev, "register failed with error %d\n", ret); +@@ -276,16 +300,51 @@ static int __maybe_unused stm32_vrefbuf_runtime_resume(struct device *dev) + return clk_prepare_enable(priv->clk); + } + ++#if defined(CONFIG_PM_SLEEP) ++static int stm32_vrefbuf_suspend(struct device *dev) ++{ ++ struct regulator_dev *rdev = dev_get_drvdata(dev); ++ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); ++ int ret; ++ ++ ret = pm_runtime_get_sync(priv->dev); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->dev); ++ return ret; ++ } ++ ++ priv->backup_val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); ++ ++ return pm_runtime_force_suspend(dev); ++} ++ ++static int stm32_vrefbuf_resume(struct device *dev) ++{ ++ struct regulator_dev *rdev = dev_get_drvdata(dev); ++ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); ++ int ret; ++ ++ ret = pm_runtime_force_resume(dev); ++ if (ret < 0) ++ return ret; ++ ++ writel_relaxed(priv->backup_val, priv->base + STM32_VREFBUF_CSR); ++ ++ return 0; ++} ++#endif ++ + static const struct dev_pm_ops stm32_vrefbuf_pm_ops = { +- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, +- pm_runtime_force_resume) ++ SET_SYSTEM_SLEEP_PM_OPS(stm32_vrefbuf_suspend, ++ stm32_vrefbuf_resume) + SET_RUNTIME_PM_OPS(stm32_vrefbuf_runtime_suspend, + stm32_vrefbuf_runtime_resume, + NULL) + }; + + static const struct of_device_id __maybe_unused stm32_vrefbuf_of_match[] = { +- { .compatible = "st,stm32-vrefbuf", }, ++ { .compatible = "st,stm32-vrefbuf", .data = (void *)&stm32_vrefbuf_regu }, ++ { .compatible = "st,stm32mp13-vrefbuf", .data = (void *)&stm32mp13_vrefbuf_regu }, + {}, + }; + MODULE_DEVICE_TABLE(of, stm32_vrefbuf_of_match); +diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c +index 2d7597c76e4a..c2cddba6dcda 100644 +--- a/drivers/regulator/stpmic1_regulator.c ++++ b/drivers/regulator/stpmic1_regulator.c +@@ -2,7 +2,9 @@ + // Copyright (C) STMicroelectronics 2018 + // Author: Pascal Paillet for STMicroelectronics. + ++#include + #include ++#include + #include + #include + #include +@@ -30,11 +32,27 @@ struct stpmic1_regulator_cfg { + u8 icc_mask; + }; + ++/** ++ * struct boost_data - this structure is used as driver data for the usb boost ++ * @boost_rdev: device for boost regulator ++ * @vbus_otg_rdev: device for vbus_otg regulator ++ * @sw_out_rdev: device for sw_out regulator ++ * @occ_timeout: overcurrent detection timeout ++ */ ++struct boost_data { ++ struct regulator_dev *boost_rdev; ++ struct regulator_dev *vbus_otg_rdev; ++ struct regulator_dev *sw_out_rdev; ++ ktime_t occ_timeout; ++}; ++ + static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode); + static unsigned int stpmic1_get_mode(struct regulator_dev *rdev); + static int stpmic1_set_icc(struct regulator_dev *rdev, int lim, int severity, + bool enable); + static unsigned int stpmic1_map_mode(unsigned int mode); ++static int regulator_enable_boost(struct regulator_dev *rdev); ++static int regulator_disable_boost(struct regulator_dev *rdev); + + enum { + STPMIC1_BUCK1 = 0, +@@ -182,8 +200,8 @@ static const struct regulator_ops stpmic1_vref_ddr_ops = { + + static const struct regulator_ops stpmic1_boost_regul_ops = { + .is_enabled = regulator_is_enabled_regmap, +- .enable = regulator_enable_regmap, +- .disable = regulator_disable_regmap, ++ .enable = regulator_enable_boost, ++ .disable = regulator_disable_boost, + .set_over_current_protection = stpmic1_set_icc, + }; + +@@ -529,6 +547,79 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) + return IRQ_HANDLED; + } + ++static int regulator_enable_boost(struct regulator_dev *rdev) ++{ ++ struct boost_data *usb_data = rdev_get_drvdata(rdev); ++ ++ usb_data->occ_timeout = ktime_add_us(ktime_get(), 100000); ++ ++ return regulator_enable_regmap(rdev); ++} ++ ++static int regulator_disable_boost(struct regulator_dev *rdev) ++{ ++ struct boost_data *usb_data = rdev_get_drvdata(rdev); ++ ++ usb_data->occ_timeout = 0; ++ ++ return regulator_disable_regmap(rdev); ++} ++ ++static void stpmic1_reset_boost(struct boost_data *usb_data) ++{ ++ int otg_on = 0; ++ int sw_out_on = 0; ++ ++ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "reset usb boost\n"); ++ ++ /* the boost was actually disabled by the over-current protection */ ++ regulator_disable_regmap(usb_data->boost_rdev); ++ ++ if (usb_data->vbus_otg_rdev) ++ otg_on = regulator_is_enabled_regmap(usb_data->vbus_otg_rdev); ++ if (otg_on) ++ regulator_disable_regmap(usb_data->vbus_otg_rdev); ++ ++ if (usb_data->sw_out_rdev) ++ sw_out_on = regulator_is_enabled_regmap(usb_data->sw_out_rdev); ++ if (sw_out_on) ++ regulator_disable_regmap(usb_data->sw_out_rdev); ++ ++ regulator_enable_regmap(usb_data->boost_rdev); ++ ++ /* sleep at least 5ms */ ++ usleep_range(5000, 10000); ++ ++ if (otg_on) ++ regulator_enable_regmap(usb_data->vbus_otg_rdev); ++ ++ if (sw_out_on) ++ regulator_enable_regmap(usb_data->sw_out_rdev); ++ ++} ++ ++static irqreturn_t stpmic1_boost_irq_handler(int irq, void *data) ++{ ++ struct boost_data *usb_data = (struct boost_data *)data; ++ ++ dev_dbg(rdev_get_dev(usb_data->boost_rdev), "usb boost irq handler\n"); ++ ++ /* overcurrent detected on boost after timeout */ ++ if (usb_data->occ_timeout != 0 && ++ ktime_compare(ktime_get(), usb_data->occ_timeout) > 0) { ++ /* reset usb boost and usb power switches */ ++ stpmic1_reset_boost(usb_data); ++ return IRQ_HANDLED; ++ } ++ ++ /* Send an overcurrent notification */ ++ regulator_notifier_call_chain(usb_data->boost_rdev, ++ REGULATOR_EVENT_OVER_CURRENT, ++ NULL); ++ ++ return IRQ_HANDLED; ++} ++ + #define MATCH(_name, _id) \ + [STPMIC1_##_id] = { \ + .name = #_name, \ +@@ -552,9 +643,10 @@ static struct of_regulator_match stpmic1_matches[] = { + MATCH(pwr_sw2, SW_OUT), + }; + +-static int stpmic1_regulator_register(struct platform_device *pdev, int id, +- struct of_regulator_match *match, +- const struct stpmic1_regulator_cfg *cfg) ++static struct regulator_dev * ++stpmic1_regulator_register(struct platform_device *pdev, int id, ++ struct of_regulator_match *match, ++ const struct stpmic1_regulator_cfg *cfg) + { + struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); + struct regulator_dev *rdev; +@@ -572,7 +664,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s regulator\n", + cfg->desc.name); +- return PTR_ERR(rdev); ++ return rdev; + } + + /* set mask reset */ +@@ -584,7 +676,7 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, + cfg->mask_reset_mask); + if (ret) { + dev_err(&pdev->dev, "set mask reset failed\n"); +- return ret; ++ return ERR_PTR(ret); + } + } + +@@ -598,15 +690,60 @@ static int stpmic1_regulator_register(struct platform_device *pdev, int id, + pdev->name, rdev); + if (ret) { + dev_err(&pdev->dev, "Request IRQ failed\n"); +- return ret; ++ return ERR_PTR(ret); + } + } +- return 0; ++ ++ return rdev; ++} ++ ++static struct regulator_dev * ++stpmic1_boost_register(struct platform_device *pdev, int id, ++ struct of_regulator_match *match, ++ const struct stpmic1_regulator_cfg *cfg, ++ struct boost_data *usb_data) ++{ ++ struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); ++ struct regulator_dev *rdev; ++ struct regulator_config config = {}; ++ int ret = 0; ++ int irq; ++ ++ config.dev = &pdev->dev; ++ config.init_data = match->init_data; ++ config.of_node = match->of_node; ++ config.regmap = pmic_dev->regmap; ++ config.driver_data = (void *)usb_data; ++ ++ rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config); ++ if (IS_ERR(rdev)) { ++ dev_err(&pdev->dev, "failed to register %s regulator\n", ++ cfg->desc.name); ++ return rdev; ++ } ++ ++ /* setup an irq handler for over-current detection */ ++ irq = of_irq_get(config.of_node, 0); ++ if (irq > 0) { ++ ret = devm_request_threaded_irq(&pdev->dev, ++ irq, NULL, ++ stpmic1_boost_irq_handler, ++ IRQF_ONESHOT, pdev->name, ++ usb_data); ++ if (ret) { ++ dev_err(&pdev->dev, "Request IRQ failed\n"); ++ return ERR_PTR(ret); ++ } ++ } ++ ++ return rdev; + } + + static int stpmic1_regulator_probe(struct platform_device *pdev) + { + int i, ret; ++ struct boost_data *usb_data; ++ struct regulator_dev *rdev; + + ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches, + ARRAY_SIZE(stpmic1_matches)); +@@ -616,11 +753,30 @@ static int stpmic1_regulator_probe(struct platform_device *pdev) + return ret; + } + ++ usb_data = devm_kzalloc(&pdev->dev, sizeof(*usb_data), GFP_KERNEL); ++ if (!usb_data) ++ return -ENOMEM; ++ + for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) { +- ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], +- &stpmic1_regulator_cfgs[i]); +- if (ret < 0) +- return ret; ++ if (i == STPMIC1_BOOST) { ++ rdev = ++ stpmic1_boost_register(pdev, i, &stpmic1_matches[i], ++ &stpmic1_regulator_cfgs[i], ++ usb_data); ++ ++ usb_data->boost_rdev = rdev; ++ } else { ++ rdev = ++ stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], ++ &stpmic1_regulator_cfgs[i]); ++ ++ if (i == STPMIC1_VBUS_OTG) ++ usb_data->vbus_otg_rdev = rdev; ++ else if (i == STPMIC1_SW_OUT) ++ usb_data->sw_out_rdev = rdev; ++ } ++ if (IS_ERR(rdev)) ++ return PTR_ERR(rdev); + } + + dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n"); +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 83e352b0c8f9..a9342e57843f 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -807,6 +807,7 @@ config SPI_SPRD_ADI + config SPI_STM32 + tristate "STMicroelectronics STM32 SPI controller" + depends on ARCH_STM32 || COMPILE_TEST ++ select SPI_SLAVE + help + SPI driver for STMicroelectronics STM32 SoCs. + +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index 37f4443ce9a0..96f718634ac7 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -795,7 +795,7 @@ int spi_mem_poll_status(struct spi_mem *mem, + op->data.dir != SPI_MEM_DATA_IN) + return -EINVAL; + +- if (ctlr->mem_ops && ctlr->mem_ops->poll_status) { ++ if (ctlr->mem_ops && ctlr->mem_ops->poll_status && !mem->spi->cs_gpiod) { + ret = spi_mem_access_start(mem); + if (ret) + return ret; +diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c +index dd38cb8ffbc2..00e84f3cb239 100644 +--- a/drivers/spi/spi-stm32-qspi.c ++++ b/drivers/spi/spi-stm32-qspi.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -299,15 +300,11 @@ static int stm32_qspi_wait_nobusy(struct stm32_qspi *qspi) + STM32_BUSY_TIMEOUT_US); + } + +-static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi, +- const struct spi_mem_op *op) ++static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi) + { + u32 cr, sr; + int err = 0; + +- if (!op->data.nbytes) +- goto wait_nobusy; +- + if ((readl_relaxed(qspi->io_base + QSPI_SR) & SR_TCF) || + qspi->fmode == CCR_FMODE_APM) + goto out; +@@ -328,15 +325,13 @@ static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi, + out: + /* clear flags */ + writel_relaxed(FCR_CTCF | FCR_CTEF, qspi->io_base + QSPI_FCR); +-wait_nobusy: + if (!err) + err = stm32_qspi_wait_nobusy(qspi); + + return err; + } + +-static int stm32_qspi_wait_poll_status(struct stm32_qspi *qspi, +- const struct spi_mem_op *op) ++static int stm32_qspi_wait_poll_status(struct stm32_qspi *qspi) + { + u32 cr; + +@@ -353,7 +348,7 @@ static int stm32_qspi_wait_poll_status(struct stm32_qspi *qspi, + return 0; + } + +-static int stm32_qspi_get_mode(struct stm32_qspi *qspi, u8 buswidth) ++static int stm32_qspi_get_mode(u8 buswidth) + { + if (buswidth == 4) + return CCR_BUSWIDTH_4; +@@ -361,10 +356,10 @@ static int stm32_qspi_get_mode(struct stm32_qspi *qspi, u8 buswidth) + return buswidth; + } + +-static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) ++static int stm32_qspi_send(struct spi_device *spi, const struct spi_mem_op *op) + { +- struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); +- struct stm32_qspi_flash *flash = &qspi->flash[mem->spi->chip_select]; ++ struct stm32_qspi *qspi = spi_controller_get_devdata(spi->master); ++ struct stm32_qspi_flash *flash = &qspi->flash[spi->chip_select]; + u32 ccr, cr; + int timeout, err = 0, err_poll_status = 0; + +@@ -373,10 +368,6 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) + op->dummy.buswidth, op->data.buswidth, + op->addr.val, op->data.nbytes); + +- err = stm32_qspi_wait_nobusy(qspi); +- if (err) +- goto abort; +- + cr = readl_relaxed(qspi->io_base + QSPI_CR); + cr &= ~CR_PRESC_MASK & ~CR_FSEL; + cr |= FIELD_PREP(CR_PRESC_MASK, flash->presc); +@@ -390,11 +381,11 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) + ccr = qspi->fmode; + ccr |= FIELD_PREP(CCR_INST_MASK, op->cmd.opcode); + ccr |= FIELD_PREP(CCR_IMODE_MASK, +- stm32_qspi_get_mode(qspi, op->cmd.buswidth)); ++ stm32_qspi_get_mode(op->cmd.buswidth)); + + if (op->addr.nbytes) { + ccr |= FIELD_PREP(CCR_ADMODE_MASK, +- stm32_qspi_get_mode(qspi, op->addr.buswidth)); ++ stm32_qspi_get_mode(op->addr.buswidth)); + ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1); + } + +@@ -404,7 +395,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) + + if (op->data.nbytes) { + ccr |= FIELD_PREP(CCR_DMODE_MASK, +- stm32_qspi_get_mode(qspi, op->data.buswidth)); ++ stm32_qspi_get_mode(op->data.buswidth)); + } + + writel_relaxed(ccr, qspi->io_base + QSPI_CCR); +@@ -413,7 +404,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) + writel_relaxed(op->addr.val, qspi->io_base + QSPI_AR); + + if (qspi->fmode == CCR_FMODE_APM) +- err_poll_status = stm32_qspi_wait_poll_status(qspi, op); ++ err_poll_status = stm32_qspi_wait_poll_status(qspi); + + err = stm32_qspi_tx(qspi, op); + +@@ -428,7 +419,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) + goto abort; + + /* wait end of tx in indirect mode */ +- err = stm32_qspi_wait_cmd(qspi, op); ++ err = stm32_qspi_wait_cmd(qspi); + if (err) + goto abort; + +@@ -477,7 +468,7 @@ static int stm32_qspi_poll_status(struct spi_mem *mem, const struct spi_mem_op * + qspi->fmode = CCR_FMODE_APM; + qspi->status_timeout = timeout_ms; + +- ret = stm32_qspi_send(mem, op); ++ ret = stm32_qspi_send(mem->spi, op); + mutex_unlock(&qspi->lock); + + pm_runtime_mark_last_busy(qspi->dev); +@@ -503,7 +494,7 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + else + qspi->fmode = CCR_FMODE_INDW; + +- ret = stm32_qspi_send(mem, op); ++ ret = stm32_qspi_send(mem->spi, op); + mutex_unlock(&qspi->lock); + + pm_runtime_mark_last_busy(qspi->dev); +@@ -561,7 +552,7 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, + else + qspi->fmode = CCR_FMODE_INDR; + +- ret = stm32_qspi_send(desc->mem, &op); ++ ret = stm32_qspi_send(desc->mem->spi, &op); + mutex_unlock(&qspi->lock); + + pm_runtime_mark_last_busy(qspi->dev); +@@ -570,12 +561,96 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, + return ret ?: len; + } + ++static int stm32_qspi_transfer_one_message(struct spi_controller *ctrl, ++ struct spi_message *msg) ++{ ++ struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl); ++ struct spi_transfer *transfer; ++ struct spi_device *spi = msg->spi; ++ struct spi_mem_op op; ++ int ret = 0; ++ ++ if (!spi->cs_gpiod) ++ return -EOPNOTSUPP; ++ ++ ret = pm_runtime_resume_and_get(qspi->dev); ++ if (ret < 0) ++ return ret; ++ ++ mutex_lock(&qspi->lock); ++ ++ gpiod_set_value_cansleep(spi->cs_gpiod, true); ++ ++ list_for_each_entry(transfer, &msg->transfers, transfer_list) { ++ u8 dummy_bytes = 0; ++ ++ memset(&op, 0, sizeof(op)); ++ ++ dev_dbg(qspi->dev, "tx_buf:%p tx_nbits:%d rx_buf:%p rx_nbits:%d len:%d dummy_data:%d\n", ++ transfer->tx_buf, transfer->tx_nbits, ++ transfer->rx_buf, transfer->rx_nbits, ++ transfer->len, transfer->dummy_data); ++ ++ /* ++ * QSPI hardware supports dummy bytes transfer. ++ * If current transfer is dummy byte, merge it with the next ++ * transfer in order to take into account QSPI block constraint ++ */ ++ if (transfer->dummy_data) { ++ op.dummy.buswidth = transfer->tx_nbits; ++ op.dummy.nbytes = transfer->len; ++ dummy_bytes = transfer->len; ++ ++ /* if happens, means that message is not correctly built */ ++ if (list_is_last(&transfer->transfer_list, &msg->transfers)) { ++ ret = -EINVAL; ++ goto end_of_transfer; ++ } ++ ++ transfer = list_next_entry(transfer, transfer_list); ++ } ++ ++ op.data.nbytes = transfer->len; ++ ++ if (transfer->rx_buf) { ++ qspi->fmode = CCR_FMODE_INDR; ++ op.data.buswidth = transfer->rx_nbits; ++ op.data.dir = SPI_MEM_DATA_IN; ++ op.data.buf.in = transfer->rx_buf; ++ } else { ++ qspi->fmode = CCR_FMODE_INDW; ++ op.data.buswidth = transfer->tx_nbits; ++ op.data.dir = SPI_MEM_DATA_OUT; ++ op.data.buf.out = transfer->tx_buf; ++ } ++ ++ ret = stm32_qspi_send(spi, &op); ++ if (ret) ++ goto end_of_transfer; ++ ++ msg->actual_length += transfer->len + dummy_bytes; ++ } ++ ++end_of_transfer: ++ gpiod_set_value_cansleep(spi->cs_gpiod, false); ++ ++ mutex_unlock(&qspi->lock); ++ ++ msg->status = ret; ++ spi_finalize_current_message(ctrl); ++ ++ pm_runtime_mark_last_busy(qspi->dev); ++ pm_runtime_put_autosuspend(qspi->dev); ++ ++ return ret; ++} ++ + static int stm32_qspi_setup(struct spi_device *spi) + { + struct spi_controller *ctrl = spi->master; + struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl); + struct stm32_qspi_flash *flash; +- u32 presc; ++ u32 presc, mode; + int ret; + + if (ctrl->busy) +@@ -584,6 +659,16 @@ static int stm32_qspi_setup(struct spi_device *spi) + if (!spi->max_speed_hz) + return -EINVAL; + ++ mode = spi->mode & (SPI_TX_OCTAL | SPI_RX_OCTAL); ++ if ((mode == SPI_TX_OCTAL || mode == SPI_RX_OCTAL) || ++ ((mode == (SPI_TX_OCTAL | SPI_RX_OCTAL)) && ++ gpiod_count(qspi->dev, "cs") == -ENOENT)) { ++ dev_err(qspi->dev, "spi-rx-bus-width\\/spi-tx-bus-width\\/cs-gpios\n"); ++ dev_err(qspi->dev, "configuration not supported\n"); ++ ++ return -EINVAL; ++ } ++ + ret = pm_runtime_get_sync(qspi->dev); + if (ret < 0) { + pm_runtime_put_noidle(qspi->dev); +@@ -598,6 +683,16 @@ static int stm32_qspi_setup(struct spi_device *spi) + + mutex_lock(&qspi->lock); + qspi->cr_reg = CR_APMS | 3 << CR_FTHRES_SHIFT | CR_SSHIFT | CR_EN; ++ ++ /* ++ * Dual flash mode is only enable in case SPI_TX_OCTAL and SPI_TX_OCTAL ++ * are both set in spi->mode and "cs-gpios" properties is found in DT ++ */ ++ if (mode == (SPI_TX_OCTAL | SPI_RX_OCTAL)) { ++ qspi->cr_reg |= CR_DFM; ++ dev_dbg(qspi->dev, "Dual flash mode enable"); ++ } ++ + writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); + + /* set dcr fsize to max address */ +@@ -759,11 +854,13 @@ static int stm32_qspi_probe(struct platform_device *pdev) + + mutex_init(&qspi->lock); + +- ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD +- | SPI_TX_DUAL | SPI_TX_QUAD; ++ ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_OCTAL ++ | SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_OCTAL; + ctrl->setup = stm32_qspi_setup; + ctrl->bus_num = -1; + ctrl->mem_ops = &stm32_qspi_mem_ops; ++ ctrl->use_gpio_descriptors = true; ++ ctrl->transfer_one_message = stm32_qspi_transfer_one_message; + ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP; + ctrl->dev.of_node = dev->of_node; + +diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c +index 9bd3fd1652f7..573f51e630d3 100644 +--- a/drivers/spi/spi-stm32.c ++++ b/drivers/spi/spi-stm32.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + // +-// STMicroelectronics STM32 SPI Controller driver (master mode only) ++// STMicroelectronics STM32 SPI Controller driver + // + // Copyright (C) 2017, STMicroelectronics - All Rights Reserved + // Author(s): Amelie Delaunay for STMicroelectronics. +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #define DRIVER_NAME "spi_stm32" + +@@ -84,6 +85,7 @@ + #define STM32H7_SPI_IFCR 0x18 + #define STM32H7_SPI_TXDR 0x20 + #define STM32H7_SPI_RXDR 0x30 ++#define STM32H7_SPI_UDRDR 0x4C + #define STM32H7_SPI_I2SCFGR 0x50 + + /* STM32H7_SPI_CR1 bit fields */ +@@ -101,6 +103,14 @@ + /* STM32H7_SPI_CFG1 bit fields */ + #define STM32H7_SPI_CFG1_DSIZE GENMASK(4, 0) + #define STM32H7_SPI_CFG1_FTHLV GENMASK(8, 5) ++#define STM32H7_SPI_CFG1_UDRDET GENMASK(12, 11) ++#define STM32H7_SPI_CFG1_UDRDET_BEGIN 0 ++#define STM32H7_SPI_CFG1_UDRDET_LAST 1 ++#define STM32H7_SPI_CFG1_UDRDET_SS 2 ++#define STM32H7_SPI_CFG1_UDRCFG GENMASK(10, 9) ++#define STM32H7_SPI_CFG1_UDRCFG_PTRN 0 ++#define STM32H7_SPI_CFG1_UDRCFG_LAST_R 1 ++#define STM32H7_SPI_CFG1_UDRCFG_LAST_T 2 + #define STM32H7_SPI_CFG1_RXDMAEN BIT(14) + #define STM32H7_SPI_CFG1_TXDMAEN BIT(15) + #define STM32H7_SPI_CFG1_MBR GENMASK(30, 28) +@@ -117,6 +127,7 @@ + #define STM32H7_SPI_CFG2_CPHA BIT(24) + #define STM32H7_SPI_CFG2_CPOL BIT(25) + #define STM32H7_SPI_CFG2_SSM BIT(26) ++#define STM32H7_SPI_CFG2_SSIOP BIT(28) + #define STM32H7_SPI_CFG2_AFCNTR BIT(31) + + /* STM32H7_SPI_IER bit fields */ +@@ -125,6 +136,7 @@ + #define STM32H7_SPI_IER_DXPIE BIT(2) + #define STM32H7_SPI_IER_EOTIE BIT(3) + #define STM32H7_SPI_IER_TXTFIE BIT(4) ++#define STM32H7_SPI_IER_UDRIE BIT(5) + #define STM32H7_SPI_IER_OVRIE BIT(6) + #define STM32H7_SPI_IER_MODFIE BIT(9) + #define STM32H7_SPI_IER_ALL GENMASK(10, 0) +@@ -133,6 +145,7 @@ + #define STM32H7_SPI_SR_RXP BIT(0) + #define STM32H7_SPI_SR_TXP BIT(1) + #define STM32H7_SPI_SR_EOT BIT(3) ++#define STM32H7_SPI_SR_UDR BIT(5) + #define STM32H7_SPI_SR_OVR BIT(6) + #define STM32H7_SPI_SR_MODF BIT(9) + #define STM32H7_SPI_SR_SUSP BIT(11) +@@ -170,6 +183,10 @@ + */ + #define SPI_DMA_MIN_BYTES 16 + ++/* STM32 SPI driver helpers */ ++#define STM32_SPI_MASTER_MODE(stm32_spi) (!(stm32_spi)->slave_mode) ++#define STM32_SPI_SLAVE_MODE(stm32_spi) ((stm32_spi)->slave_mode) ++ + /** + * struct stm32_spi_reg - stm32 SPI register & bitfield desc + * @reg: register offset +@@ -190,6 +207,7 @@ struct stm32_spi_reg { + * @cpol: clock polarity register and polarity bit + * @cpha: clock phase register and phase bit + * @lsb_first: LSB transmitted first register and bit ++ * @cs_high: chips select active value + * @br: baud rate register and bitfields + * @rx: SPI RX data register + * @tx: SPI TX data register +@@ -201,6 +219,7 @@ struct stm32_spi_regspec { + const struct stm32_spi_reg cpol; + const struct stm32_spi_reg cpha; + const struct stm32_spi_reg lsb_first; ++ const struct stm32_spi_reg cs_high; + const struct stm32_spi_reg br; + const struct stm32_spi_reg rx; + const struct stm32_spi_reg tx; +@@ -221,7 +240,6 @@ struct stm32_spi; + * time between frames (if driver has this functionality) + * @set_number_of_data: optional routine to configure registers to desired + * number of data (if driver has this functionality) +- * @can_dma: routine to determine if the transfer is eligible for DMA use + * @transfer_one_dma_start: routine to start transfer a single spi_transfer + * using DMA + * @dma_rx_cb: routine to call after DMA RX channel operation is complete +@@ -232,7 +250,9 @@ struct stm32_spi; + * @baud_rate_div_min: minimum baud rate divisor + * @baud_rate_div_max: maximum baud rate divisor + * @has_fifo: boolean to know if fifo is used for driver +- * @has_startbit: boolean to know if start bit is used to start transfer ++ * @set_slave_udr: routine to configure registers to desired slave underrun ++ * behavior (if driver has this functionality) ++ * @flags: compatible specific SPI controller flags used at registration time + */ + struct stm32_spi_cfg { + const struct stm32_spi_regspec *regs; +@@ -253,12 +273,14 @@ struct stm32_spi_cfg { + unsigned int baud_rate_div_min; + unsigned int baud_rate_div_max; + bool has_fifo; ++ void (*set_slave_udr)(struct stm32_spi *spi); ++ u16 flags; + }; + + /** + * struct stm32_spi - private data of the SPI controller + * @dev: driver model representation of the controller +- * @master: controller master interface ++ * @ctrl: controller interface + * @cfg: compatible configuration data + * @base: virtual memory area + * @clk: hw kernel clock feeding the SPI clock generator +@@ -280,10 +302,13 @@ struct stm32_spi_cfg { + * @dma_tx: dma channel for TX transfer + * @dma_rx: dma channel for RX transfer + * @phys_addr: SPI registers physical base address ++ * @slave_mode: the controller is configured as SPI slave ++ * @slave_udr_mode: slave underrun behavior ++ * @slave_udr_pattern: slave underrun pattern parameter + */ + struct stm32_spi { + struct device *dev; +- struct spi_master *master; ++ struct spi_controller *ctrl; + const struct stm32_spi_cfg *cfg; + void __iomem *base; + struct clk *clk; +@@ -307,6 +332,10 @@ struct stm32_spi { + struct dma_chan *dma_tx; + struct dma_chan *dma_rx; + dma_addr_t phys_addr; ++ ++ bool slave_mode; ++ u32 slave_udr_mode; ++ u32 slave_udr_pattern; + }; + + static const struct stm32_spi_regspec stm32f4_spi_regspec = { +@@ -318,6 +347,7 @@ static const struct stm32_spi_regspec stm32f4_spi_regspec = { + .cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL }, + .cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA }, + .lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST }, ++ .cs_high = {}, + .br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT }, + + .rx = { STM32F4_SPI_DR }, +@@ -336,6 +366,7 @@ static const struct stm32_spi_regspec stm32h7_spi_regspec = { + .cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL }, + .cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA }, + .lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST }, ++ .cs_high = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_SSIOP }, + .br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR, + STM32H7_SPI_CFG1_MBR_SHIFT }, + +@@ -437,9 +468,9 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, + div = DIV_ROUND_UP(spi->clk_rate & ~0x1, speed_hz); + + /* +- * SPI framework set xfer->speed_hz to master->max_speed_hz if +- * xfer->speed_hz is greater than master->max_speed_hz, and it returns +- * an error when xfer->speed_hz is lower than master->min_speed_hz, so ++ * SPI framework set xfer->speed_hz to ctrl->max_speed_hz if ++ * xfer->speed_hz is greater than ctrl->max_speed_hz, and it returns ++ * an error when xfer->speed_hz is lower than ctrl->min_speed_hz, so + * no need to check it there. + * However, we need to ensure the following calculations. + */ +@@ -657,9 +688,9 @@ static void stm32f4_spi_disable(struct stm32_spi *spi) + } + + if (spi->cur_usedma && spi->dma_tx) +- dmaengine_terminate_all(spi->dma_tx); ++ dmaengine_terminate_async(spi->dma_tx); + if (spi->cur_usedma && spi->dma_rx) +- dmaengine_terminate_all(spi->dma_rx); ++ dmaengine_terminate_async(spi->dma_rx); + + stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE); + +@@ -696,9 +727,9 @@ static void stm32h7_spi_disable(struct stm32_spi *spi) + } + + if (spi->cur_usedma && spi->dma_tx) +- dmaengine_terminate_all(spi->dma_tx); ++ dmaengine_terminate_async(spi->dma_tx); + if (spi->cur_usedma && spi->dma_rx) +- dmaengine_terminate_all(spi->dma_rx); ++ dmaengine_terminate_async(spi->dma_rx); + + stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); + +@@ -714,19 +745,19 @@ static void stm32h7_spi_disable(struct stm32_spi *spi) + + /** + * stm32_spi_can_dma - Determine if the transfer is eligible for DMA use +- * @master: controller master interface ++ * @ctrl: controller interface + * @spi_dev: pointer to the spi device + * @transfer: pointer to spi transfer + * + * If driver has fifo and the current transfer size is greater than fifo size, + * use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes. + */ +-static bool stm32_spi_can_dma(struct spi_master *master, ++static bool stm32_spi_can_dma(struct spi_controller *ctrl, + struct spi_device *spi_dev, + struct spi_transfer *transfer) + { + unsigned int dma_size; +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + + if (spi->cfg->has_fifo) + dma_size = spi->fifo_size; +@@ -742,12 +773,12 @@ static bool stm32_spi_can_dma(struct spi_master *master, + /** + * stm32f4_spi_irq_event - Interrupt handler for SPI controller events + * @irq: interrupt line +- * @dev_id: SPI controller master interface ++ * @dev_id: SPI controller ctrl interface + */ + static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id) + { +- struct spi_master *master = dev_id; +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct spi_controller *ctrl = dev_id; ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + u32 sr, mask = 0; + bool end = false; + +@@ -830,14 +861,14 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id) + /** + * stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller + * @irq: interrupt line +- * @dev_id: SPI controller master interface ++ * @dev_id: SPI controller interface + */ + static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id) + { +- struct spi_master *master = dev_id; +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct spi_controller *ctrl = dev_id; ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + +- spi_finalize_current_transfer(master); ++ spi_finalize_current_transfer(ctrl); + stm32f4_spi_disable(spi); + + return IRQ_HANDLED; +@@ -846,12 +877,12 @@ static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id) + /** + * stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller + * @irq: interrupt line +- * @dev_id: SPI controller master interface ++ * @dev_id: SPI controller interface + */ + static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) + { +- struct spi_master *master = dev_id; +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct spi_controller *ctrl = dev_id; ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + u32 sr, ier, mask; + unsigned long flags; + bool end = false; +@@ -908,6 +939,14 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) + end = true; + } + ++ if (sr & STM32H7_SPI_SR_UDR) { ++ static DEFINE_RATELIMIT_STATE(rs, ++ DEFAULT_RATELIMIT_INTERVAL * 10, ++ 1); ++ if (__ratelimit(&rs)) ++ dev_dbg_ratelimited(spi->dev, "Underrun detected\n"); ++ } ++ + if (sr & STM32H7_SPI_SR_EOT) { + if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) + stm32h7_spi_read_rxfifo(spi); +@@ -930,7 +969,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) + + if (end) { + stm32h7_spi_disable(spi); +- spi_finalize_current_transfer(master); ++ spi_finalize_current_transfer(ctrl); + } + + return IRQ_HANDLED; +@@ -938,13 +977,13 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) + + /** + * stm32_spi_prepare_msg - set up the controller to transfer a single message +- * @master: controller master interface ++ * @ctrl: controller interface + * @msg: pointer to spi message + */ +-static int stm32_spi_prepare_msg(struct spi_master *master, ++static int stm32_spi_prepare_msg(struct spi_controller *ctrl, + struct spi_message *msg) + { +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + struct spi_device *spi_dev = msg->spi; + struct device_node *np = spi_dev->dev.of_node; + unsigned long flags; +@@ -970,6 +1009,11 @@ static int stm32_spi_prepare_msg(struct spi_master *master, + else + clrb |= spi->cfg->regs->lsb_first.mask; + ++ if (STM32_SPI_SLAVE_MODE(spi) && spi_dev->mode & SPI_CS_HIGH) ++ setb |= spi->cfg->regs->cs_high.mask; ++ else ++ clrb |= spi->cfg->regs->cs_high.mask; ++ + dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n", + !!(spi_dev->mode & SPI_CPOL), + !!(spi_dev->mode & SPI_CPHA), +@@ -983,7 +1027,7 @@ static int stm32_spi_prepare_msg(struct spi_master *master, + if (spi->cfg->set_number_of_data) { + int ret; + +- ret = spi_split_transfers_maxsize(master, msg, ++ ret = spi_split_transfers_maxsize(ctrl, msg, + STM32H7_SPI_TSIZE_MAX, + GFP_KERNEL | GFP_DMA); + if (ret) +@@ -1015,7 +1059,7 @@ static void stm32f4_spi_dma_tx_cb(void *data) + struct stm32_spi *spi = data; + + if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { +- spi_finalize_current_transfer(spi->master); ++ spi_finalize_current_transfer(spi->ctrl); + stm32f4_spi_disable(spi); + } + } +@@ -1030,7 +1074,7 @@ static void stm32_spi_dma_rx_cb(void *data) + { + struct stm32_spi *spi = data; + +- spi_finalize_current_transfer(spi->master); ++ spi_finalize_current_transfer(spi->ctrl); + spi->cfg->disable(spi); + } + +@@ -1160,7 +1204,11 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) + if (spi->tx_buf) + stm32h7_spi_write_txfifo(spi); + +- stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); ++ if (STM32_SPI_SLAVE_MODE(spi) && spi->slave_udr_mode != SPI_NO_ACTION) ++ ier |= STM32H7_SPI_IER_UDRIE; ++ ++ if (STM32_SPI_MASTER_MODE(spi)) ++ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); + + writel_relaxed(ier, spi->base + STM32H7_SPI_IER); + +@@ -1203,11 +1251,15 @@ static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) + if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) + ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE; + ++ if (STM32_SPI_SLAVE_MODE(spi) && spi->slave_udr_mode != SPI_NO_ACTION) ++ ier |= STM32H7_SPI_IER_UDRIE; ++ + stm32_spi_set_bits(spi, STM32H7_SPI_IER, ier); + + stm32_spi_enable(spi); + +- stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); ++ if (STM32_SPI_MASTER_MODE(spi)) ++ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); + } + + /** +@@ -1301,7 +1353,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, + + dma_submit_error: + if (spi->dma_rx) +- dmaengine_terminate_all(spi->dma_rx); ++ dmaengine_terminate_sync(spi->dma_rx); + + dma_desc_error: + stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg, +@@ -1510,6 +1562,53 @@ static int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words) + return 0; + } + ++/** ++ * stm32h7_spi_set_slave_udr - configure slave underrun detection and reaction ++ * @spi: pointer to the spi controller data structure ++ */ ++static void stm32h7_spi_set_slave_udr(struct stm32_spi *spi) ++{ ++ u32 max_udr_ptrn, udr_ptrn, cfg1_setb = 0; ++ ++ if (spi->slave_udr_mode == SPI_NO_ACTION) ++ return; ++ ++ switch (spi->slave_udr_mode) { ++ case SPI_SEND_PATTERN: ++ max_udr_ptrn = (1 << spi->cur_bpw) - 1; ++ if (spi->slave_udr_pattern > max_udr_ptrn) { ++ udr_ptrn = spi->slave_udr_pattern & max_udr_ptrn; ++ dev_warn(spi->dev, ++ "force slave underrun pattern to data width (> 0x%x, set 0x%x)\n", ++ max_udr_ptrn, udr_ptrn); ++ } else { ++ udr_ptrn = spi->slave_udr_pattern; ++ dev_dbg(spi->dev, "spi slave underrun: send pattern (0x%x)\n", ++ spi->slave_udr_pattern); ++ } ++ writel_relaxed(udr_ptrn, spi->base + STM32H7_SPI_UDRDR); ++ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_UDRCFG, STM32H7_SPI_CFG1_UDRCFG_PTRN); ++ break; ++ case SPI_REPEAT_LAST_RECEIVED_DATA: ++ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_UDRCFG, STM32H7_SPI_CFG1_UDRCFG_LAST_R); ++ dev_dbg(spi->dev, "spi slave underrun: repeat received data\n"); ++ break; ++ case SPI_REPEAT_LAST_TRANSMITTED_DATA: ++ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_UDRCFG, STM32H7_SPI_CFG1_UDRCFG_LAST_T); ++ dev_dbg(spi->dev, "spi slave underrun: repeat transmitted data\n"); ++ break; ++ default: ++ dev_warn(spi->dev, "slave underrun detection disabled\n"); ++ spi->slave_udr_mode = SPI_NO_ACTION; ++ } ++ ++ if (spi->slave_udr_mode != SPI_NO_ACTION) { ++ cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_UDRDET, STM32H7_SPI_CFG1_UDRDET_LAST); ++ ++ stm32_spi_set_bits(spi, STM32H7_SPI_CFG1, cfg1_setb); ++ } ++} ++ + /** + * stm32_spi_transfer_one_setup - common setup to transfer a single + * spi_transfer either using DMA or +@@ -1535,16 +1634,18 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, + spi->cfg->set_bpw(spi); + + /* Update spi->cur_speed with real clock speed */ +- mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, +- spi->cfg->baud_rate_div_min, +- spi->cfg->baud_rate_div_max); +- if (mbr < 0) { +- ret = mbr; +- goto out; +- } ++ if (STM32_SPI_MASTER_MODE(spi)) { ++ mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, ++ spi->cfg->baud_rate_div_min, ++ spi->cfg->baud_rate_div_max); ++ if (mbr < 0) { ++ ret = mbr; ++ goto out; ++ } + +- transfer->speed_hz = spi->cur_speed; +- stm32_spi_set_mbr(spi, mbr); ++ transfer->speed_hz = spi->cur_speed; ++ stm32_spi_set_mbr(spi, mbr); ++ } + + comm_type = stm32_spi_communication_type(spi_dev, transfer); + ret = spi->cfg->set_mode(spi, comm_type); +@@ -1553,7 +1654,7 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, + + spi->cur_comm = comm_type; + +- if (spi->cfg->set_data_idleness) ++ if (STM32_SPI_MASTER_MODE(spi) && spi->cfg->set_data_idleness) + spi->cfg->set_data_idleness(spi, transfer->len); + + if (spi->cur_bpw <= 8) +@@ -1569,12 +1670,16 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, + goto out; + } + ++ if (STM32_SPI_SLAVE_MODE(spi) && spi->cfg->set_slave_udr) ++ spi->cfg->set_slave_udr(spi); ++ + dev_dbg(spi->dev, "transfer communication mode set to %d\n", + spi->cur_comm); + dev_dbg(spi->dev, + "data frame of %d-bit, data packet of %d data frames\n", + spi->cur_bpw, spi->cur_fthlv); +- dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed); ++ if (STM32_SPI_MASTER_MODE(spi)) ++ dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed); + dev_dbg(spi->dev, "transfer of %d bytes (%d data frames)\n", + spi->cur_xferlen, nb_words); + dev_dbg(spi->dev, "dma %s\n", +@@ -1588,18 +1693,18 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, + + /** + * stm32_spi_transfer_one - transfer a single spi_transfer +- * @master: controller master interface ++ * @ctrl: controller interface + * @spi_dev: pointer to the spi device + * @transfer: pointer to spi transfer + * + * It must return 0 if the transfer is finished or 1 if the transfer is still + * in progress. + */ +-static int stm32_spi_transfer_one(struct spi_master *master, ++static int stm32_spi_transfer_one(struct spi_controller *ctrl, + struct spi_device *spi_dev, + struct spi_transfer *transfer) + { +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + int ret; + + spi->tx_buf = transfer->tx_buf; +@@ -1607,8 +1712,8 @@ static int stm32_spi_transfer_one(struct spi_master *master, + spi->tx_len = spi->tx_buf ? transfer->len : 0; + spi->rx_len = spi->rx_buf ? transfer->len : 0; + +- spi->cur_usedma = (master->can_dma && +- master->can_dma(master, spi_dev, transfer)); ++ spi->cur_usedma = (ctrl->can_dma && ++ ctrl->can_dma(ctrl, spi_dev, transfer)); + + ret = stm32_spi_transfer_one_setup(spi, spi_dev, transfer); + if (ret) { +@@ -1624,13 +1729,13 @@ static int stm32_spi_transfer_one(struct spi_master *master, + + /** + * stm32_spi_unprepare_msg - relax the hardware +- * @master: controller master interface ++ * @ctrl: controller interface + * @msg: pointer to the spi message + */ +-static int stm32_spi_unprepare_msg(struct spi_master *master, ++static int stm32_spi_unprepare_msg(struct spi_controller *ctrl, + struct spi_message *msg) + { +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + + spi->cfg->disable(spi); + +@@ -1669,12 +1774,13 @@ static int stm32f4_spi_config(struct stm32_spi *spi) + } + + /** +- * stm32h7_spi_config - Configure SPI controller as SPI master ++ * stm32h7_spi_config - Configure SPI controller + * @spi: pointer to the spi controller data structure + */ + static int stm32h7_spi_config(struct stm32_spi *spi) + { + unsigned long flags; ++ u32 cr1 = 0, cfg2 = 0; + + spin_lock_irqsave(&spi->lock, flags); + +@@ -1682,24 +1788,28 @@ static int stm32h7_spi_config(struct stm32_spi *spi) + stm32_spi_clr_bits(spi, STM32H7_SPI_I2SCFGR, + STM32H7_SPI_I2SCFGR_I2SMOD); + +- /* +- * - SS input value high +- * - transmitter half duplex direction +- * - automatic communication suspend when RX-Fifo is full +- */ +- stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SSI | +- STM32H7_SPI_CR1_HDDIR | +- STM32H7_SPI_CR1_MASRX); ++ if (STM32_SPI_SLAVE_MODE(spi)) { ++ /* Use native slave select */ ++ cfg2 &= ~STM32H7_SPI_CFG2_SSM; ++ } else { ++ /* ++ * - Transmitter half duplex direction ++ * - Automatic communication suspend when RX-Fifo is full ++ * - SS input value high ++ */ ++ cr1 |= STM32H7_SPI_CR1_HDDIR | STM32H7_SPI_CR1_MASRX | STM32H7_SPI_CR1_SSI; + +- /* +- * - Set the master mode (default Motorola mode) +- * - Consider 1 master/n slaves configuration and +- * SS input value is determined by the SSI bit +- * - keep control of all associated GPIOs +- */ +- stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_MASTER | +- STM32H7_SPI_CFG2_SSM | +- STM32H7_SPI_CFG2_AFCNTR); ++ /* ++ * - Set the master mode (default Motorola mode) ++ * - Consider 1 master/n slaves configuration and ++ * SS input value is determined by the SSI bit ++ * - keep control of all associated GPIOs ++ */ ++ cfg2 |= STM32H7_SPI_CFG2_MASTER | STM32H7_SPI_CFG2_SSM | STM32H7_SPI_CFG2_AFCNTR; ++ } ++ ++ stm32_spi_set_bits(spi, STM32H7_SPI_CR1, cr1); ++ stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, cfg2); + + spin_unlock_irqrestore(&spi->lock, flags); + +@@ -1722,6 +1832,7 @@ static const struct stm32_spi_cfg stm32f4_spi_cfg = { + .baud_rate_div_min = STM32F4_SPI_BR_DIV_MIN, + .baud_rate_div_max = STM32F4_SPI_BR_DIV_MAX, + .has_fifo = false, ++ .flags = SPI_MASTER_MUST_TX, + }; + + static const struct stm32_spi_cfg stm32h7_spi_cfg = { +@@ -1745,6 +1856,7 @@ static const struct stm32_spi_cfg stm32h7_spi_cfg = { + .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN, + .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX, + .has_fifo = true, ++ .set_slave_udr = stm32h7_spi_set_slave_udr, + }; + + static const struct of_device_id stm32_spi_of_match[] = { +@@ -1754,24 +1866,64 @@ static const struct of_device_id stm32_spi_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, stm32_spi_of_match); + ++static int stm32h7_spi_slave_abort(struct spi_controller *ctrl) ++{ ++ spi_finalize_current_transfer(ctrl); ++ ++ return 0; ++} ++ ++static void stm32h7_spi_parse_slave_config(struct stm32_spi *spi, struct device_node *np) ++{ ++ u32 udr_configs[2] = { 0, 0 }; ++ int count, ret; ++ ++ count = of_property_count_elems_of_size(np, "st,spi-slave-underrun", sizeof(u32)); ++ if (count <= 0) { ++ if (count != -EINVAL) ++ dev_err(spi->dev, "Invalid st,spi-slave-underrun property\n"); ++ return; ++ } ++ ++ ret = of_property_read_u32_array(np, "st,spi-slave-underrun", udr_configs, count); ++ if (ret) ++ return; ++ ++ spi->slave_udr_mode = udr_configs[0]; ++ if (spi->slave_udr_mode == SPI_SEND_PATTERN) { ++ if (count > 1) ++ spi->slave_udr_pattern = udr_configs[1]; ++ else ++ dev_warn(spi->dev, "Missing pattern in st,spi-slave-underrun property\n"); ++ } ++} ++ + static int stm32_spi_probe(struct platform_device *pdev) + { +- struct spi_master *master; ++ struct spi_controller *ctrl; + struct stm32_spi *spi; + struct resource *res; + struct reset_control *rst; ++ struct device_node *np = pdev->dev.of_node; ++ bool slave_mode; + int ret; + +- master = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); +- if (!master) { +- dev_err(&pdev->dev, "spi master allocation failed\n"); ++ slave_mode = of_property_read_bool(np, "spi-slave"); ++ ++ if (slave_mode) ++ ctrl = devm_spi_alloc_slave(&pdev->dev, sizeof(struct stm32_spi)); ++ else ++ ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); ++ if (!ctrl) { ++ dev_err(&pdev->dev, "spi controller allocation failed\n"); + return -ENOMEM; + } +- platform_set_drvdata(pdev, master); ++ platform_set_drvdata(pdev, ctrl); + +- spi = spi_master_get_devdata(master); ++ spi = spi_controller_get_devdata(ctrl); + spi->dev = &pdev->dev; +- spi->master = master; ++ spi->ctrl = ctrl; ++ spi->slave_mode = slave_mode; + spin_lock_init(&spi->lock); + + spi->cfg = (const struct stm32_spi_cfg *) +@@ -1793,13 +1945,16 @@ static int stm32_spi_probe(struct platform_device *pdev) + ret = devm_request_threaded_irq(&pdev->dev, spi->irq, + spi->cfg->irq_handler_event, + spi->cfg->irq_handler_thread, +- IRQF_ONESHOT, pdev->name, master); ++ IRQF_ONESHOT, pdev->name, ctrl); + if (ret) { + dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq, + ret); + return ret; + } + ++ if (STM32_SPI_SLAVE_MODE(spi)) ++ stm32h7_spi_parse_slave_config(spi, np); ++ + spi->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(spi->clk)) { + ret = PTR_ERR(spi->clk); +@@ -1842,19 +1997,21 @@ static int stm32_spi_probe(struct platform_device *pdev) + goto err_clk_disable; + } + +- master->dev.of_node = pdev->dev.of_node; +- master->auto_runtime_pm = true; +- master->bus_num = pdev->id; +- master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | +- SPI_3WIRE; +- master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi); +- master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; +- master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; +- master->use_gpio_descriptors = true; +- master->prepare_message = stm32_spi_prepare_msg; +- master->transfer_one = stm32_spi_transfer_one; +- master->unprepare_message = stm32_spi_unprepare_msg; +- master->flags = SPI_MASTER_MUST_TX; ++ ctrl->dev.of_node = pdev->dev.of_node; ++ ctrl->auto_runtime_pm = true; ++ ctrl->bus_num = pdev->id; ++ ctrl->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | ++ SPI_3WIRE; ++ ctrl->bits_per_word_mask = spi->cfg->get_bpw_mask(spi); ++ ctrl->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; ++ ctrl->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; ++ ctrl->use_gpio_descriptors = true; ++ ctrl->prepare_message = stm32_spi_prepare_msg; ++ ctrl->transfer_one = stm32_spi_transfer_one; ++ ctrl->unprepare_message = stm32_spi_unprepare_msg; ++ ctrl->flags = spi->cfg->flags; ++ if (STM32_SPI_SLAVE_MODE(spi)) ++ ctrl->slave_abort = stm32h7_spi_slave_abort; + + spi->dma_tx = dma_request_chan(spi->dev, "tx"); + if (IS_ERR(spi->dma_tx)) { +@@ -1865,7 +2022,7 @@ static int stm32_spi_probe(struct platform_device *pdev) + + dev_warn(&pdev->dev, "failed to request tx dma channel\n"); + } else { +- master->dma_tx = spi->dma_tx; ++ ctrl->dma_tx = spi->dma_tx; + } + + spi->dma_rx = dma_request_chan(spi->dev, "rx"); +@@ -1877,11 +2034,11 @@ static int stm32_spi_probe(struct platform_device *pdev) + + dev_warn(&pdev->dev, "failed to request rx dma channel\n"); + } else { +- master->dma_rx = spi->dma_rx; ++ ctrl->dma_rx = spi->dma_rx; + } + + if (spi->dma_tx || spi->dma_rx) +- master->can_dma = stm32_spi_can_dma; ++ ctrl->can_dma = stm32_spi_can_dma; + + pm_runtime_set_autosuspend_delay(&pdev->dev, + STM32_SPI_AUTOSUSPEND_DELAY); +@@ -1890,9 +2047,9 @@ static int stm32_spi_probe(struct platform_device *pdev) + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_enable(&pdev->dev); + +- ret = spi_register_master(master); ++ ret = spi_register_controller(ctrl); + if (ret) { +- dev_err(&pdev->dev, "spi master registration failed: %d\n", ++ dev_err(&pdev->dev, "spi controller registration failed: %d\n", + ret); + goto err_pm_disable; + } +@@ -1900,7 +2057,8 @@ static int stm32_spi_probe(struct platform_device *pdev) + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + +- dev_info(&pdev->dev, "driver initialized\n"); ++ dev_info(&pdev->dev, "driver initialized (%s mode)\n", ++ STM32_SPI_MASTER_MODE(spi) ? "master" : "slave"); + + return 0; + +@@ -1922,12 +2080,12 @@ static int stm32_spi_probe(struct platform_device *pdev) + + static int stm32_spi_remove(struct platform_device *pdev) + { +- struct spi_master *master = platform_get_drvdata(pdev); +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct spi_controller *ctrl = platform_get_drvdata(pdev); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + + pm_runtime_get_sync(&pdev->dev); + +- spi_unregister_master(master); ++ spi_unregister_controller(ctrl); + spi->cfg->disable(spi); + + pm_runtime_disable(&pdev->dev); +@@ -1935,10 +2093,10 @@ static int stm32_spi_remove(struct platform_device *pdev) + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + +- if (master->dma_tx) +- dma_release_channel(master->dma_tx); +- if (master->dma_rx) +- dma_release_channel(master->dma_rx); ++ if (ctrl->dma_tx) ++ dma_release_channel(ctrl->dma_tx); ++ if (ctrl->dma_rx) ++ dma_release_channel(ctrl->dma_rx); + + clk_disable_unprepare(spi->clk); + +@@ -1950,8 +2108,8 @@ static int stm32_spi_remove(struct platform_device *pdev) + + static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev) + { +- struct spi_master *master = dev_get_drvdata(dev); +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct spi_controller *ctrl = dev_get_drvdata(dev); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + + clk_disable_unprepare(spi->clk); + +@@ -1960,8 +2118,8 @@ static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev) + + static int __maybe_unused stm32_spi_runtime_resume(struct device *dev) + { +- struct spi_master *master = dev_get_drvdata(dev); +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct spi_controller *ctrl = dev_get_drvdata(dev); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + int ret; + + ret = pinctrl_pm_select_default_state(dev); +@@ -1973,10 +2131,10 @@ static int __maybe_unused stm32_spi_runtime_resume(struct device *dev) + + static int __maybe_unused stm32_spi_suspend(struct device *dev) + { +- struct spi_master *master = dev_get_drvdata(dev); ++ struct spi_controller *ctrl = dev_get_drvdata(dev); + int ret; + +- ret = spi_master_suspend(master); ++ ret = spi_controller_suspend(ctrl); + if (ret) + return ret; + +@@ -1985,15 +2143,15 @@ static int __maybe_unused stm32_spi_suspend(struct device *dev) + + static int __maybe_unused stm32_spi_resume(struct device *dev) + { +- struct spi_master *master = dev_get_drvdata(dev); +- struct stm32_spi *spi = spi_master_get_devdata(master); ++ struct spi_controller *ctrl = dev_get_drvdata(dev); ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + int ret; + + ret = pm_runtime_force_resume(dev); + if (ret) + return ret; + +- ret = spi_master_resume(master); ++ ret = spi_controller_resume(ctrl); + if (ret) { + clk_disable_unprepare(spi->clk); + return ret; +diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h +index e6fb8ada3f4d..370a25a9366c 100644 +--- a/include/dt-bindings/pinctrl/stm32-pinfunc.h ++++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h +@@ -26,6 +26,7 @@ + #define AF14 0xf + #define AF15 0x10 + #define ANALOG 0x11 ++#define RSVD 0x12 + + /* define Pins number*/ + #define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) +diff --git a/include/dt-bindings/spi/spi-stm32.h b/include/dt-bindings/spi/spi-stm32.h +new file mode 100644 +index 000000000000..7c818a399a0c +--- /dev/null ++++ b/include/dt-bindings/spi/spi-stm32.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ ++/* ++ * This header provides constants for STM32_SPI bindings. ++ */ ++ ++#ifndef _DT_BINDINGS_SPI_SPI_STM32_H ++#define _DT_BINDINGS_SPI_SPI_STM32_H ++ ++/* st,spi-slave-underrun first parameter */ ++#define SPI_NO_ACTION 0 ++#define SPI_SEND_PATTERN 1 ++#define SPI_REPEAT_LAST_RECEIVED_DATA 2 ++#define SPI_REPEAT_LAST_TRANSMITTED_DATA 3 ++ ++#endif +-- +2.17.1 + diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0017-ARM-5.15.24-stm32mp1-r1-RESET-RTC.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0018-v5.15-stm32mp-r2-RESET-RTC.patch similarity index 98% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0017-ARM-5.15.24-stm32mp1-r1-RESET-RTC.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0018-v5.15-stm32mp-r2-RESET-RTC.patch index 99c58cc..2ee29e6 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0017-ARM-5.15.24-stm32mp1-r1-RESET-RTC.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0018-v5.15-stm32mp-r2-RESET-RTC.patch @@ -1,9 +1,9 @@ -From 4f71b18aeac456fac466593f3baa12e5e3f698f3 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:06:36 +0200 -Subject: [PATCH 17/22] ARM-5.15.24-stm32mp1-r1-RESET-RTC +From b0e70738cf7a9a1c9b4e10c3aec7cea6004ed9a4 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 16:04:20 +0100 +Subject: [PATCH 18/22] v5.15-stm32mp-r2 RESET-RTC -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../devicetree/bindings/rtc/st,stm32-rtc.yaml | 37 ++ drivers/rtc/Kconfig | 1 + @@ -16,7 +16,7 @@ Signed-off-by: Christophe Priouzeau create mode 100644 include/dt-bindings/rtc/rtc-stm32.h diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml -index 5456604b1..d94e1d13d 100644 +index 5456604b1c14..d94e1d13d908 100644 --- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml @@ -52,6 +52,20 @@ properties: @@ -98,7 +98,7 @@ index 5456604b1..d94e1d13d 100644 ... diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig -index e1bc52144..57ef1efdf 100644 +index e1bc5214494e..57ef1efdfc3c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1867,6 +1867,7 @@ config RTC_DRV_R7301 @@ -110,7 +110,7 @@ index e1bc52144..57ef1efdf 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 ac9e228b5..20896b4b4 100644 +index ac9e228b56d0..20896b4b4641 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -5,7 +5,10 @@ @@ -714,7 +714,7 @@ index ac9e228b5..20896b4b4 100644 static struct platform_driver stm32_rtc_driver = { .probe = stm32_rtc_probe, diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h -index f3a0ed317..bdbf9e253 100644 +index f3a0ed317835..bdbf9e253015 100644 --- a/include/dt-bindings/reset/stm32mp1-resets.h +++ b/include/dt-bindings/reset/stm32mp1-resets.h @@ -107,17 +107,17 @@ @@ -749,7 +749,7 @@ index f3a0ed317..bdbf9e253 100644 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ diff --git a/include/dt-bindings/reset/stm32mp13-resets.h b/include/dt-bindings/reset/stm32mp13-resets.h new file mode 100644 -index 000000000..934864e90 +index 000000000000..934864e90da6 --- /dev/null +++ b/include/dt-bindings/reset/stm32mp13-resets.h @@ -0,0 +1,100 @@ @@ -855,7 +855,7 @@ index 000000000..934864e90 +#endif /* _DT_BINDINGS_STM32MP13_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 000000000..2fd78c2e6 +index 000000000000..2fd78c2e62d4 --- /dev/null +++ b/include/dt-bindings/rtc/rtc-stm32.h @@ -0,0 +1,14 @@ @@ -874,5 +874,5 @@ index 000000000..2fd78c2e6 + +#endif -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0018-ARM-5.15.24-stm32mp1-r1-SCMI.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0019-v5.15-stm32mp-r2-SCMI.patch similarity index 97% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0018-ARM-5.15.24-stm32mp1-r1-SCMI.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0019-v5.15-stm32mp-r2-SCMI.patch index b08132b..7b745cf 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0018-ARM-5.15.24-stm32mp1-r1-SCMI.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0019-v5.15-stm32mp-r2-SCMI.patch @@ -1,9 +1,9 @@ -From e21e9c56de8df104ae24bff08afea4907932f915 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:07:03 +0200 -Subject: [PATCH 18/22] ARM-5.15.24-stm32mp1-r1-SCMI +From ae4d172fd1f74a9adc7eed21b80dc3049a56a462 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 16:05:11 +0100 +Subject: [PATCH 19/22] v5.15-stm32mp-r2 SCMI -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- drivers/firmware/arm_scmi/Makefile | 1 + drivers/firmware/arm_scmi/clock.c | 78 +++ @@ -15,7 +15,7 @@ Signed-off-by: Christophe Priouzeau create mode 100644 drivers/firmware/arm_scmi/optee.c diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile -index 1dcf123d6..d1460cf7e 100644 +index 1dcf123d64ab..d1460cf7e9de 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -6,6 +6,7 @@ scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += mailbox.o @@ -27,7 +27,7 @@ index 1dcf123d6..d1460cf7e 100644 scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ $(scmi-transport-y) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c -index 35b56c8ba..79b81cf51 100644 +index 492f3a9197ec..47814d175ce7 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -16,6 +16,8 @@ enum scmi_clock_protocol_cmd { @@ -51,7 +51,7 @@ index 35b56c8ba..79b81cf51 100644 struct scmi_clock_set_rate { __le32 flags; #define CLOCK_SET_ASYNC BIT(0) -@@ -214,6 +221,34 @@ scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id, +@@ -215,6 +222,34 @@ scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id, return ret; } @@ -86,7 +86,7 @@ index 35b56c8ba..79b81cf51 100644 static int scmi_clock_rate_get(const struct scmi_protocol_handle *ph, u32 clk_id, u64 *value) -@@ -271,6 +306,47 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph, +@@ -272,6 +307,47 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph, return ret; } @@ -134,7 +134,7 @@ index 35b56c8ba..79b81cf51 100644 static int scmi_clock_config_set(const struct scmi_protocol_handle *ph, u32 clk_id, u32 config) -@@ -330,6 +406,8 @@ static const struct scmi_clk_proto_ops clk_proto_ops = { +@@ -331,6 +407,8 @@ static const struct scmi_clk_proto_ops clk_proto_ops = { .rate_set = scmi_clock_rate_set, .enable = scmi_clock_enable, .disable = scmi_clock_disable, @@ -144,7 +144,7 @@ index 35b56c8ba..79b81cf51 100644 static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h -index dea1bfbe1..82ff3c3a6 100644 +index dea1bfbe1052..82ff3c3a6d2d 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -421,6 +421,9 @@ extern const struct scmi_desc scmi_smc_desc; @@ -158,10 +158,10 @@ index dea1bfbe1..82ff3c3a6 100644 void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *priv); void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c -index b406b3f78..7d9c5b7b0 100644 +index e815b8f98739..4a5b9c2c0c53 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c -@@ -1997,6 +1997,9 @@ static const struct of_device_id scmi_of_match[] = { +@@ -1998,6 +1998,9 @@ static const struct of_device_id scmi_of_match[] = { #ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc}, #endif @@ -173,7 +173,7 @@ index b406b3f78..7d9c5b7b0 100644 #endif diff --git a/drivers/firmware/arm_scmi/optee.c b/drivers/firmware/arm_scmi/optee.c new file mode 100644 -index 000000000..4ec54b3c6 +index 000000000000..4ec54b3c6628 --- /dev/null +++ b/drivers/firmware/arm_scmi/optee.c @@ -0,0 +1,848 @@ @@ -1026,7 +1026,7 @@ index 000000000..4ec54b3c6 +MODULE_AUTHOR("Etienne Carriere "); +MODULE_DESCRIPTION("OP-TEE SCMI transport driver"); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h -index 80e781c51..f0b8bc4cf 100644 +index 80e781c51ddc..f0b8bc4cf83a 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -82,6 +82,10 @@ struct scmi_clk_proto_ops { @@ -1041,5 +1041,5 @@ index 80e781c51..f0b8bc4cf 100644 /** -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0019-ARM-5.15.24-stm32mp1-r1-SOUND.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0020-v5.15-stm32mp-r2-SOUND.patch similarity index 82% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0019-ARM-5.15.24-stm32mp1-r1-SOUND.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0020-v5.15-stm32mp-r2-SOUND.patch index d0bd34e..71f5455 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0019-ARM-5.15.24-stm32mp1-r1-SOUND.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0020-v5.15-stm32mp-r2-SOUND.patch @@ -1,23 +1,23 @@ -From a0c67a64074c33685451fff84871a846bc29d523 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:07:28 +0200 -Subject: [PATCH 19/22] ARM-5.15.24-stm32mp1-r1-SOUND +From bf84be1a6e25855048a341b6e8d86a660d6fac1a Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 16:05:34 +0100 +Subject: [PATCH 20/22] v5.15-stm32mp-r2 SOUND -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- sound/soc/codecs/Kconfig | 2 +- sound/soc/codecs/wm8994.c | 81 ++++++++++++++++++++++++++++++++--- - sound/soc/stm/stm32_adfsdm.c | 11 +++-- - sound/soc/stm/stm32_i2s.c | 4 ++ + sound/soc/stm/stm32_adfsdm.c | 22 ++++++++-- + sound/soc/stm/stm32_i2s.c | 6 ++- sound/soc/stm/stm32_sai_sub.c | 4 +- sound/soc/stm/stm32_spdifrx.c | 4 ++ - 6 files changed, 94 insertions(+), 12 deletions(-) + 6 files changed, 106 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index f12c9b942..4cc91bcfe 100644 +index d59a7e99ce42..31ed450b4069 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -1771,7 +1771,7 @@ config SND_SOC_WM8993 +@@ -1774,7 +1774,7 @@ config SND_SOC_WM8993 depends on I2C config SND_SOC_WM8994 @@ -27,7 +27,7 @@ index f12c9b942..4cc91bcfe 100644 config SND_SOC_WM8995 tristate diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c -index f117ec0c4..98e803516 100644 +index f117ec0c489f..98e803516fe5 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -7,6 +7,7 @@ @@ -179,7 +179,7 @@ index f117ec0c4..98e803516 100644 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, ARRAY_SIZE(wm8994_lateclk_revd_widgets)); diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c -index e6078f50e..534f96af9 100644 +index e6078f50e508..75e75cc7fa02 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -12,7 +12,7 @@ @@ -191,7 +191,32 @@ index e6078f50e..534f96af9 100644 #include #include #include -@@ -363,15 +363,20 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) +@@ -303,6 +303,11 @@ static int stm32_adfsdm_dummy_cb(const void *data, void *private) + return 0; + } + ++static void stm32_adfsdm_cleanup(void *data) ++{ ++ iio_channel_release_all_cb(data); ++} ++ + static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { + .open = stm32_adfsdm_pcm_open, + .close = stm32_adfsdm_pcm_close, +@@ -349,6 +354,12 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) + if (IS_ERR(priv->iio_cb)) + return PTR_ERR(priv->iio_cb); + ++ ret = devm_add_action_or_reset(&pdev->dev, stm32_adfsdm_cleanup, priv->iio_cb); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Unable to add action\n"); ++ return ret; ++ } ++ + component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); + if (!component) + return -ENOMEM; +@@ -363,15 +374,20 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) #endif ret = snd_soc_add_component(component, NULL, 0); @@ -215,7 +240,7 @@ index e6078f50e..534f96af9 100644 return 0; diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c -index 717f45a83..61e2c5d51 100644 +index 717f45a83445..f16dd7608b7e 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -13,6 +13,7 @@ @@ -226,6 +251,15 @@ index 717f45a83..61e2c5d51 100644 #include #include #include +@@ -1087,7 +1088,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, + if (irq < 0) + return irq; + +- ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT, ++ ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, 0, + dev_name(&pdev->dev), i2s); + if (ret) { + dev_err(&pdev->dev, "irq request returned %d\n", ret); @@ -1113,6 +1114,7 @@ static int stm32_i2s_remove(struct platform_device *pdev) { snd_dmaengine_pcm_unregister(&pdev->dev); @@ -244,7 +278,7 @@ index 717f45a83..61e2c5d51 100644 error: diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c -index 9c3b8e209..95cd38a50 100644 +index 9c3b8e209656..95cd38a502bb 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 = { @@ -266,7 +300,7 @@ index 9c3b8e209..95cd38a50 100644 .rate_max = 192000, .rates = SNDRV_PCM_RATE_CONTINUOUS, diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c -index 48145f553..e885796ca 100644 +index 48145f553588..e885796ca5f4 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -12,6 +12,7 @@ @@ -295,5 +329,5 @@ index 48145f553..e885796ca 100644 error: -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0021-ARM-5.15.24-stm32mp1-r1-DEVICETREE.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0021-v5.15-stm32mp-r2-DEVICETREE.patch similarity index 87% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0021-ARM-5.15.24-stm32mp1-r1-DEVICETREE.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0021-v5.15-stm32mp-r2-DEVICETREE.patch index 67ff304..044ca98 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0021-ARM-5.15.24-stm32mp1-r1-DEVICETREE.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0021-v5.15-stm32mp-r2-DEVICETREE.patch @@ -1,16 +1,15 @@ -From 88b9dfd710a088b600d7e76c9328cc92b3bcc176 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:10:02 +0200 -Subject: [PATCH 21/22] ARM-5.15.24-stm32mp1-r1-DEVICETREE +From 35a4e5c8d17b391a45de9feceac1a88cdae459a0 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 16:51:27 +0100 +Subject: [PATCH 21/22] v5.15-stm32mp-r2 DEVICETREE -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../arm/firmware/linaro,optee-tz.yaml | 8 + - .../devicetree/bindings/arm/stm32/stm32.yaml | 5 + - .../bindings/crypto/st,stm32-hash.yaml | 1 + + .../devicetree/bindings/arm/stm32/stm32.yaml | 4 + .../bindings/display/panel/panel-dpi.yaml | 10 + .../display/panel/rocktech,hx8394.yaml | 56 + - .../interrupt-controller/st,stm32-exti.yaml | 20 + + .../interrupt-controller/st,stm32-exti.yaml | 39 +- .../leds/backlight/gpio-backlight.yaml | 9 + .../bindings/mtd/nand-controller.yaml | 7 + .../bindings/nvmem/st,stm32-romem.yaml | 8 + @@ -18,60 +17,62 @@ Signed-off-by: Christophe Priouzeau .../devicetree/bindings/serial/rs485.yaml | 14 + .../bindings/serial/st,stm32-uart.yaml | 5 + .../devicetree/bindings/vendor-prefixes.yaml | 2 + - arch/arm/boot/dts/Makefile | 56 + - arch/arm/boot/dts/stm32mp13-pinctrl.dtsi | 644 +++++++ - arch/arm/boot/dts/stm32mp131.dtsi | 1664 +++++++++++++++++ - arch/arm/boot/dts/stm32mp133.dtsi | 87 + + arch/arm/boot/dts/Makefile | 60 + + arch/arm/boot/dts/stm32mp13-pinctrl.dtsi | 644 ++++++ + arch/arm/boot/dts/stm32mp131.dtsi | 1742 +++++++++++++++++ + arch/arm/boot/dts/stm32mp133.dtsi | 100 + arch/arm/boot/dts/stm32mp135.dtsi | 32 + - .../boot/dts/stm32mp135d-dk-a7-examples.dts | 22 + - arch/arm/boot/dts/stm32mp135d-dk.dts | 687 +++++++ .../boot/dts/stm32mp135f-dk-a7-examples.dts | 22 + - arch/arm/boot/dts/stm32mp135f-dk.dts | 689 +++++++ + arch/arm/boot/dts/stm32mp135f-dk.dts | 701 +++++++ arch/arm/boot/dts/stm32mp13xa.dtsi | 5 + - arch/arm/boot/dts/stm32mp13xc.dtsi | 18 + + arch/arm/boot/dts/stm32mp13xc.dtsi | 21 + arch/arm/boot/dts/stm32mp13xd.dtsi | 5 + - arch/arm/boot/dts/stm32mp13xf.dtsi | 18 + - .../boot/dts/stm32mp15-m4-srm-pinctrl.dtsi | 524 ++++++ + arch/arm/boot/dts/stm32mp13xf.dtsi | 21 + + .../boot/dts/stm32mp15-m4-srm-pinctrl.dtsi | 524 +++++ arch/arm/boot/dts/stm32mp15-m4-srm.dtsi | 447 +++++ - arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 176 +- - arch/arm/boot/dts/stm32mp151.dtsi | 553 ++++-- + arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 316 ++- + arch/arm/boot/dts/stm32mp151.dtsi | 657 +++++-- arch/arm/boot/dts/stm32mp153.dtsi | 15 +- arch/arm/boot/dts/stm32mp157.dtsi | 3 +- + .../boot/dts/stm32mp157a-dk1-a7-examples.dts | 95 + + .../boot/dts/stm32mp157a-dk1-m4-examples.dts | 128 ++ arch/arm/boot/dts/stm32mp157a-dk1.dts | 8 +- arch/arm/boot/dts/stm32mp157a-ed1.dts | 32 + arch/arm/boot/dts/stm32mp157a-ev1.dts | 103 + - .../boot/dts/stm32mp157c-dk2-a7-examples.dts | 67 + + .../boot/dts/stm32mp157c-dk2-a7-examples.dts | 95 + .../boot/dts/stm32mp157c-dk2-m4-examples.dts | 128 ++ - arch/arm/boot/dts/stm32mp157c-dk2.dts | 65 +- + arch/arm/boot/dts/stm32mp157c-dk2.dts | 64 +- arch/arm/boot/dts/stm32mp157c-ed1.dts | 374 +--- .../boot/dts/stm32mp157c-ev1-a7-examples.dts | 57 + .../boot/dts/stm32mp157c-ev1-m4-examples.dts | 150 ++ - arch/arm/boot/dts/stm32mp157c-ev1.dts | 326 +--- + arch/arm/boot/dts/stm32mp157c-ev1.dts | 326 +-- + .../boot/dts/stm32mp157d-dk1-a7-examples.dts | 95 + + .../boot/dts/stm32mp157d-dk1-m4-examples.dts | 128 ++ arch/arm/boot/dts/stm32mp157d-dk1.dts | 26 + arch/arm/boot/dts/stm32mp157d-ed1.dts | 32 + arch/arm/boot/dts/stm32mp157d-ev1.dts | 103 + - .../boot/dts/stm32mp157f-dk2-a7-examples.dts | 67 + + .../boot/dts/stm32mp157f-dk2-a7-examples.dts | 95 + .../boot/dts/stm32mp157f-dk2-m4-examples.dts | 128 ++ - arch/arm/boot/dts/stm32mp157f-dk2.dts | 152 ++ + arch/arm/boot/dts/stm32mp157f-dk2.dts | 151 ++ arch/arm/boot/dts/stm32mp157f-ed1.dts | 36 + .../boot/dts/stm32mp157f-ev1-a7-examples.dts | 57 + .../boot/dts/stm32mp157f-ev1-m4-examples.dts | 151 ++ arch/arm/boot/dts/stm32mp157f-ev1.dts | 99 + arch/arm/boot/dts/stm32mp15xa.dtsi | 13 + - arch/arm/boot/dts/stm32mp15xc.dtsi | 6 +- + arch/arm/boot/dts/stm32mp15xc.dtsi | 9 +- arch/arm/boot/dts/stm32mp15xd.dtsi | 42 + - arch/arm/boot/dts/stm32mp15xf.dtsi | 20 + - arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 126 +- - arch/arm/boot/dts/stm32mp15xx-edx.dtsi | 419 +++++ - arch/arm/boot/dts/stm32mp15xx-evx.dtsi | 690 +++++++ - 59 files changed, 8408 insertions(+), 885 deletions(-) + arch/arm/boot/dts/stm32mp15xf.dtsi | 23 + + arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi | 12 +- + .../boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 28 +- + arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 143 +- + arch/arm/boot/dts/stm32mp15xx-edx.dtsi | 429 ++++ + arch/arm/boot/dts/stm32mp15xx-evx.dtsi | 698 +++++++ + 62 files changed, 8558 insertions(+), 981 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/panel/rocktech,hx8394.yaml create mode 100644 arch/arm/boot/dts/stm32mp13-pinctrl.dtsi create mode 100644 arch/arm/boot/dts/stm32mp131.dtsi create mode 100644 arch/arm/boot/dts/stm32mp133.dtsi create mode 100644 arch/arm/boot/dts/stm32mp135.dtsi - create mode 100644 arch/arm/boot/dts/stm32mp135d-dk-a7-examples.dts - create mode 100644 arch/arm/boot/dts/stm32mp135d-dk.dts create mode 100644 arch/arm/boot/dts/stm32mp135f-dk-a7-examples.dts create mode 100644 arch/arm/boot/dts/stm32mp135f-dk.dts create mode 100644 arch/arm/boot/dts/stm32mp13xa.dtsi @@ -80,12 +81,16 @@ Signed-off-by: Christophe Priouzeau create mode 100644 arch/arm/boot/dts/stm32mp13xf.dtsi create mode 100644 arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi create mode 100644 arch/arm/boot/dts/stm32mp15-m4-srm.dtsi + create mode 100644 arch/arm/boot/dts/stm32mp157a-dk1-a7-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157a-dk1-m4-examples.dts create mode 100644 arch/arm/boot/dts/stm32mp157a-ed1.dts create mode 100644 arch/arm/boot/dts/stm32mp157a-ev1.dts create mode 100644 arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts create mode 100644 arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157d-dk1-a7-examples.dts + create mode 100644 arch/arm/boot/dts/stm32mp157d-dk1-m4-examples.dts create mode 100644 arch/arm/boot/dts/stm32mp157d-dk1.dts create mode 100644 arch/arm/boot/dts/stm32mp157d-ed1.dts create mode 100644 arch/arm/boot/dts/stm32mp157d-ev1.dts @@ -103,7 +108,7 @@ Signed-off-by: Christophe Priouzeau create mode 100644 arch/arm/boot/dts/stm32mp15xx-evx.dtsi diff --git a/Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.yaml b/Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.yaml -index c24047c1f..9a426110a 100644 +index c24047c1fdd5..9a426110a14a 100644 --- a/Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.yaml +++ b/Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.yaml @@ -24,6 +24,12 @@ properties: @@ -133,35 +138,22 @@ index c24047c1f..9a426110a 100644 }; diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml -index 9a77ab74b..ede14d411 100644 +index 9a77ab74be99..9ac7da01c6c3 100644 --- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml +++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml -@@ -55,6 +55,11 @@ properties: +@@ -55,6 +55,10 @@ properties: - enum: - st,stm32h750i-art-pi - const: st,stm32h750 + - items: + - enum: -+ - st,stm32mp135d-dk + - st,stm32mp135f-dk + - const: st,stm32mp135 - items: - enum: - shiratech,stm32mp157a-iot-box # IoT Box -diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml -index 6dd658f09..1a944608d 100644 ---- a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml -+++ b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml -@@ -14,6 +14,7 @@ properties: - enum: - - st,stm32f456-hash - - st,stm32f756-hash -+ - st,stm32mp13-hash - - reg: - maxItems: 1 diff --git a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml -index dae0676b5..8965b627d 100644 +index dae0676b5c6e..8965b627dd3e 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml @@ -21,6 +21,15 @@ properties: @@ -190,7 +182,7 @@ index dae0676b5..8965b627d 100644 port { diff --git a/Documentation/devicetree/bindings/display/panel/rocktech,hx8394.yaml b/Documentation/devicetree/bindings/display/panel/rocktech,hx8394.yaml new file mode 100644 -index 000000000..db548d94e +index 000000000000..db548d94e545 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/rocktech,hx8394.yaml @@ -0,0 +1,56 @@ @@ -251,7 +243,7 @@ index 000000000..db548d94e + }; +... diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml -index 6d3e68eb2..253e07503 100644 +index 6d3e68eb2e8b..e3126b712469 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml @@ -20,6 +20,7 @@ properties: @@ -262,34 +254,60 @@ index 6d3e68eb2..253e07503 100644 - const: syscon "#interrupt-cells": -@@ -41,6 +42,25 @@ properties: +@@ -41,6 +42,24 @@ properties: description: Interrupts references to primary interrupt controller ++ wakeup-parent: true ++ +patternProperties: -+ '^exti[0-9a-f]*$': ++ '^exti-interrupt-map$': + type: object + properties: -+ interrupt-controller: true ++ interrupt-map: true ++ interrupt-map-mask: true + "#interrupt-cells": + const: 2 -+ -+ st,irq-number: -+ description: -+ Interrupt number mapped on the parent. -+ $ref: "/schemas/types.yaml#/definitions/uint32" ++ "#address-cells": ++ const: 0 + + required: ++ - interrupt-map + - "#interrupt-cells" -+ - interrupt-controller -+ - st,irq-number -+ - interrupt-parent ++ - "#address-cells" + required: - "#interrupt-cells" - compatible +@@ -89,7 +108,25 @@ examples: + }; + + //Example 2 +- exti2: interrupt-controller@40013c00 { ++ exti1: interrupt-controller@5000d000 { ++ compatible = "st,stm32mp1-exti", "syscon"; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x5000d000 0x400>; ++ wakeup-parent = <&pwr_irq>; ++ exti-interrupt-map { ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ interrupt-map-mask = <0xffffffff 0>; ++ interrupt-map = ++ <0 0 &intc GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, ++ <3 0 &intc GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, ++ <55 0 &pwr_irq 0 IRQ_TYPE_EDGE_FALLING 0>; ++ }; ++ }; ++ ++ //Example 3 ++ exti3: interrupt-controller@40013c00 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; diff --git a/Documentation/devicetree/bindings/leds/backlight/gpio-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/gpio-backlight.yaml -index 75cc569b9..3097aa976 100644 +index 75cc569b9c55..3097aa976ad6 100644 --- a/Documentation/devicetree/bindings/leds/backlight/gpio-backlight.yaml +++ b/Documentation/devicetree/bindings/leds/backlight/gpio-backlight.yaml @@ -23,6 +23,15 @@ properties: @@ -309,7 +327,7 @@ index 75cc569b9..3097aa976 100644 - compatible - gpios diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml -index bd217e6f5..53b21aed0 100644 +index 5cd144a9ec99..29c9e5b0bbe7 100644 --- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml +++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml @@ -154,6 +154,13 @@ patternProperties: @@ -327,7 +345,7 @@ index bd217e6f5..53b21aed0 100644 $ref: /schemas/types.yaml#/definitions/uint64-matrix description: diff --git a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml -index 0b80ce22a..f13868d43 100644 +index 0b80ce22a2f8..f13868d4344b 100644 --- a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml +++ b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml @@ -22,8 +22,16 @@ properties: @@ -348,7 +366,7 @@ index 0b80ce22a..f13868d43 100644 "^.*@[0-9a-f]+$": type: object diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml -index 82bb2e97e..17dd4d826 100644 +index 82bb2e97e889..17dd4d826d21 100644 --- a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml +++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml @@ -15,7 +15,9 @@ maintainers: @@ -363,7 +381,7 @@ index 82bb2e97e..17dd4d826 100644 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml -index 0c9fa694f..603d74cf2 100644 +index 0c9fa694f85c..603d74cf2031 100644 --- a/Documentation/devicetree/bindings/serial/rs485.yaml +++ b/Documentation/devicetree/bindings/serial/rs485.yaml @@ -29,6 +29,20 @@ properties: @@ -388,7 +406,7 @@ index 0c9fa694f..603d74cf2 100644 description: drive RTS low when sending (default is high). $ref: /schemas/types.yaml#/definitions/flag diff --git a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml -index f50f4ca89..93ca9aa8f 100644 +index f50f4ca893a0..93ca9aa8f26e 100644 --- a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml +++ b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml @@ -61,10 +61,15 @@ properties: @@ -408,7 +426,7 @@ index f50f4ca89..93ca9aa8f 100644 description: If value is set to 1, RX FIFO threshold is disabled. diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml -index a867f7102..864e10fbf 100644 +index a867f7102c35..864e10fbf90b 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -427,6 +427,8 @@ patternProperties: @@ -421,10 +439,10 @@ index a867f7102..864e10fbf 100644 description: GARDENA GmbH "^gateworks,.*": diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 27ca1ca6e..09460432d 100644 +index 7a72fc636a7a..1f07bf84c45d 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -1,4 +1,40 @@ +@@ -1,4 +1,42 @@ # SPDX-License-Identifier: GPL-2.0 + +# board-specific dtc flags @@ -437,12 +455,14 @@ index 27ca1ca6e..09460432d 100644 +DTC_FLAGS_stm32746g-eval += -@ +DTC_FLAGS_stm32h743i-eval += -@ +DTC_FLAGS_stm32h743i-disco += -@ -+DTC_FLAGS_stm32mp135d-dk += -@ -+DTC_FLAGS_stm32mp135d-dk-a7-examples += -@ +DTC_FLAGS_stm32mp135f-dk += -@ +DTC_FLAGS_stm32mp135f-dk-a7-examples +=-@ +DTC_FLAGS_stm32mp157a-dk1 += -@ ++DTC_FLAGS_stm32mp157a-dk1-a7-examples += -@ ++DTC_FLAGS_stm32mp157a-dk1-m4-examples += -@ +DTC_FLAGS_stm32mp157d-dk1 += -@ ++DTC_FLAGS_stm32mp157d-dk1-a7-examples += -@ ++DTC_FLAGS_stm32mp157d-dk1-m4-examples += -@ +DTC_FLAGS_stm32mp157c-dk2 += -@ +DTC_FLAGS_stm32mp157f-dk2 += -@ +DTC_FLAGS_stm32mp157c-dk2-a7-examples += -@ @@ -465,23 +485,25 @@ index 27ca1ca6e..09460432d 100644 dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -1114,10 +1150,15 @@ dtb-$(CONFIG_ARCH_STM32) += \ +@@ -1115,10 +1153,17 @@ dtb-$(CONFIG_ARCH_STM32) += \ stm32h743i-eval.dtb \ stm32h743i-disco.dtb \ stm32h750i-art-pi.dtb \ -+ stm32mp135d-dk.dtb \ -+ stm32mp135d-dk-a7-examples.dtb \ + stm32mp135f-dk.dtb \ + stm32mp135f-dk-a7-examples.dtb \ stm32mp153c-dhcom-drc02.dtb \ stm32mp157a-avenger96.dtb \ stm32mp157a-dhcor-avenger96.dtb \ stm32mp157a-dk1.dtb \ ++ stm32mp157a-dk1-a7-examples.dtb \ ++ stm32mp157a-dk1-m4-examples.dtb \ + stm32mp157d-dk1.dtb \ ++ stm32mp157d-dk1-a7-examples.dtb \ ++ stm32mp157d-dk1-m4-examples.dtb \ stm32mp157a-iot-box.dtb \ stm32mp157a-microgea-stm32mp1-microdev2.0.dtb \ stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dtb \ -@@ -1127,8 +1168,23 @@ dtb-$(CONFIG_ARCH_STM32) += \ +@@ -1128,8 +1173,23 @@ dtb-$(CONFIG_ARCH_STM32) += \ stm32mp157c-dhcom-pdk2.dtb \ stm32mp157c-dhcom-picoitx.dtb \ stm32mp157c-dk2.dtb \ @@ -507,7 +529,7 @@ index 27ca1ca6e..09460432d 100644 dtb-$(CONFIG_MACH_SUN4I) += \ diff --git a/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi new file mode 100644 -index 000000000..b8d53065a +index 000000000000..b8d53065ae6a --- /dev/null +++ b/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi @@ -0,0 +1,644 @@ @@ -1157,10 +1179,10 @@ index 000000000..b8d53065a +}; diff --git a/arch/arm/boot/dts/stm32mp131.dtsi b/arch/arm/boot/dts/stm32mp131.dtsi new file mode 100644 -index 000000000..d19cf6940 +index 000000000000..8121ddc97f10 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp131.dtsi -@@ -0,0 +1,1664 @@ +@@ -0,0 +1,1742 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021 - All Rights Reserved @@ -1187,6 +1209,7 @@ index 000000000..d19cf6940 + clock-names = "cpu"; + nvmem-cells = <&part_number_otp>; + nvmem-cell-names = "part_number"; ++ #cooling-cells = <2>; + }; + }; + @@ -1211,11 +1234,13 @@ index 000000000..d19cf6940 + }; + + firmware { -+ optee { ++ optee: optee { + method = "smc"; + compatible = "linaro,optee-tz"; + interrupt-parent = <&intc>; + interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; + }; + + scmi: scmi { @@ -1311,7 +1336,12 @@ index 000000000..d19cf6940 + thermal-sensors = <&dts>; + + trips { -+ cpu-crit { ++ cpu_alert: cpu-alert0 { ++ temperature = <95000>; ++ hysteresis = <10000>; ++ type = "passive"; ++ }; ++ cpu_crit: cpu-crit0 { + temperature = <120000>; + hysteresis = <0>; + type = "critical"; @@ -1319,6 +1349,10 @@ index 000000000..d19cf6940 + }; + + cooling-maps { ++ map0 { ++ trip = <&cpu_alert>; ++ cooling-device = <&cpu0 1 1>; ++ }; + }; + }; + }; @@ -1999,6 +2033,8 @@ index 000000000..d19cf6940 + adc2: adc@0 { + compatible = "st,stm32mp13-adc"; + #io-channel-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; + reg = <0x0>; + interrupt-parent = <&adc_2>; + interrupts = <0>; @@ -2007,6 +2043,23 @@ index 000000000..d19cf6940 + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + status = "disabled"; ++ ++ channel@13 { ++ reg = <13>; ++ label = "vrefint"; ++ }; ++ channel@14 { ++ reg = <14>; ++ label = "vddcore"; ++ }; ++ channel@16 { ++ reg = <16>; ++ label = "vddcpu"; ++ }; ++ channel@17 { ++ reg = <17>; ++ label = "vddq_ddr"; ++ }; + }; + }; + @@ -2315,10 +2368,59 @@ index 000000000..d19cf6940 + }; + + exti: interrupt-controller@5000d000 { -+ compatible = "st,stm32mp13-exti", "syscon"; ++ compatible = "st,stm32mp1-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; ++ #address-cells = <0>; + reg = <0x5000d000 0x400>; ++ ++ exti-interrupt-map { ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ interrupt-map-mask = <0xffffffff 0>; ++ interrupt-map = ++ <0 0 &intc GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, ++ <1 0 &intc GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, ++ <2 0 &intc GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, ++ <3 0 &intc GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, ++ <4 0 &intc GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, ++ <5 0 &intc GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>, ++ <6 0 &intc GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, ++ <7 0 &intc GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, ++ <8 0 &intc GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, ++ <9 0 &intc GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, ++ <10 0 &intc GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>, ++ <11 0 &intc GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>, ++ <12 0 &intc GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>, ++ <13 0 &intc GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>, ++ <14 0 &intc GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, ++ <15 0 &intc GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, ++ <16 0 &intc GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, ++ <19 0 &intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, ++ <21 0 &intc GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>, ++ <22 0 &intc GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>, ++ <23 0 &intc GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>, ++ <24 0 &intc GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>, ++ <25 0 &intc GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, ++ <26 0 &intc GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>, ++ <27 0 &intc GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, ++ <28 0 &intc GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, ++ <29 0 &intc GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, ++ <30 0 &intc GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, ++ <31 0 &intc GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, ++ <32 0 &intc GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>, ++ <33 0 &intc GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, ++ <42 0 &intc GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>, ++ <43 0 &intc GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>, ++ <44 0 &intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, ++ <47 0 &intc GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, ++ <48 0 &intc GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, ++ <50 0 &intc GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, ++ <52 0 &intc GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, ++ <53 0 &intc GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, ++ <68 0 &intc GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>, ++ <70 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; ++ }; + }; + + syscfg: syscon@50020000 { @@ -2569,12 +2671,6 @@ index 000000000..d19cf6940 + status = "disabled"; + }; + -+ stmmac_axi_config_0: stmmac-axi-config { -+ snps,wr_osr_lmt = <0x7>; -+ snps,rd_osr_lmt = <0x7>; -+ snps,blen = <0 0 0 0 16 8 4>; -+ }; -+ + eth1: eth1@5800a000 { + compatible = "snps,dwmac-4.20a", "st,stm32mp13-dwmac"; + reg = <0x5800a000 0x2000>; @@ -2595,11 +2691,15 @@ index 000000000..d19cf6940 + st,syscon = <&syscfg 0x4 0xff0000>; + snps,mixed-burst; + snps,pbl = <2>; -+ snps,axi-config = <&stmmac_axi_config_0>; ++ snps,axi-config = <&stmmac_axi_config_1>; + snps,tso; -+ power-domains = <&pd_core>; -+ wakeup-source; + status = "disabled"; ++ ++ stmmac_axi_config_1: stmmac-axi-config { ++ snps,wr_osr_lmt = <0x7>; ++ snps,rd_osr_lmt = <0x7>; ++ snps,blen = <0 0 0 0 16 8 4>; ++ }; + }; + + usbh_ohci: usbh-ohci@5800c000 { @@ -2706,7 +2806,7 @@ index 000000000..d19cf6940 + * Break node order to solve dependency probe issue between + * pinctrl and exti. + */ -+ pinctrl: pin-controller@50002000 { ++ pinctrl: pinctrl@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp135-pinctrl"; @@ -2827,10 +2927,10 @@ index 000000000..d19cf6940 +}; diff --git a/arch/arm/boot/dts/stm32mp133.dtsi b/arch/arm/boot/dts/stm32mp133.dtsi new file mode 100644 -index 000000000..e00c30cb6 +index 000000000000..b46e38913643 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp133.dtsi -@@ -0,0 +1,87 @@ +@@ -0,0 +1,100 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021 - All Rights Reserved @@ -2856,6 +2956,8 @@ index 000000000..e00c30cb6 + adc1: adc@0 { + compatible = "st,stm32mp13-adc"; + #io-channel-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; + reg = <0x0>; + interrupt-parent = <&adc_1>; + interrupts = <0>; @@ -2864,6 +2966,11 @@ index 000000000..e00c30cb6 + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; + status = "disabled"; ++ ++ channel@18 { ++ reg = <18>; ++ label = "vrefint"; ++ }; + }; + }; + @@ -2912,15 +3019,21 @@ index 000000000..e00c30cb6 + st,syscon = <&syscfg 0x4 0xff000000>; + snps,mixed-burst; + snps,pbl = <2>; -+ snps,axi-config = <&stmmac_axi_config_0>; ++ snps,axi-config = <&stmmac_axi_config_2>; + snps,tso; + status = "disabled"; ++ ++ stmmac_axi_config_2: stmmac-axi-config { ++ snps,wr_osr_lmt = <0x7>; ++ snps,rd_osr_lmt = <0x7>; ++ snps,blen = <0 0 0 0 16 8 4>; ++ }; + }; + }; +}; diff --git a/arch/arm/boot/dts/stm32mp135.dtsi b/arch/arm/boot/dts/stm32mp135.dtsi new file mode 100644 -index 000000000..61052a87d +index 000000000000..61052a87d57b --- /dev/null +++ b/arch/arm/boot/dts/stm32mp135.dtsi @@ -0,0 +1,32 @@ @@ -2956,730 +3069,9 @@ index 000000000..61052a87d + }; + }; +}; -diff --git a/arch/arm/boot/dts/stm32mp135d-dk-a7-examples.dts b/arch/arm/boot/dts/stm32mp135d-dk-a7-examples.dts -new file mode 100644 -index 000000000..77f327461 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp135d-dk-a7-examples.dts -@@ -0,0 +1,22 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp135d-dk.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP135D-DK configured to run Linux A7 examples"; -+ compatible = "st,stm32mp135d-dk-a7-examples", "st,stm32mp135d-dk", "st,stm32mp135"; -+}; -+ -+&timers4 { -+ status = "okay"; -+}; -+ -+&timers8 { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/stm32mp135d-dk.dts b/arch/arm/boot/dts/stm32mp135d-dk.dts -new file mode 100644 -index 000000000..d56874fb3 ---- /dev/null -+++ b/arch/arm/boot/dts/stm32mp135d-dk.dts -@@ -0,0 +1,687 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved -+ * Author: Alexandre Torgue for STMicroelectronics. -+ */ -+ -+/dts-v1/; -+ -+#include -+#include -+#include -+#include -+#include "stm32mp135.dtsi" -+#include "stm32mp13xd.dtsi" -+#include "stm32mp13-pinctrl.dtsi" -+ -+/ { -+ model = "STMicroelectronics STM32MP135D-DK Discovery Board"; -+ compatible = "st,stm32mp135d-dk", "st,stm32mp135"; -+ -+ aliases { -+ ethernet0 = ð1; -+ ethernet1 = ð2; -+ serial0 = &uart4; -+ serial1 = &usart1; -+ serial2 = &uart8; -+ serial3 = &usart2; -+ }; -+ -+ chosen { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ stdout-path = "serial0:115200n8"; -+ -+ framebuffer { -+ compatible = "simple-framebuffer"; -+ clocks = <&rcc LTDC_PX>; -+ status = "disabled"; -+ }; -+ }; -+ -+ clocks { -+ clk_ext_camera: clk-ext-camera { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <24000000>; -+ }; -+ -+ clk_mco1: clk-mco1 { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <24000000>; -+ }; -+ }; -+ -+ memory@c0000000 { -+ device_type = "memory"; -+ reg = <0xc0000000 0x20000000>; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ -+ user-pa13 { -+ label = "User-PA13"; -+ linux,code = ; -+ gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; -+ }; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led-blue { -+ function = LED_FUNCTION_HEARTBEAT; -+ color = ; -+ gpios = <&gpioa 14 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "heartbeat"; -+ default-state = "off"; -+ }; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ optee_framebuffer@dd000000 { -+ reg = <0xdd000000 0x1000000>; -+ no-map; -+ }; -+ -+ optee@de000000 { -+ reg = <0xde000000 0x2000000>; -+ no-map; -+ }; -+ }; -+ -+ v3v3_ao: v3v3_ao { -+ compatible = "regulator-fixed"; -+ regulator-name = "v3v3_ao"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ panel_backlight: panel-backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&gpioe 12 GPIO_ACTIVE_HIGH>; -+ default-on; -+ default-brightness-level = <0>; -+ status = "okay"; -+ }; -+ -+ panel_rgb: panel-rgb { -+ compatible = "rocktech,rk043fn48h", "panel-dpi"; -+ enable-gpios = <&gpioi 7 GPIO_ACTIVE_HIGH>; -+ backlight = <&panel_backlight>; -+ power-supply = <&scmi_v3v3_sw>; -+ data-mapping = "bgr666"; -+ status = "okay"; -+ -+ width-mm = <105>; -+ height-mm = <67>; -+ -+ port { -+ panel_in_rgb: endpoint { -+ remote-endpoint = <<dc_out_rgb>; -+ }; -+ }; -+ -+ panel-timing { -+ clock-frequency = <10000000>; -+ hactive = <480>; -+ vactive = <272>; -+ hsync-len = <52>; -+ hfront-porch = <10>; -+ hback-porch = <10>; -+ vsync-len = <10>; -+ vfront-porch = <10>; -+ vback-porch = <10>; -+ hsync-active = <0>; -+ vsync-active = <0>; -+ de-active = <1>; -+ pixelclk-active = <1>; -+ }; -+ }; -+ -+ wifi_pwrseq: wifi-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ reset-gpios = <&mcp23017 11 GPIO_ACTIVE_LOW>; -+ }; -+}; -+ -+&adc_1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&adc1_usb_cc_pins_a>; -+ vdda-supply = <&scmi_vdd_adc>; -+ vref-supply = <&scmi_vdd_adc>; -+ status = "okay"; -+ adc1: adc@0 { -+ /* -+ * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in6 & in12. -+ * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: -+ * 5 * (5.1 + 47kOhms) * 5pF => 1.3us. -+ * Use arbitrary margin here (e.g. 5us). -+ */ -+ st,min-sample-time-nsecs = <5000>; -+ /* USB Type-C CC1 & CC2 */ -+ st,adc-channels = <6 12>; -+ status = "okay"; -+ }; -+}; -+ -+&crc1 { -+ status = "okay"; -+}; -+ -+&dcmipp { -+ status = "okay"; -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&dcmipp_pins_a>; -+ pinctrl-1 = <&dcmipp_sleep_pins_a>; -+ port { -+ dcmipp_0: endpoint { -+ remote-endpoint = <&mipid02_2>; -+ bus-width = <8>; -+ hsync-active = <0>; -+ vsync-active = <0>; -+ pclk-sample = <0>; -+ pclk-max-frequency = <120000000>; -+ }; -+ }; -+}; -+ -+&dma1 { -+ sram = <&dma_pool>; -+}; -+ -+&dma2 { -+ sram = <&dma_pool>; -+}; -+ -+&dts { -+ status = "okay"; -+}; -+ -+ð1 { -+ status = "okay"; -+ pinctrl-0 = <ð1_rmii_pins_a>; -+ pinctrl-1 = <ð1_rmii_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ phy-mode = "rmii"; -+ max-speed = <100>; -+ phy-handle = <&phy0_eth1>; -+ nvmem-cells = <ðernet_mac1_address>; -+ nvmem-cell-names = "mac-address"; -+ -+ mdio1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "snps,dwmac-mdio"; -+ -+ phy0_eth1: ethernet-phy@0 { -+ compatible = "ethernet-phy-id0007.c131"; -+ reset-gpios = <&mcp23017 9 GPIO_ACTIVE_LOW>; -+ reg = <0>; -+ interrupt-parent = <&gpioi>; -+ interrupts = <3 IRQ_TYPE_EDGE_RISING>; -+ }; -+ }; -+}; -+ -+ð2 { -+ status = "okay"; -+ pinctrl-0 = <ð2_rmii_pins_a>; -+ pinctrl-1 = <ð2_rmii_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ phy-mode = "rmii"; -+ max-speed = <100>; -+ phy-handle = <&phy0_eth2>; -+ st,ext-phyclk; -+ phy-supply = <&scmi_v3v3_sw>; -+ nvmem-cells = <ðernet_mac2_address>; -+ nvmem-cell-names = "mac-address"; -+ -+ mdio1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "snps,dwmac-mdio"; -+ phy0_eth2: ethernet-phy@0 { -+ compatible = "ethernet-phy-id0007.c131"; -+ reset-gpios = <&mcp23017 10 GPIO_ACTIVE_LOW>; -+ reg = <0>; -+ }; -+ }; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c1_pins_a>; -+ pinctrl-1 = <&i2c1_sleep_pins_a>; -+ i2c-scl-rising-time-ns = <96>; -+ i2c-scl-falling-time-ns = <3>; -+ clock-frequency = <1000000>; -+ status = "okay"; -+ /* spare dmas for other usage */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ -+ mcp23017: pinctrl@21 { -+ compatible = "microchip,mcp23017"; -+ reg = <0x21>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-parent = <&gpiog>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mcp23017_pins_a>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ microchip,irq-mirror; -+ }; -+ -+ stm32g0@53 { -+ compatible = "st,stm32g0-typec"; -+ reg = <0x53>; -+ /* Alert pin on PI2 */ -+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-parent = <&gpioi>; -+ /* Internal pull-up on PI2 */ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&stm32g0_intn_pins_a>; -+ firmware-name = "stm32g0-ucsi.mp135f-dk.fw"; -+ power-domains = <&pd_core>; -+ wakeup-source; -+ connector { -+ compatible = "usb-c-connector"; -+ label = "USB-C"; -+ -+ port { -+ con_usb_c_g0_ep: endpoint { -+ remote-endpoint = <&usbotg_hs_ep>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&i2c5 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&i2c5_pins_a>; -+ pinctrl-1 = <&i2c5_sleep_pins_a>; -+ i2c-scl-rising-time-ns = <170>; -+ i2c-scl-falling-time-ns = <5>; -+ clock-frequency = <400000>; -+ status = "okay"; -+ /* spare dmas for other usage */ -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ -+ gc2145: gc2145@3c { -+ compatible = "galaxycore,gc2145"; -+ reg = <0x3c>; -+ clocks = <&clk_ext_camera>; -+ IOVDD-supply = <&scmi_v3v3_sw>; -+ AVDD-supply = <&scmi_v3v3_sw>; -+ DVDD-supply = <&scmi_v3v3_sw>; -+ powerdown-gpios = <&mcp23017 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; -+ reset-gpios = <&mcp23017 4 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; -+ status = "okay"; -+ -+ port { -+ gc2145_ep: endpoint { -+ remote-endpoint = <&mipid02_0>; -+ clock-lanes = <0>; -+ data-lanes = <1 2>; -+ }; -+ }; -+ }; -+ -+ goodix: goodix_ts@5d { -+ compatible = "goodix,gt911"; -+ reg = <0x5d>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&goodix_pins_a>; -+ interrupt-parent = <&gpiof>; -+ interrupts = <5 IRQ_TYPE_EDGE_FALLING>; -+ reset-gpios = <&gpioh 2 GPIO_ACTIVE_LOW>; -+ AVDD28-supply = <&scmi_v3v3_sw>; -+ VDDIO-supply = <&scmi_v3v3_sw>; -+ touchscreen-size-x = <480>; -+ touchscreen-size-y = <272>; -+ status = "okay" ; -+ }; -+ -+ ov5640: camera@3c { -+ compatible = "ovti,ov5640"; -+ reg = <0x3c>; -+ clocks = <&clk_ext_camera>; -+ clock-names = "xclk"; -+ DOVDD-supply = <&scmi_v3v3_sw>; -+ status = "disabled"; -+ powerdown-gpios = <&mcp23017 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; -+ reset-gpios = <&mcp23017 4 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; -+ -+ port { -+ ov5640_0: endpoint { -+ clock-lanes = <0>; -+ data-lanes = <1 2>; -+ }; -+ }; -+ }; -+ -+ stmipi: stmipi@14 { -+ compatible = "st,st-mipid02"; -+ reg = <0x14>; -+ status = "okay"; -+ clocks = <&clk_mco1>; -+ clock-names = "xclk"; -+ VDDE-supply = <&scmi_v1v8_periph>; -+ VDDIN-supply = <&scmi_v1v8_periph>; -+ reset-gpios = <&mcp23017 2 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ port@0 { -+ reg = <0>; -+ -+ mipid02_0: endpoint { -+ data-lanes = <1 2>; -+ lane-polarities = <0 0 0>; -+ remote-endpoint = <&gc2145_ep>; -+ }; -+ }; -+ port@2 { -+ reg = <2>; -+ -+ mipid02_2: endpoint { -+ bus-width = <8>; -+ hsync-active = <0>; -+ vsync-active = <0>; -+ pclk-sample = <0>; -+ remote-endpoint = <&dcmipp_0>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&iwdg2 { -+ timeout-sec = <32>; -+ status = "okay"; -+}; -+ -+<dc { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <<dc_pins_a>; -+ pinctrl-1 = <<dc_sleep_pins_a>; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ltdc_out_rgb: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&panel_in_rgb>; -+ }; -+ }; -+}; -+ -+&rtc { -+ st,lsco = ; -+ pinctrl-0 = <&rtc_out2_rmp_pins_a>; -+ pinctrl-names = "default"; -+ status = "okay"; -+}; -+ -+&scmi_regu { -+ scmi_vddcpu: voltd-vddcpu { -+ voltd-name = "vddcpu"; -+ regulator-name = "vddcpu"; -+ }; -+ scmi_vdd: voltd-vdd { -+ voltd-name = "vdd"; -+ regulator-name = "vdd"; -+ }; -+ scmi_vddcore: voltd-vddcore { -+ voltd-name = "vddcore"; -+ regulator-name = "vddcore"; -+ }; -+ scmi_vdd_adc: voltd-vdd_adc { -+ voltd-name = "vdd_adc"; -+ regulator-name = "vdd_adc"; -+ }; -+ scmi_vdd_usb: voltd-vdd_usb { -+ voltd-name = "vdd_usb"; -+ regulator-name = "vdd_usb"; -+ }; -+ scmi_vdd_sd: voltd-vdd_sd { -+ voltd-name = "vdd_sd"; -+ regulator-name = "vdd_sd"; -+ }; -+ scmi_v1v8_periph: voltd-v1v8_periph { -+ voltd-name = "v1v8_periph"; -+ regulator-name = "v1v8_periph"; -+ }; -+ scmi_v3v3_sw: voltd-v3v3_sw { -+ voltd-name = "v3v3_sw"; -+ regulator-name = "v3v3_sw"; -+ }; -+}; -+ -+&sdmmc1 { -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_clk_pins_a>; -+ pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_clk_pins_a>; -+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>; -+ cd-gpios = <&gpioh 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; -+ disable-wp; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&scmi_vdd_sd>; -+ status = "okay"; -+}; -+ -+/* Wifi */ -+&sdmmc2 { -+ arm,primecell-periphid = <0x10153180>; -+ pinctrl-names = "default", "opendrain", "sleep"; -+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_clk_pins_a>; -+ pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_clk_pins_a>; -+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>; -+ non-removable; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&v3v3_ao>; -+ mmc-pwrseq = <&wifi_pwrseq>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ brcmf: bcrmf@1 { -+ reg = <1>; -+ compatible = "brcm,bcm4329-fmac"; -+ }; -+}; -+ -+&spi5 { -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&spi5_pins_a>; -+ pinctrl-1 = <&spi5_sleep_pins_a>; -+ status = "disabled"; -+}; -+ -+&sram { -+ dma_pool: dma-sram@0 { -+ reg = <0x0 0x4000>; -+ pool; -+ }; -+}; -+ -+&timers3 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm3_pins_a>; -+ pinctrl-1 = <&pwm3_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@2 { -+ status = "okay"; -+ }; -+}; -+ -+&timers4 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm4_pins_a>; -+ pinctrl-1 = <&pwm4_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@3 { -+ status = "okay"; -+ }; -+}; -+ -+&timers8 { -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm8_pins_a>; -+ pinctrl-1 = <&pwm8_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@7 { -+ status = "okay"; -+ }; -+}; -+ -+&timers14 { -+ status = "disabled"; -+ pwm { -+ pinctrl-0 = <&pwm14_pins_a>; -+ pinctrl-1 = <&pwm14_sleep_pins_a>; -+ pinctrl-names = "default", "sleep"; -+ status = "okay"; -+ }; -+ timer@13 { -+ status = "okay"; -+ }; -+}; -+ -+&uart4 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&uart4_pins_a>; -+ pinctrl-1 = <&uart4_sleep_pins_a>; -+ pinctrl-2 = <&uart4_idle_pins_a>; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "okay"; -+}; -+ -+&uart8 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&uart8_pins_a>; -+ pinctrl-1 = <&uart8_sleep_pins_a>; -+ pinctrl-2 = <&uart8_idle_pins_a>; -+ /delete-property/dmas; -+ /delete-property/dma-names; -+ status = "disabled"; -+}; -+ -+&usart1 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&usart1_pins_a>; -+ pinctrl-1 = <&usart1_sleep_pins_a>; -+ pinctrl-2 = <&usart1_idle_pins_a>; -+ uart-has-rtscts; -+ status = "disabled"; -+}; -+ -+/* Bluetooth */ -+&usart2 { -+ pinctrl-names = "default", "sleep", "idle"; -+ pinctrl-0 = <&usart2_pins_a>; -+ pinctrl-1 = <&usart2_sleep_pins_a>; -+ pinctrl-2 = <&usart2_idle_pins_a>; -+ uart-has-rtscts; -+ status = "okay"; -+ -+ bluetooth { -+ shutdown-gpios = <&mcp23017 13 GPIO_ACTIVE_HIGH>; -+ compatible = "brcm,bcm43438-bt"; -+ max-speed = <3000000>; -+ vbat-supply = <&v3v3_ao>; -+ vddio-supply = <&v3v3_ao>; -+ }; -+}; -+ -+&usbh_ehci { -+ phys = <&usbphyc_port0>; -+ status = "okay"; -+}; -+ -+&usbotg_hs { -+ phys = <&usbphyc_port1 0>; -+ phy-names = "usb2-phy"; -+ usb-role-switch; -+ status = "okay"; -+ port { -+ usbotg_hs_ep: endpoint { -+ remote-endpoint = <&con_usb_c_g0_ep>; -+ }; -+ }; -+}; -+ -+&usbphyc { -+ status = "okay"; -+}; -+ -+&usbphyc_port0 { -+ phy-supply = <&scmi_vdd_usb>; -+ st,current-boost-microamp = <1000>; -+ st,decrease-hs-slew-rate; -+ st,tune-hs-dc-level = <2>; -+ st,enable-hs-rftime-reduction; -+ st,trim-hs-current = <11>; -+ st,trim-hs-impedance = <2>; -+ st,tune-squelch-level = <1>; -+ st,enable-hs-rx-gain-eq; -+ st,no-hs-ftime-ctrl; -+ st,no-lsfs-sc; -+ -+ /* -+ * Hack to keep hub active if wakeup source is enabled -+ * otherwise the hub will wakeup the port0 as soon as the v3v3_sw is disabled -+ */ -+ connector { -+ compatible = "usb-a-connector"; -+ vbus-supply = <&scmi_v3v3_sw>; -+ }; -+}; -+ -+&usbphyc_port1 { -+ phy-supply = <&scmi_vdd_usb>; -+ st,current-boost-microamp = <1000>; -+ st,decrease-hs-slew-rate; -+ st,tune-hs-dc-level = <2>; -+ st,enable-hs-rftime-reduction; -+ st,trim-hs-current = <11>; -+ st,trim-hs-impedance = <2>; -+ st,tune-squelch-level = <1>; -+ st,enable-hs-rx-gain-eq; -+ st,no-hs-ftime-ctrl; -+ st,no-lsfs-sc; -+}; diff --git a/arch/arm/boot/dts/stm32mp135f-dk-a7-examples.dts b/arch/arm/boot/dts/stm32mp135f-dk-a7-examples.dts new file mode 100644 -index 000000000..e7c39aa5b +index 000000000000..e7c39aa5bc69 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp135f-dk-a7-examples.dts @@ -0,0 +1,22 @@ @@ -3707,10 +3099,10 @@ index 000000000..e7c39aa5b +}; diff --git a/arch/arm/boot/dts/stm32mp135f-dk.dts b/arch/arm/boot/dts/stm32mp135f-dk.dts new file mode 100644 -index 000000000..ef2d9f137 +index 000000000000..a2735571286e --- /dev/null +++ b/arch/arm/boot/dts/stm32mp135f-dk.dts -@@ -0,0 +1,689 @@ +@@ -0,0 +1,701 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021 - All Rights Reserved @@ -3864,6 +3256,18 @@ index 000000000..ef2d9f137 + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&mcp23017 11 GPIO_ACTIVE_LOW>; + }; ++ ++ wake_up { ++ compatible = "gpio-keys"; ++ status = "okay"; ++ ++ button { ++ label = "wake-up"; ++ linux,code = ; ++ interrupts-extended = <&optee 0>; ++ status = "okay"; ++ }; ++ }; +}; + +&adc_1 { @@ -3873,16 +3277,21 @@ index 000000000..ef2d9f137 + vref-supply = <&scmi_vdd_adc>; + status = "okay"; + adc1: adc@0 { ++ status = "okay"; + /* + * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in6 & in12. + * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: + * 5 * (5.1 + 47kOhms) * 5pF => 1.3us. + * Use arbitrary margin here (e.g. 5us). + */ -+ st,min-sample-time-nsecs = <5000>; -+ /* USB Type-C CC1 & CC2 */ -+ st,adc-channels = <6 12>; -+ status = "okay"; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@12 { ++ reg = <12>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; +}; + @@ -3943,6 +3352,7 @@ index 000000000..ef2d9f137 + compatible = "ethernet-phy-id0007.c131"; + reset-gpios = <&mcp23017 9 GPIO_ACTIVE_LOW>; + reg = <0>; ++ wakeup-source; + }; + }; +}; @@ -4001,14 +3411,9 @@ index 000000000..ef2d9f137 + stm32g0@53 { + compatible = "st,stm32g0-typec"; + reg = <0x53>; -+ /* Alert pin on PI2 */ -+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-parent = <&gpioi>; -+ /* Internal pull-up on PI2 */ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&stm32g0_intn_pins_a>; ++ /* Alert pin on PI2 (PWR wakeup pin), managed by optee */ ++ interrupts-extended = <&optee 1>; + firmware-name = "stm32g0-ucsi.mp135f-dk.fw"; -+ power-domains = <&pd_core>; + wakeup-source; + connector { + compatible = "usb-c-connector"; @@ -4067,7 +3472,7 @@ index 000000000..ef2d9f137 + VDDIO-supply = <&scmi_v3v3_sw>; + touchscreen-size-x = <480>; + touchscreen-size-y = <272>; -+ status = "okay" ; ++ status = "okay"; + }; + + ov5640: camera@3c { @@ -4204,7 +3609,6 @@ index 000000000..ef2d9f137 + +/* Wifi */ +&sdmmc2 { -+ arm,primecell-periphid = <0x10153180>; + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_clk_pins_a>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_clk_pins_a>; @@ -4402,7 +3806,7 @@ index 000000000..ef2d9f137 +}; diff --git a/arch/arm/boot/dts/stm32mp13xa.dtsi b/arch/arm/boot/dts/stm32mp13xa.dtsi new file mode 100644 -index 000000000..20e52cd27 +index 000000000000..20e52cd27154 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp13xa.dtsi @@ -0,0 +1,5 @@ @@ -4413,10 +3817,10 @@ index 000000000..20e52cd27 + */ diff --git a/arch/arm/boot/dts/stm32mp13xc.dtsi b/arch/arm/boot/dts/stm32mp13xc.dtsi new file mode 100644 -index 000000000..4d00e7592 +index 000000000000..fc4ba53fecaa --- /dev/null +++ b/arch/arm/boot/dts/stm32mp13xc.dtsi -@@ -0,0 +1,18 @@ +@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021 - All Rights Reserved @@ -4431,13 +3835,16 @@ index 000000000..4d00e7592 + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; ++ dmas = <&mdma 28 0x0 0x400202 0x0 0x0 0x0>, ++ <&mdma 29 0x3 0x400808 0x0 0x0 0x0>; ++ dma-names = "in", "out"; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/boot/dts/stm32mp13xd.dtsi b/arch/arm/boot/dts/stm32mp13xd.dtsi new file mode 100644 -index 000000000..aa8e23568 +index 000000000000..aa8e235686a7 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp13xd.dtsi @@ -0,0 +1,5 @@ @@ -4448,10 +3855,10 @@ index 000000000..aa8e23568 + */ diff --git a/arch/arm/boot/dts/stm32mp13xf.dtsi b/arch/arm/boot/dts/stm32mp13xf.dtsi new file mode 100644 -index 000000000..4d00e7592 +index 000000000000..fc4ba53fecaa --- /dev/null +++ b/arch/arm/boot/dts/stm32mp13xf.dtsi -@@ -0,0 +1,18 @@ +@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021 - All Rights Reserved @@ -4466,13 +3873,16 @@ index 000000000..4d00e7592 + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; ++ dmas = <&mdma 28 0x0 0x400202 0x0 0x0 0x0>, ++ <&mdma 29 0x3 0x400808 0x0 0x0 0x0>; ++ dma-names = "in", "out"; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi new file mode 100644 -index 000000000..b4030e5c9 +index 000000000000..bfa78e50b3bc --- /dev/null +++ b/arch/arm/boot/dts/stm32mp15-m4-srm-pinctrl.dtsi @@ -0,0 +1,524 @@ @@ -4567,7 +3977,7 @@ index 000000000..b4030e5c9 + }; + }; + -+ m4_ethernet0_rgmii_pins_a: m4-rgmii-0 { ++ m4_ethernet0_rgmii_pins_a: m4-ethernet0-rgmii-0 { + pins { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ @@ -4970,18 +4380,18 @@ index 000000000..b4030e5c9 + }; + }; + -+ m4_usbotg_hs_pins_a: m4-usbotg_hs-0 { -+ pins { -+ pinmux = ; /* OTG_ID */ -+ }; -+ }; -+ + m4_usbotg_fs_dp_dm_pins_a: m4-usbotg-fs-dp-dm-0 { + pins { + pinmux = , /* OTG_FS_DM */ + ; /* OTG_FS_DP */ + }; + }; ++ ++ m4_usbotg_hs_pins_a: m4-usbotg_hs-0 { ++ pins { ++ pinmux = ; /* OTG_ID */ ++ }; ++ }; +}; + +&pinctrl_z { @@ -5002,7 +4412,7 @@ index 000000000..b4030e5c9 +}; diff --git a/arch/arm/boot/dts/stm32mp15-m4-srm.dtsi b/arch/arm/boot/dts/stm32mp15-m4-srm.dtsi new file mode 100644 -index 000000000..7fa3ca411 +index 000000000000..7fa3ca411a95 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp15-m4-srm.dtsi @@ -0,0 +1,447 @@ @@ -5454,13 +4864,14 @@ index 000000000..7fa3ca411 + }; +}; diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi -index 2ebafe27a..d2f2cc8f3 100644 +index 2ebafe27a865..43eb55cb1f55 100644 --- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi -@@ -151,6 +151,45 @@ pins { +@@ -151,7 +151,46 @@ }; }; +- ethernet0_rgmii_pins_a: rgmii-0 { + dfsdm_clkout_pins_a: dfsdm-clkout-pins-0 { + pins { + pinmux = ; /* DFSDM_CKOUT */ @@ -5500,10 +4911,74 @@ index 2ebafe27a..d2f2cc8f3 100644 + }; + }; + - ethernet0_rgmii_pins_a: rgmii-0 { ++ ethernet0_rgmii_pins_a: ethernet0-rgmii-0 { pins1 { pinmux = , /* ETH_RGMII_CLK125 */ -@@ -437,6 +476,51 @@ pins { + , /* ETH_RGMII_GTX_CLK */ +@@ -182,7 +221,7 @@ + }; + }; + +- ethernet0_rgmii_sleep_pins_a: rgmii-sleep-0 { ++ ethernet0_rgmii_sleep_pins_a: ethernet0-rgmii-sleep-0 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ +@@ -202,7 +241,7 @@ + }; + }; + +- ethernet0_rgmii_pins_b: rgmii-1 { ++ ethernet0_rgmii_pins_b: ethernet0-rgmii-1 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ +@@ -233,7 +272,7 @@ + }; + }; + +- ethernet0_rgmii_sleep_pins_b: rgmii-sleep-1 { ++ ethernet0_rgmii_sleep_pins_b: ethernet0-rgmii-sleep-1 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ +@@ -253,7 +292,7 @@ + }; + }; + +- ethernet0_rgmii_pins_c: rgmii-2 { ++ ethernet0_rgmii_pins_c: ethernet0-rgmii-2 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ +@@ -284,7 +323,7 @@ + }; + }; + +- ethernet0_rgmii_sleep_pins_c: rgmii-sleep-2 { ++ ethernet0_rgmii_sleep_pins_c: ethernet0-rgmii-sleep-2 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ +@@ -304,7 +343,7 @@ + }; + }; + +- ethernet0_rmii_pins_a: rmii-0 { ++ ethernet0_rmii_pins_a: ethernet0-rmii-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ +@@ -324,7 +363,7 @@ + }; + }; + +- ethernet0_rmii_sleep_pins_a: rmii-sleep-0 { ++ ethernet0_rmii_sleep_pins_a: ethernet0-rmii-sleep-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ +@@ -437,6 +476,51 @@ }; }; @@ -5555,20 +5030,208 @@ index 2ebafe27a..d2f2cc8f3 100644 i2c1_pins_a: i2c1-0 { pins { pinmux = , /* I2C1_SCL */ -@@ -1139,6 +1223,12 @@ pins { +@@ -861,7 +945,7 @@ }; }; -+ rtc_out2_rmp_pins_a: rtc-out2-rmp-pins-0 { +- m_can1_sleep_pins_a: m_can1-sleep-0 { ++ m_can1_sleep_pins_a: m-can1-sleep-0 { + pins { + pinmux = , /* CAN1_TX */ + ; /* CAN1_RX */ +@@ -881,7 +965,7 @@ + }; + }; + +- m_can1_sleep_pins_b: m_can1-sleep-1 { ++ m_can1_sleep_pins_b: m-can1-sleep-1 { + pins { + pinmux = , /* CAN1_TX */ + ; /* CAN1_RX */ +@@ -901,7 +985,7 @@ + }; + }; + +- m_can2_sleep_pins_a: m_can2-sleep-0 { ++ m_can2_sleep_pins_a: m-can2-sleep-0 { + pins { + pinmux = , /* CAN2_TX */ + ; /* CAN2_RX */ +@@ -1068,23 +1152,8 @@ + }; + }; + +- qspi_clk_pins_a: qspi-clk-0 { +- pins { +- pinmux = ; /* QSPI_CLK */ +- bias-disable; +- drive-push-pull; +- slew-rate = <3>; +- }; +- }; +- +- qspi_clk_sleep_pins_a: qspi-clk-sleep-0 { +- pins { +- pinmux = ; /* QSPI_CLK */ +- }; +- }; +- + qspi_bk1_pins_a: qspi-bk1-0 { +- pins1 { + pins { -+ pinmux = ; /* RTC_OUT2_RMP */ + pinmux = , /* QSPI_BK1_IO0 */ + , /* QSPI_BK1_IO1 */ + , /* QSPI_BK1_IO2 */ +@@ -1093,12 +1162,6 @@ + drive-push-pull; + slew-rate = <1>; + }; +- pins2 { +- pinmux = ; /* QSPI_BK1_NCS */ +- bias-pull-up; +- drive-push-pull; +- slew-rate = <1>; +- }; + }; + + qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 { +@@ -1106,13 +1169,12 @@ + pinmux = , /* QSPI_BK1_IO0 */ + , /* QSPI_BK1_IO1 */ + , /* QSPI_BK1_IO2 */ +- , /* QSPI_BK1_IO3 */ +- ; /* QSPI_BK1_NCS */ ++ ; /* QSPI_BK1_IO3 */ + }; + }; + + qspi_bk2_pins_a: qspi-bk2-0 { +- pins1 { ++ pins { + pinmux = , /* QSPI_BK2_IO0 */ + , /* QSPI_BK2_IO1 */ + , /* QSPI_BK2_IO2 */ +@@ -1121,7 +1183,49 @@ + drive-push-pull; + slew-rate = <1>; + }; +- pins2 { ++ }; ++ ++ qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 { ++ pins { ++ pinmux = , /* QSPI_BK2_IO0 */ ++ , /* QSPI_BK2_IO1 */ ++ , /* QSPI_BK2_IO2 */ ++ ; /* QSPI_BK2_IO3 */ + }; + }; + - sai2a_pins_a: sai2a-0 { ++ qspi_clk_pins_a: qspi-clk-0 { ++ pins { ++ pinmux = ; /* QSPI_CLK */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <3>; ++ }; ++ }; ++ ++ qspi_clk_sleep_pins_a: qspi-clk-sleep-0 { ++ pins { ++ pinmux = ; /* QSPI_CLK */ ++ }; ++ }; ++ ++ qspi_cs1_pins_a: qspi-cs1-0 { ++ pins { ++ pinmux = ; /* QSPI_BK1_NCS */ ++ bias-pull-up; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ }; ++ ++ qspi_cs1_sleep_pins_a: qspi-cs1-sleep-0 { ++ pins { ++ pinmux = ; /* QSPI_BK1_NCS */ ++ }; ++ }; ++ ++ qspi_cs2_pins_a: qspi-cs2-0 { ++ pins { + pinmux = ; /* QSPI_BK2_NCS */ + bias-pull-up; + drive-push-pull; +@@ -1129,13 +1233,15 @@ + }; + }; + +- qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 { ++ qspi_cs2_sleep_pins_a: qspi-cs2-sleep-0 { pins { - pinmux = , /* SAI2_SCK_A */ -@@ -1716,9 +1806,55 @@ pins2 { +- pinmux = , /* QSPI_BK2_IO0 */ +- , /* QSPI_BK2_IO1 */ +- , /* QSPI_BK2_IO2 */ +- , /* QSPI_BK2_IO3 */ +- ; /* QSPI_BK2_NCS */ ++ pinmux = ; /* QSPI_BK2_NCS */ ++ }; ++ }; ++ ++ rtc_out2_rmp_pins_a: rtc-out2-rmp-pins-0 { ++ pins { ++ pinmux = ; /* RTC_OUT2_RMP */ + }; + }; + +@@ -1190,7 +1296,7 @@ + }; + }; + +- sai2a_sleep_pins_c: sai2a-2 { ++ sai2a_sleep_pins_c: sai2a-sleep-2 { + pins { + pinmux = , /* SAI2_SCK_A */ + , /* SAI2_SD_A */ +@@ -1282,6 +1388,18 @@ + }; + }; + ++ sdmmc1_b4_init_pins_a: sdmmc1-b4-init-0 { ++ pins1 { ++ pinmux = , /* SDMMC1_D0 */ ++ , /* SDMMC1_D1 */ ++ , /* SDMMC1_D2 */ ++ ; /* SDMMC1_D3 */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-disable; ++ }; ++ }; ++ + sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ +@@ -1306,18 +1424,6 @@ + }; + }; + +- sdmmc1_b4_init_pins_a: sdmmc1-b4-init-0 { +- pins1 { +- pinmux = , /* SDMMC1_D0 */ +- , /* SDMMC1_D1 */ +- , /* SDMMC1_D2 */ +- ; /* SDMMC1_D3 */ +- slew-rate = <1>; +- drive-push-pull; +- bias-disable; +- }; +- }; +- + sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 { + pins { + pinmux = , /* SDMMC1_D0 */ +@@ -1716,9 +1822,55 @@ }; }; @@ -5625,7 +5288,7 @@ index 2ebafe27a..d2f2cc8f3 100644 bias-pull-up; }; }; -@@ -1737,20 +1873,20 @@ pins2 { +@@ -1737,20 +1889,20 @@ }; uart4_idle_pins_a: uart4-idle-0 { @@ -5655,7 +5318,7 @@ index 2ebafe27a..d2f2cc8f3 100644 }; uart4_pins_b: uart4-1 { -@@ -1816,7 +1952,7 @@ pins1 { +@@ -1816,7 +1968,7 @@ }; pins2 { pinmux = ; /* UART7_RX */ @@ -5664,7 +5327,7 @@ index 2ebafe27a..d2f2cc8f3 100644 }; }; -@@ -1826,7 +1962,7 @@ pins1 { +@@ -1826,7 +1978,7 @@ }; pins2 { pinmux = ; /* UART7_RX */ @@ -5673,7 +5336,16 @@ index 2ebafe27a..d2f2cc8f3 100644 }; }; -@@ -1912,7 +2048,7 @@ pins1 { +@@ -1850,7 +2002,7 @@ + }; + }; + +- uart8_rtscts_pins_a: uart8rtscts-0 { ++ uart8_rtscts_pins_a: uart8-rtscts-0 { + pins { + pinmux = , /* UART8_RTS */ + ; /* UART8_CTS */ +@@ -1912,7 +2064,7 @@ ; /* USART2_RTS */ bias-disable; drive-push-pull; @@ -5682,7 +5354,7 @@ index 2ebafe27a..d2f2cc8f3 100644 }; pins2 { pinmux = , /* USART2_RX */ -@@ -1930,7 +2066,7 @@ pins2 { +@@ -1930,7 +2082,7 @@ pinmux = ; /* USART2_RTS */ bias-disable; drive-push-pull; @@ -5691,7 +5363,7 @@ index 2ebafe27a..d2f2cc8f3 100644 }; pins3 { pinmux = ; /* USART2_RX */ -@@ -2012,7 +2148,7 @@ pins1 { +@@ -2012,7 +2164,7 @@ pins2 { pinmux = , /* USART3_RX */ ; /* USART3_CTS_NSS */ @@ -5700,7 +5372,7 @@ index 2ebafe27a..d2f2cc8f3 100644 }; }; -@@ -2029,7 +2165,7 @@ pins2 { +@@ -2029,7 +2181,7 @@ }; pins3 { pinmux = ; /* USART3_RX */ @@ -5709,7 +5381,29 @@ index 2ebafe27a..d2f2cc8f3 100644 }; }; -@@ -2120,4 +2256,12 @@ pins2 { +@@ -2042,16 +2194,16 @@ + }; + }; + +- usbotg_hs_pins_a: usbotg-hs-0 { ++ usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { + pins { +- pinmux = ; /* OTG_ID */ ++ pinmux = , /* OTG_FS_DM */ ++ ; /* OTG_FS_DP */ + }; + }; + +- usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { ++ usbotg_hs_pins_a: usbotg-hs-0 { + pins { +- pinmux = , /* OTG_FS_DM */ +- ; /* OTG_FS_DP */ ++ pinmux = ; /* OTG_ID */ + }; + }; + }; +@@ -2120,4 +2272,12 @@ bias-disable; }; }; @@ -5723,7 +5417,7 @@ index 2ebafe27a..d2f2cc8f3 100644 + }; }; diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi -index 6992a4b0b..2d403bb09 100644 +index e0d483318798..4a7d413d1679 100644 --- a/arch/arm/boot/dts/stm32mp151.dtsi +++ b/arch/arm/boot/dts/stm32mp151.dtsi @@ -5,6 +5,7 @@ @@ -5734,7 +5428,7 @@ index 6992a4b0b..2d403bb09 100644 #include / { -@@ -17,9 +18,14 @@ cpus { +@@ -17,9 +18,14 @@ cpu0: cpu@0 { compatible = "arm,cortex-a7"; @@ -5750,7 +5444,7 @@ index 6992a4b0b..2d403bb09 100644 }; }; -@@ -30,6 +36,49 @@ arm-pmu { +@@ -30,6 +36,49 @@ interrupt-parent = <&intc>; }; @@ -5800,7 +5494,7 @@ index 6992a4b0b..2d403bb09 100644 psci { compatible = "arm,psci-1.0"; method = "smc"; -@@ -45,45 +94,13 @@ intc: interrupt-controller@a0021000 { +@@ -45,45 +94,13 @@ timer { compatible = "arm,armv7-timer"; @@ -5850,7 +5544,7 @@ index 6992a4b0b..2d403bb09 100644 thermal-zones { cpu_thermal: cpu-thermal { polling-delay-passive = <0>; -@@ -91,12 +108,6 @@ cpu_thermal: cpu-thermal { +@@ -91,12 +108,6 @@ thermal-sensors = <&dts>; trips { @@ -5863,7 +5557,7 @@ index 6992a4b0b..2d403bb09 100644 cpu-crit { temperature = <120000>; hysteresis = <0>; -@@ -115,6 +126,26 @@ booster: regulator-booster { +@@ -115,6 +126,26 @@ status = "disabled"; }; @@ -5890,7 +5584,7 @@ index 6992a4b0b..2d403bb09 100644 soc { compatible = "simple-bus"; #address-cells = <1>; -@@ -122,6 +153,14 @@ soc { +@@ -122,6 +153,14 @@ interrupt-parent = <&intc>; ranges; @@ -5905,7 +5599,7 @@ index 6992a4b0b..2d403bb09 100644 timers2: timer@40000000 { #address-cells = <1>; #size-cells = <0>; -@@ -129,11 +168,11 @@ timers2: timer@40000000 { +@@ -129,11 +168,11 @@ reg = <0x40000000 0x400>; clocks = <&rcc TIM2_K>; clock-names = "int"; @@ -5922,7 +5616,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "ch2", "ch3", "ch4", "up"; status = "disabled"; -@@ -162,12 +201,12 @@ timers3: timer@40001000 { +@@ -162,12 +201,12 @@ reg = <0x40001000 0x400>; clocks = <&rcc TIM3_K>; clock-names = "int"; @@ -5941,7 +5635,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; status = "disabled"; -@@ -196,10 +235,10 @@ timers4: timer@40002000 { +@@ -196,10 +235,10 @@ reg = <0x40002000 0x400>; clocks = <&rcc TIM4_K>; clock-names = "int"; @@ -5956,7 +5650,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "ch2", "ch3", "ch4"; status = "disabled"; -@@ -228,12 +267,12 @@ timers5: timer@40003000 { +@@ -228,12 +267,12 @@ reg = <0x40003000 0x400>; clocks = <&rcc TIM5_K>; clock-names = "int"; @@ -5975,7 +5669,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; status = "disabled"; -@@ -262,7 +301,7 @@ timers6: timer@40004000 { +@@ -262,7 +301,7 @@ reg = <0x40004000 0x400>; clocks = <&rcc TIM6_K>; clock-names = "int"; @@ -5984,7 +5678,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "up"; status = "disabled"; -@@ -280,7 +319,7 @@ timers7: timer@40005000 { +@@ -280,7 +319,7 @@ reg = <0x40005000 0x400>; clocks = <&rcc TIM7_K>; clock-names = "int"; @@ -5993,7 +5687,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "up"; status = "disabled"; -@@ -365,6 +404,7 @@ lptimer1: timer@40009000 { +@@ -365,6 +404,7 @@ interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM1_K>; clock-names = "mux"; @@ -6001,7 +5695,7 @@ index 6992a4b0b..2d403bb09 100644 wakeup-source; status = "disabled"; -@@ -384,6 +424,11 @@ counter { +@@ -384,6 +424,22 @@ compatible = "st,stm32-lptimer-counter"; status = "disabled"; }; @@ -6010,10 +5704,21 @@ index 6992a4b0b..2d403bb09 100644 + compatible = "st,stm32-lptimer-timer"; + status = "disabled"; + }; ++ }; ++ ++ i2s2: audio-controller@4000b000 { ++ compatible = "st,stm32h7-i2s"; ++ #sound-dai-cells = <0>; ++ reg = <0x4000b000 0x400>; ++ interrupts = ; ++ dmas = <&dmamux1 39 0x400 0x01>, ++ <&dmamux1 40 0x400 0x01>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; }; spi2: spi@4000b000 { -@@ -394,8 +439,8 @@ spi2: spi@4000b000 { +@@ -394,19 +450,19 @@ interrupts = ; clocks = <&rcc SPI2_K>; resets = <&rcc SPI2_R>; @@ -6024,18 +5729,41 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "rx", "tx"; status = "disabled"; }; -@@ -419,8 +464,8 @@ spi3: spi@4000c000 { - interrupts = ; - clocks = <&rcc SPI3_K>; - resets = <&rcc SPI3_R>; -- dmas = <&dmamux1 61 0x400 0x05>, -- <&dmamux1 62 0x400 0x05>; + +- i2s2: audio-controller@4000b000 { ++ i2s3: audio-controller@4000c000 { + compatible = "st,stm32h7-i2s"; + #sound-dai-cells = <0>; +- reg = <0x4000b000 0x400>; +- interrupts = ; +- dmas = <&dmamux1 39 0x400 0x01>, +- <&dmamux1 40 0x400 0x01>; ++ reg = <0x4000c000 0x400>; ++ interrupts = ; + dmas = <&dmamux1 61 0x400 0x01>, + <&dmamux1 62 0x400 0x01>; dma-names = "rx", "tx"; status = "disabled"; }; -@@ -455,6 +500,10 @@ usart2: serial@4000e000 { +@@ -419,17 +475,6 @@ + interrupts = ; + clocks = <&rcc SPI3_K>; + resets = <&rcc SPI3_R>; +- dmas = <&dmamux1 61 0x400 0x05>, +- <&dmamux1 62 0x400 0x05>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- i2s3: audio-controller@4000c000 { +- compatible = "st,stm32h7-i2s"; +- #sound-dai-cells = <0>; +- reg = <0x4000c000 0x400>; +- interrupts = ; + dmas = <&dmamux1 61 0x400 0x01>, + <&dmamux1 62 0x400 0x01>; + dma-names = "rx", "tx"; +@@ -455,6 +500,10 @@ interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc USART2_K>; wakeup-source; @@ -6046,7 +5774,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -464,6 +513,10 @@ usart3: serial@4000f000 { +@@ -464,6 +513,10 @@ interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc USART3_K>; wakeup-source; @@ -6057,7 +5785,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -473,6 +526,10 @@ uart4: serial@40010000 { +@@ -473,6 +526,10 @@ interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART4_K>; wakeup-source; @@ -6068,7 +5796,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -482,6 +539,10 @@ uart5: serial@40011000 { +@@ -482,6 +539,10 @@ interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART5_K>; wakeup-source; @@ -6079,7 +5807,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -489,12 +550,16 @@ i2c1: i2c@40012000 { +@@ -489,12 +550,16 @@ compatible = "st,stm32mp15-i2c"; reg = <0x40012000 0x400>; interrupt-names = "event", "error"; @@ -6098,7 +5826,7 @@ index 6992a4b0b..2d403bb09 100644 st,syscfg-fmp = <&syscfg 0x4 0x1>; wakeup-source; i2c-analog-filter; -@@ -505,12 +570,16 @@ i2c2: i2c@40013000 { +@@ -505,12 +570,16 @@ compatible = "st,stm32mp15-i2c"; reg = <0x40013000 0x400>; interrupt-names = "event", "error"; @@ -6117,7 +5845,7 @@ index 6992a4b0b..2d403bb09 100644 st,syscfg-fmp = <&syscfg 0x4 0x2>; wakeup-source; i2c-analog-filter; -@@ -521,12 +590,16 @@ i2c3: i2c@40014000 { +@@ -521,12 +590,16 @@ compatible = "st,stm32mp15-i2c"; reg = <0x40014000 0x400>; interrupt-names = "event", "error"; @@ -6136,7 +5864,7 @@ index 6992a4b0b..2d403bb09 100644 st,syscfg-fmp = <&syscfg 0x4 0x4>; wakeup-source; i2c-analog-filter; -@@ -537,12 +610,16 @@ i2c5: i2c@40015000 { +@@ -537,12 +610,16 @@ compatible = "st,stm32mp15-i2c"; reg = <0x40015000 0x400>; interrupt-names = "event", "error"; @@ -6155,16 +5883,7 @@ index 6992a4b0b..2d403bb09 100644 st,syscfg-fmp = <&syscfg 0x4 0x10>; wakeup-source; i2c-analog-filter; -@@ -553,7 +630,7 @@ cec: cec@40016000 { - compatible = "st,stm32-cec"; - reg = <0x40016000 0x400>; - interrupts = ; -- clocks = <&rcc CEC_K>, <&clk_lse>; -+ clocks = <&rcc CEC_K>, <&rcc CEC>; - clock-names = "cec", "hdmi-cec"; - status = "disabled"; - }; -@@ -588,6 +665,10 @@ uart7: serial@40018000 { +@@ -588,6 +665,10 @@ interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART7_K>; wakeup-source; @@ -6175,7 +5894,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -597,6 +678,10 @@ uart8: serial@40019000 { +@@ -597,6 +678,10 @@ interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART8_K>; wakeup-source; @@ -6186,7 +5905,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -607,13 +692,13 @@ timers1: timer@44000000 { +@@ -607,13 +692,13 @@ reg = <0x44000000 0x400>; clocks = <&rcc TIM1_K>; clock-names = "int"; @@ -6207,7 +5926,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig", "com"; status = "disabled"; -@@ -643,13 +728,13 @@ timers8: timer@44001000 { +@@ -643,13 +728,13 @@ reg = <0x44001000 0x400>; clocks = <&rcc TIM8_K>; clock-names = "int"; @@ -6228,7 +5947,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig", "com"; status = "disabled"; -@@ -678,6 +763,10 @@ usart6: serial@44003000 { +@@ -678,28 +763,32 @@ interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc USART6_K>; wakeup-source; @@ -6239,10 +5958,17 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -689,8 +778,8 @@ spi1: spi@44004000 { +- spi1: spi@44004000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32h7-spi"; ++ i2s1: audio-controller@44004000 { ++ compatible = "st,stm32h7-i2s"; ++ #sound-dai-cells = <0>; + reg = <0x44004000 0x400>; interrupts = ; - clocks = <&rcc SPI1_K>; - resets = <&rcc SPI1_R>; +- clocks = <&rcc SPI1_K>; +- resets = <&rcc SPI1_R>; - dmas = <&dmamux1 37 0x400 0x05>, - <&dmamux1 38 0x400 0x05>; + dmas = <&dmamux1 37 0x400 0x01>, @@ -6250,7 +5976,22 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "rx", "tx"; status = "disabled"; }; -@@ -714,8 +803,8 @@ spi4: spi@44005000 { + +- i2s1: audio-controller@44004000 { +- compatible = "st,stm32h7-i2s"; +- #sound-dai-cells = <0>; ++ spi1: spi@44004000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stm32h7-spi"; + reg = <0x44004000 0x400>; + interrupts = ; ++ clocks = <&rcc SPI1_K>; ++ resets = <&rcc SPI1_R>; + dmas = <&dmamux1 37 0x400 0x01>, + <&dmamux1 38 0x400 0x01>; + dma-names = "rx", "tx"; +@@ -714,8 +803,8 @@ interrupts = ; clocks = <&rcc SPI4_K>; resets = <&rcc SPI4_R>; @@ -6261,7 +6002,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "rx", "tx"; status = "disabled"; }; -@@ -727,10 +816,10 @@ timers15: timer@44006000 { +@@ -727,10 +816,10 @@ reg = <0x44006000 0x400>; clocks = <&rcc TIM15_K>; clock-names = "int"; @@ -6276,7 +6017,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "up", "trig", "com"; status = "disabled"; -@@ -754,8 +843,8 @@ timers16: timer@44007000 { +@@ -754,8 +843,8 @@ reg = <0x44007000 0x400>; clocks = <&rcc TIM16_K>; clock-names = "int"; @@ -6287,7 +6028,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "up"; status = "disabled"; -@@ -778,8 +867,8 @@ timers17: timer@44008000 { +@@ -778,8 +867,8 @@ reg = <0x44008000 0x400>; clocks = <&rcc TIM17_K>; clock-names = "int"; @@ -6298,7 +6039,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "ch1", "up"; status = "disabled"; -@@ -804,8 +893,8 @@ spi5: spi@44009000 { +@@ -804,8 +893,8 @@ interrupts = ; clocks = <&rcc SPI5_K>; resets = <&rcc SPI5_R>; @@ -6309,7 +6050,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "rx", "tx"; status = "disabled"; }; -@@ -990,6 +1079,15 @@ dma1: dma-controller@48000000 { +@@ -990,6 +1079,15 @@ #dma-cells = <4>; st,mem2mem; dma-requests = <8>; @@ -6325,7 +6066,7 @@ index 6992a4b0b..2d403bb09 100644 }; dma2: dma-controller@48001000 { -@@ -1008,6 +1106,15 @@ dma2: dma-controller@48001000 { +@@ -1008,6 +1106,15 @@ #dma-cells = <4>; st,mem2mem; dma-requests = <8>; @@ -6341,7 +6082,12 @@ index 6992a4b0b..2d403bb09 100644 }; dmamux1: dma-router@48002000 { -@@ -1041,7 +1148,7 @@ adc1: adc@0 { +@@ -1038,10 +1145,12 @@ + adc1: adc@0 { + compatible = "st,stm32mp1-adc"; + #io-channel-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; reg = <0x0>; interrupt-parent = <&adc>; interrupts = <0>; @@ -6350,7 +6096,12 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "rx"; status = "disabled"; }; -@@ -1052,14 +1159,16 @@ adc2: adc@100 { +@@ -1049,17 +1158,29 @@ + adc2: adc@100 { + compatible = "st,stm32mp1-adc"; + #io-channel-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; reg = <0x100>; interrupt-parent = <&adc>; interrupts = <1>; @@ -6360,6 +6111,14 @@ index 6992a4b0b..2d403bb09 100644 + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; status = "disabled"; ++ channel@13 { ++ reg = <13>; ++ label = "vrefint"; ++ }; ++ channel@14 { ++ reg = <14>; ++ label = "vddcore"; ++ }; }; }; @@ -6369,7 +6128,7 @@ index 6992a4b0b..2d403bb09 100644 arm,primecell-periphid = <0x00253180>; reg = <0x48004000 0x400>; interrupts = ; -@@ -1080,27 +1189,38 @@ usbotg_hs: usb-otg@49000000 { +@@ -1080,27 +1201,38 @@ clock-names = "otg"; resets = <&rcc USBO_R>; reset-names = "dwc2"; @@ -6413,7 +6172,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -1111,21 +1231,29 @@ dcmi: dcmi@4c006000 { +@@ -1111,21 +1243,29 @@ resets = <&rcc CAMITF_R>; clocks = <&rcc DCMI>; clock-names = "mclk"; @@ -6445,7 +6204,7 @@ index 6992a4b0b..2d403bb09 100644 reg11: reg11 { regulator-name = "reg11"; -@@ -1151,11 +1279,38 @@ pwr_mcu: pwr_mcu@50001014 { +@@ -1151,11 +1291,87 @@ reg = <0x50001014 0x4>; }; @@ -6468,23 +6227,72 @@ index 6992a4b0b..2d403bb09 100644 compatible = "st,stm32mp1-exti", "syscon"; interrupt-controller; #interrupt-cells = <2>; ++ #address-cells = <0>; reg = <0x5000d000 0x400>; + hwlocks = <&hsem 1 1>; ++ wakeup-parent = <&pwr_irq>; + -+ /* exti_pwr is an extra interrupt controller used for -+ * EXTI 55 to 60. It's mapped on pwr interrupt -+ * controller. -+ */ -+ exti_pwr: exti-pwr { -+ interrupt-controller; ++ exti-interrupt-map { ++ #address-cells = <0>; + #interrupt-cells = <2>; -+ interrupt-parent = <&pwr_irq>; -+ st,irq-number = <6>; ++ interrupt-map-mask = <0xffffffff 0>; ++ interrupt-map = ++ <0 0 &intc GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, ++ <1 0 &intc GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, ++ <2 0 &intc GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, ++ <3 0 &intc GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, ++ <4 0 &intc GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, ++ <5 0 &intc GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>, ++ <6 0 &intc GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, ++ <7 0 &intc GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, ++ <8 0 &intc GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, ++ <9 0 &intc GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, ++ <10 0 &intc GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, ++ <11 0 &intc GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, ++ <12 0 &intc GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>, ++ <13 0 &intc GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>, ++ <14 0 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, ++ <15 0 &intc GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, ++ <16 0 &intc GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, ++ <19 0 &intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, ++ <21 0 &intc GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>, ++ <22 0 &intc GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>, ++ <23 0 &intc GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, ++ <24 0 &intc GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, ++ <25 0 &intc GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, ++ <26 0 &intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, ++ <27 0 &intc GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>, ++ <28 0 &intc GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, ++ <29 0 &intc GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>, ++ <30 0 &intc GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>, ++ <31 0 &intc GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, ++ <32 0 &intc GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>, ++ <33 0 &intc GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>, ++ <43 0 &intc GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>, ++ <44 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, ++ <47 0 &intc GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>, ++ <48 0 &intc GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, ++ <50 0 &intc GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>, ++ <52 0 &intc GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>, ++ <53 0 &intc GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, ++ <54 0 &intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, ++ <55 0 &pwr_irq 0 IRQ_TYPE_EDGE_FALLING 0>, ++ <56 0 &pwr_irq 1 IRQ_TYPE_EDGE_FALLING 0>, ++ <57 0 &pwr_irq 2 IRQ_TYPE_EDGE_FALLING 0>, ++ <58 0 &pwr_irq 3 IRQ_TYPE_EDGE_FALLING 0>, ++ <59 0 &pwr_irq 4 IRQ_TYPE_EDGE_FALLING 0>, ++ <60 0 &pwr_irq 5 IRQ_TYPE_EDGE_FALLING 0>, ++ <61 0 &intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, ++ <65 0 &intc GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, ++ <68 0 &intc GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, ++ <69 0 &intc GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>, ++ <70 0 &intc GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>, ++ <73 0 &intc GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>; + }; }; syscfg: syscon@50020000 { -@@ -1172,6 +1327,7 @@ lptimer2: timer@50021000 { +@@ -1172,6 +1388,7 @@ interrupts-extended = <&exti 48 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM2_K>; clock-names = "mux"; @@ -6492,7 +6300,7 @@ index 6992a4b0b..2d403bb09 100644 wakeup-source; status = "disabled"; -@@ -1191,6 +1347,11 @@ counter { +@@ -1191,6 +1408,11 @@ compatible = "st,stm32-lptimer-counter"; status = "disabled"; }; @@ -6504,7 +6312,7 @@ index 6992a4b0b..2d403bb09 100644 }; lptimer3: timer@50022000 { -@@ -1201,6 +1362,7 @@ lptimer3: timer@50022000 { +@@ -1201,6 +1423,7 @@ interrupts-extended = <&exti 50 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM3_K>; clock-names = "mux"; @@ -6512,7 +6320,7 @@ index 6992a4b0b..2d403bb09 100644 wakeup-source; status = "disabled"; -@@ -1215,6 +1377,11 @@ trigger@2 { +@@ -1215,6 +1438,11 @@ reg = <2>; status = "disabled"; }; @@ -6524,7 +6332,7 @@ index 6992a4b0b..2d403bb09 100644 }; lptimer4: timer@50023000 { -@@ -1223,6 +1390,7 @@ lptimer4: timer@50023000 { +@@ -1223,6 +1451,7 @@ interrupts-extended = <&exti 52 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM4_K>; clock-names = "mux"; @@ -6532,7 +6340,7 @@ index 6992a4b0b..2d403bb09 100644 wakeup-source; status = "disabled"; -@@ -1231,6 +1399,11 @@ pwm { +@@ -1231,6 +1460,11 @@ #pwm-cells = <3>; status = "disabled"; }; @@ -6544,7 +6352,7 @@ index 6992a4b0b..2d403bb09 100644 }; lptimer5: timer@50024000 { -@@ -1239,6 +1412,7 @@ lptimer5: timer@50024000 { +@@ -1239,6 +1473,7 @@ interrupts-extended = <&exti 53 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM5_K>; clock-names = "mux"; @@ -6552,7 +6360,7 @@ index 6992a4b0b..2d403bb09 100644 wakeup-source; status = "disabled"; -@@ -1247,6 +1421,11 @@ pwm { +@@ -1247,6 +1482,11 @@ #pwm-cells = <3>; status = "disabled"; }; @@ -6564,7 +6372,7 @@ index 6992a4b0b..2d403bb09 100644 }; vrefbuf: vrefbuf@50025000 { -@@ -1299,13 +1478,21 @@ dts: thermal@50028000 { +@@ -1299,13 +1539,21 @@ status = "disabled"; }; @@ -6589,7 +6397,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "in"; dma-maxburst = <2>; status = "disabled"; -@@ -1314,8 +1501,8 @@ hash1: hash@54002000 { +@@ -1314,8 +1562,8 @@ rng1: rng@54003000 { compatible = "st,stm32-rng"; reg = <0x54003000 0x400>; @@ -6600,7 +6408,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -1324,8 +1511,8 @@ mdma1: dma-controller@58000000 { +@@ -1324,8 +1572,8 @@ reg = <0x58000000 0x1000>; interrupts = ; clocks = <&rcc MDMA>; @@ -6611,7 +6419,7 @@ index 6992a4b0b..2d403bb09 100644 dma-channels = <32>; dma-requests = <48>; }; -@@ -1356,9 +1543,9 @@ nand-controller@4,0 { +@@ -1356,9 +1604,9 @@ <4 0x09010000 0x1000>, <4 0x09020000 0x1000>; interrupts = ; @@ -6624,7 +6432,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "tx", "rx", "ecc"; status = "disabled"; }; -@@ -1369,8 +1556,8 @@ qspi: spi@58003000 { +@@ -1369,8 +1617,8 @@ reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; reg-names = "qspi", "qspi_mm"; interrupts = ; @@ -6635,7 +6443,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "tx", "rx"; clocks = <&rcc QSPI_K>; resets = <&rcc QSPI_R>; -@@ -1380,7 +1567,7 @@ qspi: spi@58003000 { +@@ -1380,7 +1628,7 @@ }; sdmmc1: mmc@58005000 { @@ -6644,7 +6452,7 @@ index 6992a4b0b..2d403bb09 100644 arm,primecell-periphid = <0x00253180>; reg = <0x58005000 0x1000>; interrupts = ; -@@ -1395,7 +1582,7 @@ sdmmc1: mmc@58005000 { +@@ -1395,7 +1643,7 @@ }; sdmmc2: mmc@58007000 { @@ -6653,7 +6461,7 @@ index 6992a4b0b..2d403bb09 100644 arm,primecell-periphid = <0x00253180>; reg = <0x58007000 0x1000>; interrupts = ; -@@ -1420,8 +1607,10 @@ ethernet0: ethernet@5800a000 { +@@ -1420,8 +1668,10 @@ compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; reg = <0x5800a000 0x2000>; reg-names = "stmmaceth"; @@ -6666,7 +6474,7 @@ index 6992a4b0b..2d403bb09 100644 clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx", -@@ -1441,6 +1630,7 @@ ethernet0: ethernet@5800a000 { +@@ -1441,6 +1691,7 @@ snps,axi-config = <&stmmac_axi_config_0>; snps,tso; status = "disabled"; @@ -6674,21 +6482,9 @@ index 6992a4b0b..2d403bb09 100644 stmmac_axi_config_0: stmmac-axi-config { snps,wr_osr_lmt = <0x7>; -@@ -1452,7 +1642,7 @@ stmmac_axi_config_0: stmmac-axi-config { - usbh_ohci: usb@5800c000 { - compatible = "generic-ohci"; - reg = <0x5800c000 0x1000>; -- clocks = <&rcc USBH>; -+ clocks = <&usbphyc>, <&rcc USBH>; - resets = <&rcc USBH_R>; - interrupts = ; - status = "disabled"; -@@ -1461,10 +1651,12 @@ usbh_ohci: usb@5800c000 { - usbh_ehci: usb@5800d000 { - compatible = "generic-ehci"; +@@ -1463,8 +1714,10 @@ reg = <0x5800d000 0x1000>; -- clocks = <&rcc USBH>; -+ clocks = <&usbphyc>, <&rcc USBH>; + clocks = <&usbphyc>, <&rcc USBH>; resets = <&rcc USBH_R>; - interrupts = ; + interrupts-extended = <&exti 43 IRQ_TYPE_LEVEL_HIGH>; @@ -6698,7 +6494,7 @@ index 6992a4b0b..2d403bb09 100644 status = "disabled"; }; -@@ -1487,7 +1679,7 @@ port { +@@ -1487,7 +1740,7 @@ iwdg2: watchdog@5a002000 { compatible = "st,stm32mp1-iwdg"; reg = <0x5a002000 0x400>; @@ -6707,7 +6503,7 @@ index 6992a4b0b..2d403bb09 100644 clock-names = "pclk", "lsi"; status = "disabled"; }; -@@ -1515,12 +1707,22 @@ usbphyc_port1: usb-phy@1 { +@@ -1515,12 +1768,21 @@ }; }; @@ -6725,13 +6521,12 @@ index 6992a4b0b..2d403bb09 100644 interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc USART1_K>; + clocks = <&scmi_clk CK_SCMI_USART1>; -+ resets = <&scmi_reset RST_SCMI_USART1>; wakeup-source; + power-domains = <&pd_core>; status = "disabled"; }; -@@ -1530,10 +1732,10 @@ spi6: spi@5c001000 { +@@ -1530,10 +1792,10 @@ compatible = "st,stm32h7-spi"; reg = <0x5c001000 0x400>; interrupts = ; @@ -6746,7 +6541,7 @@ index 6992a4b0b..2d403bb09 100644 dma-names = "rx", "tx"; status = "disabled"; }; -@@ -1542,12 +1744,16 @@ i2c4: i2c@5c002000 { +@@ -1542,12 +1804,16 @@ compatible = "st,stm32mp15-i2c"; reg = <0x5c002000 0x400>; interrupt-names = "event", "error"; @@ -6767,7 +6562,7 @@ index 6992a4b0b..2d403bb09 100644 st,syscfg-fmp = <&syscfg 0x4 0x8>; wakeup-source; i2c-analog-filter; -@@ -1557,35 +1763,50 @@ i2c4: i2c@5c002000 { +@@ -1557,35 +1823,50 @@ rtc: rtc@5c004000 { compatible = "st,stm32mp1-rtc"; reg = <0x5c004000 0x400>; @@ -6824,7 +6619,7 @@ index 6992a4b0b..2d403bb09 100644 st,syscfg-fmp = <&syscfg 0x4 0x20>; wakeup-source; i2c-analog-filter; -@@ -1595,6 +1816,19 @@ i2c6: i2c@5c009000 { +@@ -1595,19 +1876,33 @@ tamp: tamp@5c00a000 { compatible = "st,stm32-tamp", "syscon", "simple-mfd"; reg = <0x5c00a000 0x400>; @@ -6844,7 +6639,14 @@ index 6992a4b0b..2d403bb09 100644 }; /* -@@ -1608,6 +1842,7 @@ pinctrl: pin-controller@50002000 { + * Break node order to solve dependency probe issue between + * pinctrl and exti. + */ +- pinctrl: pin-controller@50002000 { ++ pinctrl: pinctrl@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-pinctrl"; ranges = <0 0x50002000 0xa400>; interrupt-parent = <&exti>; st,syscfg = <&exti 0x60 0xff>; @@ -6852,7 +6654,16 @@ index 6992a4b0b..2d403bb09 100644 pins-are-numbered; gpioa: gpio@50002000 { -@@ -1740,6 +1975,7 @@ pinctrl_z: pin-controller-z@54004000 { +@@ -1732,7 +2027,7 @@ + }; + }; + +- pinctrl_z: pin-controller-z@54004000 { ++ pinctrl_z: pinctrl@54004000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-z-pinctrl"; +@@ -1740,6 +2035,7 @@ pins-are-numbered; interrupt-parent = <&exti>; st,syscfg = <&exti 0x60 0xff>; @@ -6860,7 +6671,7 @@ index 6992a4b0b..2d403bb09 100644 gpioz: gpio@54004000 { gpio-controller; -@@ -1747,7 +1983,7 @@ gpioz: gpio@54004000 { +@@ -1747,7 +2043,7 @@ interrupt-controller; #interrupt-cells = <2>; reg = <0 0x400>; @@ -6869,7 +6680,7 @@ index 6992a4b0b..2d403bb09 100644 st,bank-name = "GPIOZ"; st,bank-ioport = <11>; status = "disabled"; -@@ -1769,13 +2005,18 @@ m4_rproc: m4@10000000 { +@@ -1769,13 +2065,18 @@ reg = <0x10000000 0x40000>, <0x30000000 0x40000>, <0x38000000 0x10000>; @@ -6892,10 +6703,10 @@ index 6992a4b0b..2d403bb09 100644 }; }; diff --git a/arch/arm/boot/dts/stm32mp153.dtsi b/arch/arm/boot/dts/stm32mp153.dtsi -index 1c1889b19..56ff32b4a 100644 +index 1c1889b194cf..56ff32b4a42f 100644 --- a/arch/arm/boot/dts/stm32mp153.dtsi +++ b/arch/arm/boot/dts/stm32mp153.dtsi -@@ -10,9 +10,11 @@ / { +@@ -10,9 +10,11 @@ cpus { cpu1: cpu@1 { compatible = "arm,cortex-a7"; @@ -6908,7 +6719,7 @@ index 1c1889b19..56ff32b4a 100644 }; }; -@@ -22,6 +24,13 @@ arm-pmu { +@@ -22,6 +24,13 @@ interrupt-affinity = <&cpu0>, <&cpu1>; }; @@ -6922,7 +6733,7 @@ index 1c1889b19..56ff32b4a 100644 soc { m_can1: can@4400e000 { compatible = "bosch,m_can"; -@@ -30,7 +39,7 @@ m_can1: can@4400e000 { +@@ -30,7 +39,7 @@ interrupts = , ; interrupt-names = "int0", "int1"; @@ -6931,7 +6742,7 @@ index 1c1889b19..56ff32b4a 100644 clock-names = "hclk", "cclk"; bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; status = "disabled"; -@@ -43,7 +52,7 @@ m_can2: can@4400f000 { +@@ -43,7 +52,7 @@ interrupts = , ; interrupt-names = "int0", "int1"; @@ -6941,10 +6752,10 @@ index 1c1889b19..56ff32b4a 100644 bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; status = "disabled"; diff --git a/arch/arm/boot/dts/stm32mp157.dtsi b/arch/arm/boot/dts/stm32mp157.dtsi -index 54e73ccea..1d82868f3 100644 +index 54e73ccea446..1d82868f3657 100644 --- a/arch/arm/boot/dts/stm32mp157.dtsi +++ b/arch/arm/boot/dts/stm32mp157.dtsi -@@ -20,7 +20,8 @@ gpu: gpu@59000000 { +@@ -20,7 +20,8 @@ dsi: dsi@5a000000 { compatible = "st,stm32-dsi"; reg = <0x5a000000 0x800>; @@ -6954,8 +6765,243 @@ index 54e73ccea..1d82868f3 100644 clock-names = "pclk", "ref", "px_clk"; resets = <&rcc DSI_R>; reset-names = "apb"; +diff --git a/arch/arm/boot/dts/stm32mp157a-dk1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157a-dk1-a7-examples.dts +new file mode 100644 +index 000000000000..f58b679ef127 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157a-dk1-a7-examples.dts +@@ -0,0 +1,95 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved ++ * Author: Amelie Delaunay for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157a-dk1.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157A-DK1 configured to run Linux A7 examples"; ++ compatible = "st,stm32mp157a-dk1-a7-examples", "st,stm32mp157a-dk1", "st,stm32mp157"; ++}; ++ ++&adc { ++ pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; ++ ++ adc1: adc@0 { ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@13 { ++ reg = <13>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ }; ++ ++ adc2: adc@100 { ++ /* Set IRQ mode as example. DMA is the preferred mode, yet. */ ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@2 { ++ reg = <2>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ }; ++}; ++ ++&i2c5 { ++ status = "okay"; ++}; ++ ++&timers1 { ++ status = "okay"; ++}; ++ ++&timers3 { ++ status = "okay"; ++}; ++ ++&timers4 { ++ status = "okay"; ++}; ++ ++&timers5 { ++ status = "okay"; ++}; ++ ++&timers6 { ++ status = "okay"; ++}; ++ ++&timers12 { ++ status = "okay"; ++}; ++ ++&uart7 { ++ status = "okay"; ++}; ++ ++&usart3 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157a-dk1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157a-dk1-m4-examples.dts +new file mode 100644 +index 000000000000..a6e9e1af9e16 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157a-dk1-m4-examples.dts +@@ -0,0 +1,128 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved ++ * Author: Amelie Delaunay for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157a-dk1.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157A-DK1 configured to run M4 examples"; ++ compatible = "st,stm32mp157a-dk1-m4-examples", "st,stm32mp157a-dk1", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "disabled"; ++}; ++ ++&dac { ++ status = "disabled"; ++}; ++ ++&dma2 { ++ status = "disabled"; ++}; ++ ++&dmamux1 { ++ dma-masters = <&dma1>; ++ dma-channels = <8>; ++}; ++ ++&m4_adc { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ ++&m4_dac { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_dma2 { ++ status = "okay"; ++}; ++ ++&m4_hash2 { ++ status = "okay"; ++}; ++ ++&m4_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_i2c5_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_rng2 { ++ status = "okay"; ++}; ++ ++&m4_rproc { ++ m4_system_resources { ++ status = "okay"; ++ ++ button { ++ compatible = "rproc-srm-dev"; ++ interrupt-parent = <&gpioa>; ++ interrupts = <14 2>; ++ interrupt-names = "irq"; ++ status = "okay"; ++ }; ++ ++ m4_led: m4_led { ++ compatible = "rproc-srm-dev"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_leds_orange_pins>; ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&m4_spi4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_spi4_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_timers1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_pwm1_pins_a_ch1>; ++ status = "okay"; ++}; ++ ++&m4_timers2 { ++ status = "okay"; ++}; ++ ++&m4_uart7 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_uart7_pins_a>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ m4_leds_orange_pins: m4-leds-orange-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_pwm1_pins_a_ch1: m4-pwm1-0-ch1 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++}; ++ ++&timers1 { ++ status = "disabled"; ++}; diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts -index 4c8be9c8e..f48207dad 100644 +index 4c8be9c8eb20..f48207dad581 100644 --- a/arch/arm/boot/dts/stm32mp157a-dk1.dts +++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts @@ -7,6 +7,7 @@ @@ -6966,7 +7012,7 @@ index 4c8be9c8e..f48207dad 100644 #include "stm32mp15-pinctrl.dtsi" #include "stm32mp15xxac-pinctrl.dtsi" #include "stm32mp15xx-dkx.dtsi" -@@ -15,13 +16,6 @@ / { +@@ -15,13 +16,6 @@ model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; @@ -6982,7 +7028,7 @@ index 4c8be9c8e..f48207dad 100644 }; diff --git a/arch/arm/boot/dts/stm32mp157a-ed1.dts b/arch/arm/boot/dts/stm32mp157a-ed1.dts new file mode 100644 -index 000000000..0213ca5c1 +index 000000000000..0213ca5c17fa --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157a-ed1.dts @@ -0,0 +1,32 @@ @@ -7020,7 +7066,7 @@ index 000000000..0213ca5c1 +}; diff --git a/arch/arm/boot/dts/stm32mp157a-ev1.dts b/arch/arm/boot/dts/stm32mp157a-ev1.dts new file mode 100644 -index 000000000..a96fbc840 +index 000000000000..a96fbc84067a --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157a-ev1.dts @@ -0,0 +1,103 @@ @@ -7129,10 +7175,10 @@ index 000000000..a96fbc840 +}; diff --git a/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts b/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts new file mode 100644 -index 000000000..d0f13953a +index 000000000000..6c7608fc45f8 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157c-dk2-a7-examples.dts -@@ -0,0 +1,67 @@ +@@ -0,0 +1,95 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved @@ -7148,27 +7194,55 @@ index 000000000..d0f13953a + compatible = "st,stm32mp157c-dk2-a7-examples", "st,stm32mp157c-dk2", "st,stm32mp157"; +}; + -+&i2c5 { -+ status = "okay"; -+}; -+ +&adc { + pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; + + adc1: adc@0 { -+ st,min-sample-time-nsecs = <5000>; -+ st,adc-channels = <0 1 6 13 18 19>; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@13 { ++ reg = <13>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; + + adc2: adc@100 { + /* Set IRQ mode as example. DMA is the preferred mode, yet. */ + /delete-property/dmas; + /delete-property/dma-names; -+ st,min-sample-time-nsecs = <5000>; -+ st,adc-channels = <0 1 2 6 18 19>; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@2 { ++ reg = <2>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; +}; + ++&i2c5 { ++ status = "okay"; ++}; ++ +&timers1 { + status = "okay"; +}; @@ -7202,7 +7276,7 @@ index 000000000..d0f13953a +}; diff --git a/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts b/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts new file mode 100644 -index 000000000..c1221a5f2 +index 000000000000..e770942e8369 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157c-dk2-m4-examples.dts @@ -0,0 +1,128 @@ @@ -7243,6 +7317,14 @@ index 000000000..c1221a5f2 + status = "okay"; +}; + ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ +&m4_dac { + vref-supply = <&vrefbuf>; + status = "okay"; @@ -7252,14 +7334,6 @@ index 000000000..c1221a5f2 + status = "okay"; +}; + -+&m4_crc2 { -+ status = "okay"; -+}; -+ -+&m4_cryp2 { -+ status = "okay"; -+}; -+ +&m4_hash2 { + status = "okay"; +}; @@ -7301,16 +7375,16 @@ index 000000000..c1221a5f2 + status = "okay"; +}; + -+&m4_timers2 { -+ status = "okay"; -+}; -+ +&m4_timers1 { + pinctrl-names = "default"; + pinctrl-0 = <&m4_pwm1_pins_a_ch1>; + status = "okay"; +}; + ++&m4_timers2 { ++ status = "okay"; ++}; ++ +&m4_uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&m4_uart7_pins_a>; @@ -7335,7 +7409,7 @@ index 000000000..c1221a5f2 + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts -index 2bc92ef3a..a46941d6f 100644 +index 2bc92ef3aeb9..0190bd17dd1b 100644 --- a/arch/arm/boot/dts/stm32mp157c-dk2.dts +++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts @@ -11,21 +11,32 @@ @@ -7375,7 +7449,7 @@ index 2bc92ef3a..a46941d6f 100644 }; }; -@@ -35,7 +46,6 @@ &cryp1 { +@@ -35,7 +46,6 @@ &dsi { status = "okay"; @@ -7383,7 +7457,7 @@ index 2bc92ef3a..a46941d6f 100644 ports { port@0 { -@@ -53,7 +63,7 @@ dsi_out: endpoint { +@@ -53,7 +63,7 @@ }; }; @@ -7392,7 +7466,7 @@ index 2bc92ef3a..a46941d6f 100644 compatible = "orisetech,otm8009a"; reg = <0>; reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; -@@ -77,6 +87,9 @@ touchscreen@38 { +@@ -77,6 +87,9 @@ interrupt-controller; touchscreen-size-x = <480>; touchscreen-size-y = <800>; @@ -7402,7 +7476,7 @@ index 2bc92ef3a..a46941d6f 100644 status = "okay"; }; }; -@@ -92,10 +105,48 @@ ltdc_ep1_out: endpoint@1 { +@@ -92,10 +105,47 @@ }; }; @@ -7414,7 +7488,6 @@ index 2bc92ef3a..a46941d6f 100644 + +/* Wifi */ +&sdmmc2 { -+ arm,primecell-periphid = <0x10153180>; + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a>; @@ -7453,7 +7526,7 @@ index 2bc92ef3a..a46941d6f 100644 + }; }; diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts -index 46b471d09..d2c24803b 100644 +index 46b471d09c50..d2c24803b99e 100644 --- a/arch/arm/boot/dts/stm32mp157c-ed1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts @@ -1,7 +1,7 @@ @@ -7476,7 +7549,7 @@ index 46b471d09..d2c24803b 100644 / { model = "STMicroelectronics STM32MP157C eval daughter"; -@@ -20,381 +19,18 @@ chosen { +@@ -20,381 +19,18 @@ stdout-path = "serial0:115200n8"; }; @@ -7862,7 +7935,7 @@ index 46b471d09..d2c24803b 100644 -}; diff --git a/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts new file mode 100644 -index 000000000..9f516309c +index 000000000000..9f516309c29f --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157c-ev1-a7-examples.dts @@ -0,0 +1,57 @@ @@ -7925,7 +7998,7 @@ index 000000000..9f516309c +}; diff --git a/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts new file mode 100644 -index 000000000..0333a3490 +index 000000000000..07684f340b39 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157c-ev1-m4-examples.dts @@ -0,0 +1,150 @@ @@ -8012,6 +8085,10 @@ index 000000000..0333a3490 + status = "okay"; +}; + ++&m4_rng2 { ++ status = "okay"; ++}; ++ +&m4_rproc { + m4_system_resources { + status = "okay"; @@ -8034,10 +8111,6 @@ index 000000000..0333a3490 + }; +}; + -+&m4_rng2 { -+ status = "okay"; -+}; -+ +&m4_spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&m4_spi1_pins_a>; @@ -8080,7 +8153,7 @@ index 000000000..0333a3490 + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts -index 5c5b1ddf7..17434d903 100644 +index 5c5b1ddf7bfd..17434d903f10 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts @@ -1,69 +1,27 @@ @@ -8163,7 +8236,7 @@ index 5c5b1ddf7..17434d903 100644 }; }; -@@ -75,35 +33,15 @@ panel_backlight: panel-backlight { +@@ -75,35 +33,15 @@ }; }; @@ -8204,7 +8277,7 @@ index 5c5b1ddf7..17434d903 100644 port@0 { reg = <0>; dsi_in: endpoint { -@@ -119,7 +57,7 @@ dsi_out: endpoint { +@@ -119,7 +57,7 @@ }; }; @@ -8213,7 +8286,7 @@ index 5c5b1ddf7..17434d903 100644 compatible = "raydium,rm68200"; reg = <0>; reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; -@@ -135,106 +73,20 @@ dsi_panel_in: endpoint { +@@ -135,106 +73,20 @@ }; }; @@ -8328,7 +8401,7 @@ index 5c5b1ddf7..17434d903 100644 <dc { status = "okay"; -@@ -245,133 +97,3 @@ ltdc_ep0_out: endpoint@0 { +@@ -245,133 +97,3 @@ }; }; }; @@ -8462,9 +8535,244 @@ index 5c5b1ddf7..17434d903 100644 -&usbphyc { - status = "okay"; -}; +diff --git a/arch/arm/boot/dts/stm32mp157d-dk1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157d-dk1-a7-examples.dts +new file mode 100644 +index 000000000000..745cec886c25 +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157d-dk1-a7-examples.dts +@@ -0,0 +1,95 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved ++ * Author: Amelie Delaunay for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157d-dk1.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157D-DK1 configured to run Linux A7 examples"; ++ compatible = "st,stm32mp157d-dk1-a7-examples", "st,stm32mp157d-dk1", "st,stm32mp157"; ++}; ++ ++&adc { ++ pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; ++ ++ adc1: adc@0 { ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@13 { ++ reg = <13>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ }; ++ ++ adc2: adc@100 { ++ /* Set IRQ mode as example. DMA is the preferred mode, yet. */ ++ /delete-property/dmas; ++ /delete-property/dma-names; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@2 { ++ reg = <2>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ }; ++}; ++ ++&i2c5 { ++ status = "okay"; ++}; ++ ++&timers1 { ++ status = "okay"; ++}; ++ ++&timers3 { ++ status = "okay"; ++}; ++ ++&timers4 { ++ status = "okay"; ++}; ++ ++&timers5 { ++ status = "okay"; ++}; ++ ++&timers6 { ++ status = "okay"; ++}; ++ ++&timers12 { ++ status = "okay"; ++}; ++ ++&uart7 { ++ status = "okay"; ++}; ++ ++&usart3 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/stm32mp157d-dk1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157d-dk1-m4-examples.dts +new file mode 100644 +index 000000000000..d1088b95f7fd +--- /dev/null ++++ b/arch/arm/boot/dts/stm32mp157d-dk1-m4-examples.dts +@@ -0,0 +1,128 @@ ++// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved ++ * Author: Amelie Delaunay for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157d-dk1.dts" ++ ++/ { ++ model = "STMicroelectronics STM32MP157D-DK1 configured to run M4 examples"; ++ compatible = "st,stm32mp157d-dk1-m4-examples", "st,stm32mp157d-dk1", "st,stm32mp157"; ++}; ++ ++&adc { ++ status = "disabled"; ++}; ++ ++&dac { ++ status = "disabled"; ++}; ++ ++&dma2 { ++ status = "disabled"; ++}; ++ ++&dmamux1 { ++ dma-masters = <&dma1>; ++ dma-channels = <8>; ++}; ++ ++&m4_adc { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ ++&m4_dac { ++ vref-supply = <&vrefbuf>; ++ status = "okay"; ++}; ++ ++&m4_dma2 { ++ status = "okay"; ++}; ++ ++&m4_hash2 { ++ status = "okay"; ++}; ++ ++&m4_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_i2c5_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_rng2 { ++ status = "okay"; ++}; ++ ++&m4_rproc { ++ m4_system_resources { ++ status = "okay"; ++ ++ button { ++ compatible = "rproc-srm-dev"; ++ interrupt-parent = <&gpioa>; ++ interrupts = <14 2>; ++ interrupt-names = "irq"; ++ status = "okay"; ++ }; ++ ++ m4_led: m4_led { ++ compatible = "rproc-srm-dev"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_leds_orange_pins>; ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&m4_spi4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_spi4_pins_a>; ++ status = "okay"; ++}; ++ ++&m4_timers1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_pwm1_pins_a_ch1>; ++ status = "okay"; ++}; ++ ++&m4_timers2 { ++ status = "okay"; ++}; ++ ++&m4_uart7 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&m4_uart7_pins_a>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ m4_leds_orange_pins: m4-leds-orange-0 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++ ++ m4_pwm1_pins_a_ch1: m4-pwm1-0-ch1 { ++ pins { ++ pinmux = ; ++ }; ++ }; ++}; ++ ++&timers1 { ++ status = "disabled"; ++}; diff --git a/arch/arm/boot/dts/stm32mp157d-dk1.dts b/arch/arm/boot/dts/stm32mp157d-dk1.dts new file mode 100644 -index 000000000..99a4e0f9c +index 000000000000..99a4e0f9c471 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157d-dk1.dts @@ -0,0 +1,26 @@ @@ -8496,7 +8804,7 @@ index 000000000..99a4e0f9c +}; diff --git a/arch/arm/boot/dts/stm32mp157d-ed1.dts b/arch/arm/boot/dts/stm32mp157d-ed1.dts new file mode 100644 -index 000000000..18d807437 +index 000000000000..18d807437632 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157d-ed1.dts @@ -0,0 +1,32 @@ @@ -8534,7 +8842,7 @@ index 000000000..18d807437 +}; diff --git a/arch/arm/boot/dts/stm32mp157d-ev1.dts b/arch/arm/boot/dts/stm32mp157d-ev1.dts new file mode 100644 -index 000000000..f19ca6ada +index 000000000000..f19ca6ada2d6 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157d-ev1.dts @@ -0,0 +1,103 @@ @@ -8643,10 +8951,10 @@ index 000000000..f19ca6ada +}; diff --git a/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts b/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts new file mode 100644 -index 000000000..7ca70b56b +index 000000000000..99dc3ed596bd --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157f-dk2-a7-examples.dts -@@ -0,0 +1,67 @@ +@@ -0,0 +1,95 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved @@ -8662,27 +8970,55 @@ index 000000000..7ca70b56b + compatible = "st,stm32mp157f-dk2-a7-examples", "st,stm32mp157f-dk2", "st,stm32mp157"; +}; + -+&i2c5 { -+ status = "okay"; -+}; -+ +&adc { + pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; + + adc1: adc@0 { -+ st,min-sample-time-nsecs = <5000>; -+ st,adc-channels = <0 1 6 13 18 19>; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@13 { ++ reg = <13>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; + + adc2: adc@100 { + /* Set IRQ mode as example. DMA is the preferred mode, yet. */ + /delete-property/dmas; + /delete-property/dma-names; -+ st,min-sample-time-nsecs = <5000>; -+ st,adc-channels = <0 1 2 6 18 19>; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@2 { ++ reg = <2>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; +}; + ++&i2c5 { ++ status = "okay"; ++}; ++ +&timers1 { + status = "okay"; +}; @@ -8716,7 +9052,7 @@ index 000000000..7ca70b56b +}; diff --git a/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts b/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts new file mode 100644 -index 000000000..e05ac247b +index 000000000000..38f8a1bbb8dd --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157f-dk2-m4-examples.dts @@ -0,0 +1,128 @@ @@ -8757,6 +9093,14 @@ index 000000000..e05ac247b + status = "okay"; +}; + ++&m4_crc2 { ++ status = "okay"; ++}; ++ ++&m4_cryp2 { ++ status = "okay"; ++}; ++ +&m4_dac { + vref-supply = <&vrefbuf>; + status = "okay"; @@ -8766,14 +9110,6 @@ index 000000000..e05ac247b + status = "okay"; +}; + -+&m4_crc2 { -+ status = "okay"; -+}; -+ -+&m4_cryp2 { -+ status = "okay"; -+}; -+ +&m4_hash2 { + status = "okay"; +}; @@ -8815,16 +9151,16 @@ index 000000000..e05ac247b + status = "okay"; +}; + -+&m4_timers2 { -+ status = "okay"; -+}; -+ +&m4_timers1 { + pinctrl-names = "default"; + pinctrl-0 = <&m4_pwm1_pins_a_ch1>; + status = "okay"; +}; + ++&m4_timers2 { ++ status = "okay"; ++}; ++ +&m4_uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&m4_uart7_pins_a>; @@ -8850,10 +9186,10 @@ index 000000000..e05ac247b +}; diff --git a/arch/arm/boot/dts/stm32mp157f-dk2.dts b/arch/arm/boot/dts/stm32mp157f-dk2.dts new file mode 100644 -index 000000000..3cd2e7303 +index 000000000000..d854ed0ac1d1 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157f-dk2.dts -@@ -0,0 +1,152 @@ +@@ -0,0 +1,151 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved @@ -8969,7 +9305,6 @@ index 000000000..3cd2e7303 + +/* Wifi */ +&sdmmc2 { -+ arm,primecell-periphid = <0x10153180>; + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a>; @@ -9008,7 +9343,7 @@ index 000000000..3cd2e7303 +}; diff --git a/arch/arm/boot/dts/stm32mp157f-ed1.dts b/arch/arm/boot/dts/stm32mp157f-ed1.dts new file mode 100644 -index 000000000..bb3f8dfdc +index 000000000000..bb3f8dfdcb8b --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157f-ed1.dts @@ -0,0 +1,36 @@ @@ -9050,7 +9385,7 @@ index 000000000..bb3f8dfdc +}; diff --git a/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts b/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts new file mode 100644 -index 000000000..373307ff6 +index 000000000000..373307ff60a6 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157f-ev1-a7-examples.dts @@ -0,0 +1,57 @@ @@ -9113,7 +9448,7 @@ index 000000000..373307ff6 +}; diff --git a/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts b/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts new file mode 100644 -index 000000000..5fc061bfb +index 000000000000..fd7be9c73b72 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157f-ev1-m4-examples.dts @@ -0,0 +1,151 @@ @@ -9200,6 +9535,10 @@ index 000000000..5fc061bfb + status = "okay"; +}; + ++&m4_rng2 { ++ status = "okay"; ++}; ++ +&m4_rproc { + m4_system_resources { + status = "okay"; @@ -9223,10 +9562,6 @@ index 000000000..5fc061bfb + }; +}; + -+&m4_rng2 { -+ status = "okay"; -+}; -+ +&m4_spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&m4_spi1_pins_a>; @@ -9270,7 +9605,7 @@ index 000000000..5fc061bfb +}; diff --git a/arch/arm/boot/dts/stm32mp157f-ev1.dts b/arch/arm/boot/dts/stm32mp157f-ev1.dts new file mode 100644 -index 000000000..b831f0453 +index 000000000000..b831f04532fd --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157f-ev1.dts @@ -0,0 +1,99 @@ @@ -9375,7 +9710,7 @@ index 000000000..b831f0453 +}; diff --git a/arch/arm/boot/dts/stm32mp15xa.dtsi b/arch/arm/boot/dts/stm32mp15xa.dtsi new file mode 100644 -index 000000000..5ed7e594f +index 000000000000..5ed7e594f4cd --- /dev/null +++ b/arch/arm/boot/dts/stm32mp15xa.dtsi @@ -0,0 +1,13 @@ @@ -9393,10 +9728,10 @@ index 000000000..5ed7e594f + }; +}; diff --git a/arch/arm/boot/dts/stm32mp15xc.dtsi b/arch/arm/boot/dts/stm32mp15xc.dtsi -index b06a55a2f..67d38d133 100644 +index b06a55a2fa18..71787e804f3a 100644 --- a/arch/arm/boot/dts/stm32mp15xc.dtsi +++ b/arch/arm/boot/dts/stm32mp15xc.dtsi -@@ -4,14 +4,16 @@ +@@ -4,14 +4,19 @@ * Author: Alexandre Torgue for STMicroelectronics. */ @@ -9412,12 +9747,15 @@ index b06a55a2f..67d38d133 100644 - resets = <&rcc CRYP1_R>; + clocks = <&scmi_clk CK_SCMI_CRYP1>; + resets = <&scmi_reset RST_SCMI_CRYP1>; ++ dmas = <&mdma1 29 0x0 0x400202 0x0 0x0 0x0>, ++ <&mdma1 30 0x3 0x400808 0x0 0x0 0x0>; ++ dma-names = "in", "out"; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/stm32mp15xd.dtsi b/arch/arm/boot/dts/stm32mp15xd.dtsi new file mode 100644 -index 000000000..e2f8b1297 +index 000000000000..e2f8b1297c33 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp15xd.dtsi @@ -0,0 +1,42 @@ @@ -9465,10 +9803,10 @@ index 000000000..e2f8b1297 +}; diff --git a/arch/arm/boot/dts/stm32mp15xf.dtsi b/arch/arm/boot/dts/stm32mp15xf.dtsi new file mode 100644 -index 000000000..f4a77bf9a +index 000000000000..26989fae4739 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp15xf.dtsi -@@ -0,0 +1,20 @@ +@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved @@ -9485,12 +9823,87 @@ index 000000000..f4a77bf9a + interrupts = ; + clocks = <&scmi_clk CK_SCMI_CRYP1>; + resets = <&scmi_reset RST_SCMI_CRYP1>; ++ dmas = <&mdma1 29 0x0 0x400202 0x0 0x0 0x0>, ++ <&mdma1 30 0x3 0x400808 0x0 0x0 0x0>; ++ dma-names = "in", "out"; + status = "disabled"; + }; + }; +}; +diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi +index 8c41f819f776..dfaf71b9a5e0 100644 +--- a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi +@@ -82,15 +82,19 @@ + status = "okay"; + + adc1: adc@0 { +- st,min-sample-time-nsecs = <5000>; +- st,adc-channels = <0>; + status = "okay"; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; + + adc2: adc@100 { +- st,adc-channels = <1>; +- st,min-sample-time-nsecs = <5000>; + status = "okay"; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; + }; + +diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +index 8eb51d84b698..9ae521097ac0 100644 +--- a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +@@ -114,15 +114,35 @@ + status = "okay"; + + adc1: adc@0 { +- st,adc-channels = <0 1 6>; +- st,min-sample-time-nsecs = <5000>; + status = "okay"; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; + + adc2: adc@100 { +- st,adc-channels = <0 1 2>; +- st,min-sample-time-nsecs = <5000>; + status = "okay"; ++ channel@0 { ++ reg = <0>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@2 { ++ reg = <2>; ++ st,min-sample-time-ns = <5000>; ++ }; + }; + }; + diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi -index 48beed0f1..d5abbfd51 100644 +index 48beed0f1f30..58bb9eca86a0 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi @@ -4,10 +4,19 @@ @@ -9513,7 +9926,7 @@ index 48beed0f1..d5abbfd51 100644 memory@c0000000 { device_type = "memory"; reg = <0xc0000000 0x20000000>; -@@ -42,6 +51,12 @@ vdev0buffer: vdev0buffer@10042000 { +@@ -42,6 +51,12 @@ no-map; }; @@ -9526,7 +9939,7 @@ index 48beed0f1..d5abbfd51 100644 mcuram: mcuram@30000000 { compatible = "shared-dma-pool"; reg = <0x30000000 0x40000>; -@@ -58,6 +73,11 @@ gpu_reserved: gpu@d4000000 { +@@ -58,6 +73,11 @@ reg = <0xd4000000 0x4000000>; no-map; }; @@ -9538,7 +9951,7 @@ index 48beed0f1..d5abbfd51 100644 }; led { -@@ -70,9 +90,9 @@ led-blue { +@@ -70,9 +90,9 @@ }; }; @@ -9550,7 +9963,7 @@ index 48beed0f1..d5abbfd51 100644 routing = "Playback" , "MCLK", "Capture" , "MCLK", -@@ -92,11 +112,11 @@ vin: vin { +@@ -92,28 +112,39 @@ &adc { pinctrl-names = "default"; @@ -9562,27 +9975,44 @@ index 48beed0f1..d5abbfd51 100644 - status = "disabled"; + status = "okay"; adc1: adc@0 { ++ status = "okay"; /* * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19. -@@ -105,13 +125,13 @@ adc1: adc@0 { + * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: + * 5 * (56 + 47kOhms) * 5pF => 2.5us. * Use arbitrary margin here (e.g. 5us). */ - st,min-sample-time-nsecs = <5000>; +- st,min-sample-time-nsecs = <5000>; - /* AIN connector, USB Type-C CC1 & CC2 */ - st,adc-channels = <0 1 6 13 18 19>; -+ /* USB Type-C CC1 & CC2 */ -+ st,adc-channels = <18 19>; - status = "okay"; +- status = "okay"; ++ channel@18 { ++ reg = <18>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@19 { ++ reg = <19>; ++ st,min-sample-time-ns = <5000>; ++ }; }; adc2: adc@100 { - /* AIN connector, USB Type-C CC1 & CC2 */ - st,adc-channels = <0 1 2 6 18 19>; -+ /* USB Type-C CC1 & CC2 */ -+ st,adc-channels = <18 19>; - st,min-sample-time-nsecs = <5000>; +- st,min-sample-time-nsecs = <5000>; status = "okay"; ++ /* USB Type-C CC1 & CC2 */ ++ channel@18 { ++ reg = <18>; ++ st,min-sample-time-ns = <5000>; ++ }; ++ channel@19 { ++ reg = <19>; ++ st,min-sample-time-ns = <5000>; ++ }; }; -@@ -124,10 +144,26 @@ &cec { + }; + +@@ -124,10 +155,26 @@ status = "okay"; }; @@ -9609,7 +10039,7 @@ index 48beed0f1..d5abbfd51 100644 &dts { status = "okay"; }; -@@ -140,6 +176,8 @@ ðernet0 { +@@ -140,6 +187,8 @@ phy-mode = "rgmii-id"; max-speed = <1000>; phy-handle = <&phy0>; @@ -9618,16 +10048,16 @@ index 48beed0f1..d5abbfd51 100644 mdio0 { #address-cells = <1>; -@@ -273,7 +311,7 @@ con_usbotg_hs_ep: endpoint { +@@ -273,7 +322,7 @@ pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; - interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; -+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; ++ interrupts-extended = <&exti 55 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <2>; status = "okay"; -@@ -382,21 +420,21 @@ vref_ddr: vref_ddr { +@@ -382,21 +431,21 @@ regulator-always-on; }; @@ -9654,7 +10084,7 @@ index 48beed0f1..d5abbfd51 100644 }; onkey { -@@ -469,11 +507,12 @@ ltdc_ep0_out: endpoint@0 { +@@ -469,11 +518,12 @@ &m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, @@ -9668,7 +10098,7 @@ index 48beed0f1..d5abbfd51 100644 status = "okay"; }; -@@ -482,10 +521,6 @@ &pwr_regulators { +@@ -482,10 +532,6 @@ vdd_3v3_usbfs-supply = <&vdd_usb>; }; @@ -9679,7 +10109,7 @@ index 48beed0f1..d5abbfd51 100644 &rtc { status = "okay"; }; -@@ -501,8 +536,6 @@ &sai2 { +@@ -501,8 +547,6 @@ sai2a: audio-controller@4400b004 { #clock-cells = <0>; dma-names = "tx"; @@ -9688,7 +10118,7 @@ index 48beed0f1..d5abbfd51 100644 status = "okay"; sai2a_port: port { -@@ -560,6 +593,27 @@ &sdmmc3 { +@@ -560,6 +604,27 @@ status = "disabled"; }; @@ -9716,7 +10146,7 @@ index 48beed0f1..d5abbfd51 100644 &timers1 { /* spare dmas for other usage */ /delete-property/dmas; -@@ -650,6 +704,8 @@ &uart4 { +@@ -650,6 +715,8 @@ pinctrl-0 = <&uart4_pins_a>; pinctrl-1 = <&uart4_sleep_pins_a>; pinctrl-2 = <&uart4_idle_pins_a>; @@ -9725,7 +10155,7 @@ index 48beed0f1..d5abbfd51 100644 status = "okay"; }; -@@ -658,6 +714,8 @@ &uart7 { +@@ -658,6 +725,8 @@ pinctrl-0 = <&uart7_pins_c>; pinctrl-1 = <&uart7_sleep_pins_c>; pinctrl-2 = <&uart7_idle_pins_c>; @@ -9734,7 +10164,7 @@ index 48beed0f1..d5abbfd51 100644 status = "disabled"; }; -@@ -694,10 +752,36 @@ &usbphyc { +@@ -694,10 +763,36 @@ &usbphyc_port0 { phy-supply = <&vdd_usb>; @@ -9773,10 +10203,10 @@ index 48beed0f1..d5abbfd51 100644 &vrefbuf { diff --git a/arch/arm/boot/dts/stm32mp15xx-edx.dtsi b/arch/arm/boot/dts/stm32mp15xx-edx.dtsi new file mode 100644 -index 000000000..db0f91135 +index 000000000000..014ce3863d3e --- /dev/null +++ b/arch/arm/boot/dts/stm32mp15xx-edx.dtsi -@@ -0,0 +1,419 @@ +@@ -0,0 +1,429 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved @@ -9893,10 +10323,20 @@ index 000000000..db0f91135 + vref-supply = <&vdda>; + status = "disabled"; + adc1: adc@0 { -+ st,adc-channels = <0 1 6>; -+ /* 16.5 ck_cycles sampling time */ -+ st,min-sample-time-nsecs = <400>; + status = "okay"; ++ channel@0 { ++ reg = <0>; ++ /* 16.5 ck_cycles sampling time */ ++ st,min-sample-time-ns = <400>; ++ }; ++ channel@1 { ++ reg = <1>; ++ st,min-sample-time-ns = <400>; ++ }; ++ channel@6 { ++ reg = <6>; ++ st,min-sample-time-ns = <400>; ++ }; + }; +}; + @@ -9956,7 +10396,7 @@ index 000000000..db0f91135 + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; -+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; ++ interrupts-extended = <&exti 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; @@ -10198,10 +10638,10 @@ index 000000000..db0f91135 +}; diff --git a/arch/arm/boot/dts/stm32mp15xx-evx.dtsi b/arch/arm/boot/dts/stm32mp15xx-evx.dtsi new file mode 100644 -index 000000000..fa453817a +index 000000000000..fe8a8dfc46b8 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp15xx-evx.dtsi -@@ -0,0 +1,690 @@ +@@ -0,0 +1,698 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved @@ -10667,8 +11107,16 @@ index 000000000..fa453817a + +&qspi { + pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; -+ pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; ++ pinctrl-0 = <&qspi_clk_pins_a ++ &qspi_bk1_pins_a ++ &qspi_cs1_pins_a ++ &qspi_bk2_pins_a ++ &qspi_cs2_pins_a>; ++ pinctrl-1 = <&qspi_clk_sleep_pins_a ++ &qspi_bk1_sleep_pins_a ++ &qspi_cs1_sleep_pins_a ++ &qspi_bk2_sleep_pins_a ++ &qspi_cs2_sleep_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; + #address-cells = <1>; + #size-cells = <0>; @@ -10893,5 +11341,5 @@ index 000000000..fa453817a + st,no-lsfs-sc; +}; -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0022-ARM-5.15.24-stm32mp1-r1-CONFIG.patch b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0022-v5.15-stm32mp-r2-CONFIG.patch similarity index 96% rename from recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0022-ARM-5.15.24-stm32mp1-r1-CONFIG.patch rename to recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0022-v5.15-stm32mp-r2-CONFIG.patch index d5a9d44..6100ad5 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/5.15.24/0022-ARM-5.15.24-stm32mp1-r1-CONFIG.patch +++ b/recipes-kernel/linux/linux-stm32mp/5.15/5.15.67/0022-v5.15-stm32mp-r2-CONFIG.patch @@ -1,20 +1,20 @@ -From 334f4603a6c9a1bb69ca6b65edf385156dac578b Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Tue, 31 May 2022 12:10:24 +0200 -Subject: [PATCH 22/22] ARM-5.15.24-stm32mp1-r1-CONFIG +From ff0775651b034096b3f72ed6ec90efc39eb8627c Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Thu, 3 Nov 2022 16:51:45 +0100 +Subject: [PATCH 22/22] v5.15-stm32mp-r2 CONFIG -Signed-off-by: Christophe Priouzeau +Signed-off-by: Romuald JEANNE --- .../fragment-01-multiv7_cleanup.config | 408 +++++++++++++++++ - .../configs/fragment-02-multiv7_addons.config | 419 ++++++++++++++++++ + .../configs/fragment-02-multiv7_addons.config | 426 ++++++++++++++++++ arch/arm/configs/multi_v7_defconfig | 1 + - 3 files changed, 828 insertions(+) + 3 files changed, 835 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 000000000..52f28a765 +index 000000000000..52f28a765b25 --- /dev/null +++ b/arch/arm/configs/fragment-01-multiv7_cleanup.config @@ -0,0 +1,408 @@ @@ -428,10 +428,10 @@ index 000000000..52f28a765 +# CONFIG_FRAMEBUFFER_CONSOLE is not set 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 000000000..5ce8ee7aa +index 000000000000..7b5ffd562d8a --- /dev/null +++ b/arch/arm/configs/fragment-02-multiv7_addons.config -@@ -0,0 +1,419 @@ +@@ -0,0 +1,426 @@ +# +# General setup +# @@ -851,8 +851,15 @@ index 000000000..5ce8ee7aa +# +CONFIG_SAMPLES=y +CONFIG_SAMPLE_RPMSG_CLIENT=m ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CFB=m ++CONFIG_CRYPTO_LRW=m ++CONFIG_CRYPTO_OFB=m diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig -index 33572998d..afb97c505 100644 +index 33572998dbbe..afb97c5051c9 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -646,6 +646,7 @@ CONFIG_V4L_PLATFORM_DRIVERS=y @@ -864,5 +871,5 @@ index 33572998d..afb97c505 100644 CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS=m CONFIG_VIDEO_S5P_FIMC=m -- -2.25.1 +2.17.1 diff --git a/recipes-kernel/linux/linux-stm32mp/5.15/fragment-04-modules.config b/recipes-kernel/linux/linux-stm32mp/5.15/fragment-04-modules.config index 7fd8bcb..ea832c5 100644 --- a/recipes-kernel/linux/linux-stm32mp/5.15/fragment-04-modules.config +++ b/recipes-kernel/linux/linux-stm32mp/5.15/fragment-04-modules.config @@ -1,7 +1,6 @@ # CONFIG_GCC_PLUGINS is not set # Allow to load kernel modules built with different kernel version -CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODVERSIONS=y # Support of iks01a2 diff --git a/recipes-kernel/linux/linux-stm32mp_5.15.bb b/recipes-kernel/linux/linux-stm32mp_5.15.bb index f4fbd85..21fb05f 100644 --- a/recipes-kernel/linux/linux-stm32mp_5.15.bb +++ b/recipes-kernel/linux/linux-stm32mp_5.15.bb @@ -7,41 +7,41 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46" include linux-stm32mp.inc LINUX_VERSION = "5.15" -LINUX_SUBVERSION = "24" +LINUX_SUBVERSION = "67" LINUX_TARNAME = "linux-${LINUX_VERSION}.${LINUX_SUBVERSION}" SRC_URI = "https://cdn.kernel.org/pub/linux/kernel/v5.x/${LINUX_TARNAME}.tar.xz;name=kernel" #SRC_URI = "https://git.kernel.org/torvalds/t/linux-${LINUX_VERSION}-${LINUX_SUBVERSION}.tar.gz;name=kernel" -SRC_URI[kernel.sha256sum] = "f496eb03c88731540d483837f919c083148875a7b400468237f0217b5e5ca97f" +SRC_URI[kernel.sha256sum] = "da47d9a80b694548835ccb553b6eb1a1f3f5d5cddd9e2bd6f4886b99ca14f940" SRC_URI += " \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-ARM-5.15.24-stm32mp1-r1-MACHINE.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0002-ARM-5.15.24-stm32mp1-r1-CLOCK.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0003-ARM-5.15.24-stm32mp1-r1-CPUFREQ.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0004-ARM-5.15.24-stm32mp1-r1-CRYPTO.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0005-ARM-5.15.24-stm32mp1-r1-DMA.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0006-ARM-5.15.24-stm32mp1-r1-DRM.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0007-ARM-5.15.24-stm32mp1-r1-HWSPINLOCK.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0008-ARM-5.15.24-stm32mp1-r1-I2C-IIO-IRQCHIP.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0009-ARM-5.15.24-stm32mp1-r1-REMOTEPROC-RPMSG.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0010-ARM-5.15.24-stm32mp1-r1-MISC-MEDIA-SOC-THERMAL.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0011-ARM-5.15.24-stm32mp1-r1-MFD.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0012-ARM-5.15.24-stm32mp1-r1-MMC.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0013-ARM-5.15.24-stm32mp1-r1-NET-TTY.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0014-ARM-5.15.24-stm32mp1-r1-PERF.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0015-ARM-5.15.24-stm32mp1-r1-PHY-USB.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0016-ARM-5.15.24-stm32mp1-r1-PINCTRL-REGULATOR-SPI.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0017-ARM-5.15.24-stm32mp1-r1-RESET-RTC.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0018-ARM-5.15.24-stm32mp1-r1-SCMI.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0019-ARM-5.15.24-stm32mp1-r1-SOUND.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0020-ARM-5.15.24-stm32mp1-r1-CPUIDLE-POWER.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0021-ARM-5.15.24-stm32mp1-r1-DEVICETREE.patch \ - file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-ARM-5.15.24-stm32mp1-r1-CONFIG.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0001-v5.15-stm32mp-r2-MACHINE.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0002-v5.15-stm32mp-r2-CLOCK.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0003-v5.15-stm32mp-r2-CPUFREQ.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0004-v5.15-stm32mp-r2-CPUIDLE-POWER.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0005-v5.15-stm32mp-r2-CRYPTO.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0006-v5.15-stm32mp-r2-DMA.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0007-v5.15-stm32mp-r2-DRM.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0008-v5.15-stm32mp-r2-HWSPINLOCK.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0009-v5.15-stm32mp-r2-I2C-IIO-IRQCHIP.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0010-v5.15-stm32mp-r2-REMOTEPROC-RPMSG.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0011-v5.15-stm32mp-r2-MISC-MEDIA-SOC-THERMAL.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0012-v5.15-stm32mp-r2-MFD.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0013-v5.15-stm32mp-r2-MMC.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0014-v5.15-stm32mp-r2-NET-TTY.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0015-v5.15-stm32mp-r2-PERF.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0016-v5.15-stm32mp-r2-PHY-USB.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0017-v5.15-stm32mp-r2-PINCTRL-REGULATOR-SPI.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0018-v5.15-stm32mp-r2-RESET-RTC.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0019-v5.15-stm32mp-r2-SCMI.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0020-v5.15-stm32mp-r2-SOUND.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0021-v5.15-stm32mp-r2-DEVICETREE.patch \ + file://${LINUX_VERSION}/${LINUX_VERSION}.${LINUX_SUBVERSION}/0022-v5.15-stm32mp-r2-CONFIG.patch \ " LINUX_TARGET = "stm32mp" -LINUX_RELEASE = "r1" +LINUX_RELEASE = "r2" PV = "${LINUX_VERSION}.${LINUX_SUBVERSION}-${LINUX_TARGET}-${LINUX_RELEASE}" @@ -59,7 +59,7 @@ S = "${WORKDIR}/linux-${LINUX_VERSION}.${LINUX_SUBVERSION}" BBCLASSEXTEND = "devupstream:target" SRC_URI:class-devupstream = "git://github.com/STMicroelectronics/linux.git;protocol=https;branch=${ARCHIVER_ST_BRANCH}" -SRCREV:class-devupstream = "0ea7234e7642a404115908c4688a050cb6cc2503" +SRCREV:class-devupstream = "661e4b11da679e4e1f4de088279282f6fbbe528b" # --------------------------------- # Configure default preference to manage dynamic selection between tarball and github