Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
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.");
	}
}
Exemplo n.º 5
0
static int omap4_rng_resume(struct platform_device *pdev)
{
	trng_write(trng_read(CONTROL) | RNG_REG_CONTROL_ENABLE_TRNG, CONTROL);

	return 0;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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;
}