Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * rockchip-rng.c True Random Number Generator driver for Rockchip RK3568 SoC
  4 *
  5 * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd.
  6 * Copyright (c) 2022, Aurelien Jarno
  7 * Authors:
  8 *  Lin Jinhan <troy.lin@rock-chips.com>
  9 *  Aurelien Jarno <aurelien@aurel32.net>
 10 */
 11#include <linux/clk.h>
 12#include <linux/hw_random.h>
 13#include <linux/io.h>
 14#include <linux/iopoll.h>
 15#include <linux/kernel.h>
 16#include <linux/module.h>
 17#include <linux/of.h>
 18#include <linux/platform_device.h>
 19#include <linux/pm_runtime.h>
 20#include <linux/reset.h>
 21#include <linux/slab.h>
 22
 23#define RK_RNG_AUTOSUSPEND_DELAY	100
 24#define RK_RNG_MAX_BYTE			32
 25#define RK_RNG_POLL_PERIOD_US		100
 26#define RK_RNG_POLL_TIMEOUT_US		10000
 27
 28/*
 29 * TRNG collects osc ring output bit every RK_RNG_SAMPLE_CNT time. The value is
 30 * a tradeoff between speed and quality and has been adjusted to get a quality
 31 * of ~900 (~87.5% of FIPS 140-2 successes).
 32 */
 33#define RK_RNG_SAMPLE_CNT		1000
 34
 35/* TRNG registers from RK3568 TRM-Part2, section 5.4.1 */
 36#define TRNG_RST_CTL			0x0004
 37#define TRNG_RNG_CTL			0x0400
 38#define TRNG_RNG_CTL_LEN_64_BIT		(0x00 << 4)
 39#define TRNG_RNG_CTL_LEN_128_BIT	(0x01 << 4)
 40#define TRNG_RNG_CTL_LEN_192_BIT	(0x02 << 4)
 41#define TRNG_RNG_CTL_LEN_256_BIT	(0x03 << 4)
 42#define TRNG_RNG_CTL_OSC_RING_SPEED_0	(0x00 << 2)
 43#define TRNG_RNG_CTL_OSC_RING_SPEED_1	(0x01 << 2)
 44#define TRNG_RNG_CTL_OSC_RING_SPEED_2	(0x02 << 2)
 45#define TRNG_RNG_CTL_OSC_RING_SPEED_3	(0x03 << 2)
 46#define TRNG_RNG_CTL_MASK		GENMASK(15, 0)
 47#define TRNG_RNG_CTL_ENABLE		BIT(1)
 48#define TRNG_RNG_CTL_START		BIT(0)
 49#define TRNG_RNG_SAMPLE_CNT		0x0404
 50#define TRNG_RNG_DOUT			0x0410
 51
 52struct rk_rng {
 53	struct hwrng rng;
 54	void __iomem *base;
 55	int clk_num;
 56	struct clk_bulk_data *clk_bulks;
 57};
 58
 59/* The mask in the upper 16 bits determines the bits that are updated */
 60static void rk_rng_write_ctl(struct rk_rng *rng, u32 val, u32 mask)
 61{
 62	writel((mask << 16) | val, rng->base + TRNG_RNG_CTL);
 63}
 64
 65static int rk_rng_init(struct hwrng *rng)
 66{
 67	struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
 68	int ret;
 69
 70	/* start clocks */
 71	ret = clk_bulk_prepare_enable(rk_rng->clk_num, rk_rng->clk_bulks);
 72	if (ret < 0) {
 73		dev_err((struct device *) rk_rng->rng.priv,
 74			"Failed to enable clks %d\n", ret);
 75		return ret;
 76	}
 77
 78	/* set the sample period */
 79	writel(RK_RNG_SAMPLE_CNT, rk_rng->base + TRNG_RNG_SAMPLE_CNT);
 80
 81	/* set osc ring speed and enable it */
 82	rk_rng_write_ctl(rk_rng, TRNG_RNG_CTL_LEN_256_BIT |
 83				 TRNG_RNG_CTL_OSC_RING_SPEED_0 |
 84				 TRNG_RNG_CTL_ENABLE,
 85			 TRNG_RNG_CTL_MASK);
 86
 87	return 0;
 88}
 89
 90static void rk_rng_cleanup(struct hwrng *rng)
 91{
 92	struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
 93
 94	/* stop TRNG */
 95	rk_rng_write_ctl(rk_rng, 0, TRNG_RNG_CTL_MASK);
 96
 97	/* stop clocks */
 98	clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks);
 99}
100
101static int rk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
102{
103	struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
104	size_t to_read = min_t(size_t, max, RK_RNG_MAX_BYTE);
105	u32 reg;
106	int ret = 0;
107
108	ret = pm_runtime_resume_and_get((struct device *) rk_rng->rng.priv);
109	if (ret < 0)
110		return ret;
111
112	/* Start collecting random data */
113	rk_rng_write_ctl(rk_rng, TRNG_RNG_CTL_START, TRNG_RNG_CTL_START);
114
115	ret = readl_poll_timeout(rk_rng->base + TRNG_RNG_CTL, reg,
116				 !(reg & TRNG_RNG_CTL_START),
117				 RK_RNG_POLL_PERIOD_US,
118				 RK_RNG_POLL_TIMEOUT_US);
119	if (ret < 0)
120		goto out;
121
122	/* Read random data stored in the registers */
123	memcpy_fromio(buf, rk_rng->base + TRNG_RNG_DOUT, to_read);
124out:
125	pm_runtime_mark_last_busy((struct device *) rk_rng->rng.priv);
126	pm_runtime_put_sync_autosuspend((struct device *) rk_rng->rng.priv);
127
128	return (ret < 0) ? ret : to_read;
129}
130
131static int rk_rng_probe(struct platform_device *pdev)
132{
133	struct device *dev = &pdev->dev;
134	struct reset_control *rst;
135	struct rk_rng *rk_rng;
136	int ret;
137
138	rk_rng = devm_kzalloc(dev, sizeof(*rk_rng), GFP_KERNEL);
139	if (!rk_rng)
140		return -ENOMEM;
141
142	rk_rng->base = devm_platform_ioremap_resource(pdev, 0);
143	if (IS_ERR(rk_rng->base))
144		return PTR_ERR(rk_rng->base);
145
146	rk_rng->clk_num = devm_clk_bulk_get_all(dev, &rk_rng->clk_bulks);
147	if (rk_rng->clk_num < 0)
148		return dev_err_probe(dev, rk_rng->clk_num,
149				     "Failed to get clks property\n");
150
151	rst = devm_reset_control_array_get_exclusive(&pdev->dev);
152	if (IS_ERR(rst))
153		return dev_err_probe(dev, PTR_ERR(rst), "Failed to get reset property\n");
154
155	reset_control_assert(rst);
156	udelay(2);
157	reset_control_deassert(rst);
158
159	platform_set_drvdata(pdev, rk_rng);
160
161	rk_rng->rng.name = dev_driver_string(dev);
162	if (!IS_ENABLED(CONFIG_PM)) {
163		rk_rng->rng.init = rk_rng_init;
164		rk_rng->rng.cleanup = rk_rng_cleanup;
165	}
166	rk_rng->rng.read = rk_rng_read;
167	rk_rng->rng.priv = (unsigned long) dev;
168	rk_rng->rng.quality = 900;
169
170	pm_runtime_set_autosuspend_delay(dev, RK_RNG_AUTOSUSPEND_DELAY);
171	pm_runtime_use_autosuspend(dev);
172	ret = devm_pm_runtime_enable(dev);
173	if (ret)
174		return dev_err_probe(&pdev->dev, ret, "Runtime pm activation failed.\n");
175
176	ret = devm_hwrng_register(dev, &rk_rng->rng);
177	if (ret)
178		return dev_err_probe(&pdev->dev, ret, "Failed to register Rockchip hwrng\n");
179
180	return 0;
181}
182
183static int __maybe_unused rk_rng_runtime_suspend(struct device *dev)
184{
185	struct rk_rng *rk_rng = dev_get_drvdata(dev);
186
187	rk_rng_cleanup(&rk_rng->rng);
188
189	return 0;
190}
191
192static int __maybe_unused rk_rng_runtime_resume(struct device *dev)
193{
194	struct rk_rng *rk_rng = dev_get_drvdata(dev);
195
196	return rk_rng_init(&rk_rng->rng);
197}
198
199static const struct dev_pm_ops rk_rng_pm_ops = {
200	SET_RUNTIME_PM_OPS(rk_rng_runtime_suspend,
201				rk_rng_runtime_resume, NULL)
202	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
203				pm_runtime_force_resume)
204};
205
206static const struct of_device_id rk_rng_dt_match[] = {
207	{ .compatible = "rockchip,rk3568-rng", },
208	{ /* sentinel */ },
209};
210
211MODULE_DEVICE_TABLE(of, rk_rng_dt_match);
212
213static struct platform_driver rk_rng_driver = {
214	.driver	= {
215		.name	= "rockchip-rng",
216		.pm	= &rk_rng_pm_ops,
217		.of_match_table = rk_rng_dt_match,
218	},
219	.probe	= rk_rng_probe,
220};
221
222module_platform_driver(rk_rng_driver);
223
224MODULE_DESCRIPTION("Rockchip RK3568 True Random Number Generator driver");
225MODULE_AUTHOR("Lin Jinhan <troy.lin@rock-chips.com>");
226MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
227MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
228MODULE_LICENSE("GPL");