Path: blob/master/drivers/char/hw_random/omap3-rom-rng.c
29269 views
/*1* omap3-rom-rng.c - RNG driver for TI OMAP3 CPU family2*3* Copyright (C) 2009 Nokia Corporation4* Author: Juha Yrjola <[email protected]>5*6* Copyright (C) 2013 Pali Rohár <[email protected]>7*8* This file is licensed under the terms of the GNU General Public9* License version 2. This program is licensed "as is" without any10* warranty of any kind, whether express or implied.11*/1213#include <linux/module.h>14#include <linux/init.h>15#include <linux/random.h>16#include <linux/hw_random.h>17#include <linux/workqueue.h>18#include <linux/clk.h>19#include <linux/err.h>20#include <linux/io.h>21#include <linux/of.h>22#include <linux/platform_device.h>23#include <linux/pm_runtime.h>2425#define RNG_RESET 0x0126#define RNG_GEN_PRNG_HW_INIT 0x0227#define RNG_GEN_HW 0x082829struct omap_rom_rng {30struct clk *clk;31struct device *dev;32struct hwrng ops;33u32 (*rom_rng_call)(u32 ptr, u32 count, u32 flag);34};3536static int omap3_rom_rng_read(struct hwrng *rng, void *data, size_t max, bool w)37{38struct omap_rom_rng *ddata;39u32 ptr;40int r;4142ddata = (struct omap_rom_rng *)rng->priv;4344r = pm_runtime_get_sync(ddata->dev);45if (r < 0) {46pm_runtime_put_noidle(ddata->dev);4748return r;49}5051ptr = virt_to_phys(data);52r = ddata->rom_rng_call(ptr, 4, RNG_GEN_HW);53if (r != 0)54r = -EINVAL;55else56r = 4;5758pm_runtime_put_autosuspend(ddata->dev);5960return r;61}6263static int __maybe_unused omap_rom_rng_runtime_suspend(struct device *dev)64{65struct omap_rom_rng *ddata;66int r;6768ddata = dev_get_drvdata(dev);6970r = ddata->rom_rng_call(0, 0, RNG_RESET);71if (r != 0)72dev_err(dev, "reset failed: %d\n", r);7374clk_disable_unprepare(ddata->clk);7576return 0;77}7879static int __maybe_unused omap_rom_rng_runtime_resume(struct device *dev)80{81struct omap_rom_rng *ddata;82int r;8384ddata = dev_get_drvdata(dev);8586r = clk_prepare_enable(ddata->clk);87if (r < 0)88return r;8990r = ddata->rom_rng_call(0, 0, RNG_GEN_PRNG_HW_INIT);91if (r != 0) {92clk_disable_unprepare(ddata->clk);93dev_err(dev, "HW init failed: %d\n", r);9495return -EIO;96}9798return 0;99}100101static void omap_rom_rng_finish(void *data)102{103struct omap_rom_rng *ddata = data;104105pm_runtime_dont_use_autosuspend(ddata->dev);106pm_runtime_disable(ddata->dev);107}108109static int omap3_rom_rng_probe(struct platform_device *pdev)110{111struct omap_rom_rng *ddata;112int ret = 0;113114ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);115if (!ddata)116return -ENOMEM;117118ddata->dev = &pdev->dev;119ddata->ops.priv = (unsigned long)ddata;120ddata->ops.name = "omap3-rom";121ddata->ops.read = of_device_get_match_data(&pdev->dev);122ddata->ops.quality = 900;123if (!ddata->ops.read) {124dev_err(&pdev->dev, "missing rom code handler\n");125126return -ENODEV;127}128dev_set_drvdata(ddata->dev, ddata);129130ddata->rom_rng_call = pdev->dev.platform_data;131if (!ddata->rom_rng_call) {132dev_err(ddata->dev, "rom_rng_call is NULL\n");133return -EINVAL;134}135136ddata->clk = devm_clk_get(ddata->dev, "ick");137if (IS_ERR(ddata->clk)) {138dev_err(ddata->dev, "unable to get RNG clock\n");139return PTR_ERR(ddata->clk);140}141142pm_runtime_enable(&pdev->dev);143pm_runtime_set_autosuspend_delay(&pdev->dev, 500);144pm_runtime_use_autosuspend(&pdev->dev);145146ret = devm_add_action_or_reset(ddata->dev, omap_rom_rng_finish,147ddata);148if (ret)149return ret;150151return devm_hwrng_register(ddata->dev, &ddata->ops);152}153154static const struct of_device_id omap_rom_rng_match[] = {155{ .compatible = "nokia,n900-rom-rng", .data = omap3_rom_rng_read, },156{ /* sentinel */ },157};158MODULE_DEVICE_TABLE(of, omap_rom_rng_match);159160static const struct dev_pm_ops omap_rom_rng_pm_ops = {161SET_SYSTEM_SLEEP_PM_OPS(omap_rom_rng_runtime_suspend,162omap_rom_rng_runtime_resume)163};164165static struct platform_driver omap3_rom_rng_driver = {166.driver = {167.name = "omap3-rom-rng",168.of_match_table = omap_rom_rng_match,169.pm = &omap_rom_rng_pm_ops,170},171.probe = omap3_rom_rng_probe,172};173174module_platform_driver(omap3_rom_rng_driver);175176MODULE_ALIAS("platform:omap3-rom-rng");177MODULE_AUTHOR("Juha Yrjola");178MODULE_AUTHOR("Pali Rohár <[email protected]>");179MODULE_DESCRIPTION("RNG driver for TI OMAP3 CPU family");180MODULE_LICENSE("GPL");181182183