145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis/* 245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * RNG driver for Freescale RNGA 345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * 445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. 545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * Author: Alan Carvalho de Assis <acassis@gmail.com> 645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis */ 745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis/* 945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * The code contained herein is licensed under the GNU General Public 1045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * License. You may obtain a copy of the GNU General Public License 1145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * Version 2 or later at the following locations: 1245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * 1345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * http://www.opensource.org/licenses/gpl-license.html 1445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * http://www.gnu.org/copyleft/gpl.html 1545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * 1645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis * This driver is based on other RNG drivers. 1745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis */ 1845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 1945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/module.h> 2045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/init.h> 2145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/kernel.h> 2245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/clk.h> 2345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/err.h> 2445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/ioport.h> 2545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/platform_device.h> 2645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/hw_random.h> 2745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#include <linux/io.h> 2845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 2945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis/* RNGA Registers */ 3045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_CONTROL 0x00 3145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS 0x04 3245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_ENTROPY 0x08 3345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_OUTPUT_FIFO 0x0c 3445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_MODE 0x10 3545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_VERIFICATION_CONTROL 0x14 3645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_OSC_CONTROL_COUNTER 0x18 3745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_OSC1_COUNTER 0x1c 3845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_OSC2_COUNTER 0x20 3945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_OSC_COUNTER_STATUS 0x24 4045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 4145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis/* RNGA Registers Range */ 4245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNG_ADDR_RANGE 0x28 4345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 4445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis/* RNGA Control Register */ 4545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_CONTROL_SLEEP 0x00000010 4645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_CONTROL_CLEAR_INT 0x00000008 4745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_CONTROL_MASK_INTS 0x00000004 4845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_CONTROL_HIGH_ASSURANCE 0x00000002 4945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_CONTROL_GO 0x00000001 5045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 5145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS_LEVEL_MASK 0x0000ff00 5245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 5345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis/* RNGA Status Register */ 5445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS_OSC_DEAD 0x80000000 5545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS_SLEEP 0x00000010 5645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS_ERROR_INT 0x00000008 5745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS_FIFO_UNDERFLOW 0x00000004 5845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS_LAST_READ_STATUS 0x00000002 5945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis#define RNGA_STATUS_SECURITY_VIOLATION 0x00000001 6045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 6145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic struct platform_device *rng_dev; 6245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 6345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic int mxc_rnga_data_present(struct hwrng *rng) 6445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 6545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis int level; 6645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis void __iomem *rng_base = (void __iomem *)rng->priv; 6745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 6845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* how many random numbers is in FIFO? [0-16] */ 6945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis level = ((__raw_readl(rng_base + RNGA_STATUS) & 7045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis RNGA_STATUS_LEVEL_MASK) >> 8); 7145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 7245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return level > 0 ? 1 : 0; 7345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 7445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 7545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic int mxc_rnga_data_read(struct hwrng *rng, u32 * data) 7645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 7745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis int err; 7845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis u32 ctrl; 7945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis void __iomem *rng_base = (void __iomem *)rng->priv; 8045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 8145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* retrieve a random number from FIFO */ 8245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis *data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO); 8345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 8445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* some error while reading this random number? */ 8545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT; 8645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 8745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* if error: clear error interrupt, but doesn't return random number */ 8845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (err) { 8945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis dev_dbg(&rng_dev->dev, "Error while reading random number!\n"); 9045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis ctrl = __raw_readl(rng_base + RNGA_CONTROL); 9145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT, 9245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis rng_base + RNGA_CONTROL); 9345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return 0; 9445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis } else 9545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return 4; 9645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 9745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 9845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic int mxc_rnga_init(struct hwrng *rng) 9945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 10045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis u32 ctrl, osc; 10145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis void __iomem *rng_base = (void __iomem *)rng->priv; 10245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 10345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* wake up */ 10445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis ctrl = __raw_readl(rng_base + RNGA_CONTROL); 10545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL); 10645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 10745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* verify if oscillator is working */ 10845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis osc = __raw_readl(rng_base + RNGA_STATUS); 10945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (osc & RNGA_STATUS_OSC_DEAD) { 11045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n"); 11145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return -ENODEV; 11245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis } 11345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 11445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* go running */ 11545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis ctrl = __raw_readl(rng_base + RNGA_CONTROL); 11645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis __raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); 11745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 11845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return 0; 11945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 12045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 12145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic void mxc_rnga_cleanup(struct hwrng *rng) 12245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 12345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis u32 ctrl; 12445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis void __iomem *rng_base = (void __iomem *)rng->priv; 12545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 12645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis ctrl = __raw_readl(rng_base + RNGA_CONTROL); 12745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 12845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis /* stop rnga */ 12945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis __raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); 13045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 13145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 13245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic struct hwrng mxc_rnga = { 13345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .name = "mxc-rnga", 13445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .init = mxc_rnga_init, 13545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .cleanup = mxc_rnga_cleanup, 13645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .data_present = mxc_rnga_data_present, 13745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .data_read = mxc_rnga_data_read 13845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis}; 13945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 14045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic int __init mxc_rnga_probe(struct platform_device *pdev) 14145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 14245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis int err = -ENODEV; 14345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis struct clk *clk; 14445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis struct resource *res, *mem; 14545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis void __iomem *rng_base = NULL; 14645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 14745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (rng_dev) 14845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return -EBUSY; 14945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 15045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis clk = clk_get(&pdev->dev, "rng"); 15145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (IS_ERR(clk)) { 15245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis dev_err(&pdev->dev, "Could not get rng_clk!\n"); 15345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis err = PTR_ERR(clk); 15445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis goto out; 15545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis } 15645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 15745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis clk_enable(clk); 15845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 15945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 16045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (!res) { 16145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis err = -ENOENT; 16245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis goto err_region; 16345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis } 16445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 16545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis mem = request_mem_region(res->start, resource_size(res), pdev->name); 16645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (mem == NULL) { 16745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis err = -EBUSY; 16845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis goto err_region; 16945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis } 17045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 17145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis rng_base = ioremap(res->start, resource_size(res)); 17245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (!rng_base) { 17345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis err = -ENOMEM; 17445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis goto err_ioremap; 17545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis } 17645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 17745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis mxc_rnga.priv = (unsigned long)rng_base; 17845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 17945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis err = hwrng_register(&mxc_rnga); 18045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis if (err) { 18145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err); 18245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis goto err_register; 18345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis } 18445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 18545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis rng_dev = pdev; 18645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 18745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis dev_info(&pdev->dev, "MXC RNGA Registered.\n"); 18845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 18945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return 0; 19045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 19145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assiserr_register: 19245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis iounmap(rng_base); 19345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis rng_base = NULL; 19445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 19545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assiserr_ioremap: 19645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis release_mem_region(res->start, resource_size(res)); 19745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 19845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assiserr_region: 19945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis clk_disable(clk); 20045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis clk_put(clk); 20145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 20245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisout: 20345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return err; 20445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 20545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 20645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic int __exit mxc_rnga_remove(struct platform_device *pdev) 20745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 20845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 20945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis void __iomem *rng_base = (void __iomem *)mxc_rnga.priv; 21045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis struct clk *clk = clk_get(&pdev->dev, "rng"); 21145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 21245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis hwrng_unregister(&mxc_rnga); 21345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 21445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis iounmap(rng_base); 21545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 21645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis release_mem_region(res->start, resource_size(res)); 21745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 21845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis clk_disable(clk); 21945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis clk_put(clk); 22045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 22145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return 0; 22245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 22345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 22445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic struct platform_driver mxc_rnga_driver = { 22545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .driver = { 22645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .name = "mxc_rnga", 22745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .owner = THIS_MODULE, 22845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis }, 22945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis .remove = __exit_p(mxc_rnga_remove), 23045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis}; 23145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 23245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic int __init mod_init(void) 23345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 23445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis return platform_driver_probe(&mxc_rnga_driver, mxc_rnga_probe); 23545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 23645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 23745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assisstatic void __exit mod_exit(void) 23845001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis{ 23945001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis platform_driver_unregister(&mxc_rnga_driver); 24045001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis} 24145001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 24245001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assismodule_init(mod_init); 24345001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assismodule_exit(mod_exit); 24445001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de Assis 24545001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de AssisMODULE_AUTHOR("Freescale Semiconductor, Inc."); 24645001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de AssisMODULE_DESCRIPTION("H/W RNGA driver for i.MX"); 24745001e92d0249a8c4b9f6c3695215652e8e8493dAlan Carvalho de AssisMODULE_LICENSE("GPL"); 248