Path: blob/master/drivers/char/hw_random/rockchip-rng.c
29269 views
// SPDX-License-Identifier: GPL-2.01/*2* rockchip-rng.c True Random Number Generator driver for Rockchip SoCs3*4* Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd.5* Copyright (c) 2022, Aurelien Jarno6* Copyright (c) 2025, Collabora Ltd.7* Authors:8* Lin Jinhan <[email protected]>9* Aurelien Jarno <[email protected]>10* Nicolas Frattaroli <[email protected]>11*/12#include <linux/clk.h>13#include <linux/hw_random.h>14#include <linux/io.h>15#include <linux/iopoll.h>16#include <linux/kernel.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/platform_device.h>20#include <linux/pm_runtime.h>21#include <linux/reset.h>22#include <linux/slab.h>2324#define RK_RNG_AUTOSUSPEND_DELAY 10025#define RK_RNG_MAX_BYTE 3226#define RK_RNG_POLL_PERIOD_US 10027#define RK_RNG_POLL_TIMEOUT_US 100002829/*30* TRNG collects osc ring output bit every RK_RNG_SAMPLE_CNT time. The value is31* a tradeoff between speed and quality and has been adjusted to get a quality32* of ~900 (~87.5% of FIPS 140-2 successes).33*/34#define RK_RNG_SAMPLE_CNT 10003536/* after how many bytes of output TRNGv1 implementations should be reseeded */37#define RK_TRNG_V1_AUTO_RESEED_CNT 160003839/* TRNG registers from RK3568 TRM-Part2, section 5.4.1 */40#define TRNG_RST_CTL 0x000441#define TRNG_RNG_CTL 0x040042#define TRNG_RNG_CTL_LEN_64_BIT (0x00 << 4)43#define TRNG_RNG_CTL_LEN_128_BIT (0x01 << 4)44#define TRNG_RNG_CTL_LEN_192_BIT (0x02 << 4)45#define TRNG_RNG_CTL_LEN_256_BIT (0x03 << 4)46#define TRNG_RNG_CTL_OSC_RING_SPEED_0 (0x00 << 2)47#define TRNG_RNG_CTL_OSC_RING_SPEED_1 (0x01 << 2)48#define TRNG_RNG_CTL_OSC_RING_SPEED_2 (0x02 << 2)49#define TRNG_RNG_CTL_OSC_RING_SPEED_3 (0x03 << 2)50#define TRNG_RNG_CTL_MASK GENMASK(15, 0)51#define TRNG_RNG_CTL_ENABLE BIT(1)52#define TRNG_RNG_CTL_START BIT(0)53#define TRNG_RNG_SAMPLE_CNT 0x040454#define TRNG_RNG_DOUT 0x04105556/*57* TRNG V1 register definitions58* The TRNG V1 IP is a stand-alone TRNG implementation (not part of a crypto IP)59* and can be found in the Rockchip RK3588 SoC60*/61#define TRNG_V1_CTRL 0x000062#define TRNG_V1_CTRL_NOP 0x0063#define TRNG_V1_CTRL_RAND 0x0164#define TRNG_V1_CTRL_SEED 0x026566#define TRNG_V1_STAT 0x000467#define TRNG_V1_STAT_SEEDED BIT(9)68#define TRNG_V1_STAT_GENERATING BIT(30)69#define TRNG_V1_STAT_RESEEDING BIT(31)7071#define TRNG_V1_MODE 0x000872#define TRNG_V1_MODE_128_BIT (0x00 << 3)73#define TRNG_V1_MODE_256_BIT (0x01 << 3)7475/* Interrupt Enable register; unused because polling is faster */76#define TRNG_V1_IE 0x001077#define TRNG_V1_IE_GLBL_EN BIT(31)78#define TRNG_V1_IE_SEED_DONE_EN BIT(1)79#define TRNG_V1_IE_RAND_RDY_EN BIT(0)8081#define TRNG_V1_ISTAT 0x001482#define TRNG_V1_ISTAT_RAND_RDY BIT(0)8384/* RAND0 ~ RAND7 */85#define TRNG_V1_RAND0 0x002086#define TRNG_V1_RAND7 0x003C8788/* Auto Reseed Register */89#define TRNG_V1_AUTO_RQSTS 0x00609091#define TRNG_V1_VERSION 0x00F092#define TRNG_v1_VERSION_CODE 0x46bc93/* end of TRNG_V1 register definitions */9495/*96* RKRNG register definitions97* The RKRNG IP is a stand-alone TRNG implementation (not part of a crypto IP)98* and can be found in the Rockchip RK3576, Rockchip RK3562 and Rockchip RK352899* SoCs. It can either output true randomness (TRNG) or "deterministic"100* randomness derived from hashing the true entropy (DRNG). This driver101* implementation uses just the true entropy, and leaves stretching the entropy102* up to Linux.103*/104#define RKRNG_CFG 0x0000105#define RKRNG_CTRL 0x0010106#define RKRNG_CTRL_REQ_TRNG BIT(4)107#define RKRNG_STATE 0x0014108#define RKRNG_STATE_TRNG_RDY BIT(4)109#define RKRNG_TRNG_DATA0 0x0050110#define RKRNG_TRNG_DATA1 0x0054111#define RKRNG_TRNG_DATA2 0x0058112#define RKRNG_TRNG_DATA3 0x005C113#define RKRNG_TRNG_DATA4 0x0060114#define RKRNG_TRNG_DATA5 0x0064115#define RKRNG_TRNG_DATA6 0x0068116#define RKRNG_TRNG_DATA7 0x006C117#define RKRNG_READ_LEN 32118119/* Before removing this assert, give rk3588_rng_read an upper bound of 32 */120static_assert(RK_RNG_MAX_BYTE <= (TRNG_V1_RAND7 + 4 - TRNG_V1_RAND0),121"You raised RK_RNG_MAX_BYTE and broke rk3588-rng, congrats.");122123struct rk_rng {124struct hwrng rng;125void __iomem *base;126int clk_num;127struct clk_bulk_data *clk_bulks;128const struct rk_rng_soc_data *soc_data;129struct device *dev;130};131132struct rk_rng_soc_data {133int (*rk_rng_init)(struct hwrng *rng);134int (*rk_rng_read)(struct hwrng *rng, void *buf, size_t max, bool wait);135void (*rk_rng_cleanup)(struct hwrng *rng);136unsigned short quality;137bool reset_optional;138};139140/* The mask in the upper 16 bits determines the bits that are updated */141static void rk_rng_write_ctl(struct rk_rng *rng, u32 val, u32 mask)142{143writel((mask << 16) | val, rng->base + TRNG_RNG_CTL);144}145146static inline void rk_rng_writel(struct rk_rng *rng, u32 val, u32 offset)147{148writel(val, rng->base + offset);149}150151static inline u32 rk_rng_readl(struct rk_rng *rng, u32 offset)152{153return readl(rng->base + offset);154}155156static int rk_rng_enable_clks(struct rk_rng *rk_rng)157{158int ret;159/* start clocks */160ret = clk_bulk_prepare_enable(rk_rng->clk_num, rk_rng->clk_bulks);161if (ret < 0) {162dev_err(rk_rng->dev, "Failed to enable clocks: %d\n", ret);163return ret;164}165166return 0;167}168169static int rk3568_rng_init(struct hwrng *rng)170{171struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);172int ret;173174ret = rk_rng_enable_clks(rk_rng);175if (ret < 0)176return ret;177178/* set the sample period */179writel(RK_RNG_SAMPLE_CNT, rk_rng->base + TRNG_RNG_SAMPLE_CNT);180181/* set osc ring speed and enable it */182rk_rng_write_ctl(rk_rng, TRNG_RNG_CTL_LEN_256_BIT |183TRNG_RNG_CTL_OSC_RING_SPEED_0 |184TRNG_RNG_CTL_ENABLE,185TRNG_RNG_CTL_MASK);186187return 0;188}189190static void rk3568_rng_cleanup(struct hwrng *rng)191{192struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);193194/* stop TRNG */195rk_rng_write_ctl(rk_rng, 0, TRNG_RNG_CTL_MASK);196197/* stop clocks */198clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks);199}200201static int rk3568_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)202{203struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);204size_t to_read = min_t(size_t, max, RK_RNG_MAX_BYTE);205u32 reg;206int ret = 0;207208ret = pm_runtime_resume_and_get(rk_rng->dev);209if (ret < 0)210return ret;211212/* Start collecting random data */213rk_rng_write_ctl(rk_rng, TRNG_RNG_CTL_START, TRNG_RNG_CTL_START);214215ret = readl_poll_timeout(rk_rng->base + TRNG_RNG_CTL, reg,216!(reg & TRNG_RNG_CTL_START),217RK_RNG_POLL_PERIOD_US,218RK_RNG_POLL_TIMEOUT_US);219if (ret < 0)220goto out;221222/* Read random data stored in the registers */223memcpy_fromio(buf, rk_rng->base + TRNG_RNG_DOUT, to_read);224out:225pm_runtime_put_sync_autosuspend(rk_rng->dev);226227return (ret < 0) ? ret : to_read;228}229230static int rk3576_rng_init(struct hwrng *rng)231{232struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);233234return rk_rng_enable_clks(rk_rng);235}236237static int rk3576_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)238{239struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);240size_t to_read = min_t(size_t, max, RKRNG_READ_LEN);241int ret = 0;242u32 val;243244ret = pm_runtime_resume_and_get(rk_rng->dev);245if (ret < 0)246return ret;247248rk_rng_writel(rk_rng, RKRNG_CTRL_REQ_TRNG | (RKRNG_CTRL_REQ_TRNG << 16),249RKRNG_CTRL);250251if (readl_poll_timeout(rk_rng->base + RKRNG_STATE, val,252(val & RKRNG_STATE_TRNG_RDY), RK_RNG_POLL_PERIOD_US,253RK_RNG_POLL_TIMEOUT_US)) {254dev_err(rk_rng->dev, "timed out waiting for data\n");255ret = -ETIMEDOUT;256goto out;257}258259rk_rng_writel(rk_rng, RKRNG_STATE_TRNG_RDY, RKRNG_STATE);260261memcpy_fromio(buf, rk_rng->base + RKRNG_TRNG_DATA0, to_read);262263out:264pm_runtime_put_sync_autosuspend(rk_rng->dev);265266return (ret < 0) ? ret : to_read;267}268269static int rk3588_rng_init(struct hwrng *rng)270{271struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);272u32 version, status, mask, istat;273int ret;274275ret = rk_rng_enable_clks(rk_rng);276if (ret < 0)277return ret;278279version = rk_rng_readl(rk_rng, TRNG_V1_VERSION);280if (version != TRNG_v1_VERSION_CODE) {281dev_err(rk_rng->dev,282"wrong trng version, expected = %08x, actual = %08x\n",283TRNG_V1_VERSION, version);284ret = -EFAULT;285goto err_disable_clk;286}287288mask = TRNG_V1_STAT_SEEDED | TRNG_V1_STAT_GENERATING |289TRNG_V1_STAT_RESEEDING;290if (readl_poll_timeout(rk_rng->base + TRNG_V1_STAT, status,291(status & mask) == TRNG_V1_STAT_SEEDED,292RK_RNG_POLL_PERIOD_US, RK_RNG_POLL_TIMEOUT_US) < 0) {293dev_err(rk_rng->dev, "timed out waiting for hwrng to reseed\n");294ret = -ETIMEDOUT;295goto err_disable_clk;296}297298/*299* clear ISTAT flag, downstream advises to do this to avoid300* auto-reseeding "on power on"301*/302istat = rk_rng_readl(rk_rng, TRNG_V1_ISTAT);303rk_rng_writel(rk_rng, istat, TRNG_V1_ISTAT);304305/* auto reseed after RK_TRNG_V1_AUTO_RESEED_CNT bytes */306rk_rng_writel(rk_rng, RK_TRNG_V1_AUTO_RESEED_CNT / 16, TRNG_V1_AUTO_RQSTS);307308return 0;309err_disable_clk:310clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks);311return ret;312}313314static void rk3588_rng_cleanup(struct hwrng *rng)315{316struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);317318clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks);319}320321static int rk3588_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)322{323struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);324size_t to_read = min_t(size_t, max, RK_RNG_MAX_BYTE);325int ret = 0;326u32 reg;327328ret = pm_runtime_resume_and_get(rk_rng->dev);329if (ret < 0)330return ret;331332/* Clear ISTAT, even without interrupts enabled, this will be updated */333reg = rk_rng_readl(rk_rng, TRNG_V1_ISTAT);334rk_rng_writel(rk_rng, reg, TRNG_V1_ISTAT);335336/* generate 256 bits of random data */337rk_rng_writel(rk_rng, TRNG_V1_MODE_256_BIT, TRNG_V1_MODE);338rk_rng_writel(rk_rng, TRNG_V1_CTRL_RAND, TRNG_V1_CTRL);339340ret = readl_poll_timeout_atomic(rk_rng->base + TRNG_V1_ISTAT, reg,341(reg & TRNG_V1_ISTAT_RAND_RDY), 0,342RK_RNG_POLL_TIMEOUT_US);343if (ret < 0)344goto out;345346/* Read random data that's in registers TRNG_V1_RAND0 through RAND7 */347memcpy_fromio(buf, rk_rng->base + TRNG_V1_RAND0, to_read);348349out:350/* Clear ISTAT */351rk_rng_writel(rk_rng, reg, TRNG_V1_ISTAT);352/* close the TRNG */353rk_rng_writel(rk_rng, TRNG_V1_CTRL_NOP, TRNG_V1_CTRL);354355pm_runtime_put_sync_autosuspend(rk_rng->dev);356357return (ret < 0) ? ret : to_read;358}359360static const struct rk_rng_soc_data rk3568_soc_data = {361.rk_rng_init = rk3568_rng_init,362.rk_rng_read = rk3568_rng_read,363.rk_rng_cleanup = rk3568_rng_cleanup,364.quality = 900,365.reset_optional = false,366};367368static const struct rk_rng_soc_data rk3576_soc_data = {369.rk_rng_init = rk3576_rng_init,370.rk_rng_read = rk3576_rng_read,371.rk_rng_cleanup = rk3588_rng_cleanup,372.quality = 999, /* as determined by actual testing */373.reset_optional = true,374};375376static const struct rk_rng_soc_data rk3588_soc_data = {377.rk_rng_init = rk3588_rng_init,378.rk_rng_read = rk3588_rng_read,379.rk_rng_cleanup = rk3588_rng_cleanup,380.quality = 999, /* as determined by actual testing */381.reset_optional = true,382};383384static int rk_rng_probe(struct platform_device *pdev)385{386struct device *dev = &pdev->dev;387struct reset_control *rst;388struct rk_rng *rk_rng;389int ret;390391rk_rng = devm_kzalloc(dev, sizeof(*rk_rng), GFP_KERNEL);392if (!rk_rng)393return -ENOMEM;394395rk_rng->soc_data = of_device_get_match_data(dev);396rk_rng->base = devm_platform_ioremap_resource(pdev, 0);397if (IS_ERR(rk_rng->base))398return PTR_ERR(rk_rng->base);399400rk_rng->clk_num = devm_clk_bulk_get_all(dev, &rk_rng->clk_bulks);401if (rk_rng->clk_num < 0)402return dev_err_probe(dev, rk_rng->clk_num,403"Failed to get clks property\n");404405if (rk_rng->soc_data->reset_optional)406rst = devm_reset_control_array_get_optional_exclusive(dev);407else408rst = devm_reset_control_array_get_exclusive(dev);409410if (rst) {411if (IS_ERR(rst))412return dev_err_probe(dev, PTR_ERR(rst), "Failed to get reset property\n");413414reset_control_assert(rst);415udelay(2);416reset_control_deassert(rst);417}418419platform_set_drvdata(pdev, rk_rng);420421rk_rng->rng.name = dev_driver_string(dev);422if (!IS_ENABLED(CONFIG_PM)) {423rk_rng->rng.init = rk_rng->soc_data->rk_rng_init;424rk_rng->rng.cleanup = rk_rng->soc_data->rk_rng_cleanup;425}426rk_rng->rng.read = rk_rng->soc_data->rk_rng_read;427rk_rng->dev = dev;428rk_rng->rng.quality = rk_rng->soc_data->quality;429430pm_runtime_set_autosuspend_delay(dev, RK_RNG_AUTOSUSPEND_DELAY);431pm_runtime_use_autosuspend(dev);432ret = devm_pm_runtime_enable(dev);433if (ret)434return dev_err_probe(dev, ret, "Runtime pm activation failed.\n");435436ret = devm_hwrng_register(dev, &rk_rng->rng);437if (ret)438return dev_err_probe(dev, ret, "Failed to register Rockchip hwrng\n");439440return 0;441}442443static int __maybe_unused rk_rng_runtime_suspend(struct device *dev)444{445struct rk_rng *rk_rng = dev_get_drvdata(dev);446447rk_rng->soc_data->rk_rng_cleanup(&rk_rng->rng);448449return 0;450}451452static int __maybe_unused rk_rng_runtime_resume(struct device *dev)453{454struct rk_rng *rk_rng = dev_get_drvdata(dev);455456return rk_rng->soc_data->rk_rng_init(&rk_rng->rng);457}458459static const struct dev_pm_ops rk_rng_pm_ops = {460SET_RUNTIME_PM_OPS(rk_rng_runtime_suspend,461rk_rng_runtime_resume, NULL)462SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,463pm_runtime_force_resume)464};465466static const struct of_device_id rk_rng_dt_match[] = {467{ .compatible = "rockchip,rk3568-rng", .data = (void *)&rk3568_soc_data },468{ .compatible = "rockchip,rk3576-rng", .data = (void *)&rk3576_soc_data },469{ .compatible = "rockchip,rk3588-rng", .data = (void *)&rk3588_soc_data },470{ /* sentinel */ },471};472473MODULE_DEVICE_TABLE(of, rk_rng_dt_match);474475static struct platform_driver rk_rng_driver = {476.driver = {477.name = "rockchip-rng",478.pm = &rk_rng_pm_ops,479.of_match_table = rk_rng_dt_match,480},481.probe = rk_rng_probe,482};483484module_platform_driver(rk_rng_driver);485486MODULE_DESCRIPTION("Rockchip True Random Number Generator driver");487MODULE_AUTHOR("Lin Jinhan <[email protected]>");488MODULE_AUTHOR("Aurelien Jarno <[email protected]>");489MODULE_AUTHOR("Daniel Golle <[email protected]>");490MODULE_AUTHOR("Nicolas Frattaroli <[email protected]>");491MODULE_LICENSE("GPL");492493494