72 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright 2013 Michael Ellerman, Guo Chao, IBM Corp.4 */5 6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt7 8#include <linux/module.h>9#include <linux/mod_devicetable.h>10#include <linux/kernel.h>11#include <linux/platform_device.h>12#include <linux/random.h>13#include <linux/hw_random.h>14#include <asm/archrandom.h>15 16static int powernv_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)17{18 unsigned long *buf;19 int i, len;20 21 /* We rely on rng_buffer_size() being >= sizeof(unsigned long) */22 len = max / sizeof(unsigned long);23 24 buf = (unsigned long *)data;25 26 for (i = 0; i < len; i++)27 pnv_get_random_long(buf++);28 29 return len * sizeof(unsigned long);30}31 32static struct hwrng powernv_hwrng = {33 .name = "powernv-rng",34 .read = powernv_rng_read,35};36 37static int powernv_rng_probe(struct platform_device *pdev)38{39 int rc;40 41 rc = devm_hwrng_register(&pdev->dev, &powernv_hwrng);42 if (rc) {43 /* We only register one device, ignore any others */44 if (rc == -EEXIST)45 rc = -ENODEV;46 47 return rc;48 }49 50 pr_info("Registered powernv hwrng.\n");51 52 return 0;53}54 55static const struct of_device_id powernv_rng_match[] = {56 { .compatible = "ibm,power-rng",},57 {},58};59MODULE_DEVICE_TABLE(of, powernv_rng_match);60 61static struct platform_driver powernv_rng_driver = {62 .driver = {63 .name = "powernv_rng",64 .of_match_table = powernv_rng_match,65 },66 .probe = powernv_rng_probe,67};68module_platform_driver(powernv_rng_driver);69 70MODULE_LICENSE("GPL");71MODULE_DESCRIPTION("Bare metal HWRNG driver for POWER7+ and above");72