drivers/rng: add Amlogic hardware RNG driver
Add support for the hardware random number generator of Amlogic SOCs. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Sughosh Ganu <sughosh.ganu@linaro.org>
This commit is contained in:
		
							parent
							
								
									c312c4b4dc
								
							
						
					
					
						commit
						bc40eb278b
					
				|  | @ -8,6 +8,14 @@ config DM_RNG | ||||||
| 
 | 
 | ||||||
| if DM_RNG | if DM_RNG | ||||||
| 
 | 
 | ||||||
|  | config RNG_MESON | ||||||
|  | 	bool "Amlogic Meson Random Number Generator support" | ||||||
|  | 	depends on ARCH_MESON | ||||||
|  | 	default y | ||||||
|  | 	help | ||||||
|  | 	  Enable support for hardware random number generator | ||||||
|  | 	  of Amlogic Meson SoCs. | ||||||
|  | 
 | ||||||
| config RNG_SANDBOX | config RNG_SANDBOX | ||||||
| 	bool "Sandbox random number generator" | 	bool "Sandbox random number generator" | ||||||
| 	depends on SANDBOX | 	depends on SANDBOX | ||||||
|  |  | ||||||
|  | @ -4,5 +4,6 @@ | ||||||
| #
 | #
 | ||||||
| 
 | 
 | ||||||
| obj-$(CONFIG_DM_RNG) += rng-uclass.o | obj-$(CONFIG_DM_RNG) += rng-uclass.o | ||||||
|  | obj-$(CONFIG_RNG_MESON) += meson-rng.o | ||||||
| obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o | obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o | ||||||
| obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o | obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o | ||||||
|  |  | ||||||
|  | @ -0,0 +1,120 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | /*
 | ||||||
|  |  * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> | ||||||
|  |  * | ||||||
|  |  * Driver for Amlogic hardware random number generator | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <common.h> | ||||||
|  | #include <clk.h> | ||||||
|  | #include <dm.h> | ||||||
|  | #include <rng.h> | ||||||
|  | #include <asm/io.h> | ||||||
|  | 
 | ||||||
|  | struct meson_rng_platdata { | ||||||
|  | 	fdt_addr_t base; | ||||||
|  | 	struct clk clk; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * meson_rng_read() - fill buffer with random bytes | ||||||
|  |  * | ||||||
|  |  * @buffer:	buffer to receive data | ||||||
|  |  * @size:	size of buffer | ||||||
|  |  * | ||||||
|  |  * Return:	0 | ||||||
|  |  */ | ||||||
|  | static int meson_rng_read(struct udevice *dev, void *data, size_t len) | ||||||
|  | { | ||||||
|  | 	struct meson_rng_platdata *pdata = dev_get_platdata(dev); | ||||||
|  | 	char *buffer = (char *)data; | ||||||
|  | 
 | ||||||
|  | 	while (len) { | ||||||
|  | 		u32 rand = readl(pdata->base); | ||||||
|  | 		size_t step; | ||||||
|  | 
 | ||||||
|  | 		if (len >= 4) | ||||||
|  | 			step = 4; | ||||||
|  | 		else | ||||||
|  | 			step = len; | ||||||
|  | 		memcpy(buffer, &rand, step); | ||||||
|  | 		buffer += step; | ||||||
|  | 		len -= step; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * meson_rng_probe() - probe rng device | ||||||
|  |  * | ||||||
|  |  * @dev:	device | ||||||
|  |  * Return:	0 if ok | ||||||
|  |  */ | ||||||
|  | static int meson_rng_probe(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct meson_rng_platdata *pdata = dev_get_platdata(dev); | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	err = clk_enable(&pdata->clk); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * meson_rng_remove() - deinitialize rng device | ||||||
|  |  * | ||||||
|  |  * @dev:	device | ||||||
|  |  * Return:	0 if ok | ||||||
|  |  */ | ||||||
|  | static int meson_rng_remove(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct meson_rng_platdata *pdata = dev_get_platdata(dev); | ||||||
|  | 
 | ||||||
|  | 	return clk_disable(&pdata->clk); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * meson_rng_ofdata_to_platdata() - transfer device tree data to plaform data | ||||||
|  |  * | ||||||
|  |  * @dev:	device | ||||||
|  |  * Return:	0 if ok | ||||||
|  |  */ | ||||||
|  | static int meson_rng_ofdata_to_platdata(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct meson_rng_platdata *pdata = dev_get_platdata(dev); | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	pdata->base = dev_read_addr(dev); | ||||||
|  | 	if (!pdata->base) | ||||||
|  | 		return -ENODEV; | ||||||
|  | 
 | ||||||
|  | 	err = clk_get_by_name(dev, "core", &pdata->clk); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct dm_rng_ops meson_rng_ops = { | ||||||
|  | 	.read = meson_rng_read, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct udevice_id meson_rng_match[] = { | ||||||
|  | 	{ | ||||||
|  | 		.compatible = "amlogic,meson-rng", | ||||||
|  | 	}, | ||||||
|  | 	{}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | U_BOOT_DRIVER(meson_rng) = { | ||||||
|  | 	.name = "meson-rng", | ||||||
|  | 	.id = UCLASS_RNG, | ||||||
|  | 	.of_match = meson_rng_match, | ||||||
|  | 	.ops = &meson_rng_ops, | ||||||
|  | 	.probe = meson_rng_probe, | ||||||
|  | 	.remove = meson_rng_remove, | ||||||
|  | 	.platdata_auto_alloc_size = sizeof(struct meson_rng_platdata), | ||||||
|  | 	.ofdata_to_platdata = meson_rng_ofdata_to_platdata, | ||||||
|  | }; | ||||||
		Loading…
	
		Reference in New Issue