You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
481 lines
13 KiB
481 lines
13 KiB
From 5343e674f32fb82b7a80a24b5a84eee62d3fe624 Mon Sep 17 00:00:00 2001
|
|
From: Christian Lamparter <chunkeey@googlemail.com>
|
|
Date: Mon, 18 Apr 2016 12:57:41 +0200
|
|
Subject: [PATCH] crypto4xx: integrate ppc4xx-rng into crypto4xx
|
|
|
|
This patch integrates the ppc4xx-rng driver into the existing
|
|
crypto4xx. This is because the true random number generator
|
|
is controlled and part of the security core.
|
|
|
|
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
|
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
|
---
|
|
drivers/char/hw_random/Kconfig | 13 ---
|
|
drivers/char/hw_random/Makefile | 1 -
|
|
drivers/char/hw_random/ppc4xx-rng.c | 147 --------------------------------
|
|
drivers/crypto/Kconfig | 8 ++
|
|
drivers/crypto/amcc/Makefile | 1 +
|
|
drivers/crypto/amcc/crypto4xx_core.c | 7 +-
|
|
drivers/crypto/amcc/crypto4xx_core.h | 4 +
|
|
drivers/crypto/amcc/crypto4xx_reg_def.h | 1 +
|
|
drivers/crypto/amcc/crypto4xx_trng.c | 131 ++++++++++++++++++++++++++++
|
|
drivers/crypto/amcc/crypto4xx_trng.h | 34 ++++++++
|
|
10 files changed, 184 insertions(+), 163 deletions(-)
|
|
delete mode 100644 drivers/char/hw_random/ppc4xx-rng.c
|
|
create mode 100644 drivers/crypto/amcc/crypto4xx_trng.c
|
|
create mode 100644 drivers/crypto/amcc/crypto4xx_trng.h
|
|
|
|
--- a/drivers/char/hw_random/Kconfig
|
|
+++ b/drivers/char/hw_random/Kconfig
|
|
@@ -268,19 +268,6 @@ config HW_RANDOM_NOMADIK
|
|
|
|
If unsure, say Y.
|
|
|
|
-config HW_RANDOM_PPC4XX
|
|
- tristate "PowerPC 4xx generic true random number generator support"
|
|
- depends on PPC && 4xx
|
|
- default HW_RANDOM
|
|
- ---help---
|
|
- This driver provides the kernel-side support for the TRNG hardware
|
|
- found in the security function of some PowerPC 4xx SoCs.
|
|
-
|
|
- To compile this driver as a module, choose M here: the
|
|
- module will be called ppc4xx-rng.
|
|
-
|
|
- If unsure, say N.
|
|
-
|
|
config HW_RANDOM_PSERIES
|
|
tristate "pSeries HW Random Number Generator support"
|
|
depends on PPC64 && IBMVIO
|
|
--- a/drivers/char/hw_random/Makefile
|
|
+++ b/drivers/char/hw_random/Makefile
|
|
@@ -22,7 +22,6 @@ obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939
|
|
obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
|
|
obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
|
|
obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
|
|
-obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
|
|
obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
|
|
obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
|
|
obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
|
|
--- a/drivers/char/hw_random/ppc4xx-rng.c
|
|
+++ /dev/null
|
|
@@ -1,147 +0,0 @@
|
|
-/*
|
|
- * Generic PowerPC 44x RNG driver
|
|
- *
|
|
- * Copyright 2011 IBM Corporation
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or modify it
|
|
- * under the terms of the GNU General Public License as published by the
|
|
- * Free Software Foundation; version 2 of the License.
|
|
- */
|
|
-
|
|
-#include <linux/module.h>
|
|
-#include <linux/kernel.h>
|
|
-#include <linux/platform_device.h>
|
|
-#include <linux/hw_random.h>
|
|
-#include <linux/delay.h>
|
|
-#include <linux/of_address.h>
|
|
-#include <linux/of_platform.h>
|
|
-#include <asm/io.h>
|
|
-
|
|
-#define PPC4XX_TRNG_DEV_CTRL 0x60080
|
|
-
|
|
-#define PPC4XX_TRNGE 0x00020000
|
|
-#define PPC4XX_TRNG_CTRL 0x0008
|
|
-#define PPC4XX_TRNG_CTRL_DALM 0x20
|
|
-#define PPC4XX_TRNG_STAT 0x0004
|
|
-#define PPC4XX_TRNG_STAT_B 0x1
|
|
-#define PPC4XX_TRNG_DATA 0x0000
|
|
-
|
|
-#define MODULE_NAME "ppc4xx_rng"
|
|
-
|
|
-static int ppc4xx_rng_data_present(struct hwrng *rng, int wait)
|
|
-{
|
|
- void __iomem *rng_regs = (void __iomem *) rng->priv;
|
|
- int busy, i, present = 0;
|
|
-
|
|
- for (i = 0; i < 20; i++) {
|
|
- busy = (in_le32(rng_regs + PPC4XX_TRNG_STAT) & PPC4XX_TRNG_STAT_B);
|
|
- if (!busy || !wait) {
|
|
- present = 1;
|
|
- break;
|
|
- }
|
|
- udelay(10);
|
|
- }
|
|
- return present;
|
|
-}
|
|
-
|
|
-static int ppc4xx_rng_data_read(struct hwrng *rng, u32 *data)
|
|
-{
|
|
- void __iomem *rng_regs = (void __iomem *) rng->priv;
|
|
- *data = in_le32(rng_regs + PPC4XX_TRNG_DATA);
|
|
- return 4;
|
|
-}
|
|
-
|
|
-static int ppc4xx_rng_enable(int enable)
|
|
-{
|
|
- struct device_node *ctrl;
|
|
- void __iomem *ctrl_reg;
|
|
- int err = 0;
|
|
- u32 val;
|
|
-
|
|
- /* Find the main crypto device node and map it to turn the TRNG on */
|
|
- ctrl = of_find_compatible_node(NULL, NULL, "amcc,ppc4xx-crypto");
|
|
- if (!ctrl)
|
|
- return -ENODEV;
|
|
-
|
|
- ctrl_reg = of_iomap(ctrl, 0);
|
|
- if (!ctrl_reg) {
|
|
- err = -ENODEV;
|
|
- goto out;
|
|
- }
|
|
-
|
|
- val = in_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL);
|
|
-
|
|
- if (enable)
|
|
- val |= PPC4XX_TRNGE;
|
|
- else
|
|
- val = val & ~PPC4XX_TRNGE;
|
|
-
|
|
- out_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL, val);
|
|
- iounmap(ctrl_reg);
|
|
-
|
|
-out:
|
|
- of_node_put(ctrl);
|
|
-
|
|
- return err;
|
|
-}
|
|
-
|
|
-static struct hwrng ppc4xx_rng = {
|
|
- .name = MODULE_NAME,
|
|
- .data_present = ppc4xx_rng_data_present,
|
|
- .data_read = ppc4xx_rng_data_read,
|
|
-};
|
|
-
|
|
-static int ppc4xx_rng_probe(struct platform_device *dev)
|
|
-{
|
|
- void __iomem *rng_regs;
|
|
- int err = 0;
|
|
-
|
|
- rng_regs = of_iomap(dev->dev.of_node, 0);
|
|
- if (!rng_regs)
|
|
- return -ENODEV;
|
|
-
|
|
- err = ppc4xx_rng_enable(1);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
- out_le32(rng_regs + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM);
|
|
- ppc4xx_rng.priv = (unsigned long) rng_regs;
|
|
-
|
|
- err = hwrng_register(&ppc4xx_rng);
|
|
-
|
|
- return err;
|
|
-}
|
|
-
|
|
-static int ppc4xx_rng_remove(struct platform_device *dev)
|
|
-{
|
|
- void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
|
|
-
|
|
- hwrng_unregister(&ppc4xx_rng);
|
|
- ppc4xx_rng_enable(0);
|
|
- iounmap(rng_regs);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const struct of_device_id ppc4xx_rng_match[] = {
|
|
- { .compatible = "ppc4xx-rng", },
|
|
- { .compatible = "amcc,ppc460ex-rng", },
|
|
- { .compatible = "amcc,ppc440epx-rng", },
|
|
- {},
|
|
-};
|
|
-MODULE_DEVICE_TABLE(of, ppc4xx_rng_match);
|
|
-
|
|
-static struct platform_driver ppc4xx_rng_driver = {
|
|
- .driver = {
|
|
- .name = MODULE_NAME,
|
|
- .of_match_table = ppc4xx_rng_match,
|
|
- },
|
|
- .probe = ppc4xx_rng_probe,
|
|
- .remove = ppc4xx_rng_remove,
|
|
-};
|
|
-
|
|
-module_platform_driver(ppc4xx_rng_driver);
|
|
-
|
|
-MODULE_LICENSE("GPL");
|
|
-MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>");
|
|
-MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors");
|
|
--- a/drivers/crypto/Kconfig
|
|
+++ b/drivers/crypto/Kconfig
|
|
@@ -277,6 +277,14 @@ config CRYPTO_DEV_PPC4XX
|
|
help
|
|
This option allows you to have support for AMCC crypto acceleration.
|
|
|
|
+config HW_RANDOM_PPC4XX
|
|
+ bool "PowerPC 4xx generic true random number generator support"
|
|
+ depends on CRYPTO_DEV_PPC4XX && HW_RANDOM
|
|
+ default y
|
|
+ ---help---
|
|
+ This option provides the kernel-side support for the TRNG hardware
|
|
+ found in the security function of some PowerPC 4xx SoCs.
|
|
+
|
|
config CRYPTO_DEV_OMAP_SHAM
|
|
tristate "Support for OMAP MD5/SHA1/SHA2 hw accelerator"
|
|
depends on ARCH_OMAP2PLUS
|
|
--- a/drivers/crypto/amcc/Makefile
|
|
+++ b/drivers/crypto/amcc/Makefile
|
|
@@ -1,2 +1,3 @@
|
|
obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o
|
|
crypto4xx-y := crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o
|
|
+crypto4xx-$(CONFIG_HW_RANDOM_PPC4XX) += crypto4xx_trng.o
|
|
--- a/drivers/crypto/amcc/crypto4xx_core.c
|
|
+++ b/drivers/crypto/amcc/crypto4xx_core.c
|
|
@@ -40,6 +40,7 @@
|
|
#include "crypto4xx_reg_def.h"
|
|
#include "crypto4xx_core.h"
|
|
#include "crypto4xx_sa.h"
|
|
+#include "crypto4xx_trng.h"
|
|
|
|
#define PPC4XX_SEC_VERSION_STR "0.5"
|
|
|
|
@@ -1221,6 +1222,7 @@ static int crypto4xx_probe(struct platfo
|
|
if (rc)
|
|
goto err_start_dev;
|
|
|
|
+ ppc4xx_trng_probe(core_dev);
|
|
return 0;
|
|
|
|
err_start_dev:
|
|
@@ -1248,6 +1250,8 @@ static int crypto4xx_remove(struct platf
|
|
struct device *dev = &ofdev->dev;
|
|
struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
|
|
|
|
+ ppc4xx_trng_remove(core_dev);
|
|
+
|
|
free_irq(core_dev->irq, dev);
|
|
irq_dispose_mapping(core_dev->irq);
|
|
|
|
@@ -1268,7 +1272,7 @@ MODULE_DEVICE_TABLE(of, crypto4xx_match)
|
|
|
|
static struct platform_driver crypto4xx_driver = {
|
|
.driver = {
|
|
- .name = "crypto4xx",
|
|
+ .name = MODULE_NAME,
|
|
.of_match_table = crypto4xx_match,
|
|
},
|
|
.probe = crypto4xx_probe,
|
|
@@ -1280,4 +1284,3 @@ module_platform_driver(crypto4xx_driver)
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("James Hsiao <jhsiao@amcc.com>");
|
|
MODULE_DESCRIPTION("Driver for AMCC PPC4xx crypto accelerator");
|
|
-
|
|
--- a/drivers/crypto/amcc/crypto4xx_core.h
|
|
+++ b/drivers/crypto/amcc/crypto4xx_core.h
|
|
@@ -24,6 +24,8 @@
|
|
|
|
#include <crypto/internal/hash.h>
|
|
|
|
+#define MODULE_NAME "crypto4xx"
|
|
+
|
|
#define PPC460SX_SDR0_SRST 0x201
|
|
#define PPC405EX_SDR0_SRST 0x200
|
|
#define PPC460EX_SDR0_SRST 0x201
|
|
@@ -72,6 +74,7 @@ struct crypto4xx_device {
|
|
char *name;
|
|
u64 ce_phy_address;
|
|
void __iomem *ce_base;
|
|
+ void __iomem *trng_base;
|
|
|
|
void *pdr; /* base address of packet
|
|
descriptor ring */
|
|
@@ -106,6 +109,7 @@ struct crypto4xx_core_device {
|
|
struct device *device;
|
|
struct platform_device *ofdev;
|
|
struct crypto4xx_device *dev;
|
|
+ struct hwrng *trng;
|
|
u32 int_status;
|
|
u32 irq;
|
|
struct tasklet_struct tasklet;
|
|
--- a/drivers/crypto/amcc/crypto4xx_reg_def.h
|
|
+++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
|
|
@@ -125,6 +125,7 @@
|
|
#define PPC4XX_INTERRUPT_CLR 0x3ffff
|
|
#define PPC4XX_PRNG_CTRL_AUTO_EN 0x3
|
|
#define PPC4XX_DC_3DES_EN 1
|
|
+#define PPC4XX_TRNG_EN 0x00020000
|
|
#define PPC4XX_INT_DESCR_CNT 4
|
|
#define PPC4XX_INT_TIMEOUT_CNT 0
|
|
#define PPC4XX_INT_CFG 1
|
|
--- /dev/null
|
|
+++ b/drivers/crypto/amcc/crypto4xx_trng.c
|
|
@@ -0,0 +1,131 @@
|
|
+/*
|
|
+ * Generic PowerPC 44x RNG driver
|
|
+ *
|
|
+ * Copyright 2011 IBM Corporation
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License as published by the
|
|
+ * Free Software Foundation; version 2 of the License.
|
|
+ */
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/hw_random.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/of_address.h>
|
|
+#include <linux/of_platform.h>
|
|
+#include <linux/io.h>
|
|
+
|
|
+#include "crypto4xx_core.h"
|
|
+#include "crypto4xx_trng.h"
|
|
+#include "crypto4xx_reg_def.h"
|
|
+
|
|
+#define PPC4XX_TRNG_CTRL 0x0008
|
|
+#define PPC4XX_TRNG_CTRL_DALM 0x20
|
|
+#define PPC4XX_TRNG_STAT 0x0004
|
|
+#define PPC4XX_TRNG_STAT_B 0x1
|
|
+#define PPC4XX_TRNG_DATA 0x0000
|
|
+
|
|
+static int ppc4xx_trng_data_present(struct hwrng *rng, int wait)
|
|
+{
|
|
+ struct crypto4xx_device *dev = (void *)rng->priv;
|
|
+ int busy, i, present = 0;
|
|
+
|
|
+ for (i = 0; i < 20; i++) {
|
|
+ busy = (in_le32(dev->trng_base + PPC4XX_TRNG_STAT) &
|
|
+ PPC4XX_TRNG_STAT_B);
|
|
+ if (!busy || !wait) {
|
|
+ present = 1;
|
|
+ break;
|
|
+ }
|
|
+ udelay(10);
|
|
+ }
|
|
+ return present;
|
|
+}
|
|
+
|
|
+static int ppc4xx_trng_data_read(struct hwrng *rng, u32 *data)
|
|
+{
|
|
+ struct crypto4xx_device *dev = (void *)rng->priv;
|
|
+ *data = in_le32(dev->trng_base + PPC4XX_TRNG_DATA);
|
|
+ return 4;
|
|
+}
|
|
+
|
|
+static void ppc4xx_trng_enable(struct crypto4xx_device *dev, bool enable)
|
|
+{
|
|
+ u32 device_ctrl;
|
|
+
|
|
+ device_ctrl = readl(dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
|
|
+ if (enable)
|
|
+ device_ctrl |= PPC4XX_TRNG_EN;
|
|
+ else
|
|
+ device_ctrl &= ~PPC4XX_TRNG_EN;
|
|
+ writel(device_ctrl, dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
|
|
+}
|
|
+
|
|
+static const struct of_device_id ppc4xx_trng_match[] = {
|
|
+ { .compatible = "ppc4xx-rng", },
|
|
+ { .compatible = "amcc,ppc460ex-rng", },
|
|
+ { .compatible = "amcc,ppc440epx-rng", },
|
|
+ {},
|
|
+};
|
|
+
|
|
+void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
|
|
+{
|
|
+ struct crypto4xx_device *dev = core_dev->dev;
|
|
+ struct device_node *trng = NULL;
|
|
+ struct hwrng *rng = NULL;
|
|
+ int err;
|
|
+
|
|
+ /* Find the TRNG device node and map it */
|
|
+ trng = of_find_matching_node(NULL, ppc4xx_trng_match);
|
|
+ if (!trng || !of_device_is_available(trng))
|
|
+ return;
|
|
+
|
|
+ dev->trng_base = of_iomap(trng, 0);
|
|
+ of_node_put(trng);
|
|
+ if (!dev->trng_base)
|
|
+ goto err_out;
|
|
+
|
|
+ rng = kzalloc(sizeof(*rng), GFP_KERNEL);
|
|
+ if (!rng)
|
|
+ goto err_out;
|
|
+
|
|
+ rng->name = MODULE_NAME;
|
|
+ rng->data_present = ppc4xx_trng_data_present;
|
|
+ rng->data_read = ppc4xx_trng_data_read;
|
|
+ rng->priv = (unsigned long) dev;
|
|
+ core_dev->trng = rng;
|
|
+ ppc4xx_trng_enable(dev, true);
|
|
+ out_le32(dev->trng_base + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM);
|
|
+ err = devm_hwrng_register(core_dev->device, core_dev->trng);
|
|
+ if (err) {
|
|
+ ppc4xx_trng_enable(dev, false);
|
|
+ dev_err(core_dev->device, "failed to register hwrng (%d).\n",
|
|
+ err);
|
|
+ goto err_out;
|
|
+ }
|
|
+ return;
|
|
+
|
|
+err_out:
|
|
+ of_node_put(trng);
|
|
+ iounmap(dev->trng_base);
|
|
+ kfree(rng);
|
|
+ dev->trng_base = NULL;
|
|
+ core_dev->trng = NULL;
|
|
+}
|
|
+
|
|
+void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev)
|
|
+{
|
|
+ if (core_dev && core_dev->trng) {
|
|
+ struct crypto4xx_device *dev = core_dev->dev;
|
|
+
|
|
+ devm_hwrng_unregister(core_dev->device, core_dev->trng);
|
|
+ ppc4xx_trng_enable(dev, false);
|
|
+ iounmap(dev->trng_base);
|
|
+ kfree(core_dev->trng);
|
|
+ }
|
|
+}
|
|
+
|
|
+MODULE_ALIAS("ppc4xx_rng");
|
|
--- /dev/null
|
|
+++ b/drivers/crypto/amcc/crypto4xx_trng.h
|
|
@@ -0,0 +1,34 @@
|
|
+/**
|
|
+ * AMCC SoC PPC4xx Crypto Driver
|
|
+ *
|
|
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
|
|
+ * All rights reserved. James Hsiao <jhsiao@amcc.com>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * This file defines the security context
|
|
+ * associate format.
|
|
+ */
|
|
+
|
|
+#ifndef __CRYPTO4XX_TRNG_H__
|
|
+#define __CRYPTO4XX_TRNG_H__
|
|
+
|
|
+#ifdef CONFIG_HW_RANDOM_PPC4XX
|
|
+void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev);
|
|
+void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev);
|
|
+#else
|
|
+static inline void ppc4xx_trng_probe(
|
|
+ struct crypto4xx_device *dev __maybe_unused) { }
|
|
+static inline void ppc4xx_trng_remove(
|
|
+ struct crypto4xx_device *dev __maybe_unused) { }
|
|
+#endif
|
|
+
|
|
+#endif
|
|
|