272 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Random Number Generator driver for the Keystone SOC4 *5 * Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com6 *7 * Authors: Sandeep Nair8 * Vitaly Andrianov9 */10 11#include <linux/hw_random.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/io.h>15#include <linux/platform_device.h>16#include <linux/clk.h>17#include <linux/pm_runtime.h>18#include <linux/err.h>19#include <linux/regmap.h>20#include <linux/mfd/syscon.h>21#include <linux/of.h>22#include <linux/of_address.h>23#include <linux/delay.h>24#include <linux/timekeeping.h>25 26#define SA_CMD_STATUS_OFS 0x827 28/* TRNG enable control in SA System module*/29#define SA_CMD_STATUS_REG_TRNG_ENABLE BIT(3)30 31/* TRNG start control in TRNG module */32#define TRNG_CNTL_REG_TRNG_ENABLE BIT(10)33 34/* Data ready indicator in STATUS register */35#define TRNG_STATUS_REG_READY BIT(0)36 37/* Data ready clear control in INTACK register */38#define TRNG_INTACK_REG_READY BIT(0)39 40/*41 * Number of samples taken to gather entropy during startup.42 * If value is 0, the number of samples is 2^24 else43 * equals value times 2^8.44 */45#define TRNG_DEF_STARTUP_CYCLES 046#define TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT 1647 48/*49 * Minimum number of samples taken to regenerate entropy50 * If value is 0, the number of samples is 2^24 else51 * equals value times 2^6.52 */53#define TRNG_DEF_MIN_REFILL_CYCLES 154#define TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT 055 56/*57 * Maximum number of samples taken to regenerate entropy58 * If value is 0, the number of samples is 2^24 else59 * equals value times 2^8.60 */61#define TRNG_DEF_MAX_REFILL_CYCLES 062#define TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT 1663 64/* Number of CLK input cycles between samples */65#define TRNG_DEF_CLK_DIV_CYCLES 066#define TRNG_CFG_REG_SAMPLE_DIV_SHIFT 867 68/* Maximum retries to get rng data */69#define SA_MAX_RNG_DATA_RETRIES 570/* Delay between retries (in usecs) */71#define SA_RNG_DATA_RETRY_DELAY 572 73struct trng_regs {74 u32 output_l;75 u32 output_h;76 u32 status;77 u32 intmask;78 u32 intack;79 u32 control;80 u32 config;81};82 83struct ks_sa_rng {84 struct hwrng rng;85 struct clk *clk;86 struct regmap *regmap_cfg;87 struct trng_regs __iomem *reg_rng;88 u64 ready_ts;89 unsigned int refill_delay_ns;90};91 92static unsigned int cycles_to_ns(unsigned long clk_rate, unsigned int cycles)93{94 return DIV_ROUND_UP_ULL((TRNG_DEF_CLK_DIV_CYCLES + 1) * 1000000000ull *95 cycles, clk_rate);96}97 98static unsigned int startup_delay_ns(unsigned long clk_rate)99{100 if (!TRNG_DEF_STARTUP_CYCLES)101 return cycles_to_ns(clk_rate, BIT(24));102 return cycles_to_ns(clk_rate, 256 * TRNG_DEF_STARTUP_CYCLES);103}104 105static unsigned int refill_delay_ns(unsigned long clk_rate)106{107 if (!TRNG_DEF_MAX_REFILL_CYCLES)108 return cycles_to_ns(clk_rate, BIT(24));109 return cycles_to_ns(clk_rate, 256 * TRNG_DEF_MAX_REFILL_CYCLES);110}111 112static int ks_sa_rng_init(struct hwrng *rng)113{114 u32 value;115 struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);116 unsigned long clk_rate = clk_get_rate(ks_sa_rng->clk);117 118 /* Enable RNG module */119 regmap_write_bits(ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS,120 SA_CMD_STATUS_REG_TRNG_ENABLE,121 SA_CMD_STATUS_REG_TRNG_ENABLE);122 123 /* Configure RNG module */124 writel(0, &ks_sa_rng->reg_rng->control);125 value = TRNG_DEF_STARTUP_CYCLES << TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT;126 writel(value, &ks_sa_rng->reg_rng->control);127 128 value = (TRNG_DEF_MIN_REFILL_CYCLES <<129 TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT) |130 (TRNG_DEF_MAX_REFILL_CYCLES <<131 TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT) |132 (TRNG_DEF_CLK_DIV_CYCLES <<133 TRNG_CFG_REG_SAMPLE_DIV_SHIFT);134 135 writel(value, &ks_sa_rng->reg_rng->config);136 137 /* Disable all interrupts from TRNG */138 writel(0, &ks_sa_rng->reg_rng->intmask);139 140 /* Enable RNG */141 value = readl(&ks_sa_rng->reg_rng->control);142 value |= TRNG_CNTL_REG_TRNG_ENABLE;143 writel(value, &ks_sa_rng->reg_rng->control);144 145 ks_sa_rng->refill_delay_ns = refill_delay_ns(clk_rate);146 ks_sa_rng->ready_ts = ktime_get_ns() +147 startup_delay_ns(clk_rate);148 149 return 0;150}151 152static void ks_sa_rng_cleanup(struct hwrng *rng)153{154 struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);155 156 /* Disable RNG */157 writel(0, &ks_sa_rng->reg_rng->control);158 regmap_write_bits(ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS,159 SA_CMD_STATUS_REG_TRNG_ENABLE, 0);160}161 162static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data)163{164 struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);165 166 /* Read random data */167 data[0] = readl(&ks_sa_rng->reg_rng->output_l);168 data[1] = readl(&ks_sa_rng->reg_rng->output_h);169 170 writel(TRNG_INTACK_REG_READY, &ks_sa_rng->reg_rng->intack);171 ks_sa_rng->ready_ts = ktime_get_ns() + ks_sa_rng->refill_delay_ns;172 173 return sizeof(u32) * 2;174}175 176static int ks_sa_rng_data_present(struct hwrng *rng, int wait)177{178 struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);179 u64 now = ktime_get_ns();180 181 u32 ready;182 int j;183 184 if (wait && now < ks_sa_rng->ready_ts) {185 /* Max delay expected here is 81920000 ns */186 unsigned long min_delay =187 DIV_ROUND_UP((u32)(ks_sa_rng->ready_ts - now), 1000);188 189 usleep_range(min_delay, min_delay + SA_RNG_DATA_RETRY_DELAY);190 }191 192 for (j = 0; j < SA_MAX_RNG_DATA_RETRIES; j++) {193 ready = readl(&ks_sa_rng->reg_rng->status);194 ready &= TRNG_STATUS_REG_READY;195 196 if (ready || !wait)197 break;198 199 udelay(SA_RNG_DATA_RETRY_DELAY);200 }201 202 return ready;203}204 205static int ks_sa_rng_probe(struct platform_device *pdev)206{207 struct ks_sa_rng *ks_sa_rng;208 struct device *dev = &pdev->dev;209 int ret;210 211 ks_sa_rng = devm_kzalloc(dev, sizeof(*ks_sa_rng), GFP_KERNEL);212 if (!ks_sa_rng)213 return -ENOMEM;214 215 ks_sa_rng->rng = (struct hwrng) {216 .name = "ks_sa_hwrng",217 .init = ks_sa_rng_init,218 .data_read = ks_sa_rng_data_read,219 .data_present = ks_sa_rng_data_present,220 .cleanup = ks_sa_rng_cleanup,221 };222 223 ks_sa_rng->reg_rng = devm_platform_ioremap_resource(pdev, 0);224 if (IS_ERR(ks_sa_rng->reg_rng))225 return PTR_ERR(ks_sa_rng->reg_rng);226 227 ks_sa_rng->regmap_cfg =228 syscon_regmap_lookup_by_phandle(dev->of_node,229 "ti,syscon-sa-cfg");230 231 if (IS_ERR(ks_sa_rng->regmap_cfg))232 return dev_err_probe(dev, -EINVAL, "syscon_node_to_regmap failed\n");233 234 pm_runtime_enable(dev);235 ret = pm_runtime_resume_and_get(dev);236 if (ret < 0) {237 pm_runtime_disable(dev);238 return dev_err_probe(dev, ret, "Failed to enable SA power-domain\n");239 }240 241 return devm_hwrng_register(&pdev->dev, &ks_sa_rng->rng);242}243 244static void ks_sa_rng_remove(struct platform_device *pdev)245{246 pm_runtime_put_sync(&pdev->dev);247 pm_runtime_disable(&pdev->dev);248}249 250static const struct of_device_id ks_sa_rng_dt_match[] = {251 {252 .compatible = "ti,keystone-rng",253 },254 { },255};256MODULE_DEVICE_TABLE(of, ks_sa_rng_dt_match);257 258static struct platform_driver ks_sa_rng_driver = {259 .driver = {260 .name = "ks-sa-rng",261 .of_match_table = ks_sa_rng_dt_match,262 },263 .probe = ks_sa_rng_probe,264 .remove_new = ks_sa_rng_remove,265};266 267module_platform_driver(ks_sa_rng_driver);268 269MODULE_DESCRIPTION("Keystone NETCP SA H/W Random Number Generator driver");270MODULE_AUTHOR("Vitaly Andrianov <vitalya@ti.com>");271MODULE_LICENSE("GPL");272