mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-31 00:24:12 +00:00
ipq40xx: 5.10: drop upstreamed patches
Drop patches that have been upstreamed in before 5.10. Signed-off-by: Robert Marko <robert.marko@sartura.hr>
This commit is contained in:
parent
8f27ac5ec0
commit
9fe5516ee5
@ -1,42 +0,0 @@
|
||||
From f125e2d4339dda6937865f975470b29c84714c9b Mon Sep 17 00:00:00 2001
|
||||
From: Christian Lamparter <chunkeey@gmail.com>
|
||||
Date: Mon, 6 Jan 2020 14:57:15 +0100
|
||||
Subject: [PATCH] ARM: qcom: Add support for IPQ40xx
|
||||
|
||||
Add support for the Qualcomm IPQ40xx SoC in Kconfig.
|
||||
Also add its appropriate textofs.
|
||||
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Tested-by: Robert Marko <robert.marko@sartura.hr>
|
||||
Cc: Luka Perkov <luka.perkov@sartura.hr>
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
---
|
||||
arch/arm/Makefile | 1 +
|
||||
arch/arm/mach-qcom/Kconfig | 5 +++++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
--- a/arch/arm/Makefile
|
||||
+++ b/arch/arm/Makefile
|
||||
@@ -152,6 +152,7 @@ textofs-$(CONFIG_PM_H1940) := 0x001
|
||||
ifeq ($(CONFIG_ARCH_SA1100),y)
|
||||
textofs-$(CONFIG_SA1111) := 0x00208000
|
||||
endif
|
||||
+textofs-$(CONFIG_ARCH_IPQ40XX) := 0x00208000
|
||||
textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
|
||||
textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
|
||||
textofs-$(CONFIG_ARCH_MESON) := 0x00208000
|
||||
--- a/arch/arm/mach-qcom/Kconfig
|
||||
+++ b/arch/arm/mach-qcom/Kconfig
|
||||
@@ -12,6 +12,11 @@ menuconfig ARCH_QCOM
|
||||
|
||||
if ARCH_QCOM
|
||||
|
||||
+config ARCH_IPQ40XX
|
||||
+ bool "Enable support for IPQ40XX"
|
||||
+ select CLKSRC_QCOM
|
||||
+ select HAVE_ARM_ARCH_TIMER
|
||||
+
|
||||
config ARCH_MSM8X60
|
||||
bool "Enable support for MSM8X60"
|
||||
select CLKSRC_QCOM
|
@ -1,153 +0,0 @@
|
||||
From 97043d292365ae39d62b54a6d79dff98d048b501 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
Date: Wed, 22 Jan 2020 12:44:14 +0100
|
||||
Subject: [PATCH] From ebf652b408200504194be32ad0a3f5bb49d6000a Mon Sep 17
|
||||
00:00:00 2001 From: Robert Marko <robert.marko@sartura.hr> Date: Sun, 12 Jan
|
||||
2020 12:30:01 +0100 Subject: [PATCH] regulator: add IPQ4019 SDHCI VQMMC LDO
|
||||
driver
|
||||
|
||||
This introduces the IPQ4019 VQMMC LDO driver needed for
|
||||
the SD/EMMC driver I/O level operation.
|
||||
This will enable introducing SD/EMMC support for the built-in controller.
|
||||
|
||||
Signed-off-by: Mantas Pucka <mantas@8devices.com>
|
||||
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
Link: https://lore.kernel.org/r/20200112113003.11110-1-robert.marko@sartura.hr
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/regulator/Kconfig | 7 ++
|
||||
drivers/regulator/Makefile | 1 +
|
||||
drivers/regulator/vqmmc-ipq4019-regulator.c | 101 ++++++++++++++++++++
|
||||
3 files changed, 109 insertions(+)
|
||||
create mode 100644 drivers/regulator/vqmmc-ipq4019-regulator.c
|
||||
|
||||
--- a/drivers/regulator/Kconfig
|
||||
+++ b/drivers/regulator/Kconfig
|
||||
@@ -1077,6 +1077,13 @@ config REGULATOR_VEXPRESS
|
||||
This driver provides support for voltage regulators available
|
||||
on the ARM Ltd's Versatile Express platform.
|
||||
|
||||
+config REGULATOR_VQMMC_IPQ4019
|
||||
+ tristate "IPQ4019 VQMMC SD LDO regulator support"
|
||||
+ depends on ARCH_QCOM
|
||||
+ help
|
||||
+ This driver provides support for the VQMMC LDO I/0
|
||||
+ voltage regulator of the IPQ4019 SD/EMMC controller.
|
||||
+
|
||||
config REGULATOR_WM831X
|
||||
tristate "Wolfson Microelectronics WM831x PMIC regulators"
|
||||
depends on MFD_WM831X
|
||||
--- a/drivers/regulator/Makefile
|
||||
+++ b/drivers/regulator/Makefile
|
||||
@@ -132,6 +132,7 @@ obj-$(CONFIG_REGULATOR_TWL4030) += twl-r
|
||||
obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
|
||||
+obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/regulator/vqmmc-ipq4019-regulator.c
|
||||
@@ -0,0 +1,101 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+//
|
||||
+// Copyright (c) 2019 Mantas Pucka <mantas@8devices.com>
|
||||
+// Copyright (c) 2019 Robert Marko <robert.marko@sartura.hr>
|
||||
+//
|
||||
+// Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator
|
||||
+
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/regulator/driver.h>
|
||||
+#include <linux/regulator/machine.h>
|
||||
+#include <linux/regulator/of_regulator.h>
|
||||
+
|
||||
+static const unsigned int ipq4019_vmmc_voltages[] = {
|
||||
+ 1500000, 1800000, 2500000, 3000000,
|
||||
+};
|
||||
+
|
||||
+static const struct regulator_ops ipq4019_regulator_voltage_ops = {
|
||||
+ .list_voltage = regulator_list_voltage_table,
|
||||
+ .map_voltage = regulator_map_voltage_ascend,
|
||||
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
+};
|
||||
+
|
||||
+static const struct regulator_desc vmmc_regulator = {
|
||||
+ .name = "vmmcq",
|
||||
+ .ops = &ipq4019_regulator_voltage_ops,
|
||||
+ .type = REGULATOR_VOLTAGE,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .volt_table = ipq4019_vmmc_voltages,
|
||||
+ .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages),
|
||||
+ .vsel_reg = 0,
|
||||
+ .vsel_mask = 0x3,
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_config ipq4019_vmmcq_regmap_config = {
|
||||
+ .reg_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .val_bits = 32,
|
||||
+};
|
||||
+
|
||||
+static int ipq4019_regulator_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct regulator_init_data *init_data;
|
||||
+ struct regulator_config cfg = {};
|
||||
+ struct regulator_dev *rdev;
|
||||
+ struct resource *res;
|
||||
+ struct regmap *rmap;
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ init_data = of_get_regulator_init_data(dev, dev->of_node,
|
||||
+ &vmmc_regulator);
|
||||
+ if (!init_data)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ base = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config);
|
||||
+ if (IS_ERR(rmap))
|
||||
+ return PTR_ERR(rmap);
|
||||
+
|
||||
+ cfg.dev = dev;
|
||||
+ cfg.init_data = init_data;
|
||||
+ cfg.of_node = dev->of_node;
|
||||
+ cfg.regmap = rmap;
|
||||
+
|
||||
+ rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg);
|
||||
+ if (IS_ERR(rdev)) {
|
||||
+ dev_err(dev, "Failed to register regulator: %ld\n",
|
||||
+ PTR_ERR(rdev));
|
||||
+ return PTR_ERR(rdev);
|
||||
+ }
|
||||
+ platform_set_drvdata(pdev, rdev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id regulator_ipq4019_of_match[] = {
|
||||
+ { .compatible = "qcom,vqmmc-ipq4019-regulator", },
|
||||
+ {},
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver ipq4019_regulator_driver = {
|
||||
+ .probe = ipq4019_regulator_probe,
|
||||
+ .driver = {
|
||||
+ .name = "vqmmc-ipq4019-regulator",
|
||||
+ .of_match_table = of_match_ptr(regulator_ipq4019_of_match),
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(ipq4019_regulator_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Mantas Pucka <mantas@8devices.com>");
|
||||
+MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator");
|
@ -1,36 +0,0 @@
|
||||
From 04b3b72b5b8fdb883bfdc619cb29b03641b1cc6a Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Thu, 15 Aug 2019 19:28:23 +0200
|
||||
Subject: [PATCH] ARM: dts: qcom: ipq4019: Add SDHCI controller node
|
||||
|
||||
IPQ4019 has a built in SD/eMMC controller which is supported by the
|
||||
SDHCI MSM driver, by the "qcom,sdhci-msm-v4" binding.
|
||||
So lets add the appropriate node for it.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
---
|
||||
arch/arm/boot/dts/qcom-ipq4019.dtsi | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
@@ -206,6 +206,18 @@
|
||||
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
+ sdhci: sdhci@7824900 {
|
||||
+ compatible = "qcom,sdhci-msm-v4";
|
||||
+ reg = <0x7824900 0x11c>, <0x7824000 0x800>;
|
||||
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "hc_irq", "pwr_irq";
|
||||
+ bus-width = <8>;
|
||||
+ clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>,
|
||||
+ <&gcc GCC_DCD_XO_CLK>;
|
||||
+ clock-names = "core", "iface", "xo";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
blsp_dma: dma@7884000 {
|
||||
compatible = "qcom,bam-v1.7.0";
|
||||
reg = <0x07884000 0x23000>;
|
@ -1,71 +0,0 @@
|
||||
From 5e4548922009870a38bcf1d887317676d4e08f54 Mon Sep 17 00:00:00 2001
|
||||
From: Damir Franusic <damir.franusic@sartura.hr>
|
||||
Date: Thu, 21 Nov 2019 16:29:02 +0100
|
||||
Subject: [PATCH] ARM: dts: qcom: Add nodes for SMP boot in IPQ40xx
|
||||
|
||||
Add missing nodes and properties to enable SMP
|
||||
support on IPQ40xx devices.
|
||||
|
||||
Booting without "saw_l2" node:
|
||||
|
||||
[ 0.001400] CPU: Testing write buffer coherency: ok
|
||||
[ 0.001856] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
|
||||
[ 0.060163] Setting up static identity map for 0x80300000 - 0x80300060
|
||||
[ 0.080140] rcu: Hierarchical SRCU implementation.
|
||||
[ 0.120258] smp: Bringing up secondary CPUs ...
|
||||
[ 0.200540] CPU1: failed to boot: -19
|
||||
[ 0.280689] CPU2: failed to boot: -19
|
||||
[ 0.360874] CPU3: failed to boot: -19
|
||||
[ 0.360966] smp: Brought up 1 node, 1 CPU
|
||||
[ 0.360979] SMP: Total of 1 processors activated (96.00 BogoMIPS).
|
||||
[ 0.360988] CPU: All CPU(s) started in SVC mode.
|
||||
|
||||
Then, booting with "saw_l2" node present (this patch applied):
|
||||
|
||||
[ 0.001450] CPU: Testing write buffer coherency: ok
|
||||
[ 0.001904] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
|
||||
[ 0.060161] Setting up static identity map for 0x80300000 - 0x80300060
|
||||
[ 0.080137] rcu: Hierarchical SRCU implementation.
|
||||
[ 0.120252] smp: Bringing up secondary CPUs ...
|
||||
[ 0.200958] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
|
||||
[ 0.281091] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002
|
||||
[ 0.361264] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003
|
||||
[ 0.361430] smp: Brought up 1 node, 4 CPUs
|
||||
[ 0.361460] SMP: Total of 4 processors activated (384.00 BogoMIPS).
|
||||
[ 0.361469] CPU: All CPU(s) started in SVC mode.
|
||||
|
||||
Signed-off-by: Damir Franusic <damir.franusic@sartura.hr>
|
||||
Cc: Luka Perkov <luka.perkov@sartura.hr>
|
||||
Cc: Robert Marko <robert.marko@sartura.hr>
|
||||
Cc: Andy Gross <agross@kernel.org>
|
||||
Cc: Rob Herring <robh+dt@kernel.org>
|
||||
Cc: linux-arm-msm@vger.kernel.org
|
||||
Link: https://lore.kernel.org/r/20191121152902.21394-1-damir.franusic@gmail.com
|
||||
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
---
|
||||
arch/arm/boot/dts/qcom-ipq4019.dtsi | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
@@ -102,6 +102,7 @@
|
||||
L2: l2-cache {
|
||||
compatible = "cache";
|
||||
cache-level = <2>;
|
||||
+ qcom,saw = <&saw_l2>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -353,6 +354,12 @@
|
||||
regulator;
|
||||
};
|
||||
|
||||
+ saw_l2: regulator@b012000 {
|
||||
+ compatible = "qcom,saw2";
|
||||
+ reg = <0xb012000 0x1000>;
|
||||
+ regulator;
|
||||
+ };
|
||||
+
|
||||
blsp1_uart1: serial@78af000 {
|
||||
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
|
||||
reg = <0x78af000 0x200>;
|
@ -1,119 +0,0 @@
|
||||
From 8b99dc0922618062a1589ebd74df6108b4f9ac22 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Lamparter <chunkeey@gmail.com>
|
||||
Date: Wed, 8 Jan 2020 13:54:55 +0100
|
||||
Subject: [PATCH] ARM: dts: qcom: add gpio-ranges property
|
||||
|
||||
This patch adds the gpio-ranges property to almost all of
|
||||
the Qualcomm ARM platforms that utilize the pinctrl-msm
|
||||
framework.
|
||||
|
||||
The gpio-ranges property is part of the gpiolib subsystem.
|
||||
As a result, the binding text is available in section
|
||||
"2.1 gpio- and pin-controller interaction" of
|
||||
Documentation/devicetree/bindings/gpio/gpio.txt
|
||||
|
||||
For more information please see the patch titled:
|
||||
"pinctrl: msm: fix gpio-hog related boot issues" from
|
||||
this series.
|
||||
|
||||
Reported-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
|
||||
Tested-by: Sven Eckelmann <sven.eckelmann@openmesh.com> [ipq4019]
|
||||
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Tested-by: Robert Marko <robert.marko@sartura.hr> [ipq4019]
|
||||
Cc: Luka Perkov <luka.perkov@sartura.hr>
|
||||
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
Link: https://lore.kernel.org/r/20200108125455.308969-1-robert.marko@sartura.hr
|
||||
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
---
|
||||
arch/arm/boot/dts/qcom-apq8064.dtsi | 1 +
|
||||
arch/arm/boot/dts/qcom-apq8084.dtsi | 1 +
|
||||
arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 +
|
||||
arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 +
|
||||
arch/arm/boot/dts/qcom-mdm9615.dtsi | 1 +
|
||||
arch/arm/boot/dts/qcom-msm8660.dtsi | 1 +
|
||||
arch/arm/boot/dts/qcom-msm8960.dtsi | 1 +
|
||||
arch/arm/boot/dts/qcom-msm8974.dtsi | 1 +
|
||||
8 files changed, 8 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
|
||||
@@ -350,6 +350,7 @@
|
||||
reg = <0x800000 0x4000>;
|
||||
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&tlmm_pinmux 0 0 90>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
|
||||
@@ -401,6 +401,7 @@
|
||||
compatible = "qcom,apq8084-pinctrl";
|
||||
reg = <0xfd510000 0x4000>;
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&tlmm 0 0 147>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
@@ -201,6 +201,7 @@
|
||||
compatible = "qcom,ipq4019-pinctrl";
|
||||
reg = <0x01000000 0x300000>;
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&tlmm 0 0 100>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||
@@ -119,6 +119,7 @@
|
||||
reg = <0x800000 0x4000>;
|
||||
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&qcom_pinmux 0 0 69>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
--- a/arch/arm/boot/dts/qcom-mdm9615.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi
|
||||
@@ -128,6 +128,7 @@
|
||||
msmgpio: pinctrl@800000 {
|
||||
compatible = "qcom,mdm9615-pinctrl";
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&msmgpio 0 0 88>;
|
||||
#gpio-cells = <2>;
|
||||
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
--- a/arch/arm/boot/dts/qcom-msm8660.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi
|
||||
@@ -115,6 +115,7 @@
|
||||
reg = <0x800000 0x4000>;
|
||||
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&tlmm 0 0 173>;
|
||||
#gpio-cells = <2>;
|
||||
interrupts = <0 16 0x4>;
|
||||
interrupt-controller;
|
||||
--- a/arch/arm/boot/dts/qcom-msm8960.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi
|
||||
@@ -107,6 +107,7 @@
|
||||
msmgpio: pinctrl@800000 {
|
||||
compatible = "qcom,msm8960-pinctrl";
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&msmgpio 0 0 152>;
|
||||
#gpio-cells = <2>;
|
||||
interrupts = <0 16 0x4>;
|
||||
interrupt-controller;
|
||||
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
|
||||
@@ -707,6 +707,7 @@
|
||||
compatible = "qcom,msm8974-pinctrl";
|
||||
reg = <0xfd510000 0x4000>;
|
||||
gpio-controller;
|
||||
+ gpio-ranges = <&msmgpio 0 0 146>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
@ -1,33 +0,0 @@
|
||||
From 8acc36189dcaf4487d8c6ba7445948f39b1d248a Mon Sep 17 00:00:00 2001
|
||||
From: Abhishek Sahu <absahu@codeaurora.org>
|
||||
Date: Fri, 3 Apr 2020 13:40:40 +0200
|
||||
Subject: [PATCH] ARM: dts: qcom: ipq4019: fix high resolution timer
|
||||
|
||||
Cherry-picked from CAF QSDK repo.
|
||||
Original commit message:
|
||||
The kernel is failing in switching the timer for high resolution
|
||||
mode and clock source operates in 10ms resolution. The always-on
|
||||
property needs to be given for timer device tree node to make
|
||||
clock source working in 1ns resolution.
|
||||
|
||||
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
|
||||
Signed-off-by: Pavel Kubelun <be.dissent@gmail.com>
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Tested-by: Robert Marko <robert.marko@sartura.hr>
|
||||
Cc: Luka Perkov <luka.perkov@sartura.hr>
|
||||
Link: https://lore.kernel.org/r/20200403114040.349787-1-robert.marko@sartura.hr
|
||||
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
---
|
||||
arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
@@ -166,6 +166,7 @@
|
||||
<1 4 0xf08>,
|
||||
<1 1 0xf08>;
|
||||
clock-frequency = <48000000>;
|
||||
+ always-on;
|
||||
};
|
||||
|
||||
soc {
|
@ -1,210 +0,0 @@
|
||||
From 466ed24fb22342f3ae1c10758a6a0c6a8c081b2d Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
Date: Thu, 30 Apr 2020 11:07:05 +0200
|
||||
Subject: [PATCH] net: phy: mdio: add IPQ4019 MDIO driver
|
||||
|
||||
This patch adds the driver for the MDIO interface
|
||||
inside of Qualcomm IPQ40xx series SoC-s.
|
||||
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Cc: Luka Perkov <luka.perkov@sartura.hr>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/Kconfig | 7 ++
|
||||
drivers/net/phy/Makefile | 1 +
|
||||
drivers/net/phy/mdio-ipq4019.c | 160 +++++++++++++++++++++++++++++++++
|
||||
3 files changed, 168 insertions(+)
|
||||
create mode 100644 drivers/net/phy/mdio-ipq4019.c
|
||||
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -156,6 +156,13 @@ config MDIO_I2C
|
||||
|
||||
This is library mode.
|
||||
|
||||
+config MDIO_IPQ4019
|
||||
+ tristate "Qualcomm IPQ4019 MDIO interface support"
|
||||
+ depends on HAS_IOMEM && OF_MDIO
|
||||
+ help
|
||||
+ This driver supports the MDIO interface found in Qualcomm
|
||||
+ IPQ40xx series Soc-s.
|
||||
+
|
||||
config MDIO_MOXART
|
||||
tristate "MOXA ART MDIO interface support"
|
||||
depends on ARCH_MOXART || COMPILE_TEST
|
||||
--- a/drivers/net/phy/Makefile
|
||||
+++ b/drivers/net/phy/Makefile
|
||||
@@ -50,6 +50,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium
|
||||
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
|
||||
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
|
||||
obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o
|
||||
+obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
|
||||
obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
|
||||
obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
|
||||
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/phy/mdio-ipq4019.c
|
||||
@@ -0,0 +1,160 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved. */
|
||||
+/* Copyright (c) 2020 Sartura Ltd. */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/of_mdio.h>
|
||||
+#include <linux/phy.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#define MDIO_ADDR_REG 0x44
|
||||
+#define MDIO_DATA_WRITE_REG 0x48
|
||||
+#define MDIO_DATA_READ_REG 0x4c
|
||||
+#define MDIO_CMD_REG 0x50
|
||||
+#define MDIO_CMD_ACCESS_BUSY BIT(16)
|
||||
+#define MDIO_CMD_ACCESS_START BIT(8)
|
||||
+#define MDIO_CMD_ACCESS_CODE_READ 0
|
||||
+#define MDIO_CMD_ACCESS_CODE_WRITE 1
|
||||
+
|
||||
+#define ipq4019_MDIO_TIMEOUT 10000
|
||||
+#define ipq4019_MDIO_SLEEP 10
|
||||
+
|
||||
+struct ipq4019_mdio_data {
|
||||
+ void __iomem *membase;
|
||||
+};
|
||||
+
|
||||
+static int ipq4019_mdio_wait_busy(struct mii_bus *bus)
|
||||
+{
|
||||
+ struct ipq4019_mdio_data *priv = bus->priv;
|
||||
+ unsigned int busy;
|
||||
+
|
||||
+ return readl_poll_timeout(priv->membase + MDIO_CMD_REG, busy,
|
||||
+ (busy & MDIO_CMD_ACCESS_BUSY) == 0,
|
||||
+ ipq4019_MDIO_SLEEP, ipq4019_MDIO_TIMEOUT);
|
||||
+}
|
||||
+
|
||||
+static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||
+{
|
||||
+ struct ipq4019_mdio_data *priv = bus->priv;
|
||||
+ unsigned int cmd;
|
||||
+
|
||||
+ /* Reject clause 45 */
|
||||
+ if (regnum & MII_ADDR_C45)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (ipq4019_mdio_wait_busy(bus))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ /* issue the phy address and reg */
|
||||
+ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
|
||||
+
|
||||
+ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ;
|
||||
+
|
||||
+ /* issue read command */
|
||||
+ writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
+
|
||||
+ /* Wait read complete */
|
||||
+ if (ipq4019_mdio_wait_busy(bus))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ /* Read and return data */
|
||||
+ return readl(priv->membase + MDIO_DATA_READ_REG);
|
||||
+}
|
||||
+
|
||||
+static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
||||
+ u16 value)
|
||||
+{
|
||||
+ struct ipq4019_mdio_data *priv = bus->priv;
|
||||
+ unsigned int cmd;
|
||||
+
|
||||
+ /* Reject clause 45 */
|
||||
+ if (regnum & MII_ADDR_C45)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (ipq4019_mdio_wait_busy(bus))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ /* issue the phy address and reg */
|
||||
+ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
|
||||
+
|
||||
+ /* issue write data */
|
||||
+ writel(value, priv->membase + MDIO_DATA_WRITE_REG);
|
||||
+
|
||||
+ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE;
|
||||
+ /* issue write command */
|
||||
+ writel(cmd, priv->membase + MDIO_CMD_REG);
|
||||
+
|
||||
+ /* Wait write complete */
|
||||
+ if (ipq4019_mdio_wait_busy(bus))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq4019_mdio_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct ipq4019_mdio_data *priv;
|
||||
+ struct mii_bus *bus;
|
||||
+ int ret;
|
||||
+
|
||||
+ bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv));
|
||||
+ if (!bus)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ priv = bus->priv;
|
||||
+
|
||||
+ priv->membase = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(priv->membase))
|
||||
+ return PTR_ERR(priv->membase);
|
||||
+
|
||||
+ bus->name = "ipq4019_mdio";
|
||||
+ bus->read = ipq4019_mdio_read;
|
||||
+ bus->write = ipq4019_mdio_write;
|
||||
+ bus->parent = &pdev->dev;
|
||||
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id);
|
||||
+
|
||||
+ ret = of_mdiobus_register(bus, pdev->dev.of_node);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, bus);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq4019_mdio_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mii_bus *bus = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ mdiobus_unregister(bus);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id ipq4019_mdio_dt_ids[] = {
|
||||
+ { .compatible = "qcom,ipq4019-mdio" },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, ipq4019_mdio_dt_ids);
|
||||
+
|
||||
+static struct platform_driver ipq4019_mdio_driver = {
|
||||
+ .probe = ipq4019_mdio_probe,
|
||||
+ .remove = ipq4019_mdio_remove,
|
||||
+ .driver = {
|
||||
+ .name = "ipq4019-mdio",
|
||||
+ .of_match_table = ipq4019_mdio_dt_ids,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(ipq4019_mdio_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("ipq4019 MDIO interface driver");
|
||||
+MODULE_AUTHOR("Qualcomm Atheros");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
@ -1,57 +0,0 @@
|
||||
From 9c8c0f70ec6fdac2398632c723c48277be09b7c0 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
Date: Thu, 30 Apr 2020 11:07:07 +0200
|
||||
Subject: [PATCH] ARM: dts: qcom: ipq4019: add MDIO node
|
||||
|
||||
This patch adds the necessary MDIO interface node
|
||||
to the Qualcomm IPQ4019 DTSI.
|
||||
|
||||
Built-in QCA8337N switch is managed using it,
|
||||
and since we have a driver for it lets add it.
|
||||
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Cc: Luka Perkov <luka.perkov@sartura.hr>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
arch/arm/boot/dts/qcom-ipq4019.dtsi | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
@@ -577,5 +577,33 @@
|
||||
"legacy";
|
||||
status = "disabled";
|
||||
};
|
||||
+
|
||||
+ mdio: mdio@90000 {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ compatible = "qcom,ipq4019-mdio";
|
||||
+ reg = <0x90000 0x64>;
|
||||
+ status = "disabled";
|
||||
+
|
||||
+ ethphy0: ethernet-phy@0 {
|
||||
+ reg = <0>;
|
||||
+ };
|
||||
+
|
||||
+ ethphy1: ethernet-phy@1 {
|
||||
+ reg = <1>;
|
||||
+ };
|
||||
+
|
||||
+ ethphy2: ethernet-phy@2 {
|
||||
+ reg = <2>;
|
||||
+ };
|
||||
+
|
||||
+ ethphy3: ethernet-phy@3 {
|
||||
+ reg = <3>;
|
||||
+ };
|
||||
+
|
||||
+ ethphy4: ethernet-phy@4 {
|
||||
+ reg = <4>;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
};
|
@ -1,31 +0,0 @@
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Subject: [PATCH] crypto: qce - add CRYPTO_ALG_KERN_DRIVER_ONLY flag
|
||||
|
||||
Set the CRYPTO_ALG_KERN_DRIVER_ONLY flag to all algorithms exposed by
|
||||
the qce driver, since they are all hardware accelerated, accessible
|
||||
through a kernel driver only, and not available directly to userspace.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
|
||||
--- a/drivers/crypto/qce/ablkcipher.c
|
||||
+++ b/drivers/crypto/qce/ablkcipher.c
|
||||
@@ -380,7 +380,7 @@ static int qce_ablkcipher_register_one(c
|
||||
|
||||
alg->cra_priority = 300;
|
||||
alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
|
||||
- CRYPTO_ALG_NEED_FALLBACK;
|
||||
+ CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||
alg->cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||
alg->cra_alignmask = 0;
|
||||
alg->cra_type = &crypto_ablkcipher_type;
|
||||
--- a/drivers/crypto/qce/sha.c
|
||||
+++ b/drivers/crypto/qce/sha.c
|
||||
@@ -495,7 +495,7 @@ static int qce_ahash_register_one(const
|
||||
base = &alg->halg.base;
|
||||
base->cra_blocksize = def->blocksize;
|
||||
base->cra_priority = 300;
|
||||
- base->cra_flags = CRYPTO_ALG_ASYNC;
|
||||
+ base->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||
base->cra_ctxsize = sizeof(struct qce_sha_ctx);
|
||||
base->cra_alignmask = 0;
|
||||
base->cra_module = THIS_MODULE;
|
@ -1,993 +0,0 @@
|
||||
From f441873642eebf20566c18d2966a8cd4b433ec1c Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Tue, 5 Nov 2019 14:28:17 +0100
|
||||
Subject: [PATCH] crypto: qce - switch to skcipher API
|
||||
|
||||
Commit 7a7ffe65c8c5 ("crypto: skcipher - Add top-level skcipher interface")
|
||||
dated 20 august 2015 introduced the new skcipher API which is supposed to
|
||||
replace both blkcipher and ablkcipher. While all consumers of the API have
|
||||
been converted long ago, some producers of the ablkcipher remain, forcing
|
||||
us to keep the ablkcipher support routines alive, along with the matching
|
||||
code to expose [a]blkciphers via the skcipher API.
|
||||
|
||||
So switch this driver to the skcipher API, allowing us to finally drop the
|
||||
blkcipher code in the near future.
|
||||
|
||||
Reviewed-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Backported-to-4.19-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
|
||||
--- a/drivers/crypto/qce/Makefile
|
||||
+++ b/drivers/crypto/qce/Makefile
|
||||
@@ -4,4 +4,4 @@ qcrypto-objs := core.o \
|
||||
common.o \
|
||||
dma.o \
|
||||
sha.o \
|
||||
- ablkcipher.o
|
||||
+ skcipher.o
|
||||
--- a/drivers/crypto/qce/cipher.h
|
||||
+++ b/drivers/crypto/qce/cipher.h
|
||||
@@ -45,12 +45,12 @@ struct qce_cipher_reqctx {
|
||||
unsigned int cryptlen;
|
||||
};
|
||||
|
||||
-static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm)
|
||||
+static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm)
|
||||
{
|
||||
- struct crypto_alg *alg = tfm->__crt_alg;
|
||||
- return container_of(alg, struct qce_alg_template, alg.crypto);
|
||||
+ struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
|
||||
+ return container_of(alg, struct qce_alg_template, alg.skcipher);
|
||||
}
|
||||
|
||||
-extern const struct qce_algo_ops ablkcipher_ops;
|
||||
+extern const struct qce_algo_ops skcipher_ops;
|
||||
|
||||
#endif /* _CIPHER_H_ */
|
||||
--- a/drivers/crypto/qce/common.c
|
||||
+++ b/drivers/crypto/qce/common.c
|
||||
@@ -304,13 +304,13 @@ go_proc:
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req,
|
||||
+static int qce_setup_regs_skcipher(struct crypto_async_request *async_req,
|
||||
u32 totallen, u32 offset)
|
||||
{
|
||||
- struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
|
||||
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||
+ struct skcipher_request *req = skcipher_request_cast(async_req);
|
||||
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||
struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
|
||||
- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
|
||||
+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||
struct qce_device *qce = tmpl->qce;
|
||||
__be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0};
|
||||
__be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0};
|
||||
@@ -389,8 +389,8 @@ int qce_start(struct crypto_async_reques
|
||||
u32 offset)
|
||||
{
|
||||
switch (type) {
|
||||
- case CRYPTO_ALG_TYPE_ABLKCIPHER:
|
||||
- return qce_setup_regs_ablkcipher(async_req, totallen, offset);
|
||||
+ case CRYPTO_ALG_TYPE_SKCIPHER:
|
||||
+ return qce_setup_regs_skcipher(async_req, totallen, offset);
|
||||
case CRYPTO_ALG_TYPE_AHASH:
|
||||
return qce_setup_regs_ahash(async_req, totallen, offset);
|
||||
default:
|
||||
--- a/drivers/crypto/qce/common.h
|
||||
+++ b/drivers/crypto/qce/common.h
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/hash.h>
|
||||
+#include <crypto/internal/skcipher.h>
|
||||
|
||||
/* key size in bytes */
|
||||
#define QCE_SHA_HMAC_KEY_SIZE 64
|
||||
@@ -79,7 +80,7 @@ struct qce_alg_template {
|
||||
unsigned long alg_flags;
|
||||
const u32 *std_iv;
|
||||
union {
|
||||
- struct crypto_alg crypto;
|
||||
+ struct skcipher_alg skcipher;
|
||||
struct ahash_alg ahash;
|
||||
} alg;
|
||||
struct qce_device *qce;
|
||||
--- a/drivers/crypto/qce/core.c
|
||||
+++ b/drivers/crypto/qce/core.c
|
||||
@@ -22,7 +22,7 @@
|
||||
#define QCE_QUEUE_LENGTH 1
|
||||
|
||||
static const struct qce_algo_ops *qce_ops[] = {
|
||||
- &ablkcipher_ops,
|
||||
+ &skcipher_ops,
|
||||
&ahash_ops,
|
||||
};
|
||||
|
||||
--- a/drivers/crypto/qce/ablkcipher.c
|
||||
+++ /dev/null
|
||||
@@ -1,440 +0,0 @@
|
||||
-// SPDX-License-Identifier: GPL-2.0-only
|
||||
-/*
|
||||
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
|
||||
- */
|
||||
-
|
||||
-#include <linux/device.h>
|
||||
-#include <linux/interrupt.h>
|
||||
-#include <linux/types.h>
|
||||
-#include <crypto/aes.h>
|
||||
-#include <crypto/internal/des.h>
|
||||
-#include <crypto/internal/skcipher.h>
|
||||
-
|
||||
-#include "cipher.h"
|
||||
-
|
||||
-static LIST_HEAD(ablkcipher_algs);
|
||||
-
|
||||
-static void qce_ablkcipher_done(void *data)
|
||||
-{
|
||||
- struct crypto_async_request *async_req = data;
|
||||
- struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
|
||||
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||
- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
|
||||
- struct qce_device *qce = tmpl->qce;
|
||||
- enum dma_data_direction dir_src, dir_dst;
|
||||
- u32 status;
|
||||
- int error;
|
||||
- bool diff_dst;
|
||||
-
|
||||
- diff_dst = (req->src != req->dst) ? true : false;
|
||||
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||
-
|
||||
- error = qce_dma_terminate_all(&qce->dma);
|
||||
- if (error)
|
||||
- dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n",
|
||||
- error);
|
||||
-
|
||||
- if (diff_dst)
|
||||
- dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
|
||||
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||
-
|
||||
- sg_free_table(&rctx->dst_tbl);
|
||||
-
|
||||
- error = qce_check_status(qce, &status);
|
||||
- if (error < 0)
|
||||
- dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status);
|
||||
-
|
||||
- qce->async_req_done(tmpl->qce, error);
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
|
||||
-{
|
||||
- struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
|
||||
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||
- struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||
- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
|
||||
- struct qce_device *qce = tmpl->qce;
|
||||
- enum dma_data_direction dir_src, dir_dst;
|
||||
- struct scatterlist *sg;
|
||||
- bool diff_dst;
|
||||
- gfp_t gfp;
|
||||
- int ret;
|
||||
-
|
||||
- rctx->iv = req->info;
|
||||
- rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||
- rctx->cryptlen = req->nbytes;
|
||||
-
|
||||
- diff_dst = (req->src != req->dst) ? true : false;
|
||||
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||
-
|
||||
- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes);
|
||||
- if (diff_dst)
|
||||
- rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes);
|
||||
- else
|
||||
- rctx->dst_nents = rctx->src_nents;
|
||||
- if (rctx->src_nents < 0) {
|
||||
- dev_err(qce->dev, "Invalid numbers of src SG.\n");
|
||||
- return rctx->src_nents;
|
||||
- }
|
||||
- if (rctx->dst_nents < 0) {
|
||||
- dev_err(qce->dev, "Invalid numbers of dst SG.\n");
|
||||
- return -rctx->dst_nents;
|
||||
- }
|
||||
-
|
||||
- rctx->dst_nents += 1;
|
||||
-
|
||||
- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
|
||||
- GFP_KERNEL : GFP_ATOMIC;
|
||||
-
|
||||
- ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||
-
|
||||
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
|
||||
- if (IS_ERR(sg)) {
|
||||
- ret = PTR_ERR(sg);
|
||||
- goto error_free;
|
||||
- }
|
||||
-
|
||||
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
|
||||
- if (IS_ERR(sg)) {
|
||||
- ret = PTR_ERR(sg);
|
||||
- goto error_free;
|
||||
- }
|
||||
-
|
||||
- sg_mark_end(sg);
|
||||
- rctx->dst_sg = rctx->dst_tbl.sgl;
|
||||
-
|
||||
- ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||
- if (ret < 0)
|
||||
- goto error_free;
|
||||
-
|
||||
- if (diff_dst) {
|
||||
- ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||
- if (ret < 0)
|
||||
- goto error_unmap_dst;
|
||||
- rctx->src_sg = req->src;
|
||||
- } else {
|
||||
- rctx->src_sg = rctx->dst_sg;
|
||||
- }
|
||||
-
|
||||
- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
|
||||
- rctx->dst_sg, rctx->dst_nents,
|
||||
- qce_ablkcipher_done, async_req);
|
||||
- if (ret)
|
||||
- goto error_unmap_src;
|
||||
-
|
||||
- qce_dma_issue_pending(&qce->dma);
|
||||
-
|
||||
- ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0);
|
||||
- if (ret)
|
||||
- goto error_terminate;
|
||||
-
|
||||
- return 0;
|
||||
-
|
||||
-error_terminate:
|
||||
- qce_dma_terminate_all(&qce->dma);
|
||||
-error_unmap_src:
|
||||
- if (diff_dst)
|
||||
- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||
-error_unmap_dst:
|
||||
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||
-error_free:
|
||||
- sg_free_table(&rctx->dst_tbl);
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
|
||||
- unsigned int keylen)
|
||||
-{
|
||||
- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk);
|
||||
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
- int ret;
|
||||
-
|
||||
- if (!key || !keylen)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- switch (keylen) {
|
||||
- case AES_KEYSIZE_128:
|
||||
- case AES_KEYSIZE_256:
|
||||
- break;
|
||||
- default:
|
||||
- goto fallback;
|
||||
- }
|
||||
-
|
||||
- ctx->enc_keylen = keylen;
|
||||
- memcpy(ctx->enc_key, key, keylen);
|
||||
- return 0;
|
||||
-fallback:
|
||||
- ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen);
|
||||
- if (!ret)
|
||||
- ctx->enc_keylen = keylen;
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int qce_des_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
|
||||
- unsigned int keylen)
|
||||
-{
|
||||
- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk);
|
||||
- int err;
|
||||
-
|
||||
- err = verify_ablkcipher_des_key(ablk, key);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- ctx->enc_keylen = keylen;
|
||||
- memcpy(ctx->enc_key, key, keylen);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int qce_des3_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
|
||||
- unsigned int keylen)
|
||||
-{
|
||||
- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk);
|
||||
- int err;
|
||||
-
|
||||
- err = verify_ablkcipher_des3_key(ablk, key);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- ctx->enc_keylen = keylen;
|
||||
- memcpy(ctx->enc_key, key, keylen);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt)
|
||||
-{
|
||||
- struct crypto_tfm *tfm =
|
||||
- crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
|
||||
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||
- struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
|
||||
- int ret;
|
||||
-
|
||||
- rctx->flags = tmpl->alg_flags;
|
||||
- rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||
-
|
||||
- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
|
||||
- ctx->enc_keylen != AES_KEYSIZE_256) {
|
||||
- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||
-
|
||||
- skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
||||
- skcipher_request_set_callback(subreq, req->base.flags,
|
||||
- NULL, NULL);
|
||||
- skcipher_request_set_crypt(subreq, req->src, req->dst,
|
||||
- req->nbytes, req->info);
|
||||
- ret = encrypt ? crypto_skcipher_encrypt(subreq) :
|
||||
- crypto_skcipher_decrypt(subreq);
|
||||
- skcipher_request_zero(subreq);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
|
||||
-}
|
||||
-
|
||||
-static int qce_ablkcipher_encrypt(struct ablkcipher_request *req)
|
||||
-{
|
||||
- return qce_ablkcipher_crypt(req, 1);
|
||||
-}
|
||||
-
|
||||
-static int qce_ablkcipher_decrypt(struct ablkcipher_request *req)
|
||||
-{
|
||||
- return qce_ablkcipher_crypt(req, 0);
|
||||
-}
|
||||
-
|
||||
-static int qce_ablkcipher_init(struct crypto_tfm *tfm)
|
||||
-{
|
||||
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
-
|
||||
- memset(ctx, 0, sizeof(*ctx));
|
||||
- tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx);
|
||||
-
|
||||
- ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(tfm),
|
||||
- 0, CRYPTO_ALG_NEED_FALLBACK);
|
||||
- return PTR_ERR_OR_ZERO(ctx->fallback);
|
||||
-}
|
||||
-
|
||||
-static void qce_ablkcipher_exit(struct crypto_tfm *tfm)
|
||||
-{
|
||||
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
-
|
||||
- crypto_free_sync_skcipher(ctx->fallback);
|
||||
-}
|
||||
-
|
||||
-struct qce_ablkcipher_def {
|
||||
- unsigned long flags;
|
||||
- const char *name;
|
||||
- const char *drv_name;
|
||||
- unsigned int blocksize;
|
||||
- unsigned int ivsize;
|
||||
- unsigned int min_keysize;
|
||||
- unsigned int max_keysize;
|
||||
-};
|
||||
-
|
||||
-static const struct qce_ablkcipher_def ablkcipher_def[] = {
|
||||
- {
|
||||
- .flags = QCE_ALG_AES | QCE_MODE_ECB,
|
||||
- .name = "ecb(aes)",
|
||||
- .drv_name = "ecb-aes-qce",
|
||||
- .blocksize = AES_BLOCK_SIZE,
|
||||
- .ivsize = AES_BLOCK_SIZE,
|
||||
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||
- },
|
||||
- {
|
||||
- .flags = QCE_ALG_AES | QCE_MODE_CBC,
|
||||
- .name = "cbc(aes)",
|
||||
- .drv_name = "cbc-aes-qce",
|
||||
- .blocksize = AES_BLOCK_SIZE,
|
||||
- .ivsize = AES_BLOCK_SIZE,
|
||||
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||
- },
|
||||
- {
|
||||
- .flags = QCE_ALG_AES | QCE_MODE_CTR,
|
||||
- .name = "ctr(aes)",
|
||||
- .drv_name = "ctr-aes-qce",
|
||||
- .blocksize = AES_BLOCK_SIZE,
|
||||
- .ivsize = AES_BLOCK_SIZE,
|
||||
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||
- },
|
||||
- {
|
||||
- .flags = QCE_ALG_AES | QCE_MODE_XTS,
|
||||
- .name = "xts(aes)",
|
||||
- .drv_name = "xts-aes-qce",
|
||||
- .blocksize = AES_BLOCK_SIZE,
|
||||
- .ivsize = AES_BLOCK_SIZE,
|
||||
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||
- },
|
||||
- {
|
||||
- .flags = QCE_ALG_DES | QCE_MODE_ECB,
|
||||
- .name = "ecb(des)",
|
||||
- .drv_name = "ecb-des-qce",
|
||||
- .blocksize = DES_BLOCK_SIZE,
|
||||
- .ivsize = 0,
|
||||
- .min_keysize = DES_KEY_SIZE,
|
||||
- .max_keysize = DES_KEY_SIZE,
|
||||
- },
|
||||
- {
|
||||
- .flags = QCE_ALG_DES | QCE_MODE_CBC,
|
||||
- .name = "cbc(des)",
|
||||
- .drv_name = "cbc-des-qce",
|
||||
- .blocksize = DES_BLOCK_SIZE,
|
||||
- .ivsize = DES_BLOCK_SIZE,
|
||||
- .min_keysize = DES_KEY_SIZE,
|
||||
- .max_keysize = DES_KEY_SIZE,
|
||||
- },
|
||||
- {
|
||||
- .flags = QCE_ALG_3DES | QCE_MODE_ECB,
|
||||
- .name = "ecb(des3_ede)",
|
||||
- .drv_name = "ecb-3des-qce",
|
||||
- .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||
- .ivsize = 0,
|
||||
- .min_keysize = DES3_EDE_KEY_SIZE,
|
||||
- .max_keysize = DES3_EDE_KEY_SIZE,
|
||||
- },
|
||||
- {
|
||||
- .flags = QCE_ALG_3DES | QCE_MODE_CBC,
|
||||
- .name = "cbc(des3_ede)",
|
||||
- .drv_name = "cbc-3des-qce",
|
||||
- .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||
- .ivsize = DES3_EDE_BLOCK_SIZE,
|
||||
- .min_keysize = DES3_EDE_KEY_SIZE,
|
||||
- .max_keysize = DES3_EDE_KEY_SIZE,
|
||||
- },
|
||||
-};
|
||||
-
|
||||
-static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def,
|
||||
- struct qce_device *qce)
|
||||
-{
|
||||
- struct qce_alg_template *tmpl;
|
||||
- struct crypto_alg *alg;
|
||||
- int ret;
|
||||
-
|
||||
- tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
|
||||
- if (!tmpl)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- alg = &tmpl->alg.crypto;
|
||||
-
|
||||
- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
|
||||
- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
|
||||
- def->drv_name);
|
||||
-
|
||||
- alg->cra_blocksize = def->blocksize;
|
||||
- alg->cra_ablkcipher.ivsize = def->ivsize;
|
||||
- alg->cra_ablkcipher.min_keysize = def->min_keysize;
|
||||
- alg->cra_ablkcipher.max_keysize = def->max_keysize;
|
||||
- alg->cra_ablkcipher.setkey = IS_3DES(def->flags) ? qce_des3_setkey :
|
||||
- IS_DES(def->flags) ? qce_des_setkey :
|
||||
- qce_ablkcipher_setkey;
|
||||
- alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt;
|
||||
- alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt;
|
||||
-
|
||||
- alg->cra_priority = 300;
|
||||
- alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
|
||||
- CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||
- alg->cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||
- alg->cra_alignmask = 0;
|
||||
- alg->cra_type = &crypto_ablkcipher_type;
|
||||
- alg->cra_module = THIS_MODULE;
|
||||
- alg->cra_init = qce_ablkcipher_init;
|
||||
- alg->cra_exit = qce_ablkcipher_exit;
|
||||
-
|
||||
- INIT_LIST_HEAD(&tmpl->entry);
|
||||
- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER;
|
||||
- tmpl->alg_flags = def->flags;
|
||||
- tmpl->qce = qce;
|
||||
-
|
||||
- ret = crypto_register_alg(alg);
|
||||
- if (ret) {
|
||||
- kfree(tmpl);
|
||||
- dev_err(qce->dev, "%s registration failed\n", alg->cra_name);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- list_add_tail(&tmpl->entry, &ablkcipher_algs);
|
||||
- dev_dbg(qce->dev, "%s is registered\n", alg->cra_name);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void qce_ablkcipher_unregister(struct qce_device *qce)
|
||||
-{
|
||||
- struct qce_alg_template *tmpl, *n;
|
||||
-
|
||||
- list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) {
|
||||
- crypto_unregister_alg(&tmpl->alg.crypto);
|
||||
- list_del(&tmpl->entry);
|
||||
- kfree(tmpl);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int qce_ablkcipher_register(struct qce_device *qce)
|
||||
-{
|
||||
- int ret, i;
|
||||
-
|
||||
- for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) {
|
||||
- ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce);
|
||||
- if (ret)
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-err:
|
||||
- qce_ablkcipher_unregister(qce);
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-const struct qce_algo_ops ablkcipher_ops = {
|
||||
- .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
|
||||
- .register_algs = qce_ablkcipher_register,
|
||||
- .unregister_algs = qce_ablkcipher_unregister,
|
||||
- .async_req_handle = qce_ablkcipher_async_req_handle,
|
||||
-};
|
||||
--- /dev/null
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -0,0 +1,440 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <crypto/aes.h>
|
||||
+#include <crypto/internal/des.h>
|
||||
+#include <crypto/internal/skcipher.h>
|
||||
+
|
||||
+#include "cipher.h"
|
||||
+
|
||||
+static LIST_HEAD(skcipher_algs);
|
||||
+
|
||||
+static void qce_skcipher_done(void *data)
|
||||
+{
|
||||
+ struct crypto_async_request *async_req = data;
|
||||
+ struct skcipher_request *req = skcipher_request_cast(async_req);
|
||||
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||
+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||
+ struct qce_device *qce = tmpl->qce;
|
||||
+ enum dma_data_direction dir_src, dir_dst;
|
||||
+ u32 status;
|
||||
+ int error;
|
||||
+ bool diff_dst;
|
||||
+
|
||||
+ diff_dst = (req->src != req->dst) ? true : false;
|
||||
+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||
+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||
+
|
||||
+ error = qce_dma_terminate_all(&qce->dma);
|
||||
+ if (error)
|
||||
+ dev_dbg(qce->dev, "skcipher dma termination error (%d)\n",
|
||||
+ error);
|
||||
+
|
||||
+ if (diff_dst)
|
||||
+ dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
|
||||
+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||
+
|
||||
+ sg_free_table(&rctx->dst_tbl);
|
||||
+
|
||||
+ error = qce_check_status(qce, &status);
|
||||
+ if (error < 0)
|
||||
+ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status);
|
||||
+
|
||||
+ qce->async_req_done(tmpl->qce, error);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qce_skcipher_async_req_handle(struct crypto_async_request *async_req)
|
||||
+{
|
||||
+ struct skcipher_request *req = skcipher_request_cast(async_req);
|
||||
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||
+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
|
||||
+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||
+ struct qce_device *qce = tmpl->qce;
|
||||
+ enum dma_data_direction dir_src, dir_dst;
|
||||
+ struct scatterlist *sg;
|
||||
+ bool diff_dst;
|
||||
+ gfp_t gfp;
|
||||
+ int ret;
|
||||
+
|
||||
+ rctx->iv = req->iv;
|
||||
+ rctx->ivsize = crypto_skcipher_ivsize(skcipher);
|
||||
+ rctx->cryptlen = req->cryptlen;
|
||||
+
|
||||
+ diff_dst = (req->src != req->dst) ? true : false;
|
||||
+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||
+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||
+
|
||||
+ rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen);
|
||||
+ if (diff_dst)
|
||||
+ rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen);
|
||||
+ else
|
||||
+ rctx->dst_nents = rctx->src_nents;
|
||||
+ if (rctx->src_nents < 0) {
|
||||
+ dev_err(qce->dev, "Invalid numbers of src SG.\n");
|
||||
+ return rctx->src_nents;
|
||||
+ }
|
||||
+ if (rctx->dst_nents < 0) {
|
||||
+ dev_err(qce->dev, "Invalid numbers of dst SG.\n");
|
||||
+ return -rctx->dst_nents;
|
||||
+ }
|
||||
+
|
||||
+ rctx->dst_nents += 1;
|
||||
+
|
||||
+ gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
|
||||
+ GFP_KERNEL : GFP_ATOMIC;
|
||||
+
|
||||
+ ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||
+
|
||||
+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
|
||||
+ if (IS_ERR(sg)) {
|
||||
+ ret = PTR_ERR(sg);
|
||||
+ goto error_free;
|
||||
+ }
|
||||
+
|
||||
+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
|
||||
+ if (IS_ERR(sg)) {
|
||||
+ ret = PTR_ERR(sg);
|
||||
+ goto error_free;
|
||||
+ }
|
||||
+
|
||||
+ sg_mark_end(sg);
|
||||
+ rctx->dst_sg = rctx->dst_tbl.sgl;
|
||||
+
|
||||
+ ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||
+ if (ret < 0)
|
||||
+ goto error_free;
|
||||
+
|
||||
+ if (diff_dst) {
|
||||
+ ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||
+ if (ret < 0)
|
||||
+ goto error_unmap_dst;
|
||||
+ rctx->src_sg = req->src;
|
||||
+ } else {
|
||||
+ rctx->src_sg = rctx->dst_sg;
|
||||
+ }
|
||||
+
|
||||
+ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
|
||||
+ rctx->dst_sg, rctx->dst_nents,
|
||||
+ qce_skcipher_done, async_req);
|
||||
+ if (ret)
|
||||
+ goto error_unmap_src;
|
||||
+
|
||||
+ qce_dma_issue_pending(&qce->dma);
|
||||
+
|
||||
+ ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0);
|
||||
+ if (ret)
|
||||
+ goto error_terminate;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+error_terminate:
|
||||
+ qce_dma_terminate_all(&qce->dma);
|
||||
+error_unmap_src:
|
||||
+ if (diff_dst)
|
||||
+ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||
+error_unmap_dst:
|
||||
+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||
+error_free:
|
||||
+ sg_free_table(&rctx->dst_tbl);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key,
|
||||
+ unsigned int keylen)
|
||||
+{
|
||||
+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk);
|
||||
+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!key || !keylen)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ switch (keylen) {
|
||||
+ case AES_KEYSIZE_128:
|
||||
+ case AES_KEYSIZE_256:
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto fallback;
|
||||
+ }
|
||||
+
|
||||
+ ctx->enc_keylen = keylen;
|
||||
+ memcpy(ctx->enc_key, key, keylen);
|
||||
+ return 0;
|
||||
+fallback:
|
||||
+ ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen);
|
||||
+ if (!ret)
|
||||
+ ctx->enc_keylen = keylen;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key,
|
||||
+ unsigned int keylen)
|
||||
+{
|
||||
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk);
|
||||
+ int err;
|
||||
+
|
||||
+ err = verify_skcipher_des_key(ablk, key);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ ctx->enc_keylen = keylen;
|
||||
+ memcpy(ctx->enc_key, key, keylen);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key,
|
||||
+ unsigned int keylen)
|
||||
+{
|
||||
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk);
|
||||
+ int err;
|
||||
+
|
||||
+ err = verify_skcipher_des3_key(ablk, key);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ ctx->enc_keylen = keylen;
|
||||
+ memcpy(ctx->enc_key, key, keylen);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt)
|
||||
+{
|
||||
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||
+ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
|
||||
+ int ret;
|
||||
+
|
||||
+ rctx->flags = tmpl->alg_flags;
|
||||
+ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||
+
|
||||
+ if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
|
||||
+ ctx->enc_keylen != AES_KEYSIZE_256) {
|
||||
+ SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||
+
|
||||
+ skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
||||
+ skcipher_request_set_callback(subreq, req->base.flags,
|
||||
+ NULL, NULL);
|
||||
+ skcipher_request_set_crypt(subreq, req->src, req->dst,
|
||||
+ req->cryptlen, req->iv);
|
||||
+ ret = encrypt ? crypto_skcipher_encrypt(subreq) :
|
||||
+ crypto_skcipher_decrypt(subreq);
|
||||
+ skcipher_request_zero(subreq);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
|
||||
+}
|
||||
+
|
||||
+static int qce_skcipher_encrypt(struct skcipher_request *req)
|
||||
+{
|
||||
+ return qce_skcipher_crypt(req, 1);
|
||||
+}
|
||||
+
|
||||
+static int qce_skcipher_decrypt(struct skcipher_request *req)
|
||||
+{
|
||||
+ return qce_skcipher_crypt(req, 0);
|
||||
+}
|
||||
+
|
||||
+static int qce_skcipher_init(struct crypto_skcipher *tfm)
|
||||
+{
|
||||
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
+
|
||||
+ memset(ctx, 0, sizeof(*ctx));
|
||||
+ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx));
|
||||
+
|
||||
+ ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base),
|
||||
+ 0, CRYPTO_ALG_NEED_FALLBACK);
|
||||
+ return PTR_ERR_OR_ZERO(ctx->fallback);
|
||||
+}
|
||||
+
|
||||
+static void qce_skcipher_exit(struct crypto_skcipher *tfm)
|
||||
+{
|
||||
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
+
|
||||
+ crypto_free_sync_skcipher(ctx->fallback);
|
||||
+}
|
||||
+
|
||||
+struct qce_skcipher_def {
|
||||
+ unsigned long flags;
|
||||
+ const char *name;
|
||||
+ const char *drv_name;
|
||||
+ unsigned int blocksize;
|
||||
+ unsigned int ivsize;
|
||||
+ unsigned int min_keysize;
|
||||
+ unsigned int max_keysize;
|
||||
+};
|
||||
+
|
||||
+static const struct qce_skcipher_def skcipher_def[] = {
|
||||
+ {
|
||||
+ .flags = QCE_ALG_AES | QCE_MODE_ECB,
|
||||
+ .name = "ecb(aes)",
|
||||
+ .drv_name = "ecb-aes-qce",
|
||||
+ .blocksize = AES_BLOCK_SIZE,
|
||||
+ .ivsize = AES_BLOCK_SIZE,
|
||||
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = QCE_ALG_AES | QCE_MODE_CBC,
|
||||
+ .name = "cbc(aes)",
|
||||
+ .drv_name = "cbc-aes-qce",
|
||||
+ .blocksize = AES_BLOCK_SIZE,
|
||||
+ .ivsize = AES_BLOCK_SIZE,
|
||||
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = QCE_ALG_AES | QCE_MODE_CTR,
|
||||
+ .name = "ctr(aes)",
|
||||
+ .drv_name = "ctr-aes-qce",
|
||||
+ .blocksize = AES_BLOCK_SIZE,
|
||||
+ .ivsize = AES_BLOCK_SIZE,
|
||||
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = QCE_ALG_AES | QCE_MODE_XTS,
|
||||
+ .name = "xts(aes)",
|
||||
+ .drv_name = "xts-aes-qce",
|
||||
+ .blocksize = AES_BLOCK_SIZE,
|
||||
+ .ivsize = AES_BLOCK_SIZE,
|
||||
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = QCE_ALG_DES | QCE_MODE_ECB,
|
||||
+ .name = "ecb(des)",
|
||||
+ .drv_name = "ecb-des-qce",
|
||||
+ .blocksize = DES_BLOCK_SIZE,
|
||||
+ .ivsize = 0,
|
||||
+ .min_keysize = DES_KEY_SIZE,
|
||||
+ .max_keysize = DES_KEY_SIZE,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = QCE_ALG_DES | QCE_MODE_CBC,
|
||||
+ .name = "cbc(des)",
|
||||
+ .drv_name = "cbc-des-qce",
|
||||
+ .blocksize = DES_BLOCK_SIZE,
|
||||
+ .ivsize = DES_BLOCK_SIZE,
|
||||
+ .min_keysize = DES_KEY_SIZE,
|
||||
+ .max_keysize = DES_KEY_SIZE,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = QCE_ALG_3DES | QCE_MODE_ECB,
|
||||
+ .name = "ecb(des3_ede)",
|
||||
+ .drv_name = "ecb-3des-qce",
|
||||
+ .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||
+ .ivsize = 0,
|
||||
+ .min_keysize = DES3_EDE_KEY_SIZE,
|
||||
+ .max_keysize = DES3_EDE_KEY_SIZE,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = QCE_ALG_3DES | QCE_MODE_CBC,
|
||||
+ .name = "cbc(des3_ede)",
|
||||
+ .drv_name = "cbc-3des-qce",
|
||||
+ .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||
+ .ivsize = DES3_EDE_BLOCK_SIZE,
|
||||
+ .min_keysize = DES3_EDE_KEY_SIZE,
|
||||
+ .max_keysize = DES3_EDE_KEY_SIZE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int qce_skcipher_register_one(const struct qce_skcipher_def *def,
|
||||
+ struct qce_device *qce)
|
||||
+{
|
||||
+ struct qce_alg_template *tmpl;
|
||||
+ struct skcipher_alg *alg;
|
||||
+ int ret;
|
||||
+
|
||||
+ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
|
||||
+ if (!tmpl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ alg = &tmpl->alg.skcipher;
|
||||
+
|
||||
+ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
|
||||
+ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
|
||||
+ def->drv_name);
|
||||
+
|
||||
+ alg->base.cra_blocksize = def->blocksize;
|
||||
+ alg->ivsize = def->ivsize;
|
||||
+ alg->min_keysize = def->min_keysize;
|
||||
+ alg->max_keysize = def->max_keysize;
|
||||
+ alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey :
|
||||
+ IS_DES(def->flags) ? qce_des_setkey :
|
||||
+ qce_skcipher_setkey;
|
||||
+ alg->encrypt = qce_skcipher_encrypt;
|
||||
+ alg->decrypt = qce_skcipher_decrypt;
|
||||
+
|
||||
+ alg->base.cra_priority = 300;
|
||||
+ alg->base.cra_flags = CRYPTO_ALG_ASYNC |
|
||||
+ CRYPTO_ALG_NEED_FALLBACK |
|
||||
+ CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||
+ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||
+ alg->base.cra_alignmask = 0;
|
||||
+ alg->base.cra_module = THIS_MODULE;
|
||||
+
|
||||
+ alg->init = qce_skcipher_init;
|
||||
+ alg->exit = qce_skcipher_exit;
|
||||
+
|
||||
+ INIT_LIST_HEAD(&tmpl->entry);
|
||||
+ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER;
|
||||
+ tmpl->alg_flags = def->flags;
|
||||
+ tmpl->qce = qce;
|
||||
+
|
||||
+ ret = crypto_register_skcipher(alg);
|
||||
+ if (ret) {
|
||||
+ kfree(tmpl);
|
||||
+ dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ list_add_tail(&tmpl->entry, &skcipher_algs);
|
||||
+ dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void qce_skcipher_unregister(struct qce_device *qce)
|
||||
+{
|
||||
+ struct qce_alg_template *tmpl, *n;
|
||||
+
|
||||
+ list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) {
|
||||
+ crypto_unregister_skcipher(&tmpl->alg.skcipher);
|
||||
+ list_del(&tmpl->entry);
|
||||
+ kfree(tmpl);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int qce_skcipher_register(struct qce_device *qce)
|
||||
+{
|
||||
+ int ret, i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) {
|
||||
+ ret = qce_skcipher_register_one(&skcipher_def[i], qce);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+err:
|
||||
+ qce_skcipher_unregister(qce);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+const struct qce_algo_ops skcipher_ops = {
|
||||
+ .type = CRYPTO_ALG_TYPE_SKCIPHER,
|
||||
+ .register_algs = qce_skcipher_register,
|
||||
+ .unregister_algs = qce_skcipher_unregister,
|
||||
+ .async_req_handle = qce_skcipher_async_req_handle,
|
||||
+};
|
@ -1,43 +0,0 @@
|
||||
From bb5c863b3d3cbd10e80b2ebf409934a091058f54 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 20 Dec 2019 16:02:13 -0300
|
||||
Subject: [PATCH 02/11] crypto: qce - fix ctr-aes-qce block, chunk sizes
|
||||
|
||||
Set blocksize of ctr-aes-qce to 1, so it can operate as a stream cipher,
|
||||
adding the definition for chucksize instead, where the underlying block
|
||||
size belongs.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/qce/skcipher.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -270,6 +270,7 @@ struct qce_skcipher_def {
|
||||
const char *name;
|
||||
const char *drv_name;
|
||||
unsigned int blocksize;
|
||||
+ unsigned int chunksize;
|
||||
unsigned int ivsize;
|
||||
unsigned int min_keysize;
|
||||
unsigned int max_keysize;
|
||||
@@ -298,7 +299,8 @@ static const struct qce_skcipher_def skc
|
||||
.flags = QCE_ALG_AES | QCE_MODE_CTR,
|
||||
.name = "ctr(aes)",
|
||||
.drv_name = "ctr-aes-qce",
|
||||
- .blocksize = AES_BLOCK_SIZE,
|
||||
+ .blocksize = 1,
|
||||
+ .chunksize = AES_BLOCK_SIZE,
|
||||
.ivsize = AES_BLOCK_SIZE,
|
||||
.min_keysize = AES_MIN_KEY_SIZE,
|
||||
.max_keysize = AES_MAX_KEY_SIZE,
|
||||
@@ -368,6 +370,7 @@ static int qce_skcipher_register_one(con
|
||||
def->drv_name);
|
||||
|
||||
alg->base.cra_blocksize = def->blocksize;
|
||||
+ alg->chunksize = def->chunksize;
|
||||
alg->ivsize = def->ivsize;
|
||||
alg->min_keysize = def->min_keysize;
|
||||
alg->max_keysize = def->max_keysize;
|
@ -1,60 +0,0 @@
|
||||
From 7de4c2bd196f111e39cc60f6197654aff23ba2b4 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 20 Dec 2019 16:02:14 -0300
|
||||
Subject: [PATCH 03/11] crypto: qce - fix xts-aes-qce key sizes
|
||||
|
||||
XTS-mode uses two keys, so the keysizes should be doubled in
|
||||
skcipher_def, and halved when checking if it is AES-128/192/256.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/qce/skcipher.c | 13 ++++++++-----
|
||||
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -154,12 +154,13 @@ static int qce_skcipher_setkey(struct cr
|
||||
{
|
||||
struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk);
|
||||
struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
+ unsigned long flags = to_cipher_tmpl(ablk)->alg_flags;
|
||||
int ret;
|
||||
|
||||
if (!key || !keylen)
|
||||
return -EINVAL;
|
||||
|
||||
- switch (keylen) {
|
||||
+ switch (IS_XTS(flags) ? keylen >> 1 : keylen) {
|
||||
case AES_KEYSIZE_128:
|
||||
case AES_KEYSIZE_256:
|
||||
break;
|
||||
@@ -213,13 +214,15 @@ static int qce_skcipher_crypt(struct skc
|
||||
struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||
struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
|
||||
+ int keylen;
|
||||
int ret;
|
||||
|
||||
rctx->flags = tmpl->alg_flags;
|
||||
rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||
+ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen;
|
||||
|
||||
- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
|
||||
- ctx->enc_keylen != AES_KEYSIZE_256) {
|
||||
+ if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 &&
|
||||
+ keylen != AES_KEYSIZE_256) {
|
||||
SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||
|
||||
skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
||||
@@ -311,8 +314,8 @@ static const struct qce_skcipher_def skc
|
||||
.drv_name = "xts-aes-qce",
|
||||
.blocksize = AES_BLOCK_SIZE,
|
||||
.ivsize = AES_BLOCK_SIZE,
|
||||
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||
+ .min_keysize = AES_MIN_KEY_SIZE * 2,
|
||||
+ .max_keysize = AES_MAX_KEY_SIZE * 2,
|
||||
},
|
||||
{
|
||||
.flags = QCE_ALG_DES | QCE_MODE_ECB,
|
@ -1,85 +0,0 @@
|
||||
From 3ee50c896d712dc2fc8f34c2cd1918d035e74045 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 20 Dec 2019 16:02:15 -0300
|
||||
Subject: [PATCH 04/11] crypto: qce - save a sg table slot for result buf
|
||||
|
||||
When ctr-aes-qce is used for gcm-mode, an extra sg entry for the
|
||||
authentication tag is present, causing trouble when the qce driver
|
||||
prepares the dst-results sg table for dma.
|
||||
|
||||
It computes the number of entries needed with sg_nents_for_len, leaving
|
||||
out the tag entry. Then it creates a sg table with that number plus
|
||||
one, used to store a result buffer.
|
||||
|
||||
When copying the sg table, there's no limit to the number of entries
|
||||
copied, so the extra slot is filled with the authentication tag sg.
|
||||
When the driver tries to add the result sg, the list is full, and it
|
||||
returns EINVAL.
|
||||
|
||||
By limiting the number of sg entries copied to the dest table, the slot
|
||||
for the result buffer is guaranteed to be unused.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/qce/dma.c | 6 ++++--
|
||||
drivers/crypto/qce/dma.h | 3 ++-
|
||||
drivers/crypto/qce/skcipher.c | 4 ++--
|
||||
3 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/crypto/qce/dma.c
|
||||
+++ b/drivers/crypto/qce/dma.c
|
||||
@@ -47,7 +47,8 @@ void qce_dma_release(struct qce_dma_data
|
||||
}
|
||||
|
||||
struct scatterlist *
|
||||
-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl)
|
||||
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl,
|
||||
+ int max_ents)
|
||||
{
|
||||
struct scatterlist *sg = sgt->sgl, *sg_last = NULL;
|
||||
|
||||
@@ -60,12 +61,13 @@ qce_sgtable_add(struct sg_table *sgt, st
|
||||
if (!sg)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
- while (new_sgl && sg) {
|
||||
+ while (new_sgl && sg && max_ents) {
|
||||
sg_set_page(sg, sg_page(new_sgl), new_sgl->length,
|
||||
new_sgl->offset);
|
||||
sg_last = sg;
|
||||
sg = sg_next(sg);
|
||||
new_sgl = sg_next(new_sgl);
|
||||
+ max_ents--;
|
||||
}
|
||||
|
||||
return sg_last;
|
||||
--- a/drivers/crypto/qce/dma.h
|
||||
+++ b/drivers/crypto/qce/dma.h
|
||||
@@ -42,6 +42,7 @@ int qce_dma_prep_sgs(struct qce_dma_data
|
||||
void qce_dma_issue_pending(struct qce_dma_data *dma);
|
||||
int qce_dma_terminate_all(struct qce_dma_data *dma);
|
||||
struct scatterlist *
|
||||
-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add);
|
||||
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add,
|
||||
+ int max_ents);
|
||||
|
||||
#endif /* _DMA_H_ */
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -95,13 +95,13 @@ qce_skcipher_async_req_handle(struct cry
|
||||
|
||||
sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||
|
||||
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
|
||||
+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1);
|
||||
if (IS_ERR(sg)) {
|
||||
ret = PTR_ERR(sg);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
|
||||
+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1);
|
||||
if (IS_ERR(sg)) {
|
||||
ret = PTR_ERR(sg);
|
||||
goto error_free;
|
@ -1,31 +0,0 @@
|
||||
From 3e806a12d10af2581aa26c37b58439286eab9782 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 20 Dec 2019 16:02:16 -0300
|
||||
Subject: [PATCH 05/11] crypto: qce - update the skcipher IV
|
||||
|
||||
Update the IV after the completion of each cipher operation.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/qce/skcipher.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -21,6 +21,7 @@ static void qce_skcipher_done(void *data
|
||||
struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||
struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||
struct qce_device *qce = tmpl->qce;
|
||||
+ struct qce_result_dump *result_buf = qce->dma.result_buf;
|
||||
enum dma_data_direction dir_src, dir_dst;
|
||||
u32 status;
|
||||
int error;
|
||||
@@ -45,6 +46,7 @@ static void qce_skcipher_done(void *data
|
||||
if (error < 0)
|
||||
dev_dbg(qce->dev, "skcipher operation error (%x)\n", status);
|
||||
|
||||
+ memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize);
|
||||
qce->async_req_done(tmpl->qce, error);
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
From 8ceda883205db6dfedb82e39f67feae3b50c95a1 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 20 Dec 2019 16:02:17 -0300
|
||||
Subject: [PATCH 06/11] crypto: qce - initialize fallback only for AES
|
||||
|
||||
Adjust cra_flags to add CRYPTO_NEED_FALLBACK only for AES ciphers, where
|
||||
AES-192 is not handled by the qce hardware, and don't allocate & free
|
||||
the fallback skcipher for other algorithms.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/qce/skcipher.c | 17 ++++++++++++++---
|
||||
1 file changed, 14 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -257,7 +257,14 @@ static int qce_skcipher_init(struct cryp
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm)
|
||||
+{
|
||||
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
|
||||
+ qce_skcipher_init(tfm);
|
||||
ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base),
|
||||
0, CRYPTO_ALG_NEED_FALLBACK);
|
||||
return PTR_ERR_OR_ZERO(ctx->fallback);
|
||||
@@ -387,14 +394,18 @@ static int qce_skcipher_register_one(con
|
||||
|
||||
alg->base.cra_priority = 300;
|
||||
alg->base.cra_flags = CRYPTO_ALG_ASYNC |
|
||||
- CRYPTO_ALG_NEED_FALLBACK |
|
||||
CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||
alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||
alg->base.cra_alignmask = 0;
|
||||
alg->base.cra_module = THIS_MODULE;
|
||||
|
||||
- alg->init = qce_skcipher_init;
|
||||
- alg->exit = qce_skcipher_exit;
|
||||
+ if (IS_AES(def->flags)) {
|
||||
+ alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK;
|
||||
+ alg->init = qce_skcipher_init_fallback;
|
||||
+ alg->exit = qce_skcipher_exit;
|
||||
+ } else {
|
||||
+ alg->init = qce_skcipher_init;
|
||||
+ }
|
||||
|
||||
INIT_LIST_HEAD(&tmpl->entry);
|
||||
tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER;
|
@ -1,419 +0,0 @@
|
||||
From 59e056cda4beb5412e3653e6360c2eb0fa770baa Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 20 Dec 2019 16:02:18 -0300
|
||||
Subject: [PATCH 07/11] crypto: qce - allow building only hashes/ciphers
|
||||
|
||||
Allow the user to choose whether to build support for all algorithms
|
||||
(default), hashes-only, or skciphers-only.
|
||||
|
||||
The QCE engine does not appear to scale as well as the CPU to handle
|
||||
multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the
|
||||
QCE handles only 2 requests in parallel.
|
||||
|
||||
Ipsec throughput seems to improve when disabling either family of
|
||||
algorithms, sharing the load with the CPU. Enabling skciphers-only
|
||||
appears to work best.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
|
||||
--- a/drivers/crypto/Kconfig
|
||||
+++ b/drivers/crypto/Kconfig
|
||||
@@ -617,6 +617,14 @@ config CRYPTO_DEV_QCE
|
||||
tristate "Qualcomm crypto engine accelerator"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
+ help
|
||||
+ This driver supports Qualcomm crypto engine accelerator
|
||||
+ hardware. To compile this driver as a module, choose M here. The
|
||||
+ module will be called qcrypto.
|
||||
+
|
||||
+config CRYPTO_DEV_QCE_SKCIPHER
|
||||
+ bool
|
||||
+ depends on CRYPTO_DEV_QCE
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_LIB_DES
|
||||
select CRYPTO_ECB
|
||||
@@ -624,10 +632,57 @@ config CRYPTO_DEV_QCE
|
||||
select CRYPTO_XTS
|
||||
select CRYPTO_CTR
|
||||
select CRYPTO_BLKCIPHER
|
||||
+
|
||||
+config CRYPTO_DEV_QCE_SHA
|
||||
+ bool
|
||||
+ depends on CRYPTO_DEV_QCE
|
||||
+
|
||||
+choice
|
||||
+ prompt "Algorithms enabled for QCE acceleration"
|
||||
+ default CRYPTO_DEV_QCE_ENABLE_ALL
|
||||
+ depends on CRYPTO_DEV_QCE
|
||||
help
|
||||
- This driver supports Qualcomm crypto engine accelerator
|
||||
- hardware. To compile this driver as a module, choose M here. The
|
||||
- module will be called qcrypto.
|
||||
+ This option allows to choose whether to build support for all algorihtms
|
||||
+ (default), hashes-only, or skciphers-only.
|
||||
+
|
||||
+ The QCE engine does not appear to scale as well as the CPU to handle
|
||||
+ multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the
|
||||
+ QCE handles only 2 requests in parallel.
|
||||
+
|
||||
+ Ipsec throughput seems to improve when disabling either family of
|
||||
+ algorithms, sharing the load with the CPU. Enabling skciphers-only
|
||||
+ appears to work best.
|
||||
+
|
||||
+ config CRYPTO_DEV_QCE_ENABLE_ALL
|
||||
+ bool "All supported algorithms"
|
||||
+ select CRYPTO_DEV_QCE_SKCIPHER
|
||||
+ select CRYPTO_DEV_QCE_SHA
|
||||
+ help
|
||||
+ Enable all supported algorithms:
|
||||
+ - AES (CBC, CTR, ECB, XTS)
|
||||
+ - 3DES (CBC, ECB)
|
||||
+ - DES (CBC, ECB)
|
||||
+ - SHA1, HMAC-SHA1
|
||||
+ - SHA256, HMAC-SHA256
|
||||
+
|
||||
+ config CRYPTO_DEV_QCE_ENABLE_SKCIPHER
|
||||
+ bool "Symmetric-key ciphers only"
|
||||
+ select CRYPTO_DEV_QCE_SKCIPHER
|
||||
+ help
|
||||
+ Enable symmetric-key ciphers only:
|
||||
+ - AES (CBC, CTR, ECB, XTS)
|
||||
+ - 3DES (ECB, CBC)
|
||||
+ - DES (ECB, CBC)
|
||||
+
|
||||
+ config CRYPTO_DEV_QCE_ENABLE_SHA
|
||||
+ bool "Hash/HMAC only"
|
||||
+ select CRYPTO_DEV_QCE_SHA
|
||||
+ help
|
||||
+ Enable hashes/HMAC algorithms only:
|
||||
+ - SHA1, HMAC-SHA1
|
||||
+ - SHA256, HMAC-SHA256
|
||||
+
|
||||
+endchoice
|
||||
|
||||
config CRYPTO_DEV_QCOM_RNG
|
||||
tristate "Qualcomm Random Number Generator Driver"
|
||||
--- a/drivers/crypto/qce/Makefile
|
||||
+++ b/drivers/crypto/qce/Makefile
|
||||
@@ -2,6 +2,7 @@
|
||||
obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o
|
||||
qcrypto-objs := core.o \
|
||||
common.o \
|
||||
- dma.o \
|
||||
- sha.o \
|
||||
- skcipher.o
|
||||
+ dma.o
|
||||
+
|
||||
+qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o
|
||||
+qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o
|
||||
--- a/drivers/crypto/qce/common.c
|
||||
+++ b/drivers/crypto/qce/common.c
|
||||
@@ -45,52 +45,56 @@ qce_clear_array(struct qce_device *qce,
|
||||
qce_write(qce, offset + i * sizeof(u32), 0);
|
||||
}
|
||||
|
||||
-static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size)
|
||||
+static u32 qce_config_reg(struct qce_device *qce, int little)
|
||||
{
|
||||
- u32 cfg = 0;
|
||||
+ u32 beats = (qce->burst_size >> 3) - 1;
|
||||
+ u32 pipe_pair = qce->pipe_pair_id;
|
||||
+ u32 config;
|
||||
|
||||
- if (IS_AES(flags)) {
|
||||
- if (aes_key_size == AES_KEYSIZE_128)
|
||||
- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT;
|
||||
- else if (aes_key_size == AES_KEYSIZE_256)
|
||||
- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT;
|
||||
- }
|
||||
+ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK;
|
||||
+ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) |
|
||||
+ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT);
|
||||
+ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK;
|
||||
+ config &= ~HIGH_SPD_EN_N_SHIFT;
|
||||
|
||||
- if (IS_AES(flags))
|
||||
- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT;
|
||||
- else if (IS_DES(flags) || IS_3DES(flags))
|
||||
- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT;
|
||||
+ if (little)
|
||||
+ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT);
|
||||
|
||||
- if (IS_DES(flags))
|
||||
- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT;
|
||||
+ return config;
|
||||
+}
|
||||
|
||||
- if (IS_3DES(flags))
|
||||
- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT;
|
||||
+void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len)
|
||||
+{
|
||||
+ __be32 *d = dst;
|
||||
+ const u8 *s = src;
|
||||
+ unsigned int n;
|
||||
|
||||
- switch (flags & QCE_MODE_MASK) {
|
||||
- case QCE_MODE_ECB:
|
||||
- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT;
|
||||
- break;
|
||||
- case QCE_MODE_CBC:
|
||||
- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT;
|
||||
- break;
|
||||
- case QCE_MODE_CTR:
|
||||
- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT;
|
||||
- break;
|
||||
- case QCE_MODE_XTS:
|
||||
- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT;
|
||||
- break;
|
||||
- case QCE_MODE_CCM:
|
||||
- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT;
|
||||
- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT;
|
||||
- break;
|
||||
- default:
|
||||
- return ~0;
|
||||
+ n = len / sizeof(u32);
|
||||
+ for (; n > 0; n--) {
|
||||
+ *d = cpu_to_be32p((const __u32 *) s);
|
||||
+ s += sizeof(__u32);
|
||||
+ d++;
|
||||
}
|
||||
+}
|
||||
|
||||
- return cfg;
|
||||
+static void qce_setup_config(struct qce_device *qce)
|
||||
+{
|
||||
+ u32 config;
|
||||
+
|
||||
+ /* get big endianness */
|
||||
+ config = qce_config_reg(qce, 0);
|
||||
+
|
||||
+ /* clear status */
|
||||
+ qce_write(qce, REG_STATUS, 0);
|
||||
+ qce_write(qce, REG_CONFIG, config);
|
||||
+}
|
||||
+
|
||||
+static inline void qce_crypto_go(struct qce_device *qce)
|
||||
+{
|
||||
+ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT));
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
|
||||
static u32 qce_auth_cfg(unsigned long flags, u32 key_size)
|
||||
{
|
||||
u32 cfg = 0;
|
||||
@@ -137,88 +141,6 @@ static u32 qce_auth_cfg(unsigned long fl
|
||||
return cfg;
|
||||
}
|
||||
|
||||
-static u32 qce_config_reg(struct qce_device *qce, int little)
|
||||
-{
|
||||
- u32 beats = (qce->burst_size >> 3) - 1;
|
||||
- u32 pipe_pair = qce->pipe_pair_id;
|
||||
- u32 config;
|
||||
-
|
||||
- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK;
|
||||
- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) |
|
||||
- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT);
|
||||
- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK;
|
||||
- config &= ~HIGH_SPD_EN_N_SHIFT;
|
||||
-
|
||||
- if (little)
|
||||
- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT);
|
||||
-
|
||||
- return config;
|
||||
-}
|
||||
-
|
||||
-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len)
|
||||
-{
|
||||
- __be32 *d = dst;
|
||||
- const u8 *s = src;
|
||||
- unsigned int n;
|
||||
-
|
||||
- n = len / sizeof(u32);
|
||||
- for (; n > 0; n--) {
|
||||
- *d = cpu_to_be32p((const __u32 *) s);
|
||||
- s += sizeof(__u32);
|
||||
- d++;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize)
|
||||
-{
|
||||
- u8 swap[QCE_AES_IV_LENGTH];
|
||||
- u32 i, j;
|
||||
-
|
||||
- if (ivsize > QCE_AES_IV_LENGTH)
|
||||
- return;
|
||||
-
|
||||
- memset(swap, 0, QCE_AES_IV_LENGTH);
|
||||
-
|
||||
- for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1;
|
||||
- i < QCE_AES_IV_LENGTH; i++, j--)
|
||||
- swap[i] = src[j];
|
||||
-
|
||||
- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH);
|
||||
-}
|
||||
-
|
||||
-static void qce_xtskey(struct qce_device *qce, const u8 *enckey,
|
||||
- unsigned int enckeylen, unsigned int cryptlen)
|
||||
-{
|
||||
- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
|
||||
- unsigned int xtsklen = enckeylen / (2 * sizeof(u32));
|
||||
- unsigned int xtsdusize;
|
||||
-
|
||||
- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2,
|
||||
- enckeylen / 2);
|
||||
- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen);
|
||||
-
|
||||
- /* xts du size 512B */
|
||||
- xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen);
|
||||
- qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize);
|
||||
-}
|
||||
-
|
||||
-static void qce_setup_config(struct qce_device *qce)
|
||||
-{
|
||||
- u32 config;
|
||||
-
|
||||
- /* get big endianness */
|
||||
- config = qce_config_reg(qce, 0);
|
||||
-
|
||||
- /* clear status */
|
||||
- qce_write(qce, REG_STATUS, 0);
|
||||
- qce_write(qce, REG_CONFIG, config);
|
||||
-}
|
||||
-
|
||||
-static inline void qce_crypto_go(struct qce_device *qce)
|
||||
-{
|
||||
- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT));
|
||||
-}
|
||||
-
|
||||
static int qce_setup_regs_ahash(struct crypto_async_request *async_req,
|
||||
u32 totallen, u32 offset)
|
||||
{
|
||||
@@ -303,6 +225,87 @@ go_proc:
|
||||
|
||||
return 0;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
|
||||
+static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size)
|
||||
+{
|
||||
+ u32 cfg = 0;
|
||||
+
|
||||
+ if (IS_AES(flags)) {
|
||||
+ if (aes_key_size == AES_KEYSIZE_128)
|
||||
+ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT;
|
||||
+ else if (aes_key_size == AES_KEYSIZE_256)
|
||||
+ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (IS_AES(flags))
|
||||
+ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT;
|
||||
+ else if (IS_DES(flags) || IS_3DES(flags))
|
||||
+ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT;
|
||||
+
|
||||
+ if (IS_DES(flags))
|
||||
+ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT;
|
||||
+
|
||||
+ if (IS_3DES(flags))
|
||||
+ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT;
|
||||
+
|
||||
+ switch (flags & QCE_MODE_MASK) {
|
||||
+ case QCE_MODE_ECB:
|
||||
+ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT;
|
||||
+ break;
|
||||
+ case QCE_MODE_CBC:
|
||||
+ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT;
|
||||
+ break;
|
||||
+ case QCE_MODE_CTR:
|
||||
+ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT;
|
||||
+ break;
|
||||
+ case QCE_MODE_XTS:
|
||||
+ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT;
|
||||
+ break;
|
||||
+ case QCE_MODE_CCM:
|
||||
+ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT;
|
||||
+ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return ~0;
|
||||
+ }
|
||||
+
|
||||
+ return cfg;
|
||||
+}
|
||||
+
|
||||
+static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize)
|
||||
+{
|
||||
+ u8 swap[QCE_AES_IV_LENGTH];
|
||||
+ u32 i, j;
|
||||
+
|
||||
+ if (ivsize > QCE_AES_IV_LENGTH)
|
||||
+ return;
|
||||
+
|
||||
+ memset(swap, 0, QCE_AES_IV_LENGTH);
|
||||
+
|
||||
+ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1;
|
||||
+ i < QCE_AES_IV_LENGTH; i++, j--)
|
||||
+ swap[i] = src[j];
|
||||
+
|
||||
+ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH);
|
||||
+}
|
||||
+
|
||||
+static void qce_xtskey(struct qce_device *qce, const u8 *enckey,
|
||||
+ unsigned int enckeylen, unsigned int cryptlen)
|
||||
+{
|
||||
+ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
|
||||
+ unsigned int xtsklen = enckeylen / (2 * sizeof(u32));
|
||||
+ unsigned int xtsdusize;
|
||||
+
|
||||
+ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2,
|
||||
+ enckeylen / 2);
|
||||
+ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen);
|
||||
+
|
||||
+ /* xts du size 512B */
|
||||
+ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen);
|
||||
+ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize);
|
||||
+}
|
||||
|
||||
static int qce_setup_regs_skcipher(struct crypto_async_request *async_req,
|
||||
u32 totallen, u32 offset)
|
||||
@@ -384,15 +387,20 @@ static int qce_setup_regs_skcipher(struc
|
||||
|
||||
return 0;
|
||||
}
|
||||
+#endif
|
||||
|
||||
int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen,
|
||||
u32 offset)
|
||||
{
|
||||
switch (type) {
|
||||
+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
|
||||
case CRYPTO_ALG_TYPE_SKCIPHER:
|
||||
return qce_setup_regs_skcipher(async_req, totallen, offset);
|
||||
+#endif
|
||||
+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
|
||||
case CRYPTO_ALG_TYPE_AHASH:
|
||||
return qce_setup_regs_ahash(async_req, totallen, offset);
|
||||
+#endif
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
--- a/drivers/crypto/qce/core.c
|
||||
+++ b/drivers/crypto/qce/core.c
|
||||
@@ -22,8 +22,12 @@
|
||||
#define QCE_QUEUE_LENGTH 1
|
||||
|
||||
static const struct qce_algo_ops *qce_ops[] = {
|
||||
+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
|
||||
&skcipher_ops,
|
||||
+#endif
|
||||
+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
|
||||
&ahash_ops,
|
||||
+#endif
|
||||
};
|
||||
|
||||
static void qce_unregister_algs(struct qce_device *qce)
|
@ -1,89 +0,0 @@
|
||||
From d6364b8128439a8c0e381f80c38667de9f15eef8 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 7 Feb 2020 12:02:25 -0300
|
||||
Subject: [PATCH 09/11] crypto: qce - use cryptlen when adding extra sgl
|
||||
|
||||
The qce crypto driver appends an extra entry to the dst sgl, to maintain
|
||||
private state information.
|
||||
|
||||
When the gcm driver sends requests to the ctr skcipher, it passes the
|
||||
authentication tag after the actual crypto payload, but it must not be
|
||||
touched.
|
||||
|
||||
Commit 1336c2221bee ("crypto: qce - save a sg table slot for result
|
||||
buf") limited the destination sgl to avoid overwriting the
|
||||
authentication tag but it assumed the tag would be in a separate sgl
|
||||
entry.
|
||||
|
||||
This is not always the case, so it is better to limit the length of the
|
||||
destination buffer to req->cryptlen before appending the result buf.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/qce/dma.c | 11 ++++++-----
|
||||
drivers/crypto/qce/dma.h | 2 +-
|
||||
drivers/crypto/qce/skcipher.c | 5 +++--
|
||||
3 files changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/crypto/qce/dma.c
|
||||
+++ b/drivers/crypto/qce/dma.c
|
||||
@@ -48,9 +48,10 @@ void qce_dma_release(struct qce_dma_data
|
||||
|
||||
struct scatterlist *
|
||||
qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl,
|
||||
- int max_ents)
|
||||
+ unsigned int max_len)
|
||||
{
|
||||
struct scatterlist *sg = sgt->sgl, *sg_last = NULL;
|
||||
+ unsigned int new_len;
|
||||
|
||||
while (sg) {
|
||||
if (!sg_page(sg))
|
||||
@@ -61,13 +62,13 @@ qce_sgtable_add(struct sg_table *sgt, st
|
||||
if (!sg)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
- while (new_sgl && sg && max_ents) {
|
||||
- sg_set_page(sg, sg_page(new_sgl), new_sgl->length,
|
||||
- new_sgl->offset);
|
||||
+ while (new_sgl && sg && max_len) {
|
||||
+ new_len = new_sgl->length > max_len ? max_len : new_sgl->length;
|
||||
+ sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset);
|
||||
sg_last = sg;
|
||||
sg = sg_next(sg);
|
||||
new_sgl = sg_next(new_sgl);
|
||||
- max_ents--;
|
||||
+ max_len -= new_len;
|
||||
}
|
||||
|
||||
return sg_last;
|
||||
--- a/drivers/crypto/qce/dma.h
|
||||
+++ b/drivers/crypto/qce/dma.h
|
||||
@@ -43,6 +43,6 @@ void qce_dma_issue_pending(struct qce_dm
|
||||
int qce_dma_terminate_all(struct qce_dma_data *dma);
|
||||
struct scatterlist *
|
||||
qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add,
|
||||
- int max_ents);
|
||||
+ unsigned int max_len);
|
||||
|
||||
#endif /* _DMA_H_ */
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -97,13 +97,14 @@ qce_skcipher_async_req_handle(struct cry
|
||||
|
||||
sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||
|
||||
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1);
|
||||
+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen);
|
||||
if (IS_ERR(sg)) {
|
||||
ret = PTR_ERR(sg);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1);
|
||||
+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg,
|
||||
+ QCE_RESULT_BUF_SZ);
|
||||
if (IS_ERR(sg)) {
|
||||
ret = PTR_ERR(sg);
|
||||
goto error_free;
|
@ -1,113 +0,0 @@
|
||||
From ce163ba0bf298f1707321ac025ef639f88e62801 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 7 Feb 2020 12:02:26 -0300
|
||||
Subject: [PATCH 10/11] crypto: qce - use AES fallback for small requests
|
||||
|
||||
Process small blocks using the fallback cipher, as a workaround for an
|
||||
observed failure (DMA-related, apparently) when computing the GCM ghash
|
||||
key. This brings a speed gain as well, since it avoids the latency of
|
||||
using the hardware engine to process small blocks.
|
||||
|
||||
Using software for all 16-byte requests would be enough to make GCM
|
||||
work, but to increase performance, a larger threshold would be better.
|
||||
Measuring the performance of supported ciphers with openssl speed,
|
||||
software matches hardware at around 768-1024 bytes.
|
||||
|
||||
Considering the 256-bit ciphers, software is 2-3 times faster than qce
|
||||
at 256-bytes, 30% faster at 512, and about even at 768-bytes. With
|
||||
128-bit keys, the break-even point would be around 1024-bytes.
|
||||
|
||||
This adds the 'aes_sw_max_len' parameter, to set the largest request
|
||||
length processed by the software fallback. Its default is being set to
|
||||
512 bytes, a little lower than the break-even point, to balance the cost
|
||||
in CPU usage.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
|
||||
--- a/drivers/crypto/Kconfig
|
||||
+++ b/drivers/crypto/Kconfig
|
||||
@@ -684,6 +684,29 @@ choice
|
||||
|
||||
endchoice
|
||||
|
||||
+config CRYPTO_DEV_QCE_SW_MAX_LEN
|
||||
+ int "Default maximum request size to use software for AES"
|
||||
+ depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER
|
||||
+ default 512
|
||||
+ help
|
||||
+ This sets the default maximum request size to perform AES requests
|
||||
+ using software instead of the crypto engine. It can be changed by
|
||||
+ setting the aes_sw_max_len parameter.
|
||||
+
|
||||
+ Small blocks are processed faster in software than hardware.
|
||||
+ Considering the 256-bit ciphers, software is 2-3 times faster than
|
||||
+ qce at 256-bytes, 30% faster at 512, and about even at 768-bytes.
|
||||
+ With 128-bit keys, the break-even point would be around 1024-bytes.
|
||||
+
|
||||
+ The default is set a little lower, to 512 bytes, to balance the
|
||||
+ cost in CPU usage. The minimum recommended setting is 16-bytes
|
||||
+ (1 AES block), since AES-GCM will fail if you set it lower.
|
||||
+ Setting this to zero will send all requests to the hardware.
|
||||
+
|
||||
+ Note that 192-bit keys are not supported by the hardware and are
|
||||
+ always processed by the software fallback, and all DES requests
|
||||
+ are done by the hardware.
|
||||
+
|
||||
config CRYPTO_DEV_QCOM_RNG
|
||||
tristate "Qualcomm Random Number Generator Driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
#include <linux/types.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/internal/des.h>
|
||||
@@ -12,6 +13,13 @@
|
||||
|
||||
#include "cipher.h"
|
||||
|
||||
+static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN;
|
||||
+module_param(aes_sw_max_len, uint, 0644);
|
||||
+MODULE_PARM_DESC(aes_sw_max_len,
|
||||
+ "Only use hardware for AES requests larger than this "
|
||||
+ "[0=always use hardware; anything <16 breaks AES-GCM; default="
|
||||
+ __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]");
|
||||
+
|
||||
static LIST_HEAD(skcipher_algs);
|
||||
|
||||
static void qce_skcipher_done(void *data)
|
||||
@@ -166,15 +174,10 @@ static int qce_skcipher_setkey(struct cr
|
||||
switch (IS_XTS(flags) ? keylen >> 1 : keylen) {
|
||||
case AES_KEYSIZE_128:
|
||||
case AES_KEYSIZE_256:
|
||||
+ memcpy(ctx->enc_key, key, keylen);
|
||||
break;
|
||||
- default:
|
||||
- goto fallback;
|
||||
}
|
||||
|
||||
- ctx->enc_keylen = keylen;
|
||||
- memcpy(ctx->enc_key, key, keylen);
|
||||
- return 0;
|
||||
-fallback:
|
||||
ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen);
|
||||
if (!ret)
|
||||
ctx->enc_keylen = keylen;
|
||||
@@ -224,8 +227,9 @@ static int qce_skcipher_crypt(struct skc
|
||||
rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||
keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen;
|
||||
|
||||
- if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 &&
|
||||
- keylen != AES_KEYSIZE_256) {
|
||||
+ if (IS_AES(rctx->flags) &&
|
||||
+ ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
|
||||
+ req->cryptlen <= aes_sw_max_len)) {
|
||||
SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||
|
||||
skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
@ -1,59 +0,0 @@
|
||||
From 7f19380b2cfd412dcef2facefb3f6c62788864d7 Mon Sep 17 00:00:00 2001
|
||||
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Date: Fri, 7 Feb 2020 12:02:27 -0300
|
||||
Subject: [PATCH 11/11] crypto: qce - handle AES-XTS cases that qce fails
|
||||
|
||||
QCE hangs when presented with an AES-XTS request whose length is larger
|
||||
than QCE_SECTOR_SIZE (512-bytes), and is not a multiple of it. Let the
|
||||
fallback cipher handle them.
|
||||
|
||||
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/crypto/qce/common.c | 2 --
|
||||
drivers/crypto/qce/common.h | 3 +++
|
||||
drivers/crypto/qce/skcipher.c | 9 +++++++--
|
||||
3 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/crypto/qce/common.c
|
||||
+++ b/drivers/crypto/qce/common.c
|
||||
@@ -15,8 +15,6 @@
|
||||
#include "regs-v5.h"
|
||||
#include "sha.h"
|
||||
|
||||
-#define QCE_SECTOR_SIZE 512
|
||||
-
|
||||
static inline u32 qce_read(struct qce_device *qce, u32 offset)
|
||||
{
|
||||
return readl(qce->base + offset);
|
||||
--- a/drivers/crypto/qce/common.h
|
||||
+++ b/drivers/crypto/qce/common.h
|
||||
@@ -12,6 +12,9 @@
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
|
||||
+/* xts du size */
|
||||
+#define QCE_SECTOR_SIZE 512
|
||||
+
|
||||
/* key size in bytes */
|
||||
#define QCE_SHA_HMAC_KEY_SIZE 64
|
||||
#define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256
|
||||
--- a/drivers/crypto/qce/skcipher.c
|
||||
+++ b/drivers/crypto/qce/skcipher.c
|
||||
@@ -227,9 +227,14 @@ static int qce_skcipher_crypt(struct skc
|
||||
rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||
keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen;
|
||||
|
||||
+ /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and
|
||||
+ * is not a multiple of it; pass such requests to the fallback
|
||||
+ */
|
||||
if (IS_AES(rctx->flags) &&
|
||||
- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
|
||||
- req->cryptlen <= aes_sw_max_len)) {
|
||||
+ (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
|
||||
+ req->cryptlen <= aes_sw_max_len) ||
|
||||
+ (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE &&
|
||||
+ req->cryptlen % QCE_SECTOR_SIZE))) {
|
||||
SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||
|
||||
skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
@ -1,197 +0,0 @@
|
||||
From 3c9d8f6c03a2cda1849ec3c84f82ec030d1f49ef Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
Date: Sun, 3 May 2020 22:18:22 +0200
|
||||
Subject: [PATCH] phy: add driver for Qualcomm IPQ40xx USB PHY
|
||||
|
||||
Add a driver to setup the USB PHY-s on Qualcom m IPQ40xx series SoCs.
|
||||
The driver sets up HS and SS phys.
|
||||
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
Cc: Luka Perkov <luka.perkov@sartura.hr>
|
||||
Link: https://lore.kernel.org/r/20200503201823.531757-1-robert.marko@sartura.hr
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/qualcomm/Kconfig | 7 +
|
||||
drivers/phy/qualcomm/Makefile | 1 +
|
||||
drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c | 148 ++++++++++++++++++++
|
||||
3 files changed, 156 insertions(+)
|
||||
create mode 100644 drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
|
||||
|
||||
--- a/drivers/phy/qualcomm/Kconfig
|
||||
+++ b/drivers/phy/qualcomm/Kconfig
|
||||
@@ -18,6 +18,13 @@ config PHY_QCOM_APQ8064_SATA
|
||||
depends on OF
|
||||
select GENERIC_PHY
|
||||
|
||||
+config PHY_QCOM_IPQ4019_USB
|
||||
+ tristate "Qualcomm IPQ4019 USB PHY driver"
|
||||
+ depends on OF && (ARCH_QCOM || COMPILE_TEST)
|
||||
+ select GENERIC_PHY
|
||||
+ help
|
||||
+ Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s.
|
||||
+
|
||||
config PHY_QCOM_IPQ806X_SATA
|
||||
tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
|
||||
depends on ARCH_QCOM
|
||||
--- a/drivers/phy/qualcomm/Makefile
|
||||
+++ b/drivers/phy/qualcomm/Makefile
|
||||
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o
|
||||
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
|
||||
+obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o
|
||||
obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
|
||||
obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
|
||||
obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
|
||||
@@ -0,0 +1,148 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Copyright (C) 2018 John Crispin <john@phrozen.org>
|
||||
+ *
|
||||
+ * Based on code from
|
||||
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/phy/phy.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/reset.h>
|
||||
+
|
||||
+struct ipq4019_usb_phy {
|
||||
+ struct device *dev;
|
||||
+ struct phy *phy;
|
||||
+ void __iomem *base;
|
||||
+ struct reset_control *por_rst;
|
||||
+ struct reset_control *srif_rst;
|
||||
+};
|
||||
+
|
||||
+static int ipq4019_ss_phy_power_off(struct phy *_phy)
|
||||
+{
|
||||
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
+
|
||||
+ reset_control_assert(phy->por_rst);
|
||||
+ msleep(10);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq4019_ss_phy_power_on(struct phy *_phy)
|
||||
+{
|
||||
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
+
|
||||
+ ipq4019_ss_phy_power_off(_phy);
|
||||
+
|
||||
+ reset_control_deassert(phy->por_rst);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct phy_ops ipq4019_usb_ss_phy_ops = {
|
||||
+ .power_on = ipq4019_ss_phy_power_on,
|
||||
+ .power_off = ipq4019_ss_phy_power_off,
|
||||
+};
|
||||
+
|
||||
+static int ipq4019_hs_phy_power_off(struct phy *_phy)
|
||||
+{
|
||||
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
+
|
||||
+ reset_control_assert(phy->por_rst);
|
||||
+ msleep(10);
|
||||
+
|
||||
+ reset_control_assert(phy->srif_rst);
|
||||
+ msleep(10);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq4019_hs_phy_power_on(struct phy *_phy)
|
||||
+{
|
||||
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
+
|
||||
+ ipq4019_hs_phy_power_off(_phy);
|
||||
+
|
||||
+ reset_control_deassert(phy->srif_rst);
|
||||
+ msleep(10);
|
||||
+
|
||||
+ reset_control_deassert(phy->por_rst);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct phy_ops ipq4019_usb_hs_phy_ops = {
|
||||
+ .power_on = ipq4019_hs_phy_power_on,
|
||||
+ .power_off = ipq4019_hs_phy_power_off,
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id ipq4019_usb_phy_of_match[] = {
|
||||
+ { .compatible = "qcom,usb-hs-ipq4019-phy", .data = &ipq4019_usb_hs_phy_ops},
|
||||
+ { .compatible = "qcom,usb-ss-ipq4019-phy", .data = &ipq4019_usb_ss_phy_ops},
|
||||
+ { },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match);
|
||||
+
|
||||
+static int ipq4019_usb_phy_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct resource *res;
|
||||
+ struct phy_provider *phy_provider;
|
||||
+ struct ipq4019_usb_phy *phy;
|
||||
+
|
||||
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
||||
+ if (!phy)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ phy->dev = &pdev->dev;
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ phy->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(phy->base)) {
|
||||
+ dev_err(dev, "failed to remap register memory\n");
|
||||
+ return PTR_ERR(phy->base);
|
||||
+ }
|
||||
+
|
||||
+ phy->por_rst = devm_reset_control_get(phy->dev, "por_rst");
|
||||
+ if (IS_ERR(phy->por_rst)) {
|
||||
+ if (PTR_ERR(phy->por_rst) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "POR reset is missing\n");
|
||||
+ return PTR_ERR(phy->por_rst);
|
||||
+ }
|
||||
+
|
||||
+ phy->srif_rst = devm_reset_control_get_optional(phy->dev, "srif_rst");
|
||||
+ if (IS_ERR(phy->srif_rst))
|
||||
+ return PTR_ERR(phy->srif_rst);
|
||||
+
|
||||
+ phy->phy = devm_phy_create(dev, NULL, of_device_get_match_data(dev));
|
||||
+ if (IS_ERR(phy->phy)) {
|
||||
+ dev_err(dev, "failed to create PHY\n");
|
||||
+ return PTR_ERR(phy->phy);
|
||||
+ }
|
||||
+ phy_set_drvdata(phy->phy, phy);
|
||||
+
|
||||
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
+
|
||||
+ return PTR_ERR_OR_ZERO(phy_provider);
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver ipq4019_usb_phy_driver = {
|
||||
+ .probe = ipq4019_usb_phy_probe,
|
||||
+ .driver = {
|
||||
+ .of_match_table = ipq4019_usb_phy_of_match,
|
||||
+ .name = "ipq4019-usb-phy",
|
||||
+ }
|
||||
+};
|
||||
+module_platform_driver(ipq4019_usb_phy_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("QCOM/IPQ4019 USB phy driver");
|
||||
+MODULE_AUTHOR("John Crispin <john@phrozen.org>");
|
||||
+MODULE_LICENSE("GPL v2");
|
@ -1,81 +0,0 @@
|
||||
From 5b08c1d567ee8e6af94696b3e549997cbdb2bb80 Mon Sep 17 00:00:00 2001
|
||||
From: Jaiganesh Narayanan <njaigane@codeaurora.org>
|
||||
Date: Thu, 1 Sep 2016 10:40:38 +0530
|
||||
Subject: [PATCH] pinctrl: qcom: ipq4019: add open drain support
|
||||
|
||||
Signed-off-by: Jaiganesh Narayanan <njaigane@codeaurora.org>
|
||||
[ Brian: adapted from from the Chromium OS kernel used on IPQ4019-based
|
||||
WiFi APs. ]
|
||||
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||||
---
|
||||
https://lore.kernel.org/linux-gpio/20200703080646.23233-1-computersforpeace@gmail.com/
|
||||
|
||||
drivers/pinctrl/qcom/pinctrl-ipq4019.c | 1 +
|
||||
drivers/pinctrl/qcom/pinctrl-msm.c | 13 +++++++++++++
|
||||
drivers/pinctrl/qcom/pinctrl-msm.h | 2 ++
|
||||
3 files changed, 16 insertions(+)
|
||||
|
||||
--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c
|
||||
+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
|
||||
@@ -254,6 +254,7 @@ DECLARE_QCA_GPIO_PINS(99);
|
||||
.mux_bit = 2, \
|
||||
.pull_bit = 0, \
|
||||
.drv_bit = 6, \
|
||||
+ .od_bit = 12, \
|
||||
.oe_bit = 9, \
|
||||
.in_bit = 0, \
|
||||
.out_bit = 1, \
|
||||
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
|
||||
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
|
||||
@@ -225,6 +225,10 @@ static int msm_config_reg(struct msm_pin
|
||||
*bit = g->pull_bit;
|
||||
*mask = 3;
|
||||
break;
|
||||
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
+ *bit = g->od_bit;
|
||||
+ *mask = 1;
|
||||
+ break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
*bit = g->drv_bit;
|
||||
*mask = 7;
|
||||
@@ -302,6 +306,12 @@ static int msm_config_group_get(struct p
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
break;
|
||||
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
+ /* Pin is not open-drain */
|
||||
+ if (!arg)
|
||||
+ return -EINVAL;
|
||||
+ arg = 1;
|
||||
+ break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
arg = msm_regval_to_drive(arg);
|
||||
break;
|
||||
@@ -374,6 +384,9 @@ static int msm_config_group_set(struct p
|
||||
else
|
||||
arg = MSM_PULL_UP;
|
||||
break;
|
||||
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
+ arg = 1;
|
||||
+ break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
/* Check for invalid values */
|
||||
if (arg > 16 || arg < 2 || (arg % 2) != 0)
|
||||
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
|
||||
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
|
||||
@@ -38,6 +38,7 @@ struct msm_function {
|
||||
* @mux_bit: Offset in @ctl_reg for the pinmux function selection.
|
||||
* @pull_bit: Offset in @ctl_reg for the bias configuration.
|
||||
* @drv_bit: Offset in @ctl_reg for the drive strength configuration.
|
||||
+ * @od_bit: Offset in @ctl_reg for controlling open drain.
|
||||
* @oe_bit: Offset in @ctl_reg for controlling output enable.
|
||||
* @in_bit: Offset in @io_reg for the input bit value.
|
||||
* @out_bit: Offset in @io_reg for the output bit value.
|
||||
@@ -75,6 +76,7 @@ struct msm_pingroup {
|
||||
unsigned pull_bit:5;
|
||||
unsigned drv_bit:5;
|
||||
|
||||
+ unsigned od_bit:5;
|
||||
unsigned oe_bit:5;
|
||||
unsigned in_bit:5;
|
||||
unsigned out_bit:5;
|
@ -1,29 +0,0 @@
|
||||
From 707745e8d4e75b638b990d67950ab292b3b8ea2a Mon Sep 17 00:00:00 2001
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Mon, 16 Dec 2019 01:36:46 +0100
|
||||
Subject: [PATCH] mtd: spi-nor: Add support for mx25r3235f
|
||||
|
||||
Add MTD support for the Macronix MX25R3235F SPI NOR chip from Macronix.
|
||||
The chip has 4MB of total capacity, divided into a total of 64 sectors,
|
||||
each 64KB sized. The chip also supports 4KB large sectors.
|
||||
Additionally, it supports dual and quad read modes.
|
||||
|
||||
Functionality was verified on an HPE/Aruba AP-303 board.
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -2353,6 +2353,8 @@ static const struct flash_info spi_nor_i
|
||||
{ "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
|
||||
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
|
||||
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
|
||||
+ { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
|
||||
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
|
Loading…
x
Reference in New Issue
Block a user