389 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * APM X-Gene SoC RNG Driver4 *5 * Copyright (c) 2014, Applied Micro Circuits Corporation6 * Author: Rameshwar Prasad Sahu <rsahu@apm.com>7 * Shamal Winchurkar <swinchurkar@apm.com>8 * Feng Kan <fkan@apm.com>9 */10 11#include <linux/acpi.h>12#include <linux/clk.h>13#include <linux/delay.h>14#include <linux/hw_random.h>15#include <linux/init.h>16#include <linux/interrupt.h>17#include <linux/io.h>18#include <linux/module.h>19#include <linux/mod_devicetable.h>20#include <linux/platform_device.h>21#include <linux/timer.h>22 23#define RNG_MAX_DATUM 424#define MAX_TRY 10025#define XGENE_RNG_RETRY_COUNT 2026#define XGENE_RNG_RETRY_INTERVAL 1027 28/* RNG Registers */29#define RNG_INOUT_0 0x0030#define RNG_INTR_STS_ACK 0x1031#define RNG_CONTROL 0x1432#define RNG_CONFIG 0x1833#define RNG_ALARMCNT 0x1c34#define RNG_FROENABLE 0x2035#define RNG_FRODETUNE 0x2436#define RNG_ALARMMASK 0x2837#define RNG_ALARMSTOP 0x2c38#define RNG_OPTIONS 0x7839#define RNG_EIP_REV 0x7c40 41#define MONOBIT_FAIL_MASK BIT(7)42#define POKER_FAIL_MASK BIT(6)43#define LONG_RUN_FAIL_MASK BIT(5)44#define RUN_FAIL_MASK BIT(4)45#define NOISE_FAIL_MASK BIT(3)46#define STUCK_OUT_MASK BIT(2)47#define SHUTDOWN_OFLO_MASK BIT(1)48#define READY_MASK BIT(0)49 50#define MAJOR_HW_REV_RD(src) (((src) & 0x0f000000) >> 24)51#define MINOR_HW_REV_RD(src) (((src) & 0x00f00000) >> 20)52#define HW_PATCH_LEVEL_RD(src) (((src) & 0x000f0000) >> 16)53#define MAX_REFILL_CYCLES_SET(dst, src) \54 ((dst & ~0xffff0000) | (((u32)src << 16) & 0xffff0000))55#define MIN_REFILL_CYCLES_SET(dst, src) \56 ((dst & ~0x000000ff) | (((u32)src) & 0x000000ff))57#define ALARM_THRESHOLD_SET(dst, src) \58 ((dst & ~0x000000ff) | (((u32)src) & 0x000000ff))59#define ENABLE_RNG_SET(dst, src) \60 ((dst & ~BIT(10)) | (((u32)src << 10) & BIT(10)))61#define REGSPEC_TEST_MODE_SET(dst, src) \62 ((dst & ~BIT(8)) | (((u32)src << 8) & BIT(8)))63#define MONOBIT_FAIL_MASK_SET(dst, src) \64 ((dst & ~BIT(7)) | (((u32)src << 7) & BIT(7)))65#define POKER_FAIL_MASK_SET(dst, src) \66 ((dst & ~BIT(6)) | (((u32)src << 6) & BIT(6)))67#define LONG_RUN_FAIL_MASK_SET(dst, src) \68 ((dst & ~BIT(5)) | (((u32)src << 5) & BIT(5)))69#define RUN_FAIL_MASK_SET(dst, src) \70 ((dst & ~BIT(4)) | (((u32)src << 4) & BIT(4)))71#define NOISE_FAIL_MASK_SET(dst, src) \72 ((dst & ~BIT(3)) | (((u32)src << 3) & BIT(3)))73#define STUCK_OUT_MASK_SET(dst, src) \74 ((dst & ~BIT(2)) | (((u32)src << 2) & BIT(2)))75#define SHUTDOWN_OFLO_MASK_SET(dst, src) \76 ((dst & ~BIT(1)) | (((u32)src << 1) & BIT(1)))77 78struct xgene_rng_dev {79 u32 irq;80 void __iomem *csr_base;81 u32 revision;82 u32 datum_size;83 u32 failure_cnt; /* Failure count last minute */84 unsigned long failure_ts;/* First failure timestamp */85 struct timer_list failure_timer;86 struct device *dev;87};88 89static void xgene_rng_expired_timer(struct timer_list *t)90{91 struct xgene_rng_dev *ctx = from_timer(ctx, t, failure_timer);92 93 /* Clear failure counter as timer expired */94 disable_irq(ctx->irq);95 ctx->failure_cnt = 0;96 del_timer(&ctx->failure_timer);97 enable_irq(ctx->irq);98}99 100static void xgene_rng_start_timer(struct xgene_rng_dev *ctx)101{102 ctx->failure_timer.expires = jiffies + 120 * HZ;103 add_timer(&ctx->failure_timer);104}105 106/*107 * Initialize or reinit free running oscillators (FROs)108 */109static void xgene_rng_init_fro(struct xgene_rng_dev *ctx, u32 fro_val)110{111 writel(fro_val, ctx->csr_base + RNG_FRODETUNE);112 writel(0x00000000, ctx->csr_base + RNG_ALARMMASK);113 writel(0x00000000, ctx->csr_base + RNG_ALARMSTOP);114 writel(0xFFFFFFFF, ctx->csr_base + RNG_FROENABLE);115}116 117static void xgene_rng_chk_overflow(struct xgene_rng_dev *ctx)118{119 u32 val;120 121 val = readl(ctx->csr_base + RNG_INTR_STS_ACK);122 if (val & MONOBIT_FAIL_MASK)123 /*124 * LFSR detected an out-of-bounds number of 1s after125 * checking 20,000 bits (test T1 as specified in the126 * AIS-31 standard)127 */128 dev_err(ctx->dev, "test monobit failure error 0x%08X\n", val);129 if (val & POKER_FAIL_MASK)130 /*131 * LFSR detected an out-of-bounds value in at least one132 * of the 16 poker_count_X counters or an out of bounds sum133 * of squares value after checking 20,000 bits (test T2 as134 * specified in the AIS-31 standard)135 */136 dev_err(ctx->dev, "test poker failure error 0x%08X\n", val);137 if (val & LONG_RUN_FAIL_MASK)138 /*139 * LFSR detected a sequence of 34 identical bits140 * (test T4 as specified in the AIS-31 standard)141 */142 dev_err(ctx->dev, "test long run failure error 0x%08X\n", val);143 if (val & RUN_FAIL_MASK)144 /*145 * LFSR detected an outof-bounds value for at least one146 * of the running counters after checking 20,000 bits147 * (test T3 as specified in the AIS-31 standard)148 */149 dev_err(ctx->dev, "test run failure error 0x%08X\n", val);150 if (val & NOISE_FAIL_MASK)151 /* LFSR detected a sequence of 48 identical bits */152 dev_err(ctx->dev, "noise failure error 0x%08X\n", val);153 if (val & STUCK_OUT_MASK)154 /*155 * Detected output data registers generated same value twice156 * in a row157 */158 dev_err(ctx->dev, "stuck out failure error 0x%08X\n", val);159 160 if (val & SHUTDOWN_OFLO_MASK) {161 u32 frostopped;162 163 /* FROs shut down after a second error event. Try recover. */164 if (++ctx->failure_cnt == 1) {165 /* 1st time, just recover */166 ctx->failure_ts = jiffies;167 frostopped = readl(ctx->csr_base + RNG_ALARMSTOP);168 xgene_rng_init_fro(ctx, frostopped);169 170 /*171 * We must start a timer to clear out this error172 * in case the system timer wrap around173 */174 xgene_rng_start_timer(ctx);175 } else {176 /* 2nd time failure in lesser than 1 minute? */177 if (time_after(ctx->failure_ts + 60 * HZ, jiffies)) {178 dev_err(ctx->dev,179 "FRO shutdown failure error 0x%08X\n",180 val);181 } else {182 /* 2nd time failure after 1 minutes, recover */183 ctx->failure_ts = jiffies;184 ctx->failure_cnt = 1;185 /*186 * We must start a timer to clear out this187 * error in case the system timer wrap188 * around189 */190 xgene_rng_start_timer(ctx);191 }192 frostopped = readl(ctx->csr_base + RNG_ALARMSTOP);193 xgene_rng_init_fro(ctx, frostopped);194 }195 }196 /* Clear them all */197 writel(val, ctx->csr_base + RNG_INTR_STS_ACK);198}199 200static irqreturn_t xgene_rng_irq_handler(int irq, void *id)201{202 struct xgene_rng_dev *ctx = id;203 204 /* RNG Alarm Counter overflow */205 xgene_rng_chk_overflow(ctx);206 207 return IRQ_HANDLED;208}209 210static int xgene_rng_data_present(struct hwrng *rng, int wait)211{212 struct xgene_rng_dev *ctx = (struct xgene_rng_dev *) rng->priv;213 u32 i, val = 0;214 215 for (i = 0; i < XGENE_RNG_RETRY_COUNT; i++) {216 val = readl(ctx->csr_base + RNG_INTR_STS_ACK);217 if ((val & READY_MASK) || !wait)218 break;219 udelay(XGENE_RNG_RETRY_INTERVAL);220 }221 222 return (val & READY_MASK);223}224 225static int xgene_rng_data_read(struct hwrng *rng, u32 *data)226{227 struct xgene_rng_dev *ctx = (struct xgene_rng_dev *) rng->priv;228 int i;229 230 for (i = 0; i < ctx->datum_size; i++)231 data[i] = readl(ctx->csr_base + RNG_INOUT_0 + i * 4);232 233 /* Clear ready bit to start next transaction */234 writel(READY_MASK, ctx->csr_base + RNG_INTR_STS_ACK);235 236 return ctx->datum_size << 2;237}238 239static void xgene_rng_init_internal(struct xgene_rng_dev *ctx)240{241 u32 val;242 243 writel(0x00000000, ctx->csr_base + RNG_CONTROL);244 245 val = MAX_REFILL_CYCLES_SET(0, 10);246 val = MIN_REFILL_CYCLES_SET(val, 10);247 writel(val, ctx->csr_base + RNG_CONFIG);248 249 val = ALARM_THRESHOLD_SET(0, 0xFF);250 writel(val, ctx->csr_base + RNG_ALARMCNT);251 252 xgene_rng_init_fro(ctx, 0);253 254 writel(MONOBIT_FAIL_MASK |255 POKER_FAIL_MASK |256 LONG_RUN_FAIL_MASK |257 RUN_FAIL_MASK |258 NOISE_FAIL_MASK |259 STUCK_OUT_MASK |260 SHUTDOWN_OFLO_MASK |261 READY_MASK, ctx->csr_base + RNG_INTR_STS_ACK);262 263 val = ENABLE_RNG_SET(0, 1);264 val = MONOBIT_FAIL_MASK_SET(val, 1);265 val = POKER_FAIL_MASK_SET(val, 1);266 val = LONG_RUN_FAIL_MASK_SET(val, 1);267 val = RUN_FAIL_MASK_SET(val, 1);268 val = NOISE_FAIL_MASK_SET(val, 1);269 val = STUCK_OUT_MASK_SET(val, 1);270 val = SHUTDOWN_OFLO_MASK_SET(val, 1);271 writel(val, ctx->csr_base + RNG_CONTROL);272}273 274static int xgene_rng_init(struct hwrng *rng)275{276 struct xgene_rng_dev *ctx = (struct xgene_rng_dev *) rng->priv;277 278 ctx->failure_cnt = 0;279 timer_setup(&ctx->failure_timer, xgene_rng_expired_timer, 0);280 281 ctx->revision = readl(ctx->csr_base + RNG_EIP_REV);282 283 dev_dbg(ctx->dev, "Rev %d.%d.%d\n",284 MAJOR_HW_REV_RD(ctx->revision),285 MINOR_HW_REV_RD(ctx->revision),286 HW_PATCH_LEVEL_RD(ctx->revision));287 288 dev_dbg(ctx->dev, "Options 0x%08X",289 readl(ctx->csr_base + RNG_OPTIONS));290 291 xgene_rng_init_internal(ctx);292 293 ctx->datum_size = RNG_MAX_DATUM;294 295 return 0;296}297 298#ifdef CONFIG_ACPI299static const struct acpi_device_id xgene_rng_acpi_match[] = {300 { "APMC0D18", },301 { }302};303MODULE_DEVICE_TABLE(acpi, xgene_rng_acpi_match);304#endif305 306static struct hwrng xgene_rng_func = {307 .name = "xgene-rng",308 .init = xgene_rng_init,309 .data_present = xgene_rng_data_present,310 .data_read = xgene_rng_data_read,311};312 313static int xgene_rng_probe(struct platform_device *pdev)314{315 struct xgene_rng_dev *ctx;316 struct clk *clk;317 int rc = 0;318 319 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);320 if (!ctx)321 return -ENOMEM;322 323 ctx->dev = &pdev->dev;324 325 ctx->csr_base = devm_platform_ioremap_resource(pdev, 0);326 if (IS_ERR(ctx->csr_base))327 return PTR_ERR(ctx->csr_base);328 329 rc = platform_get_irq(pdev, 0);330 if (rc < 0)331 return rc;332 ctx->irq = rc;333 334 dev_dbg(&pdev->dev, "APM X-Gene RNG BASE %p ALARM IRQ %d",335 ctx->csr_base, ctx->irq);336 337 rc = devm_request_irq(&pdev->dev, ctx->irq, xgene_rng_irq_handler, 0,338 dev_name(&pdev->dev), ctx);339 if (rc)340 return dev_err_probe(&pdev->dev, rc, "Could not request RNG alarm IRQ\n");341 342 /* Enable IP clock */343 clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);344 if (IS_ERR(clk))345 return dev_err_probe(&pdev->dev, PTR_ERR(clk), "Couldn't get the clock for RNG\n");346 347 xgene_rng_func.priv = (unsigned long) ctx;348 349 rc = devm_hwrng_register(&pdev->dev, &xgene_rng_func);350 if (rc)351 return dev_err_probe(&pdev->dev, rc, "RNG registering failed\n");352 353 rc = device_init_wakeup(&pdev->dev, 1);354 if (rc)355 return dev_err_probe(&pdev->dev, rc, "RNG device_init_wakeup failed\n");356 357 return 0;358}359 360static void xgene_rng_remove(struct platform_device *pdev)361{362 int rc;363 364 rc = device_init_wakeup(&pdev->dev, 0);365 if (rc)366 dev_err(&pdev->dev, "RNG init wakeup failed error %d\n", rc);367}368 369static const struct of_device_id xgene_rng_of_match[] = {370 { .compatible = "apm,xgene-rng" },371 { }372};373 374MODULE_DEVICE_TABLE(of, xgene_rng_of_match);375 376static struct platform_driver xgene_rng_driver = {377 .probe = xgene_rng_probe,378 .remove_new = xgene_rng_remove,379 .driver = {380 .name = "xgene-rng",381 .of_match_table = xgene_rng_of_match,382 .acpi_match_table = ACPI_PTR(xgene_rng_acpi_match),383 },384};385 386module_platform_driver(xgene_rng_driver);387MODULE_DESCRIPTION("APM X-Gene RNG driver");388MODULE_LICENSE("GPL");389