--- zzzz-none-000/linux-5.4.213/drivers/dma/qcom/bam_dma.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/drivers/dma/qcom/bam_dma.c 2024-05-29 11:19:50.000000000 +0000 @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2021 The Linux Foundation. All rights reserved. */ /* * QCOM BAM DMA engine driver @@ -42,6 +42,10 @@ #include #include +#if defined(CONFIG_ARCH_IPQ9574) +#include +#endif /* CONFIG_ARCH_IPQ9574 */ + #include "../dmaengine.h" #include "../virt-dma.h" @@ -52,12 +56,16 @@ }; #define BAM_DMA_AUTOSUSPEND_DELAY 100 +#define PIPE_TRUST_REG_MASK 0xFFFFFFF8 +#define BAM_TRUST_LOCK_EE_CTRL BIT(13) #define DESC_FLAG_INT BIT(15) #define DESC_FLAG_EOT BIT(14) #define DESC_FLAG_EOB BIT(13) #define DESC_FLAG_NWD BIT(12) #define DESC_FLAG_CMD BIT(11) +#define DESC_FLAG_LOCK BIT(10) +#define DESC_FLAG_UNLOCK BIT(9) struct bam_async_desc { struct virt_dma_desc vd; @@ -104,6 +112,8 @@ BAM_P_DESC_FIFO_ADDR, BAM_P_EVNT_GEN_TRSHLD, BAM_P_FIFO_SIZES, + BAM_TRUST_REG, + BAM_P_TRUST_REG, }; struct reg_offset_data { @@ -138,6 +148,7 @@ [BAM_P_DESC_FIFO_ADDR] = { 0x101C, 0x00, 0x40, 0x00 }, [BAM_P_EVNT_GEN_TRSHLD] = { 0x1028, 0x00, 0x40, 0x00 }, [BAM_P_FIFO_SIZES] = { 0x1020, 0x00, 0x40, 0x00 }, + [BAM_P_TRUST_REG] = { 0x1030, 0x1000, 0x00, 0x00 }, }; static const struct reg_offset_data bam_v1_4_reg_info[] = { @@ -167,6 +178,7 @@ [BAM_P_DESC_FIFO_ADDR] = { 0x181C, 0x00, 0x1000, 0x00 }, [BAM_P_EVNT_GEN_TRSHLD] = { 0x1828, 0x00, 0x1000, 0x00 }, [BAM_P_FIFO_SIZES] = { 0x1820, 0x00, 0x1000, 0x00 }, + [BAM_P_TRUST_REG] = { 0x1030, 0x1000, 0x00, 0x00 }, }; static const struct reg_offset_data bam_v1_7_reg_info[] = { @@ -196,6 +208,8 @@ [BAM_P_DESC_FIFO_ADDR] = { 0x1381C, 0x00, 0x1000, 0x00 }, [BAM_P_EVNT_GEN_TRSHLD] = { 0x13828, 0x00, 0x1000, 0x00 }, [BAM_P_FIFO_SIZES] = { 0x13820, 0x00, 0x1000, 0x00 }, + [BAM_TRUST_REG] = { 0x02000, 0x04, 0x00, 0x00 }, + [BAM_P_TRUST_REG] = { 0x02020, 0x04, 0x00, 0x00 }, }; /* BAM CTRL */ @@ -388,10 +402,12 @@ /* execution environment ID, from DT */ u32 ee; - bool controlled_remotely; + u32 controlled_remotely; + u32 config_pipe_trust_reg; const struct reg_offset_data *layout; + struct clk *iface_clk; struct clk *bamclk; int irq; @@ -473,6 +489,16 @@ val |= BIT(bchan->id); writel_relaxed(val, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); + /* BAM Trusted configurations: set the configuration of the + * pipe interrupt to the EE configured in the dts + */ + if ((bdev->config_pipe_trust_reg == 1) && !bdev->controlled_remotely) { + val = readl_relaxed(bam_addr(bdev, bchan->id, BAM_P_TRUST_REG)); + val &= PIPE_TRUST_REG_MASK; + val |= bdev->ee; + writel_relaxed(val, bam_addr(bdev, bchan->id, BAM_P_TRUST_REG)); + } + /* don't allow cpu to reorder the channel enable done below */ wmb(); @@ -628,7 +654,7 @@ /* allocate enough room to accomodate the number of entries */ async_desc = kzalloc(struct_size(async_desc, desc, num_alloc), - GFP_NOWAIT); + GFP_ATOMIC); if (!async_desc) goto err_out; @@ -645,6 +671,13 @@ /* fill in temporary descriptors */ desc = async_desc->desc; + if (flags & DMA_PREP_CMD) { + if (flags & DMA_PREP_LOCK) + desc->flags |= cpu_to_le16(DESC_FLAG_LOCK); + if (flags & DMA_PREP_UNLOCK) + desc->flags |= cpu_to_le16(DESC_FLAG_UNLOCK); + } + for_each_sg(sgl, sg, sg_len, i) { unsigned int remainder = sg_dma_len(sg); unsigned int curr_offset = 0; @@ -1152,7 +1185,7 @@ */ static int bam_init(struct bam_device *bdev) { - u32 val; + u32 val, i, ee; /* read revision and configuration information */ if (!bdev->num_ees) { @@ -1201,6 +1234,27 @@ /* unmask global bam interrupt */ writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); + if (bdev->config_pipe_trust_reg == 2) { + ee = bdev->ee; + val = readl_relaxed(bam_addr(bdev, 0, BAM_TRUST_REG)); + val |= BAM_TRUST_LOCK_EE_CTRL; + writel_relaxed(val, bam_addr(bdev, 0, BAM_TRUST_REG)); + + for (i = 2; i < 8; i+=2) { + val = readl_relaxed(bam_addr(bdev, i, BAM_P_TRUST_REG)); + val &= PIPE_TRUST_REG_MASK; + val |= ee; + writel_relaxed(val, + bam_addr(bdev, i, BAM_P_TRUST_REG)); + + val = readl_relaxed(bam_addr(bdev, i+1, BAM_P_TRUST_REG)); + val &= PIPE_TRUST_REG_MASK; + val |= ee; + writel_relaxed(val, + bam_addr(bdev, i+1, BAM_P_TRUST_REG)); + ++ee; + } + } return 0; } @@ -1260,25 +1314,62 @@ return ret; } - bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node, - "qcom,controlled-remotely"); + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,controlled-remotely", + &bdev->controlled_remotely); + if (ret) + dev_warn(bdev->dev, "qcom,controlled-remotely unspecified\n"); if (bdev->controlled_remotely) { ret = of_property_read_u32(pdev->dev.of_node, "num-channels", &bdev->num_channels); if (ret) - dev_err(bdev->dev, "num-channels unspecified in dt\n"); + dev_warn(bdev->dev, "num-channels unspecified in dt\n"); ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees", &bdev->num_ees); if (ret) - dev_err(bdev->dev, "num-ees unspecified in dt\n"); + dev_warn(bdev->dev, "num-ees unspecified in dt\n"); } - bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); - if (IS_ERR(bdev->bamclk)) { + bdev->iface_clk = devm_clk_get_optional(bdev->dev, "iface_clk"); + if (IS_ERR(bdev->iface_clk)) { if (!bdev->controlled_remotely) - return PTR_ERR(bdev->bamclk); + return PTR_ERR(bdev->iface_clk); + + bdev->iface_clk = NULL; + } + + ret = clk_prepare_enable(bdev->iface_clk); + if (ret) { + dev_err(bdev->dev, "failed to prepare/enable iface clock\n"); + return ret; + } + + ret = of_property_read_u32(pdev->dev.of_node, + "qti,config-pipe-trust-reg", + &bdev->config_pipe_trust_reg); + +#if defined(CONFIG_ARCH_IPQ9574) + if (bdev->config_pipe_trust_reg == 2 && + !(avm_tz_supported_features() & AVM_TZ_FEAT_IPSEC_XPU_ENABLED)) { + bdev->config_pipe_trust_reg = 0; + bdev->controlled_remotely = 1; + + /* Print configuration which was finally configured to make + * directly visible if we configured correctly + */ + dev_info(bdev->dev, + "Fallback to no IPSec HW Support\n"); + } +#endif /* CONFIG_ARCH_IPQ9574 */ + + bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk"); + if (IS_ERR(bdev->bamclk)) { + if (!bdev->controlled_remotely) { + ret = PTR_ERR(bdev->bamclk); + goto err_disable_iface_clk; + } bdev->bamclk = NULL; } @@ -1286,7 +1377,7 @@ ret = clk_prepare_enable(bdev->bamclk); if (ret) { dev_err(bdev->dev, "failed to prepare/enable clock\n"); - return ret; + goto err_disable_iface_clk; } ret = bam_init(bdev); @@ -1379,6 +1470,8 @@ tasklet_kill(&bdev->task); err_disable_clk: clk_disable_unprepare(bdev->bamclk); +err_disable_iface_clk: + clk_disable_unprepare(bdev->iface_clk); return ret; } @@ -1413,6 +1506,7 @@ tasklet_kill(&bdev->task); clk_disable_unprepare(bdev->bamclk); + clk_disable_unprepare(bdev->iface_clk); return 0; } @@ -1422,6 +1516,7 @@ struct bam_device *bdev = dev_get_drvdata(dev); clk_disable(bdev->bamclk); + clk_disable(bdev->iface_clk); return 0; } @@ -1431,8 +1526,15 @@ struct bam_device *bdev = dev_get_drvdata(dev); int ret; + ret = clk_enable(bdev->iface_clk); + if (ret < 0) { + dev_err(dev, "iface clk_enable failed: %d\n", ret); + return ret; + } + ret = clk_enable(bdev->bamclk); if (ret < 0) { + clk_disable(bdev->iface_clk); dev_err(dev, "clk_enable failed: %d\n", ret); return ret; } @@ -1448,6 +1550,7 @@ pm_runtime_force_suspend(dev); clk_unprepare(bdev->bamclk); + clk_unprepare(bdev->iface_clk); return 0; } @@ -1457,10 +1560,16 @@ struct bam_device *bdev = dev_get_drvdata(dev); int ret; - ret = clk_prepare(bdev->bamclk); + ret = clk_prepare(bdev->iface_clk); if (ret) return ret; + ret = clk_prepare(bdev->bamclk); + if (ret) { + clk_unprepare(bdev->iface_clk); + return ret; + } + if (!bdev->controlled_remotely) pm_runtime_force_resume(dev);