linux/drivers/char/hw_random/omap-rng.c
<<
>>
Prefs
   1/*
   2 * omap-rng.c - RNG driver for TI OMAP CPU family
   3 *
   4 * Author: Deepak Saxena <dsaxena@plexity.net>
   5 *
   6 * Copyright 2005 (c) MontaVista Software, Inc.
   7 *
   8 * Mostly based on original driver:
   9 *
  10 * Copyright (C) 2005 Nokia Corporation
  11 * Author: Juha Yrjölä <juha.yrjola@nokia.com>
  12 *
  13 * This file is licensed under  the terms of the GNU General Public
  14 * License version 2. This program is licensed "as is" without any
  15 * warranty of any kind, whether express or implied.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/init.h>
  20#include <linux/random.h>
  21#include <linux/err.h>
  22#include <linux/platform_device.h>
  23#include <linux/hw_random.h>
  24#include <linux/delay.h>
  25#include <linux/kernel.h>
  26#include <linux/slab.h>
  27#include <linux/pm_runtime.h>
  28#include <linux/of.h>
  29#include <linux/of_device.h>
  30#include <linux/of_address.h>
  31#include <linux/interrupt.h>
  32#include <linux/clk.h>
  33#include <linux/io.h>
  34
  35#define RNG_REG_STATUS_RDY                      (1 << 0)
  36
  37#define RNG_REG_INTACK_RDY_MASK                 (1 << 0)
  38#define RNG_REG_INTACK_SHUTDOWN_OFLO_MASK       (1 << 1)
  39#define RNG_SHUTDOWN_OFLO_MASK                  (1 << 1)
  40
  41#define RNG_CONTROL_STARTUP_CYCLES_SHIFT        16
  42#define RNG_CONTROL_STARTUP_CYCLES_MASK         (0xffff << 16)
  43#define RNG_CONTROL_ENABLE_TRNG_SHIFT           10
  44#define RNG_CONTROL_ENABLE_TRNG_MASK            (1 << 10)
  45
  46#define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT       16
  47#define RNG_CONFIG_MAX_REFIL_CYCLES_MASK        (0xffff << 16)
  48#define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT       0
  49#define RNG_CONFIG_MIN_REFIL_CYCLES_MASK        (0xff << 0)
  50
  51#define RNG_CONTROL_STARTUP_CYCLES              0xff
  52#define RNG_CONFIG_MIN_REFIL_CYCLES             0x21
  53#define RNG_CONFIG_MAX_REFIL_CYCLES             0x22
  54
  55#define RNG_ALARMCNT_ALARM_TH_SHIFT             0x0
  56#define RNG_ALARMCNT_ALARM_TH_MASK              (0xff << 0)
  57#define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT          16
  58#define RNG_ALARMCNT_SHUTDOWN_TH_MASK           (0x1f << 16)
  59#define RNG_ALARM_THRESHOLD                     0xff
  60#define RNG_SHUTDOWN_THRESHOLD                  0x4
  61
  62#define RNG_REG_FROENABLE_MASK                  0xffffff
  63#define RNG_REG_FRODETUNE_MASK                  0xffffff
  64
  65#define OMAP2_RNG_OUTPUT_SIZE                   0x4
  66#define OMAP4_RNG_OUTPUT_SIZE                   0x8
  67#define EIP76_RNG_OUTPUT_SIZE                   0x10
  68
  69/*
  70 * EIP76 RNG takes approx. 700us to produce 16 bytes of output data
  71 * as per testing results. And to account for the lack of udelay()'s
  72 * reliability, we keep the timeout as 1000us.
  73 */
  74#define RNG_DATA_FILL_TIMEOUT                   100
  75
  76enum {
  77        RNG_OUTPUT_0_REG = 0,
  78        RNG_OUTPUT_1_REG,
  79        RNG_OUTPUT_2_REG,
  80        RNG_OUTPUT_3_REG,
  81        RNG_STATUS_REG,
  82        RNG_INTMASK_REG,
  83        RNG_INTACK_REG,
  84        RNG_CONTROL_REG,
  85        RNG_CONFIG_REG,
  86        RNG_ALARMCNT_REG,
  87        RNG_FROENABLE_REG,
  88        RNG_FRODETUNE_REG,
  89        RNG_ALARMMASK_REG,
  90        RNG_ALARMSTOP_REG,
  91        RNG_REV_REG,
  92        RNG_SYSCONFIG_REG,
  93};
  94
  95static const u16 reg_map_omap2[] = {
  96        [RNG_OUTPUT_0_REG]      = 0x0,
  97        [RNG_STATUS_REG]        = 0x4,
  98        [RNG_CONFIG_REG]        = 0x28,
  99        [RNG_REV_REG]           = 0x3c,
 100        [RNG_SYSCONFIG_REG]     = 0x40,
 101};
 102
 103static const u16 reg_map_omap4[] = {
 104        [RNG_OUTPUT_0_REG]      = 0x0,
 105        [RNG_OUTPUT_1_REG]      = 0x4,
 106        [RNG_STATUS_REG]        = 0x8,
 107        [RNG_INTMASK_REG]       = 0xc,
 108        [RNG_INTACK_REG]        = 0x10,
 109        [RNG_CONTROL_REG]       = 0x14,
 110        [RNG_CONFIG_REG]        = 0x18,
 111        [RNG_ALARMCNT_REG]      = 0x1c,
 112        [RNG_FROENABLE_REG]     = 0x20,
 113        [RNG_FRODETUNE_REG]     = 0x24,
 114        [RNG_ALARMMASK_REG]     = 0x28,
 115        [RNG_ALARMSTOP_REG]     = 0x2c,
 116        [RNG_REV_REG]           = 0x1FE0,
 117        [RNG_SYSCONFIG_REG]     = 0x1FE4,
 118};
 119
 120static const u16 reg_map_eip76[] = {
 121        [RNG_OUTPUT_0_REG]      = 0x0,
 122        [RNG_OUTPUT_1_REG]      = 0x4,
 123        [RNG_OUTPUT_2_REG]      = 0x8,
 124        [RNG_OUTPUT_3_REG]      = 0xc,
 125        [RNG_STATUS_REG]        = 0x10,
 126        [RNG_INTACK_REG]        = 0x10,
 127        [RNG_CONTROL_REG]       = 0x14,
 128        [RNG_CONFIG_REG]        = 0x18,
 129        [RNG_ALARMCNT_REG]      = 0x1c,
 130        [RNG_FROENABLE_REG]     = 0x20,
 131        [RNG_FRODETUNE_REG]     = 0x24,
 132        [RNG_ALARMMASK_REG]     = 0x28,
 133        [RNG_ALARMSTOP_REG]     = 0x2c,
 134        [RNG_REV_REG]           = 0x7c,
 135};
 136
 137struct omap_rng_dev;
 138/**
 139 * struct omap_rng_pdata - RNG IP block-specific data
 140 * @regs: Pointer to the register offsets structure.
 141 * @data_size: No. of bytes in RNG output.
 142 * @data_present: Callback to determine if data is available.
 143 * @init: Callback for IP specific initialization sequence.
 144 * @cleanup: Callback for IP specific cleanup sequence.
 145 */
 146struct omap_rng_pdata {
 147        u16     *regs;
 148        u32     data_size;
 149        u32     (*data_present)(struct omap_rng_dev *priv);
 150        int     (*init)(struct omap_rng_dev *priv);
 151        void    (*cleanup)(struct omap_rng_dev *priv);
 152};
 153
 154struct omap_rng_dev {
 155        void __iomem                    *base;
 156        struct device                   *dev;
 157        const struct omap_rng_pdata     *pdata;
 158        struct hwrng rng;
 159        struct clk                      *clk;
 160        struct clk                      *clk_reg;
 161};
 162
 163static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg)
 164{
 165        return __raw_readl(priv->base + priv->pdata->regs[reg]);
 166}
 167
 168static inline void omap_rng_write(struct omap_rng_dev *priv, u16 reg,
 169                                      u32 val)
 170{
 171        __raw_writel(val, priv->base + priv->pdata->regs[reg]);
 172}
 173
 174
 175static int omap_rng_do_read(struct hwrng *rng, void *data, size_t max,
 176                            bool wait)
 177{
 178        struct omap_rng_dev *priv;
 179        int i, present;
 180
 181        priv = (struct omap_rng_dev *)rng->priv;
 182
 183        if (max < priv->pdata->data_size)
 184                return 0;
 185
 186        for (i = 0; i < RNG_DATA_FILL_TIMEOUT; i++) {
 187                present = priv->pdata->data_present(priv);
 188                if (present || !wait)
 189                        break;
 190
 191                udelay(10);
 192        }
 193        if (!present)
 194                return 0;
 195
 196        memcpy_fromio(data, priv->base + priv->pdata->regs[RNG_OUTPUT_0_REG],
 197                      priv->pdata->data_size);
 198
 199        if (priv->pdata->regs[RNG_INTACK_REG])
 200                omap_rng_write(priv, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK);
 201
 202        return priv->pdata->data_size;
 203}
 204
 205static int omap_rng_init(struct hwrng *rng)
 206{
 207        struct omap_rng_dev *priv;
 208
 209        priv = (struct omap_rng_dev *)rng->priv;
 210        return priv->pdata->init(priv);
 211}
 212
 213static void omap_rng_cleanup(struct hwrng *rng)
 214{
 215        struct omap_rng_dev *priv;
 216
 217        priv = (struct omap_rng_dev *)rng->priv;
 218        priv->pdata->cleanup(priv);
 219}
 220
 221
 222static inline u32 omap2_rng_data_present(struct omap_rng_dev *priv)
 223{
 224        return omap_rng_read(priv, RNG_STATUS_REG) ? 0 : 1;
 225}
 226
 227static int omap2_rng_init(struct omap_rng_dev *priv)
 228{
 229        omap_rng_write(priv, RNG_SYSCONFIG_REG, 0x1);
 230        return 0;
 231}
 232
 233static void omap2_rng_cleanup(struct omap_rng_dev *priv)
 234{
 235        omap_rng_write(priv, RNG_SYSCONFIG_REG, 0x0);
 236}
 237
 238static struct omap_rng_pdata omap2_rng_pdata = {
 239        .regs           = (u16 *)reg_map_omap2,
 240        .data_size      = OMAP2_RNG_OUTPUT_SIZE,
 241        .data_present   = omap2_rng_data_present,
 242        .init           = omap2_rng_init,
 243        .cleanup        = omap2_rng_cleanup,
 244};
 245
 246static inline u32 omap4_rng_data_present(struct omap_rng_dev *priv)
 247{
 248        return omap_rng_read(priv, RNG_STATUS_REG) & RNG_REG_STATUS_RDY;
 249}
 250
 251static int eip76_rng_init(struct omap_rng_dev *priv)
 252{
 253        u32 val;
 254
 255        /* Return if RNG is already running. */
 256        if (omap_rng_read(priv, RNG_CONTROL_REG) & RNG_CONTROL_ENABLE_TRNG_MASK)
 257                return 0;
 258
 259        /*  Number of 512 bit blocks of raw Noise Source output data that must
 260         *  be processed by either the Conditioning Function or the
 261         *  SP 800-90 DRBG ‘BC_DF’ functionality to yield a ‘full entropy’
 262         *  output value.
 263         */
 264        val = 0x5 << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
 265
 266        /* Number of FRO samples that are XOR-ed together into one bit to be
 267         * shifted into the main shift register
 268         */
 269        val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
 270        omap_rng_write(priv, RNG_CONFIG_REG, val);
 271
 272        /* Enable all available FROs */
 273        omap_rng_write(priv, RNG_FRODETUNE_REG, 0x0);
 274        omap_rng_write(priv, RNG_FROENABLE_REG, RNG_REG_FROENABLE_MASK);
 275
 276        /* Enable TRNG */
 277        val = RNG_CONTROL_ENABLE_TRNG_MASK;
 278        omap_rng_write(priv, RNG_CONTROL_REG, val);
 279
 280        return 0;
 281}
 282
 283static int omap4_rng_init(struct omap_rng_dev *priv)
 284{
 285        u32 val;
 286
 287        /* Return if RNG is already running. */
 288        if (omap_rng_read(priv, RNG_CONTROL_REG) & RNG_CONTROL_ENABLE_TRNG_MASK)
 289                return 0;
 290
 291        val = RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
 292        val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
 293        omap_rng_write(priv, RNG_CONFIG_REG, val);
 294
 295        omap_rng_write(priv, RNG_FRODETUNE_REG, 0x0);
 296        omap_rng_write(priv, RNG_FROENABLE_REG, RNG_REG_FROENABLE_MASK);
 297        val = RNG_ALARM_THRESHOLD << RNG_ALARMCNT_ALARM_TH_SHIFT;
 298        val |= RNG_SHUTDOWN_THRESHOLD << RNG_ALARMCNT_SHUTDOWN_TH_SHIFT;
 299        omap_rng_write(priv, RNG_ALARMCNT_REG, val);
 300
 301        val = RNG_CONTROL_STARTUP_CYCLES << RNG_CONTROL_STARTUP_CYCLES_SHIFT;
 302        val |= RNG_CONTROL_ENABLE_TRNG_MASK;
 303        omap_rng_write(priv, RNG_CONTROL_REG, val);
 304
 305        return 0;
 306}
 307
 308static void omap4_rng_cleanup(struct omap_rng_dev *priv)
 309{
 310        int val;
 311
 312        val = omap_rng_read(priv, RNG_CONTROL_REG);
 313        val &= ~RNG_CONTROL_ENABLE_TRNG_MASK;
 314        omap_rng_write(priv, RNG_CONTROL_REG, val);
 315}
 316
 317static irqreturn_t omap4_rng_irq(int irq, void *dev_id)
 318{
 319        struct omap_rng_dev *priv = dev_id;
 320        u32 fro_detune, fro_enable;
 321
 322        /*
 323         * Interrupt raised by a fro shutdown threshold, do the following:
 324         * 1. Clear the alarm events.
 325         * 2. De tune the FROs which are shutdown.
 326         * 3. Re enable the shutdown FROs.
 327         */
 328        omap_rng_write(priv, RNG_ALARMMASK_REG, 0x0);
 329        omap_rng_write(priv, RNG_ALARMSTOP_REG, 0x0);
 330
 331        fro_enable = omap_rng_read(priv, RNG_FROENABLE_REG);
 332        fro_detune = ~fro_enable & RNG_REG_FRODETUNE_MASK;
 333        fro_detune = fro_detune | omap_rng_read(priv, RNG_FRODETUNE_REG);
 334        fro_enable = RNG_REG_FROENABLE_MASK;
 335
 336        omap_rng_write(priv, RNG_FRODETUNE_REG, fro_detune);
 337        omap_rng_write(priv, RNG_FROENABLE_REG, fro_enable);
 338
 339        omap_rng_write(priv, RNG_INTACK_REG, RNG_REG_INTACK_SHUTDOWN_OFLO_MASK);
 340
 341        return IRQ_HANDLED;
 342}
 343
 344static struct omap_rng_pdata omap4_rng_pdata = {
 345        .regs           = (u16 *)reg_map_omap4,
 346        .data_size      = OMAP4_RNG_OUTPUT_SIZE,
 347        .data_present   = omap4_rng_data_present,
 348        .init           = omap4_rng_init,
 349        .cleanup        = omap4_rng_cleanup,
 350};
 351
 352static struct omap_rng_pdata eip76_rng_pdata = {
 353        .regs           = (u16 *)reg_map_eip76,
 354        .data_size      = EIP76_RNG_OUTPUT_SIZE,
 355        .data_present   = omap4_rng_data_present,
 356        .init           = eip76_rng_init,
 357        .cleanup        = omap4_rng_cleanup,
 358};
 359
 360static const struct of_device_id omap_rng_of_match[] __maybe_unused = {
 361                {
 362                        .compatible     = "ti,omap2-rng",
 363                        .data           = &omap2_rng_pdata,
 364                },
 365                {
 366                        .compatible     = "ti,omap4-rng",
 367                        .data           = &omap4_rng_pdata,
 368                },
 369                {
 370                        .compatible     = "inside-secure,safexcel-eip76",
 371                        .data           = &eip76_rng_pdata,
 372                },
 373                {},
 374};
 375MODULE_DEVICE_TABLE(of, omap_rng_of_match);
 376
 377static int of_get_omap_rng_device_details(struct omap_rng_dev *priv,
 378                                          struct platform_device *pdev)
 379{
 380        struct device *dev = &pdev->dev;
 381        int irq, err;
 382
 383        priv->pdata = of_device_get_match_data(dev);
 384        if (!priv->pdata)
 385                return -ENODEV;
 386
 387
 388        if (of_device_is_compatible(dev->of_node, "ti,omap4-rng") ||
 389            of_device_is_compatible(dev->of_node, "inside-secure,safexcel-eip76")) {
 390                irq = platform_get_irq(pdev, 0);
 391                if (irq < 0)
 392                        return irq;
 393
 394                err = devm_request_irq(dev, irq, omap4_rng_irq,
 395                                       IRQF_TRIGGER_NONE, dev_name(dev), priv);
 396                if (err) {
 397                        dev_err(dev, "unable to request irq %d, err = %d\n",
 398                                irq, err);
 399                        return err;
 400                }
 401
 402                /*
 403                 * On OMAP4, enabling the shutdown_oflo interrupt is
 404                 * done in the interrupt mask register. There is no
 405                 * such register on EIP76, and it's enabled by the
 406                 * same bit in the control register
 407                 */
 408                if (priv->pdata->regs[RNG_INTMASK_REG])
 409                        omap_rng_write(priv, RNG_INTMASK_REG,
 410                                       RNG_SHUTDOWN_OFLO_MASK);
 411                else
 412                        omap_rng_write(priv, RNG_CONTROL_REG,
 413                                       RNG_SHUTDOWN_OFLO_MASK);
 414        }
 415        return 0;
 416}
 417
 418static int get_omap_rng_device_details(struct omap_rng_dev *omap_rng)
 419{
 420        /* Only OMAP2/3 can be non-DT */
 421        omap_rng->pdata = &omap2_rng_pdata;
 422        return 0;
 423}
 424
 425static int omap_rng_probe(struct platform_device *pdev)
 426{
 427        struct omap_rng_dev *priv;
 428        struct device *dev = &pdev->dev;
 429        int ret;
 430
 431        priv = devm_kzalloc(dev, sizeof(struct omap_rng_dev), GFP_KERNEL);
 432        if (!priv)
 433                return -ENOMEM;
 434
 435        priv->rng.read = omap_rng_do_read;
 436        priv->rng.init = omap_rng_init;
 437        priv->rng.cleanup = omap_rng_cleanup;
 438        priv->rng.quality = 900;
 439
 440        priv->rng.priv = (unsigned long)priv;
 441        platform_set_drvdata(pdev, priv);
 442        priv->dev = dev;
 443
 444        priv->base = devm_platform_ioremap_resource(pdev, 0);
 445        if (IS_ERR(priv->base)) {
 446                ret = PTR_ERR(priv->base);
 447                goto err_ioremap;
 448        }
 449
 450        priv->rng.name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
 451        if (!priv->rng.name) {
 452                ret = -ENOMEM;
 453                goto err_ioremap;
 454        }
 455
 456        pm_runtime_enable(&pdev->dev);
 457        ret = pm_runtime_resume_and_get(&pdev->dev);
 458        if (ret < 0) {
 459                dev_err(&pdev->dev, "Failed to runtime_get device: %d\n", ret);
 460                goto err_ioremap;
 461        }
 462
 463        priv->clk = devm_clk_get(&pdev->dev, NULL);
 464        if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
 465                return -EPROBE_DEFER;
 466        if (!IS_ERR(priv->clk)) {
 467                ret = clk_prepare_enable(priv->clk);
 468                if (ret) {
 469                        dev_err(&pdev->dev,
 470                                "Unable to enable the clk: %d\n", ret);
 471                        goto err_register;
 472                }
 473        }
 474
 475        priv->clk_reg = devm_clk_get(&pdev->dev, "reg");
 476        if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
 477                return -EPROBE_DEFER;
 478        if (!IS_ERR(priv->clk_reg)) {
 479                ret = clk_prepare_enable(priv->clk_reg);
 480                if (ret) {
 481                        dev_err(&pdev->dev,
 482                                "Unable to enable the register clk: %d\n",
 483                                ret);
 484                        goto err_register;
 485                }
 486        }
 487
 488        ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
 489                                get_omap_rng_device_details(priv);
 490        if (ret)
 491                goto err_register;
 492
 493        ret = devm_hwrng_register(&pdev->dev, &priv->rng);
 494        if (ret)
 495                goto err_register;
 496
 497        dev_info(&pdev->dev, "Random Number Generator ver. %02x\n",
 498                 omap_rng_read(priv, RNG_REV_REG));
 499
 500        return 0;
 501
 502err_register:
 503        priv->base = NULL;
 504        pm_runtime_put_sync(&pdev->dev);
 505        pm_runtime_disable(&pdev->dev);
 506
 507        clk_disable_unprepare(priv->clk_reg);
 508        clk_disable_unprepare(priv->clk);
 509err_ioremap:
 510        dev_err(dev, "initialization failed.\n");
 511        return ret;
 512}
 513
 514static int omap_rng_remove(struct platform_device *pdev)
 515{
 516        struct omap_rng_dev *priv = platform_get_drvdata(pdev);
 517
 518
 519        priv->pdata->cleanup(priv);
 520
 521        pm_runtime_put_sync(&pdev->dev);
 522        pm_runtime_disable(&pdev->dev);
 523
 524        clk_disable_unprepare(priv->clk);
 525        clk_disable_unprepare(priv->clk_reg);
 526
 527        return 0;
 528}
 529
 530static int __maybe_unused omap_rng_suspend(struct device *dev)
 531{
 532        struct omap_rng_dev *priv = dev_get_drvdata(dev);
 533
 534        priv->pdata->cleanup(priv);
 535        pm_runtime_put_sync(dev);
 536
 537        return 0;
 538}
 539
 540static int __maybe_unused omap_rng_resume(struct device *dev)
 541{
 542        struct omap_rng_dev *priv = dev_get_drvdata(dev);
 543        int ret;
 544
 545        ret = pm_runtime_resume_and_get(dev);
 546        if (ret < 0) {
 547                dev_err(dev, "Failed to runtime_get device: %d\n", ret);
 548                return ret;
 549        }
 550
 551        priv->pdata->init(priv);
 552
 553        return 0;
 554}
 555
 556static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
 557
 558static struct platform_driver omap_rng_driver = {
 559        .driver = {
 560                .name           = "omap_rng",
 561                .pm             = &omap_rng_pm,
 562                .of_match_table = of_match_ptr(omap_rng_of_match),
 563        },
 564        .probe          = omap_rng_probe,
 565        .remove         = omap_rng_remove,
 566};
 567
 568module_platform_driver(omap_rng_driver);
 569MODULE_ALIAS("platform:omap_rng");
 570MODULE_AUTHOR("Deepak Saxena (and others)");
 571MODULE_LICENSE("GPL");
 572