
On 03/06/2014 01:57 AM, Przemyslaw Marczak wrote:
This patch adds implementation of function hw_rand() based on exynos security sub system.
Signed-off-by: Przemyslaw Marczak p.marczak@samsung.com cc: Akshay Saraswat akshay.s@samsung.com cc: ARUN MANKUZHI arun.m@samsung.com cc: Minkyu Kang mk7.kang@samsung.com
Changes v2:
- none
arch/arm/include/asm/arch-exynos/cpu.h | 4 ++-- drivers/crypto/ace_sha.c | 41 ++++++++++++++++++++++++++++++++ drivers/crypto/ace_sha.h | 8 ++++--- 3 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index bccce63..a5c280d 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -48,7 +48,7 @@ #define EXYNOS4_GPIO_PART4_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_DP_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_SPI_ISP_BASE DEVICE_NOT_AVAILABLE -#define EXYNOS4_ACE_SFR_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS4_ACE_SFR_BASE 0x10830000 #define EXYNOS4_DMC_PHY_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_AUDIOSS_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE @@ -87,7 +87,7 @@ #define EXYNOS4X12_I2S_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_SPI_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_SPI_ISP_BASE DEVICE_NOT_AVAILABLE -#define EXYNOS4X12_ACE_SFR_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS4X12_ACE_SFR_BASE 0x10830000 #define EXYNOS4X12_DMC_PHY_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE diff --git a/drivers/crypto/ace_sha.c b/drivers/crypto/ace_sha.c index acbafde..d12a507 100644 --- a/drivers/crypto/ace_sha.c +++ b/drivers/crypto/ace_sha.c @@ -111,3 +111,44 @@ void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, if (ace_sha_hash_digest(pbuf, buf_len, pout, ACE_SHA_TYPE_SHA1)) debug("ACE was not setup properly or it is faulty\n"); }
+unsigned int hw_rand(void) +{
- struct exynos_ace_sfr *reg =
(struct exynos_ace_sfr *)samsung_get_base_ace_sfr();
- int status, i;
- int seed[5];
- unsigned int ret = 0;
- /* Seed data */
- for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++)
writel(seed[i], ®->hash_seed[i]);
- status = 0;
- /* Wait for seed setup done */
- while (!(status & ACE_HASH_SEEDSETTING_MASK)) {
status = readl(®->hash_status);
if (status & ACE_HASH_PRNGERROR_MASK)
return 0;
- }
Can it use "do{ }while"?
- /* Start PRNG */
- writel(ACE_HASH_ENGSEL_PRNG | ACE_HASH_STARTBIT_ON, ®->hash_control);
- status = 0;
- /* Wait for PRNG done */
- while (!(status & ACE_HASH_PRNGDONE_MASK)) {
status = readl(®->hash_status);
if (status & ACE_HASH_PRNGERROR_MASK)
return 0;
- }
- /* Clear Done IRQ */
- writel(ACE_HASH_PRNGDONE_MASK, ®->hash_status);
- /* Read a PRNG result */
- for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++)
ret += readl(®->hash_prng[i]);
- return ret;
+} diff --git a/drivers/crypto/ace_sha.h b/drivers/crypto/ace_sha.h index a426d52..f1097f7 100644 --- a/drivers/crypto/ace_sha.h +++ b/drivers/crypto/ace_sha.h @@ -72,9 +72,10 @@ struct exynos_ace_sfr { unsigned char res12[0x30]; unsigned int hash_result[8]; unsigned char res13[0x20];
- unsigned int hash_seed[8];
- unsigned int hash_prng[8];
- unsigned char res14[0x180];
unsigned int hash_seed[5];
unsigned char res14[12];
unsigned int hash_prng[5];
unsigned char res15[0x18c];
unsigned int pka_sfr[5]; /* base + 0x700 */
}; @@ -291,6 +292,7 @@ struct exynos_ace_sfr { #define ACE_HASH_PRNGERROR_MASK (1 << 7) #define ACE_HASH_PRNGERROR_OFF (0 << 7) #define ACE_HASH_PRNGERROR_ON (1 << 7) +#define ACE_HASH_PRNG_REG_NUM 5
#define ACE_SHA_TYPE_SHA1 1 #define ACE_SHA_TYPE_SHA256 2