blob: e1f7c2eb60b196ea878b38ed8ed1428d0281b4a2 [file] [log] [blame]
#ifndef _HASH_ALG_H
#define _HASH_ALG_H
/*
* Copyright (C) 2010 ST-Ericsson.
* Copyright (C) 2010 STMicroelectronics.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <mach/hcl_defs.h>
/* Number of bytes the message digest */
#define HASH_MSG_DIGEST_SIZE 32
#define HASH_BLOCK_SIZE 64
#define __HASH_ENHANCED
/* Version defines */
#define HASH_HCL_VERSION_ID 1
#define HASH_HCL_MAJOR_ID 2
#define HASH_HCL_MINOR_ID 1
#define MAX_HASH_DEVICE 2
/* Maximum value of the length's high word */
#define HASH_HIGH_WORD_MAX_VAL 0xFFFFFFFFUL
/* Power on Reset values HASH registers */
#define HASH_RESET_CONTROL_REG_VALUE 0x0
#define HASH_RESET_START_REG_VALUE 0x0
/* Number of context swap registers */
#define HASH_CSR_COUNT 52
#define HASH_RESET_CSRX_REG_VALUE 0x0
#define HASH_RESET_CSFULL_REG_VALUE 0x0
#define HASH_RESET_CSDATAIN_REG_VALUE 0x0
#define HASH_RESET_INDEX_VAL 0x0
#define HASH_RESET_BIT_INDEX_VAL 0x0
#define HASH_RESET_BUFFER_VAL 0x0
#define HASH_RESET_LEN_HIGH_VAL 0x0
#define HASH_RESET_LEN_LOW_VAL 0x0
/* Control register bitfields */
#define HASH_CR_RESUME_MASK 0x11FCF
#define HASH_CR_SWITCHON_POS 31
#define HASH_CR_SWITCHON_MASK MASK_BIT31
#define HASH_CR_EMPTYMSG_POS 20
#define HASH_CR_EMPTYMSG_MASK MASK_BIT20
#define HASH_CR_DINF_POS 12
#define HASH_CR_DINF_MASK MASK_BIT12
#define HASH_CR_NBW_POS 8
#define HASH_CR_NBW_MASK 0x00000F00UL
#define HASH_CR_LKEY_POS 16
#define HASH_CR_LKEY_MASK MASK_BIT16
#define HASH_CR_ALGO_POS 7
#define HASH_CR_ALGO_MASK MASK_BIT7
#define HASH_CR_MODE_POS 6
#define HASH_CR_MODE_MASK MASK_BIT6
#define HASH_CR_DATAFORM_POS 4
#define HASH_CR_DATAFORM_MASK (MASK_BIT4 | MASK_BIT5)
#define HASH_CR_DMAE_POS 3
#define HASH_CR_DMAE_MASK MASK_BIT3
#define HASH_CR_INIT_POS 2
#define HASH_CR_INIT_MASK MASK_BIT2
#define HASH_CR_PRIVN_POS 1
#define HASH_CR_PRIVN_MASK MASK_BIT1
#define HASH_CR_SECN_POS 0
#define HASH_CR_SECN_MASK MASK_BIT0
/* Start register bitfields */
#define HASH_STR_DCAL_POS 8
#define HASH_STR_DCAL_MASK MASK_BIT8
#define HASH_STR_NBLW_POS 0
#define HASH_STR_NBLW_MASK 0x0000001FUL
#define HASH_NBLW_MAX_VAL 0x1F
/* PrimeCell IDs */
#define HASH_P_ID0 0xE0
#define HASH_P_ID1 0x05
#define HASH_P_ID2 0x38
#define HASH_P_ID3 0x00
#define HASH_CELL_ID0 0x0D
#define HASH_CELL_ID1 0xF0
#define HASH_CELL_ID2 0x05
#define HASH_CELL_ID3 0xB1
#define HASH_SET_DIN(val) HCL_WRITE_REG(g_sys_ctx.registry[hid]->din, (val))
#define HASH_INITIALIZE \
HCL_WRITE_BITS( \
g_sys_ctx.registry[hid]->cr, \
0x01 << HASH_CR_INIT_POS, \
HASH_CR_INIT_MASK)
#define HASH_SET_DATA_FORMAT(data_format) \
HCL_WRITE_BITS( \
g_sys_ctx.registry[hid]->cr, \
(u32) (data_format) << HASH_CR_DATAFORM_POS, \
HASH_CR_DATAFORM_MASK)
#define HASH_GET_HX(pos) \
HCL_READ_REG(g_sys_ctx.registry[hid]->hx[pos])
#define HASH_SET_HX(pos, val) \
HCL_WRITE_REG(g_sys_ctx.registry[hid]->hx[pos], (val));
#define HASH_SET_NBLW(val) \
HCL_WRITE_BITS( \
g_sys_ctx.registry[hid]->str, \
(u32) (val) << HASH_STR_NBLW_POS, \
HASH_STR_NBLW_MASK)
#define HASH_SET_DCAL \
HCL_WRITE_BITS( \
g_sys_ctx.registry[hid]->str, \
0x01 << HASH_STR_DCAL_POS, \
HASH_STR_DCAL_MASK)
/**
* struct uint64 - Structure to handle 64 bits integers.
* @high_word: Most significant bits
* @high_word: Least significant bits
*
* Used to handle 64 bits integers.
*/
struct uint64 {
u32 high_word;
u32 low_word;
};
/**
* struct hash_register - Contains all registers in u8500 hash hardware.
* @cr: HASH control register (0x000)
* @din: HASH data input register (0x004)
* @str: HASH start register (0x008)
* @hx: HASH digest register 0..7 (0x00c-0x01C)
* @padding0: Reserved (0x02C)
* @itcr: Integration test control register (0x080)
* @itip: Integration test input register (0x084)
* @itop: Integration test output register (0x088)
* @padding1: Reserved (0x08C)
* @csfull: HASH context full register (0x0F8)
* @csdatain: HASH context swap data input register (0x0FC)
* @csrx: HASH context swap register 0..51 (0x100-0x1CC)
* @padding2: Reserved (0x1D0)
* @periphid0: HASH peripheral identification register 0 (0xFE0)
* @periphid1: HASH peripheral identification register 1 (0xFE4)
* @periphid2: HASH peripheral identification register 2 (0xFE8)
* @periphid3: HASH peripheral identification register 3 (0xFEC)
* @cellid0: HASH PCell identification register 0 (0xFF0)
* @cellid1: HASH PCell identification register 1 (0xFF4)
* @cellid2: HASH PCell identification register 2 (0xFF8)
* @cellid3: HASH PCell identification register 3 (0xFFC)
*
* The device communicates to the HASH via 32-bit-wide control registers
* accessible via the 32-bit width AMBA rev. 2.0 AHB Bus. Below is a structure
* with the registers used.
*/
struct hash_register {
u32 cr;
u32 din;
u32 str;
u32 hx[8];
u32 padding0[(0x080 - 0x02C) >> 2];
u32 itcr;
u32 itip;
u32 itop;
u32 padding1[(0x0F8 - 0x08C) >> 2];
u32 csfull;
u32 csdatain;
u32 csrx[HASH_CSR_COUNT];
u32 padding2[(0xFE0 - 0x1D0) >> 2];
u32 periphid0;
u32 periphid1;
u32 periphid2;
u32 periphid3;
u32 cellid0;
u32 cellid1;
u32 cellid2;
u32 cellid3;
};
/**
* struct hash_state - Hash context state.
* @temp_cr: Temporary HASH Control Register
* @str_reg: HASH Start Register
* @din_reg: HASH Data Input Register
* @csr[52]: HASH Context Swap Registers 0-39
* @csfull: HASH Context Swap Registers 40 ie Status flags
* @csdatain: HASH Context Swap Registers 41 ie Input data
* @buffer: Working buffer for messages going to the hardware
* @length: Length of the part of the message hashed so far (floor(N/64) * 64)
* @index: Valid number of bytes in buffer (N % 64)
* @bit_index: Valid number of bits in buffer (N % 8)
*
* This structure is used between context switches, i.e. when ongoing jobs are
* interupted with new jobs. When this happens we need to store intermediate
* results in software.
*
* WARNING: "index" is the member of the structure, to be sure that "buffer"
* is aligned on a 4-bytes boundary. This is highly implementation dependent
* and MUST be checked whenever this code is ported on new platforms.
*/
struct hash_state {
u32 temp_cr;
u32 str_reg;
u32 din_reg;
u32 csr[52];
u32 csfull;
u32 csdatain;
u32 buffer[HASH_BLOCK_SIZE / sizeof(u32)];
struct uint64 length;
u8 index;
u8 bit_index;
};
/**
* struct hash_system_context - Structure for the global system context.
* @registry: Pointer to the registry of the hash hardware
* @state: State of the hash device
*/
struct hash_system_context {
/* Pointer to HASH registers structure */
volatile struct hash_register *registry[MAX_HASH_DEVICE];
/* State of HASH device */
struct hash_state state[MAX_HASH_DEVICE];
};
/**
* enum hash_device_id - HASH device ID.
* @HASH_DEVICE_ID_0: Hash hardware with ID 0
* @HASH_DEVICE_ID_1: Hash hardware with ID 1
*/
enum hash_device_id {
HASH_DEVICE_ID_0 = 0,
HASH_DEVICE_ID_1 = 1
};
/**
* enum hash_data_format - HASH data format.
* @HASH_DATA_32_BITS: 32 bits data format
* @HASH_DATA_16_BITS: 16 bits data format
* @HASH_DATA_8_BITS: 8 bits data format
* @HASH_DATA_1_BITS: 1 bit data format
*/
enum hash_data_format {
HASH_DATA_32_BITS = 0x0,
HASH_DATA_16_BITS = 0x1,
HASH_DATA_8_BITS = 0x2,
HASH_DATA_1_BIT = 0x3
};
/**
* enum hash_device_state - Device state
* @DISABLE: Disable the hash hardware
* @ENABLE: Enable the hash hardware
*/
enum hash_device_state {
DISABLE = 0,
ENABLE = 1
};
/**
* struct hash_protection_config - Device protection configuration.
* @privilege_access: FIXME, add comment.
* @secure_access: FIXME, add comment.
*/
struct hash_protection_config {
int privilege_access;
int secure_access;
};
/**
* enum hash_input_status - Data Input flag status.
* @HASH_DIN_EMPTY: Indicates that nothing is in data registers
* @HASH_DIN_FULL: Indicates that data registers are full
*/
enum hash_input_status {
HASH_DIN_EMPTY = 0,
HASH_DIN_FULL = 1
};
/**
* Number of words already pushed
*/
enum hash_nbw_pushed {
HASH_NBW_00 = 0x00,
HASH_NBW_01 = 0x01,
HASH_NBW_02 = 0x02,
HASH_NBW_03 = 0x03,
HASH_NBW_04 = 0x04,
HASH_NBW_05 = 0x05,
HASH_NBW_06 = 0x06,
HASH_NBW_07 = 0x07,
HASH_NBW_08 = 0x08,
HASH_NBW_09 = 0x09,
HASH_NBW_10 = 0x0A,
HASH_NBW_11 = 0x0B,
HASH_NBW_12 = 0x0C,
HASH_NBW_13 = 0x0D,
HASH_NBW_14 = 0x0E,
HASH_NBW_15 = 0x0F
};
/**
* struct hash_device_status - Device status for DINF, NBW, and NBLW bit
* fields.
* @dinf_status: HASH data in full flag
* @nbw_status: Number of words already pushed
* @nblw_status: Number of Valid Bits Last Word of the Message
*/
struct hash_device_status {
int dinf_status;
int nbw_status;
u8 nblw_status;
};
/**
* enum hash_dma_request - Enumeration for HASH DMA request types.
*/
enum hash_dma_request {
HASH_DISABLE_DMA_REQ = 0x0,
HASH_ENABLE_DMA_REQ = 0x1
};
/**
* enum hash_digest_cal - Enumeration for digest calculation.
* @HASH_DISABLE_DCAL: Indicates that DCAL bit is not set/used.
* @HASH_ENABLE_DCAL: Indicates that DCAL bit is set/used.
*/
enum hash_digest_cal {
HASH_DISABLE_DCAL = 0x0,
HASH_ENABLE_DCAL = 0x1
};
/**
* enum hash_algo - Enumeration for selecting between SHA1 or SHA2 algorithm
* @HASH_ALGO_SHA1: Indicates that SHA1 is used.
* @HASH_ALGO_SHA2: Indicates that SHA2 (SHA256) is used.
*/
enum hash_algo {
HASH_ALGO_SHA1 = 0x0,
HASH_ALGO_SHA2 = 0x1
};
/**
* enum hash_op - Enumeration for selecting between HASH or HMAC mode
* @HASH_OPER_MODE_HASH: Indicates usage of normal HASH mode
* @HASH_OPER_MODE_HMAC: Indicates usage of HMAC
*/
enum hash_op {
HASH_OPER_MODE_HASH = 0x0,
HASH_OPER_MODE_HMAC = 0x1
};
/**
* enum hash_key_type - Enumeration for selecting between long and short key.
* @HASH_SHORT_KEY: Key used is shorter or equal to block size (64 bytes)
* @HASH_LONG_KEY: Key used is greater than block size (64 bytes)
*/
enum hash_key_type {
HASH_SHORT_KEY = 0x0,
HASH_LONG_KEY = 0x1
};
/**
* struct hash_config - Configuration data for the hardware
* @data_format: Format of data entered into the hash data in register
* @algorithm: Algorithm selection bit
* @oper_mode: Operating mode selection bit
* @hmac_key: Long key selection bit HMAC mode
*/
struct hash_config {
int data_format;
int algorithm;
int oper_mode;
int hmac_key;
};
/**
* enum hash_error - Error codes for hash.
*/
enum hash_error {
HASH_OK = 0,
HASH_MSG_LENGTH_OVERFLOW,
HASH_INTERNAL_ERROR,
HASH_NOT_CONFIGURED,
HASH_REQUEST_PENDING,
HASH_REQUEST_NOT_APPLICABLE,
HASH_INVALID_PARAMETER,
HASH_UNSUPPORTED_FEATURE,
HASH_UNSUPPORTED_HW
};
int hash_init_base_address(int hash_device_id, t_logical_address base_address);
int HASH_GetVersion(t_version *p_version);
int HASH_Reset(int hash_devive_id);
int HASH_ConfigureDmaRequest(int hash_device_id, int request_state);
int HASH_ConfigureLastValidBits(int hash_device_id, u8 nblw_val);
int HASH_ConfigureDigestCal(int hash_device_id, int dcal_state);
int HASH_ConfigureProtection(int hash_device_id,
struct hash_protection_config
*p_protect_config);
int hash_setconfiguration(int hash_device_id, struct hash_config *p_config);
int hash_begin(int hash_device_id);
int hash_get_digest(int hash_device_id, u8 digest[HASH_MSG_DIGEST_SIZE]);
int HASH_ClockGatingOff(int hash_device_id);
struct hash_device_status HASH_GetDeviceStatus(int hash_device_id);
t_bool HASH_IsDcalOngoing(int hash_device_id);
int hash_hw_update(int hash_device_id,
const u8 *p_data_buffer,
u32 msg_length);
int hash_end(int hash_device_id, u8 digest[HASH_MSG_DIGEST_SIZE]);
int hash_compute(int hash_device_id,
const u8 *p_data_buffer,
u32 msg_length,
struct hash_config *p_hash_config,
u8 digest[HASH_MSG_DIGEST_SIZE]);
int hash_end_key(int hash_device_id);
int hash_save_state(int hash_device_id, struct hash_state *state);
int hash_resume_state(int hash_device_id, const struct hash_state *state);
#ifdef __cplusplus
}
#endif
#endif