static int omap4_rng_data_read(struct hwrng *rng, void *buf, size_t max, bool wait) { int res, i; for (i = 0; i < 20; i++) { res = trng_read(STATUS) & RNG_REG_STATUS_RDY; if (res || !wait) break; /* RNG produces data fast enough (2+ MBit/sec, even * during "rngtest" loads, that these delays don't * seem to trigger. We *could* use the RNG IRQ, but * that'd be higher overhead ... so why bother? */ udelay(10); } /* If we have data waiting, collect it... */ if (res) { *(u32 *)buf = trng_read(OUTPUT_L); buf += sizeof(u32); *(u32 *)buf = trng_read(OUTPUT_H); trng_write(RNG_REG_INTACK_RDY, INTACK); res = 2 * sizeof(u32); } return res; }
static int uecc_rng_trng(uint8_t *dst, unsigned int size) { size_t num; while (size) { num = trng_read(g_trng, dst, size); dst += num; size -= num; } return 1; }
static int __exit omap4_rng_remove(struct platform_device *pdev) { struct resource *res = dev_get_drvdata(&pdev->dev); hwrng_unregister(&omap4_rng_ops); trng_write(trng_read(CONTROL) & ~RNG_REG_CONTROL_ENABLE_TRNG, CONTROL); iounmap(rng_base); clk_disable(rng_fck); clk_put(rng_fck); release_mem_region(res->start, resource_size(res)); rng_base = NULL; return 0; }
/** * \internal * \brief Test for TRNG polling mode read. * * This test reads three random data in polling mode and check the result. * * \param test Current test case */ static void run_trng_polling_read_test(const struct test_case *test) { uint32_t i; uint32_t timeout; uint32_t random_result[3]; /* Structure for TRNG configuration */ struct trng_config config; /* Initialize and enable the TRNG */ trng_get_config_defaults(&config); trng_init(&trng_instance, TRNG, &config); trng_enable(&trng_instance); /* Read random data */ for (i = 0; i < 3; i++) { /* A new 32-bits random data will be generated for every * 84 CLK_TRNG_APB clock cycles. */ timeout = 84; if (trng_read(&trng_instance, &random_result[i]) != STATUS_OK) { timeout--; if (timeout == 0) { /* Skip test if fail to read random data */ test_assert_true(test, false, "Fail to read random data in polling mode."); } } } /* Assume there is no probability to read same three * consecutive random number */ if ((random_result[0] == random_result[1]) && (random_result[0] == random_result[2])) { test_assert_true(test, false, "Get same random data in polling mode."); } }
static int omap4_rng_resume(struct platform_device *pdev) { trng_write(trng_read(CONTROL) | RNG_REG_CONTROL_ENABLE_TRNG, CONTROL); return 0; }
static int omap4_rng_suspend(struct platform_device *pdev, pm_message_t message) { trng_write(trng_read(CONTROL) & ~RNG_REG_CONTROL_ENABLE_TRNG, CONTROL); return 0; }
static int __devinit omap4_rng_probe(struct platform_device *pdev) { struct resource *res; int ret; u32 reg; /* * A bit ugly, and it will never actually happen but there can * be only one RNG and this catches any bork */ if (rng_dev) return -EBUSY; rng_fck = clk_get(&pdev->dev, "rng_fck"); if (IS_ERR(rng_fck)) { dev_err(&pdev->dev, "Could not get rng_fck\n"); ret = PTR_ERR(rng_fck); return ret; } else clk_enable(rng_fck); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENOENT; goto err_region; } if (!request_mem_region(res->start, resource_size(res), pdev->name)) { ret = -EBUSY; goto err_region; } dev_set_drvdata(&pdev->dev, res); rng_base = ioremap(res->start, resource_size(res)); if (!rng_base) { ret = -ENOMEM; goto err_ioremap; } ret = hwrng_register(&omap4_rng_ops); if (ret) goto err_register; reg = trng_read(REV); dev_info(&pdev->dev, "OMAP4 Random Number Generator ver. %u.%02u\n", ((reg & RNG_REG_REV_X_MAJOR_MASK) >> 4), (reg & RNG_REG_REV_Y_MINOR_MASK)); rng_dev = pdev; /* start TRNG if not running yet */ if (!(trng_read(CONTROL) & RNG_REG_CONTROL_ENABLE_TRNG)) { trng_write(0x00220021, CONFIG); trng_write(0x00210400, CONTROL); } return 0; err_register: iounmap(rng_base); rng_base = NULL; err_ioremap: release_mem_region(res->start, resource_size(res)); err_region: clk_disable(rng_fck); clk_put(rng_fck); return ret; }