162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Derived from arch/powerpc/platforms/powernv/rng.c, which is:
462306a36Sopenharmony_ci * Copyright 2013, Michael Ellerman, IBM Corporation.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define pr_fmt(fmt)	"microwatt-rng: " fmt
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <linux/smp.h>
1162306a36Sopenharmony_ci#include <asm/archrandom.h>
1262306a36Sopenharmony_ci#include <asm/cputable.h>
1362306a36Sopenharmony_ci#include <asm/machdep.h>
1462306a36Sopenharmony_ci#include "microwatt.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define DARN_ERR 0xFFFFFFFFFFFFFFFFul
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic int microwatt_get_random_darn(unsigned long *v)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	unsigned long val;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	/* Using DARN with L=1 - 64-bit conditioned random number */
2362306a36Sopenharmony_ci	asm volatile(PPC_DARN(%0, 1) : "=r"(val));
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	if (val == DARN_ERR)
2662306a36Sopenharmony_ci		return 0;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	*v = val;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	return 1;
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_civoid __init microwatt_rng_init(void)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	unsigned long val;
3662306a36Sopenharmony_ci	int i;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
3962306a36Sopenharmony_ci		if (microwatt_get_random_darn(&val)) {
4062306a36Sopenharmony_ci			ppc_md.get_random_seed = microwatt_get_random_darn;
4162306a36Sopenharmony_ci			return;
4262306a36Sopenharmony_ci		}
4362306a36Sopenharmony_ci	}
4462306a36Sopenharmony_ci}
45