diff options
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r-- | drivers/char/hw_random/Kconfig | 12 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/core.c | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/n2-drv.c | 29 | ||||
-rw-r--r-- | drivers/char/hw_random/n2rng.h | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/nomadik-rng.c | 3 | ||||
-rw-r--r-- | drivers/char/hw_random/omap-rng.c | 6 | ||||
-rw-r--r-- | drivers/char/hw_random/ppc4xx-rng.c | 156 | ||||
-rw-r--r-- | drivers/char/hw_random/timeriomem-rng.c | 3 |
9 files changed, 195 insertions, 19 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index a60043b3e40..1d2ebc7a494 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -210,3 +210,15 @@ config HW_RANDOM_PICOXCELL module will be called picoxcell-rng. If unsure, say Y. + +config HW_RANDOM_PPC4XX + tristate "PowerPC 4xx generic true random number generator support" + depends on HW_RANDOM && PPC && 4xx + ---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. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 3db4eb8b19c..c88f244c8a7 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -20,3 +20,4 @@ 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_PICOXCELL) += picoxcell-rng.o +obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 2016aad8520..1bafb40ec8a 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -19,7 +19,7 @@ Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> Added generic RNG API - Copyright 2006 Michael Buesch <mbuesch@freenet.de> + Copyright 2006 Michael Buesch <m@bues.ch> Copyright 2005 (c) MontaVista Software, Inc. Please read Documentation/hw_random.txt for details on use. diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index ac6739e085e..c3de70de00d 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -1,6 +1,6 @@ /* n2-drv.c: Niagara-2 RNG driver. * - * Copyright (C) 2008 David S. Miller <davem@davemloft.net> + * Copyright (C) 2008, 2011 David S. Miller <davem@davemloft.net> */ #include <linux/kernel.h> @@ -22,8 +22,8 @@ #define DRV_MODULE_NAME "n2rng" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.1" -#define DRV_MODULE_RELDATE "May 15, 2008" +#define DRV_MODULE_VERSION "0.2" +#define DRV_MODULE_RELDATE "July 27, 2011" static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -623,14 +623,14 @@ static const struct of_device_id n2rng_match[]; static int __devinit n2rng_probe(struct platform_device *op) { const struct of_device_id *match; - int victoria_falls; + int multi_capable; int err = -ENOMEM; struct n2rng *np; match = of_match_device(n2rng_match, &op->dev); if (!match) return -EINVAL; - victoria_falls = (match->data != NULL); + multi_capable = (match->data != NULL); n2rng_driver_version(); np = kzalloc(sizeof(*np), GFP_KERNEL); @@ -640,8 +640,8 @@ static int __devinit n2rng_probe(struct platform_device *op) INIT_DELAYED_WORK(&np->work, n2rng_work); - if (victoria_falls) - np->flags |= N2RNG_FLAG_VF; + if (multi_capable) + np->flags |= N2RNG_FLAG_MULTI; err = -ENODEV; np->hvapi_major = 2; @@ -658,10 +658,10 @@ static int __devinit n2rng_probe(struct platform_device *op) } } - if (np->flags & N2RNG_FLAG_VF) { + if (np->flags & N2RNG_FLAG_MULTI) { if (np->hvapi_major < 2) { - dev_err(&op->dev, "VF RNG requires HVAPI major " - "version 2 or later, got %lu\n", + dev_err(&op->dev, "multi-unit-capable RNG requires " + "HVAPI major version 2 or later, got %lu\n", np->hvapi_major); goto out_hvapi_unregister; } @@ -688,8 +688,8 @@ static int __devinit n2rng_probe(struct platform_device *op) goto out_free_units; dev_info(&op->dev, "Found %s RNG, units: %d\n", - ((np->flags & N2RNG_FLAG_VF) ? - "Victoria Falls" : "Niagara2"), + ((np->flags & N2RNG_FLAG_MULTI) ? + "multi-unit-capable" : "single-unit"), np->num_units); np->hwrng.name = "n2rng"; @@ -751,6 +751,11 @@ static const struct of_device_id n2rng_match[] = { .compatible = "SUNW,vf-rng", .data = (void *) 1, }, + { + .name = "random-number-generator", + .compatible = "SUNW,kt-rng", + .data = (void *) 1, + }, {}, }; MODULE_DEVICE_TABLE(of, n2rng_match); diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h index 4bea07f3097..f244ac89087 100644 --- a/drivers/char/hw_random/n2rng.h +++ b/drivers/char/hw_random/n2rng.h @@ -68,7 +68,7 @@ struct n2rng { struct platform_device *op; unsigned long flags; -#define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ +#define N2RNG_FLAG_MULTI 0x00000001 /* Multi-unit capable RNG */ #define N2RNG_FLAG_CONTROL 0x00000002 /* Operating in control domain */ #define N2RNG_FLAG_READY 0x00000008 /* Ready for hw-rng layer */ #define N2RNG_FLAG_SHUTDOWN 0x00000010 /* Driver unregistering */ diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index dd1d143eb8e..52e08ca3ccd 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c @@ -55,7 +55,7 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) ret = amba_request_regions(dev, dev->dev.init_name); if (ret) - return ret; + goto out_clk; ret = -ENOMEM; base = ioremap(dev->res.start, resource_size(&dev->res)); if (!base) @@ -70,6 +70,7 @@ out_unmap: iounmap(base); out_release: amba_release_regions(dev); +out_clk: clk_disable(rng_clk); clk_put(rng_clk); return ret; diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 2cc755a6430..b757fac3cd1 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -113,8 +113,10 @@ static int __devinit omap_rng_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; + if (!res) { + ret = -ENOENT; + goto err_region; + } if (!request_mem_region(res->start, resource_size(res), pdev->name)) { ret = -EBUSY; diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c new file mode 100644 index 00000000000..b8afa6a4ff6 --- /dev/null +++ b/drivers/char/hw_random/ppc4xx-rng.c @@ -0,0 +1,156 @@ +/* + * 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_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 __devinit 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 __devexit 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 struct of_device_id ppc4xx_rng_match[] = { + { .compatible = "ppc4xx-rng", }, + { .compatible = "amcc,ppc460ex-rng", }, + { .compatible = "amcc,ppc440epx-rng", }, + {}, +}; + +static struct platform_driver ppc4xx_rng_driver = { + .driver = { + .name = MODULE_NAME, + .owner = THIS_MODULE, + .of_match_table = ppc4xx_rng_match, + }, + .probe = ppc4xx_rng_probe, + .remove = ppc4xx_rng_remove, +}; + +static int __init ppc4xx_rng_init(void) +{ + return platform_driver_register(&ppc4xx_rng_driver); +} +module_init(ppc4xx_rng_init); + +static void __exit ppc4xx_rng_exit(void) +{ + platform_driver_unregister(&ppc4xx_rng_driver); +} +module_exit(ppc4xx_rng_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>"); +MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors"); diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index a94e930575f..a8428e6f64a 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c @@ -100,8 +100,7 @@ static int __devinit timeriomem_rng_probe(struct platform_device *pdev) timeriomem_rng_data = pdev->dev.platform_data; - timeriomem_rng_data->address = ioremap(res->start, - res->end - res->start + 1); + timeriomem_rng_data->address = ioremap(res->start, resource_size(res)); if (!timeriomem_rng_data->address) return -EIO; |