Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.11-rc4 154 lines 3.5 kB view raw
1/* 2 * Broadcom BCM63xx Random Number Generator support 3 * 4 * Copyright (C) 2011, Florian Fainelli <florian@openwrt.org> 5 * Copyright (C) 2009, Broadcom Corporation 6 * 7 */ 8#include <linux/module.h> 9#include <linux/slab.h> 10#include <linux/io.h> 11#include <linux/err.h> 12#include <linux/clk.h> 13#include <linux/platform_device.h> 14#include <linux/hw_random.h> 15#include <linux/of.h> 16 17#define RNG_CTRL 0x00 18#define RNG_EN (1 << 0) 19 20#define RNG_STAT 0x04 21#define RNG_AVAIL_MASK (0xff000000) 22 23#define RNG_DATA 0x08 24#define RNG_THRES 0x0c 25#define RNG_MASK 0x10 26 27struct bcm63xx_rng_priv { 28 struct hwrng rng; 29 struct clk *clk; 30 void __iomem *regs; 31}; 32 33#define to_rng_priv(rng) container_of(rng, struct bcm63xx_rng_priv, rng) 34 35static int bcm63xx_rng_init(struct hwrng *rng) 36{ 37 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 38 u32 val; 39 int error; 40 41 error = clk_prepare_enable(priv->clk); 42 if (error) 43 return error; 44 45 val = __raw_readl(priv->regs + RNG_CTRL); 46 val |= RNG_EN; 47 __raw_writel(val, priv->regs + RNG_CTRL); 48 49 return 0; 50} 51 52static void bcm63xx_rng_cleanup(struct hwrng *rng) 53{ 54 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 55 u32 val; 56 57 val = __raw_readl(priv->regs + RNG_CTRL); 58 val &= ~RNG_EN; 59 __raw_writel(val, priv->regs + RNG_CTRL); 60 61 clk_disable_unprepare(priv->clk); 62} 63 64static int bcm63xx_rng_data_present(struct hwrng *rng, int wait) 65{ 66 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 67 68 return __raw_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK; 69} 70 71static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) 72{ 73 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 74 75 *data = __raw_readl(priv->regs + RNG_DATA); 76 77 return 4; 78} 79 80static int bcm63xx_rng_probe(struct platform_device *pdev) 81{ 82 struct resource *r; 83 int ret; 84 struct bcm63xx_rng_priv *priv; 85 86 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 87 if (!r) { 88 dev_err(&pdev->dev, "no iomem resource\n"); 89 return -ENXIO; 90 } 91 92 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 93 if (!priv) 94 return -ENOMEM; 95 96 priv->rng.name = pdev->name; 97 priv->rng.init = bcm63xx_rng_init; 98 priv->rng.cleanup = bcm63xx_rng_cleanup; 99 priv->rng.data_present = bcm63xx_rng_data_present; 100 priv->rng.data_read = bcm63xx_rng_data_read; 101 102 priv->clk = devm_clk_get(&pdev->dev, "ipsec"); 103 if (IS_ERR(priv->clk)) { 104 ret = PTR_ERR(priv->clk); 105 dev_err(&pdev->dev, "no clock for device: %d\n", ret); 106 return ret; 107 } 108 109 if (!devm_request_mem_region(&pdev->dev, r->start, 110 resource_size(r), pdev->name)) { 111 dev_err(&pdev->dev, "request mem failed"); 112 return -EBUSY; 113 } 114 115 priv->regs = devm_ioremap_nocache(&pdev->dev, r->start, 116 resource_size(r)); 117 if (!priv->regs) { 118 dev_err(&pdev->dev, "ioremap failed"); 119 return -ENOMEM; 120 } 121 122 ret = devm_hwrng_register(&pdev->dev, &priv->rng); 123 if (ret) { 124 dev_err(&pdev->dev, "failed to register rng device: %d\n", 125 ret); 126 return ret; 127 } 128 129 dev_info(&pdev->dev, "registered RNG driver\n"); 130 131 return 0; 132} 133 134#ifdef CONFIG_OF 135static const struct of_device_id bcm63xx_rng_of_match[] = { 136 { .compatible = "brcm,bcm6368-rng", }, 137 {}, 138}; 139MODULE_DEVICE_TABLE(of, bcm63xx_rng_of_match); 140#endif 141 142static struct platform_driver bcm63xx_rng_driver = { 143 .probe = bcm63xx_rng_probe, 144 .driver = { 145 .name = "bcm63xx-rng", 146 .of_match_table = of_match_ptr(bcm63xx_rng_of_match), 147 }, 148}; 149 150module_platform_driver(bcm63xx_rng_driver); 151 152MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); 153MODULE_DESCRIPTION("Broadcom BCM63xx RNG driver"); 154MODULE_LICENSE("GPL");