 bcd2982a0e
			
		
	
	
	bcd2982a0e
	
	
	
		
			
			CONFIG_HOTPLUG is going away as an option. As a result, the __dev* markings need to be removed. This change removes the use of __devinit, __devexit_p, __devinitdata, __devinitconst, and __devexit from these drivers. Based on patches originally written by Bill Pemberton, but redone by me in order to handle some of the coding style issues better, by hand. Cc: Bill Pemberton <wfp5p@virginia.edu> Cc: David Airlie <airlied@linux.ie> Cc: Matt Mackall <mpm@selenic.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
		
			
				
	
	
		
			146 lines
		
	
	
	
		
			3.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
	
		
			3.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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 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 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,
 | |
| };
 | |
| 
 | |
| 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");
 |