blob: 545b3a9d2a65c8a9a4183566ab15e726eac4b04e [file] [log] [blame]
/*******************************************************************************
* Copyright 2013 MARVELL SEMICONDUCTOR, LTD. *
* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL. *
* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT *
* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE *
* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL. *
* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED, *
* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE. *
* *
* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, *
* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL *
* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K. *
* (MJKK), MARVELL ISRAEL LTD. (MSIL). *
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
//! \file : bcm_hal.c
//! \brief : BCM (Base Crypto Module) driver
//! \author: Yong Shen
//! \date : Jan, 2014
//! Note:
////////////////////////////////////////////////////////////////////////////////
#include "bcm_mailbox.h"
#include "bcm_primitive.h"
#include "bcm_status.h"
#if 0
#define bcm_display printf
#else
#define bcm_display(...)
#endif
#define devmem_phy_to_virt(x) (x)
extern unsigned berlin_delay_us(unsigned us);
inline void bcm_memclr(void *p, int numInt)
{
volatile unsigned int *pStart = (unsigned int *)p;
volatile unsigned int *pEnd = pStart + numInt;
while (pStart < pEnd)
*pStart++ = 0;
}
inline void bcm_clear_command(BCM_MAILBOX_COMMAND * pCmd)
{
bcm_memclr(pCmd, sizeof(BCM_MAILBOX_COMMAND)/sizeof(int));
}
inline void bcm_clear_status(BCM_MAILBOX_STATUS * pStatus)
{
bcm_memclr(pStatus, sizeof(BCM_MAILBOX_STATUS)/sizeof(int));
}
static void bcm_send_command(BCM_MAILBOX_COMMAND *pCmd)
{
volatile _BCM_MAILBOX * biu = (_BCM_MAILBOX *)devmem_phy_to_virt(BCM_MAILBOX_BASE);
biu->command_parameter0 = pCmd->arg0;
biu->command_parameter1 = pCmd->arg1;
biu->command_parameter2 = pCmd->arg2;
biu->command_parameter3 = pCmd->arg3;
biu->command_parameter4 = pCmd->arg4;
biu->command_parameter5 = pCmd->arg5;
biu->command_parameter6 = pCmd->arg6;
biu->command_parameter7 = pCmd->arg7;
biu->command_parameter8 = pCmd->arg8;
biu->command_parameter9 = pCmd->arg9;
biu->command_parameter10 = pCmd->arg10;
biu->command_parameter11 = pCmd->arg11;
biu->command_parameter12 = pCmd->arg12;
biu->command_parameter13 = pCmd->arg13;
biu->command_parameter14 = pCmd->arg14;
biu->command_parameter15 = pCmd->arg15;
biu->secure_processor_command = pCmd->command;
bcm_display("Sending BCM command, command=0x%x\n", pCmd->command);
}
static int bcm_wait_for_complete(int wait_count)
{
volatile _BCM_MAILBOX * biu = (_BCM_MAILBOX *)devmem_phy_to_virt(BCM_MAILBOX_BASE);
volatile unsigned int intr_stat;
while(1) {
intr_stat = biu->host_interrupt_register; // 0xc8 Write-to-Clear
if(intr_stat & 1)
break;
berlin_delay_us(1000);
}
return 0;
}
static void bcm_get_status(BCM_MAILBOX_STATUS *pStatus)
{
volatile _BCM_MAILBOX * biu = (_BCM_MAILBOX *)devmem_phy_to_virt(BCM_MAILBOX_BASE);
pStatus->return_status = biu->command_return_status;
pStatus->arg0 = biu->command_status0;
pStatus->arg1 = biu->command_status1;
pStatus->arg2 = biu->command_status2;
pStatus->arg3 = biu->command_status3;
pStatus->arg4 = biu->command_status4;
pStatus->arg5 = biu->command_status5;
pStatus->arg6 = biu->command_status6;
pStatus->arg7 = biu->command_status7;
pStatus->arg8 = biu->command_status8;
pStatus->arg9 = biu->command_status9;
pStatus->arg10 = biu->command_status10;
pStatus->arg11 = biu->command_status11;
pStatus->arg12 = biu->command_status12;
pStatus->arg13 = biu->command_status13;
pStatus->arg14 = biu->command_status14;
pStatus->arg15 = biu->command_status15;
if(pStatus->return_status!=0)
bcm_display("!!!!!!BCM Return ERROR, return_status=0x%x!!!!!\n", pStatus->return_status);
}
void bcm_clear_interrupts(unsigned int mask)
{
volatile _BCM_MAILBOX * biu = (_BCM_MAILBOX *)devmem_phy_to_virt(BCM_MAILBOX_BASE);
#if 0
biu->host_interrupt_register = mask; // 0xc8 Write-to-Clear
#else
biu->host_interrupt_register = 0x70001;
#endif
}
void execute_bcm_command(BCM_MAILBOX_COMMAND *pCmd, BCM_MAILBOX_STATUS *pStatus)
{
bcm_send_command(pCmd);
bcm_wait_for_complete(0);
bcm_get_status(pStatus);
bcm_clear_interrupts(~0);
}
int bcm_wait_for_boot()
{
volatile _BCM_MAILBOX * biu = (_BCM_MAILBOX *)devmem_phy_to_virt(BCM_MAILBOX_BASE);
unsigned int intr_stat;
unsigned int fifo_stat;
unsigned int cmd_stat;
while(1) {
intr_stat = biu->host_interrupt_register; // 0xc8 Write-to-Clear
fifo_stat = biu->command_fifo_status; // 0xc4 Read Only
if( (intr_stat & 0x00010001) != 0) {
cmd_stat = biu->command_return_status; // 0x80 Read Only
bcm_display("Error: BCM boot fail. intr=%0x status=%0x\n", intr_stat, cmd_stat);
return -1;
}
if (fifo_stat & 0x100) {
bcm_display("\n=========================================");
bcm_display("BCM booted successfully. status=%0x", fifo_stat);
bcm_display("=========================================\n");
break;
}
}
return 0;
}
//clear fields not used in cmd before call.
int bcm_usb_boot_func(const BCM_MAILBOX_COMMAND* cmd)
{
BCM_MAILBOX_STATUS status;
bcm_clear_status(&status);
execute_bcm_command(cmd, &status);
if(status.return_status != STATUS_SUCCESS)
return -1;
return 0;
}