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>
2013-09-17 23:28:33 +04:00
# include <linux/of_address.h>
2008-05-23 10:20:05 +04:00
# include <linux/of_platform.h>
2016-09-06 11:28:39 +03:00
# include <linux/io.h>
2007-05-09 13:33:35 +04:00
# 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 ,
} ;
2016-09-04 21:13:08 +03:00
static int rng_probe ( struct platform_device * pdev )
2007-05-09 13:33:35 +04:00
{
void __iomem * rng_regs ;
2016-09-04 21:13:08 +03:00
struct resource * res ;
2007-05-09 13:33:35 +04:00
2016-09-04 21:13:08 +03:00
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
rng_regs = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( rng_regs ) )
return PTR_ERR ( rng_regs ) ;
2007-05-09 13:33:35 +04:00
pasemi_rng . priv = ( unsigned long ) rng_regs ;
2014-09-15 19:01:20 +04:00
pr_info ( " Registering PA Semi RNG \n " ) ;
2016-09-04 21:13:08 +03:00
return devm_hwrng_register ( & pdev - > dev , & pasemi_rng ) ;
2007-05-09 13:33:35 +04:00
}
2015-03-16 22:17:13 +03:00
static const 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
} ;
2015-09-15 19:41:33 +03:00
MODULE_DEVICE_TABLE ( of , rng_match ) ;
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 " ,
. of_match_table = rng_match ,
} ,
2007-05-09 13:33:35 +04:00
. probe = rng_probe ,
} ;
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 " ) ;