2007-05-09 13:33:35 +04:00
/*
* Copyright ( C ) 2006 - 2007 PA Semi , Inc
*
* Maintained by : Olof Johansson < olof @ lixom . net >
*
* Driver for the PWRficient onchip rng
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/platform_device.h>
# include <linux/hw_random.h>
2007-11-21 07:24:45 +03:00
# include <linux/delay.h>
2008-05-23 10:20:05 +04:00
# include <linux/of_platform.h>
2007-05-09 13:33:35 +04:00
# include <asm/io.h>
# define SDCRNG_CTL_REG 0x00
# define SDCRNG_CTL_FVLD_M 0x0000f000
# define SDCRNG_CTL_FVLD_S 12
# define SDCRNG_CTL_KSZ 0x00000800
# define SDCRNG_CTL_RSRC_CRG 0x00000010
# define SDCRNG_CTL_RSRC_RRG 0x00000000
# define SDCRNG_CTL_CE 0x00000004
# define SDCRNG_CTL_RE 0x00000002
# define SDCRNG_CTL_DR 0x00000001
# define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG)
# define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG)
# define SDCRNG_VAL_REG 0x20
# define MODULE_NAME "pasemi_rng"
2007-12-01 04:52:35 +03:00
static int pasemi_rng_data_present ( struct hwrng * rng , int wait )
2007-05-09 13:33:35 +04:00
{
void __iomem * rng_regs = ( void __iomem * ) rng - > priv ;
2007-11-21 07:24:45 +03:00
int data , i ;
2007-05-09 13:33:35 +04:00
2007-11-21 07:24:45 +03:00
for ( i = 0 ; i < 20 ; i + + ) {
data = ( in_le32 ( rng_regs + SDCRNG_CTL_REG )
& SDCRNG_CTL_FVLD_M ) ? 1 : 0 ;
if ( data | | ! wait )
break ;
udelay ( 10 ) ;
}
return data ;
2007-05-09 13:33:35 +04:00
}
static int pasemi_rng_data_read ( struct hwrng * rng , u32 * data )
{
void __iomem * rng_regs = ( void __iomem * ) rng - > priv ;
* data = in_le32 ( rng_regs + SDCRNG_VAL_REG ) ;
return 4 ;
}
static int pasemi_rng_init ( struct hwrng * rng )
{
void __iomem * rng_regs = ( void __iomem * ) rng - > priv ;
u32 ctl ;
ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ ;
out_le32 ( rng_regs + SDCRNG_CTL_REG , ctl ) ;
out_le32 ( rng_regs + SDCRNG_CTL_REG , ctl & ~ SDCRNG_CTL_DR ) ;
return 0 ;
}
static void pasemi_rng_cleanup ( struct hwrng * rng )
{
void __iomem * rng_regs = ( void __iomem * ) rng - > priv ;
u32 ctl ;
ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE ;
out_le32 ( rng_regs + SDCRNG_CTL_REG ,
in_le32 ( rng_regs + SDCRNG_CTL_REG ) & ~ ctl ) ;
}
static struct hwrng pasemi_rng = {
. name = MODULE_NAME ,
. init = pasemi_rng_init ,
. cleanup = pasemi_rng_cleanup ,
. data_present = pasemi_rng_data_present ,
. data_read = pasemi_rng_data_read ,
} ;
2012-12-22 03:12:08 +04:00
static int rng_probe ( struct platform_device * ofdev )
2007-05-09 13:33:35 +04:00
{
void __iomem * rng_regs ;
2010-04-14 03:12:29 +04:00
struct device_node * rng_np = ofdev - > dev . of_node ;
2007-05-09 13:33:35 +04:00
struct resource res ;
int err = 0 ;
err = of_address_to_resource ( rng_np , 0 , & res ) ;
if ( err )
return - ENODEV ;
rng_regs = ioremap ( res . start , 0x100 ) ;
if ( ! rng_regs )
return - ENOMEM ;
pasemi_rng . priv = ( unsigned long ) rng_regs ;
printk ( KERN_INFO " Registering PA Semi RNG \n " ) ;
err = hwrng_register ( & pasemi_rng ) ;
if ( err )
iounmap ( rng_regs ) ;
return err ;
}
2012-11-19 22:26:26 +04:00
static int rng_remove ( struct platform_device * dev )
2007-05-09 13:33:35 +04:00
{
void __iomem * rng_regs = ( void __iomem * ) pasemi_rng . priv ;
hwrng_unregister ( & pasemi_rng ) ;
iounmap ( rng_regs ) ;
return 0 ;
}
static struct of_device_id rng_match [ ] = {
2007-11-05 05:57:45 +03:00
{ . compatible = " 1682m-rng " , } ,
{ . compatible = " pasemi,pwrficient-rng " , } ,
{ } ,
2007-05-09 13:33:35 +04:00
} ;
2011-02-23 05:59:54 +03:00
static struct platform_driver rng_driver = {
2010-04-14 03:13:02 +04:00
. driver = {
. name = " pasemi-rng " ,
. owner = THIS_MODULE ,
. of_match_table = rng_match ,
} ,
2007-05-09 13:33:35 +04:00
. probe = rng_probe ,
. remove = rng_remove ,
} ;
2011-11-26 17:11:06 +04:00
module_platform_driver ( rng_driver ) ;
2007-05-09 13:33:35 +04:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Egor Martovetsky <egor@pasemi.com> " ) ;
MODULE_DESCRIPTION ( " H/W RNG driver for PA Semi processor " ) ;